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);
205 show_me_the_size (Requisition* r, const char* what)
207 cerr << "size of " << what << " = " << r->width << " x " << r->height << endl;
210 Editor::Editor (AudioEngine& eng)
213 /* time display buttons */
215 minsec_label (_("Mins:Secs")),
216 bbt_label (_("Bars:Beats")),
217 smpte_label (_("SMPTE")),
218 frame_label (_("Frames")),
219 tempo_label (_("Tempo")),
220 meter_label (_("Meter")),
221 mark_label (_("Location Markers")),
222 range_mark_label (_("Range Markers")),
223 transport_mark_label (_("Loop/Punch Ranges")),
225 edit_packer (3, 3, false),
227 /* the values here don't matter: layout widgets
228 reset them as needed.
231 vertical_adjustment (0.0, 0.0, 400.0, 10),
232 horizontal_adjustment (0.0, 0.0, 1200.0, 20),
234 /* tool bar related */
236 editor_mixer_button (_("editor\nmixer")),
238 selection_start_clock (X_("SelectionStartClock"), true),
239 selection_end_clock (X_("SelectionEndClock"), true),
240 edit_cursor_clock (X_("EditCursorClock"), true),
241 zoom_range_clock (X_("ZoomRangeClock"), true, true),
243 toolbar_selection_clock_table (2,3),
245 mouse_mode_button_table (2, 3),
247 mouse_select_button (_("range")),
248 mouse_move_button (_("object")),
249 mouse_gain_button (_("gain")),
250 mouse_zoom_button (_("zoom")),
251 mouse_timefx_button (_("timefx")),
252 mouse_audition_button (_("listen")),
254 automation_mode_button (_("mode")),
255 global_automation_button (_("automation")),
257 edit_mode_label (_("Edit Mode")),
258 snap_type_label (_("Snap To")),
259 snap_mode_label(_("Snap Mode")),
260 zoom_focus_label (_("Zoom Focus")),
262 /* <CMT Additions> */
263 image_socket_listener(0),
264 /* </CMT Additions> */
268 nudge_label (_("Nudge")),
269 nudge_clock (X_("NudgeClock"), true, true)
274 /* we are a singleton */
276 PublicEditor::_instance = this;
282 selection = new Selection;
283 cut_buffer = new Selection;
285 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
286 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
287 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
288 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
290 clicked_regionview = 0;
291 clicked_trackview = 0;
292 clicked_audio_trackview = 0;
293 clicked_crossfadeview = 0;
294 clicked_control_point = 0;
295 latest_regionview = 0;
296 last_update_frame = 0;
298 last_audition_region = 0;
299 current_mixer_strip = 0;
300 current_bbt_points = 0;
302 snap_type = SnapToFrame;
303 set_snap_to (snap_type);
304 snap_mode = SnapNormal;
305 set_snap_mode (snap_mode);
306 snap_threshold = 5.0;
307 bbt_beat_subdivision = 4;
310 autoscroll_timeout_tag = -1;
311 interthread_progress_window = 0;
312 current_interthread_info = 0;
313 _show_measures = true;
314 _show_waveforms = true;
315 _show_waveforms_recording = true;
316 first_action_message = 0;
318 show_gain_after_trim = false;
319 no_zoom_repos_update = false;
320 ignore_route_list_reorder = false;
321 verbose_cursor_on = true;
322 route_removal = false;
324 show_automatic_regions_in_region_list = true;
325 have_pending_keyboard_selection = false;
326 _follow_playhead = true;
327 _xfade_visibility = true;
328 editor_ruler_menu = 0;
329 no_ruler_shown_update = false;
330 edit_hscroll_dragging = false;
331 edit_group_list_menu = 0;
333 region_list_menu = 0;
335 marker_menu_item = 0;
337 transport_marker_menu = 0;
338 new_transport_marker_menu = 0;
339 editor_mixer_strip_width = Wide;
340 repos_zoom_queued = false;
341 import_audio_item = 0;
342 embed_audio_item = 0;
343 region_edit_menu_split_item = 0;
345 region_edit_menu_split_multichannel_item = 0;
347 ignore_mouse_mode_toggle = false;
348 current_stepping_trackview = 0;
350 entered_regionview = 0;
351 clear_entered_track = false;
352 _new_regionviews_show_envelope = false;
353 current_timestretch = 0;
358 location_marker_color = color_map[cLocationMarker];
359 location_range_color = color_map[cLocationRange];
360 location_cd_marker_color = color_map[cLocationCDMarker];
361 location_loop_color = color_map[cLocationLoop];
362 location_punch_color = color_map[cLocationPunch];
364 range_marker_drag_rect = 0;
365 marker_drag_line = 0;
367 mouse_mode = MouseZoom; /* force change in next call */
368 set_mouse_mode (MouseObject, true);
370 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
371 zoom_focus = ZoomFocusLeft;
372 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
374 initialize_rulers ();
375 initialize_canvas ();
377 edit_controls_vbox.set_spacing (track_spacing);
378 horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
379 vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
381 track_canvas.set_hadjustment (horizontal_adjustment);
382 track_canvas.set_vadjustment (vertical_adjustment);
383 time_canvas.set_hadjustment (horizontal_adjustment);
385 track_canvas.signal_map_event().connect (mem_fun (*this, &Editor::track_canvas_map_handler));
386 time_canvas.signal_map_event().connect (mem_fun (*this, &Editor::time_canvas_map_handler));
388 // edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
389 controls_layout.add (edit_controls_vbox);
390 controls_layout.set_name ("EditControlsBase");
391 controls_layout.signal_size_request().connect (mem_fun(*this, &Editor::set_layout_width), false);
393 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
394 controls_layout.signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
396 edit_vscrollbar.set_adjustment (vertical_adjustment);
397 edit_hscrollbar.set_adjustment (horizontal_adjustment);
399 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscrollbar_button_press));
400 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscrollbar_button_release));
401 edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscrollbar_allocate));
406 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
408 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
409 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
410 time_canvas_vbox.pack_start (*frames_ruler, false, false);
411 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
412 time_canvas_vbox.pack_start (time_canvas, true, true);
413 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
415 bbt_label.set_name ("EditorTimeButton");
416 bbt_label.set_size_request (-1, (int)timebar_height);
417 bbt_label.set_alignment (1.0, 0.5);
418 bbt_label.set_padding (5,0);
419 minsec_label.set_name ("EditorTimeButton");
420 minsec_label.set_size_request (-1, (int)timebar_height);
421 minsec_label.set_alignment (1.0, 0.5);
422 minsec_label.set_padding (5,0);
423 smpte_label.set_name ("EditorTimeButton");
424 smpte_label.set_size_request (-1, (int)timebar_height);
425 smpte_label.set_alignment (1.0, 0.5);
426 smpte_label.set_padding (5,0);
427 frame_label.set_name ("EditorTimeButton");
428 frame_label.set_size_request (-1, (int)timebar_height);
429 frame_label.set_alignment (1.0, 0.5);
430 frame_label.set_padding (5,0);
431 tempo_label.set_name ("EditorTimeButton");
432 tempo_label.set_size_request (-1, (int)timebar_height);
433 tempo_label.set_alignment (1.0, 0.5);
434 tempo_label.set_padding (5,0);
435 meter_label.set_name ("EditorTimeButton");
436 meter_label.set_size_request (-1, (int)timebar_height);
437 meter_label.set_alignment (1.0, 0.5);
438 meter_label.set_padding (5,0);
439 mark_label.set_name ("EditorTimeButton");
440 mark_label.set_size_request (-1, (int)timebar_height);
441 mark_label.set_alignment (1.0, 0.5);
442 mark_label.set_padding (5,0);
443 range_mark_label.set_name ("EditorTimeButton");
444 range_mark_label.set_size_request (-1, (int)timebar_height);
445 range_mark_label.set_alignment (1.0, 0.5);
446 range_mark_label.set_padding (5,0);
447 transport_mark_label.set_name ("EditorTimeButton");
448 transport_mark_label.set_size_request (-1, (int)timebar_height);
449 transport_mark_label.set_alignment (1.0, 0.5);
450 transport_mark_label.set_padding (5,0);
452 time_button_vbox.pack_start (minsec_label, false, false);
453 time_button_vbox.pack_start (smpte_label, false, false);
454 time_button_vbox.pack_start (frame_label, false, false);
455 time_button_vbox.pack_start (bbt_label, false, false);
456 time_button_vbox.pack_start (meter_label, false, false);
457 time_button_vbox.pack_start (tempo_label, false, false);
458 time_button_vbox.pack_start (mark_label, false, false);
460 time_button_event_box.add (time_button_vbox);
462 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
463 time_button_event_box.set_name ("TimebarLabelBase");
464 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
466 /* these enable us to have a dedicated window (for cursor setting, etc.)
467 for the canvas areas.
470 track_canvas_event_box.add (track_canvas);
472 time_canvas_event_box.add (time_canvas_vbox);
473 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
475 edit_packer.set_col_spacings (0);
476 edit_packer.set_row_spacings (0);
477 edit_packer.set_homogeneous (false);
478 edit_packer.set_name ("EditorWindow");
480 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
482 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
483 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
485 edit_packer.attach (controls_layout, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
486 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
487 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
489 edit_frame.set_name ("BaseFrame");
490 edit_frame.set_shadow_type (SHADOW_IN);
491 edit_frame.add (edit_packer);
493 zoom_in_button.set_name ("EditorTimeButton");
494 zoom_out_button.set_name ("EditorTimeButton");
495 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
496 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
498 zoom_out_full_button.set_name ("EditorTimeButton");
499 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
501 zoom_in_button.add (*(manage (new Gtk::Image (Stock::ZOOM_IN, ICON_SIZE_BUTTON))));
502 zoom_out_button.add (*(manage (new Gtk::Image (Stock::ZOOM_OUT, ICON_SIZE_BUTTON))));
503 zoom_out_full_button.add (*(manage (new Gtk::Image (Stock::ZOOM_FIT, ICON_SIZE_BUTTON))));
505 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
506 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
507 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
509 zoom_indicator_box.pack_start (zoom_out_button, false, false);
510 zoom_indicator_box.pack_start (zoom_in_button, false, false);
511 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
512 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
514 zoom_indicator_label.set_text (_("Zoom Span"));
515 zoom_indicator_label.set_name ("ToolBarLabel");
517 zoom_indicator_vbox.set_spacing (3);
518 zoom_indicator_vbox.set_border_width (3);
519 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
520 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
522 bottom_hbox.set_border_width (3);
523 bottom_hbox.set_spacing (3);
525 route_display_model = ListStore::create(route_display_columns);
526 route_list.set_model (route_display_model);
527 route_list.append_column (_("Tracks"), route_display_columns.text);
528 route_list.set_name ("TrackListDisplay");
529 route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
530 route_list.set_reorderable (true);
532 route_list.set_size_request (75,-1);
533 route_list.set_headers_visible (true);
534 route_list.set_headers_clickable (true);
537 // route_list.signal_rows_reordered().connect (mem_fun (*this, &Editor::queue_route_list_reordered));
540 // route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func));
543 //route_list.set_shadow_type (Gtk::SHADOW_IN);
545 route_list_scroller.add (route_list);
546 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
548 route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed));
549 route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click));
551 edit_group_list_button_label.set_text (_("Edit Groups"));
552 edit_group_list_button_label.set_name ("EditGroupTitleButton");
553 edit_group_list_button.add (edit_group_list_button_label);
554 edit_group_list_button.set_name ("EditGroupTitleButton");
556 group_model = ListStore::create(group_columns);
557 edit_group_list.set_model (group_model);
558 edit_group_list.append_column (_("active"), group_columns.is_active);
559 edit_group_list.append_column (_("groupname"), group_columns.text);
560 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
561 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
563 /* use checkbox for the active column */
565 CellRendererToggle *active_cell = dynamic_cast<CellRendererToggle*>(edit_group_list.get_column_cell_renderer (0));
566 active_cell->property_activatable() = true;
567 active_cell->property_radio() = false;
569 edit_group_list.set_name ("MixerGroupList");
570 //edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
572 edit_group_list.columns_autosize ();
573 edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
574 edit_group_list.set_reorderable (false);
576 edit_group_list.set_size_request (75, -1);
577 edit_group_list.set_headers_visible (true);
579 edit_group_list_scroller.add (edit_group_list);
580 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
582 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
583 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
584 edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed));
586 TreeModel::Row row = *(group_model->append());
587 row[group_columns.is_active] = false;
588 row[group_columns.text] = (_("-all-"));
589 edit_group_list.get_selection()->select (row);
590 /* GTK2FIX is set_data(0) setting the is_active to false here?
591 list<string> stupid_list;
593 stupid_list.push_back ("*");
594 stupid_list.push_back (_("-all-"));
596 edit_group_list.rows().push_back (stupid_list);
597 edit_group_list.rows().back().set_data (0);
598 edit_group_list.rows().back().select();
601 edit_group_vbox.pack_start (edit_group_list_button, false, false);
602 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
604 region_list_model = TreeStore::create (region_list_columns);
605 region_list_sort_model = TreeModelSort::create (region_list_model);
606 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
608 region_list_display.set_model (region_list_sort_model);
609 region_list_display.append_column (_("Regions"), region_list_columns.name);
610 region_list_display.set_reorderable (true);
611 region_list_display.set_size_request (100, -1);
612 region_list_display.set_data ("editor", this);
613 region_list_display.set_flags (Gtk::CAN_FOCUS);
614 region_list_display.set_name ("RegionListDisplay");
616 region_list_scroller.add (region_list_display);
617 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
619 list<Gtk::TargetEntry> region_list_target_table;
621 region_list_target_table.push_back (TargetEntry ("STRING"));
622 region_list_target_table.push_back (TargetEntry ("text/plain"));
623 region_list_target_table.push_back (TargetEntry ("text/uri-list"));
624 region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
627 // region_list_display.drag_dest_set (region_list_target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
628 // region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
630 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
631 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
632 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
633 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
634 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
636 //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
637 //region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click));
639 named_selection_scroller.add (named_selection_display);
640 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
642 named_selection_model = TreeStore::create (named_selection_columns);
643 named_selection_display.set_model (named_selection_model);
644 named_selection_display.append_column (_("Chunks"), named_selection_columns.text);
645 named_selection_display.set_size_request (100, -1);
646 named_selection_display.set_name ("RegionListDisplay");
648 named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
649 named_selection_display.set_size_request (100, -1);
650 named_selection_display.set_headers_visible (true);
651 named_selection_display.set_headers_clickable (true);
652 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
653 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
655 the_notebook.append_page (region_list_scroller, _("Regions"));
656 the_notebook.append_page (route_list_scroller, _("Tracks/Busses"));
657 the_notebook.append_page (edit_group_vbox, _("Edit Groups"));
658 the_notebook.append_page (named_selection_scroller, _("Chunks"));
659 the_notebook.set_show_tabs (true);
660 the_notebook.set_scrollable (true);
661 the_notebook.popup_enable ();
663 TearOff *notebook_tearoff = manage (new TearOff (the_notebook));
665 edit_pane.pack1 (edit_frame, true, true);
666 edit_pane.pack2 (*notebook_tearoff, true, true);
668 edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Gtk::Paned*> (&edit_pane)));
670 top_hbox.pack_start (toolbar_frame, true, true);
672 HBox *hbox = manage (new HBox);
673 hbox->pack_start (edit_pane, true, true);
675 global_vpacker.pack_start (top_hbox, false, false);
676 global_vpacker.pack_start (*hbox, true, true);
678 global_hpacker.pack_start (global_vpacker, true, true);
680 set_name ("EditorWindow");
681 add_accel_group (ActionManager::ui_manager->get_accel_group());
683 vpacker.pack_end (global_hpacker, true, true);
685 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
688 _playlist_selector = new PlaylistSelector();
689 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
691 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
695 nudge_forward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
696 nudge_backward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
698 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
699 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
701 nudge_forward_button.set_name ("TransportButton");
702 nudge_backward_button.set_name ("TransportButton");
704 fade_context_menu.set_name ("ArdourContextMenu");
706 set_title (_("ardour: editor"));
707 set_wmclass (_("ardour_editor"), "Ardour");
710 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
712 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
713 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
721 /* <CMT Additions> */
722 if(image_socket_listener)
724 if(image_socket_listener->is_connected())
726 image_socket_listener->close_connection() ;
729 delete image_socket_listener ;
730 image_socket_listener = 0 ;
732 /* </CMT Additions> */
736 Editor::add_toplevel_controls (Container& cont)
738 vpacker.pack_start (cont, false, false);
743 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
745 /* note: the selection will take care of the vanishing
746 audioregionview by itself.
749 if (clicked_regionview == rv) {
750 clicked_regionview = 0;
753 if (entered_regionview == rv) {
754 set_entered_regionview (0);
759 Editor::set_entered_regionview (AudioRegionView* rv)
761 if (rv == entered_regionview) {
765 if (entered_regionview) {
766 entered_regionview->exited ();
769 if ((entered_regionview = rv) != 0) {
770 entered_regionview->entered ();
775 Editor::set_entered_track (TimeAxisView* tav)
778 entered_track->exited ();
781 if ((entered_track = tav) != 0) {
782 entered_track->entered ();
787 Editor::left_track_canvas (GdkEventCrossing *ev)
789 set_entered_track (0);
790 set_entered_regionview (0);
796 Editor::show_window ()
801 /* now reset all audio_time_axis heights, because widgets might need
807 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
808 tv = (static_cast<TimeAxisView*>(*i));
814 Editor::tie_vertical_scrolling ()
816 double y1 = vertical_adjustment.get_value();
817 controls_layout.get_vadjustment()->set_value (y1);
819 playhead_cursor->set_y_axis(y1);
820 edit_cursor->set_y_axis(y1);
824 Editor::set_frames_per_unit (double fpu)
826 jack_nframes_t frames;
828 if (fpu == frames_per_unit) {
836 // convert fpu to frame count
838 frames = (jack_nframes_t) floor (fpu * canvas_width);
840 /* don't allow zooms that fit more than the maximum number
841 of frames into an 800 pixel wide space.
844 if (max_frames / fpu < 800.0) {
848 frames_per_unit = fpu;
850 if (frames != zoom_range_clock.current_duration()) {
851 zoom_range_clock.set (frames);
854 /* only update these if we not about to call reposition_x_origin,
855 which will do the same updates.
859 horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
862 if (!no_zoom_repos_update) {
863 horizontal_adjustment.set_value (leftmost_frame/frames_per_unit);
864 update_fixed_rulers ();
865 tempo_map_changed (Change (0));
868 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
869 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
870 (*i)->reshow_selection (selection->time);
874 ZoomChanged (); /* EMIT_SIGNAL */
876 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
877 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
884 Editor::instant_save ()
886 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
891 session->add_instant_xml(get_state(), session->path());
893 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
898 Editor::reposition_x_origin (jack_nframes_t frame)
900 if (frame != leftmost_frame) {
901 leftmost_frame = frame;
902 double pixel = frame_to_pixel (frame);
903 if (pixel >= horizontal_adjustment.get_upper()) {
904 horizontal_adjustment.set_upper (frame_to_pixel (frame + (current_page_frames())));
906 horizontal_adjustment.set_value (frame/frames_per_unit);
907 XOriginChanged (); /* EMIT_SIGNAL */
912 Editor::edit_cursor_clock_changed()
914 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
915 edit_cursor->set_position (edit_cursor_clock.current_time());
921 Editor::zoom_adjustment_changed ()
923 if (session == 0 || no_zoom_repos_update) {
927 double fpu = zoom_range_clock.current_duration() / canvas_width;
931 zoom_range_clock.set ((jack_nframes_t) floor (fpu * canvas_width));
932 } else if (fpu > session->current_end_frame() / canvas_width) {
933 fpu = session->current_end_frame() / canvas_width;
934 zoom_range_clock.set ((jack_nframes_t) floor (fpu * canvas_width));
941 Editor::canvas_horizontally_scrolled ()
943 leftmost_frame = (jack_nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
945 update_fixed_rulers ();
947 if (!edit_hscroll_dragging) {
948 tempo_map_changed (Change (0));
950 update_tempo_based_rulers();
955 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
957 if (!repos_zoom_queued) {
958 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
959 repos_zoom_queued = true;
964 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
966 /* if we need to force an update to the hscroller stuff,
967 don't set no_zoom_repos_update.
970 no_zoom_repos_update = (frame != leftmost_frame);
972 set_frames_per_unit (nfpu);
973 if (no_zoom_repos_update) {
974 reposition_x_origin (frame);
976 no_zoom_repos_update = false;
977 repos_zoom_queued = false;
983 Editor::on_realize ()
985 Window::on_realize ();
987 /* Even though we're not using acceleration, we want the
991 track_context_menu.accelerate (*this->get_toplevel());
992 track_region_context_menu.accelerate (*this->get_toplevel());
997 Editor::queue_session_control_changed (Session::ControlType t)
999 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1003 Editor::session_control_changed (Session::ControlType t)
1005 // right now we're only tracking the loop and punch state
1008 case Session::AutoLoop:
1009 update_loop_range_view (true);
1011 case Session::PunchIn:
1012 case Session::PunchOut:
1013 update_punch_range_view (true);
1022 Editor::fake_add_edit_group (RouteGroup *group)
1024 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1028 Editor::fake_handle_new_audio_region (AudioRegion *region)
1030 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1034 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1036 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1040 Editor::fake_handle_new_duration ()
1042 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1046 Editor::start_scrolling ()
1048 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1049 (mem_fun(*this, &Editor::update_current_screen));
1051 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1052 (mem_fun(*this, &Editor::update_slower));
1056 Editor::stop_scrolling ()
1058 scroll_connection.disconnect ();
1059 slower_update_connection.disconnect ();
1063 Editor::map_position_change (jack_nframes_t frame)
1065 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1067 if (session == 0 || !_follow_playhead) {
1071 center_screen (frame);
1072 playhead_cursor->set_position (frame);
1076 Editor::center_screen (jack_nframes_t frame)
1078 double page = canvas_width * frames_per_unit;
1080 /* if we're off the page, then scroll.
1083 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1084 center_screen_internal (frame, page);
1089 Editor::center_screen_internal (jack_nframes_t frame, float page)
1094 frame -= (jack_nframes_t) page;
1099 reposition_x_origin (frame);
1103 Editor::handle_new_duration ()
1105 reset_scrolling_region ();
1108 horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
1109 horizontal_adjustment.set_value (leftmost_frame/frames_per_unit);
1114 Editor::update_title_s (stringcr_t snap_name)
1116 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1122 Editor::update_title ()
1124 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1127 bool dirty = session->dirty();
1129 string wintitle = _("ardour: editor: ");
1135 wintitle += session->name();
1137 if (session->snap_name() != session->name()) {
1139 wintitle += session->snap_name();
1146 set_title (wintitle);
1151 Editor::connect_to_session (Session *t)
1155 if (first_action_message) {
1156 first_action_message->hide();
1159 flush_track_canvas();
1163 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1165 /* These signals can all be emitted by a non-GUI thread. Therefore the
1166 handlers for them must not attempt to directly interact with the GUI,
1167 but use Gtkmm2ext::UI::instance()->call_slot();
1170 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1171 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1172 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1173 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1174 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1175 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1176 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1177 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1178 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1179 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1180 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1181 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1182 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1184 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1185 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1187 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1189 session->foreach_edit_group(this, &Editor::add_edit_group);
1191 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1192 editor_mixer_button.set_name (X_("EditorMixerButton"));
1194 edit_cursor_clock.set_session (session);
1195 selection_start_clock.set_session (session);
1196 selection_end_clock.set_session (session);
1197 zoom_range_clock.set_session (session);
1198 _playlist_selector->set_session (session);
1199 nudge_clock.set_session (session);
1201 switch (session->get_edit_mode()) {
1203 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1207 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1211 Location* loc = session->locations()->auto_loop_location();
1213 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1214 if (loc->start() == loc->end()) {
1215 loc->set_end (loc->start() + 1);
1217 session->locations()->add (loc, false);
1218 session->set_auto_loop_location (loc);
1222 loc->set_name (_("Loop"));
1225 loc = session->locations()->auto_punch_location();
1227 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1228 if (loc->start() == loc->end()) {
1229 loc->set_end (loc->start() + 1);
1231 session->locations()->add (loc, false);
1232 session->set_auto_punch_location (loc);
1236 loc->set_name (_("Punch"));
1239 update_loop_range_view (true);
1240 update_punch_range_view (true);
1242 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1245 refresh_location_display ();
1246 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1247 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1248 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1249 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1250 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1252 reset_scrolling_region ();
1254 redisplay_regions ();
1255 redisplay_named_selections ();
1257 //route_list.freeze (); GTK2FIX
1258 route_display_model->clear ();
1259 session->foreach_route (this, &Editor::handle_new_route);
1260 // route_list.select_all ();
1262 //route_list.sort ();
1263 route_list_reordered ();
1264 //route_list.thaw ();
1266 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1267 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1270 /* ::reposition_x_origin() doesn't work right here, since the old
1271 position may be zero already, and it does nothing in such
1277 horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
1278 horizontal_adjustment.set_value (0);
1280 restore_ruler_visibility ();
1281 tempo_map_changed (Change (0));
1283 edit_cursor->set_position (0);
1284 playhead_cursor->set_position (0);
1288 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1291 /* don't show master bus in a new session */
1293 if (ARDOUR_UI::instance()->session_is_new ()) {
1295 TreeModel::Children rows = route_display_model->children();
1296 TreeModel::Children::iterator i;
1298 //route_list.freeze ();
1300 for (i = rows.begin(); i != rows.end(); ++i) {
1301 TimeAxisView *tv = (*i)[route_display_columns.tv];
1302 AudioTimeAxisView *atv;
1304 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1305 if (atv->route().master()) {
1306 route_list.get_selection()->unselect (i);
1307 //(*i)->unselect ();
1312 //route_list.thaw ();
1317 Editor::build_cursors ()
1319 using namespace Gdk;
1321 Gdk::Color mbg ("#000000" ); /* Black */
1322 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1325 RefPtr<Bitmap> source, mask;
1326 source = Bitmap::create (mag_bits, mag_width, mag_height);
1327 mask = Bitmap::create (magmask_bits, mag_width, mag_height);
1328 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1331 Gdk::Color fbg ("#ffffff" );
1332 Gdk::Color ffg ("#000000" );
1335 RefPtr<Bitmap> source, mask;
1337 source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
1338 mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
1339 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1343 RefPtr<Bitmap> source, mask;
1344 source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
1345 mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
1346 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1349 grabber_cursor = new Gdk::Cursor (HAND2);
1350 cross_hair_cursor = new Gdk::Cursor (CROSSHAIR);
1351 trimmer_cursor = new Gdk::Cursor (SB_H_DOUBLE_ARROW);
1352 selector_cursor = new Gdk::Cursor (XTERM);
1353 time_fx_cursor = new Gdk::Cursor (SIZING);
1354 wait_cursor = new Gdk::Cursor (WATCH);
1355 timebar_cursor = new Gdk::Cursor(LEFT_PTR);
1359 Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
1361 using namespace Menu_Helpers;
1362 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1365 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1369 MenuList& items (fade_context_menu.items());
1373 switch (item_type) {
1375 case FadeInHandleItem:
1376 if (arv->region.fade_in_active()) {
1377 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1379 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1382 items.push_back (SeparatorElem());
1384 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1385 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1386 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1387 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1388 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1392 case FadeOutHandleItem:
1393 if (arv->region.fade_out_active()) {
1394 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1396 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1399 items.push_back (SeparatorElem());
1401 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1402 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1403 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1404 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1405 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1409 fatal << _("programming error: ")
1410 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1415 fade_context_menu.popup (button, time);
1419 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1421 using namespace Menu_Helpers;
1422 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1425 switch (item_type) {
1427 case AudioRegionViewName:
1428 case AudioRegionViewNameHighlight:
1429 if (with_selection) {
1430 build_menu_function = &Editor::build_track_selection_context_menu;
1432 build_menu_function = &Editor::build_track_region_context_menu;
1437 if (with_selection) {
1438 build_menu_function = &Editor::build_track_selection_context_menu;
1440 build_menu_function = &Editor::build_track_context_menu;
1444 case CrossfadeViewItem:
1445 build_menu_function = &Editor::build_track_crossfade_context_menu;
1449 if (clicked_audio_trackview->get_diskstream()) {
1450 build_menu_function = &Editor::build_track_context_menu;
1452 build_menu_function = &Editor::build_track_bus_context_menu;
1457 /* probably shouldn't happen but if it does, we don't care */
1461 menu = (this->*build_menu_function)(frame);
1462 menu->set_name ("ArdourContextMenu");
1464 /* now handle specific situations */
1466 switch (item_type) {
1468 case AudioRegionViewName:
1469 case AudioRegionViewNameHighlight:
1470 if (!with_selection) {
1471 if (region_edit_menu_split_item) {
1472 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1473 // GTK2FIX find the action, change its sensitivity
1474 // region_edit_menu_split_item->set_sensitive (true);
1476 // GTK2FIX see above
1477 // region_edit_menu_split_item->set_sensitive (false);
1480 if (region_edit_menu_split_multichannel_item) {
1481 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1482 // GTK2FIX find the action, change its sensitivity
1483 // region_edit_menu_split_multichannel_item->set_sensitive (true);
1485 // GTK2FIX see above
1486 // region_edit_menu_split_multichannel_item->set_sensitive (false);
1495 case CrossfadeViewItem:
1502 /* probably shouldn't happen but if it does, we don't care */
1506 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1508 /* Bounce to disk */
1510 using namespace Menu_Helpers;
1511 MenuList& edit_items = menu->items();
1513 edit_items.push_back (SeparatorElem());
1515 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1516 case AudioTrack::NoFreeze:
1517 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1520 case AudioTrack::Frozen:
1521 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1524 case AudioTrack::UnFrozen:
1525 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1531 menu->popup (button, time);
1535 Editor::build_track_context_menu (jack_nframes_t ignored)
1537 using namespace Menu_Helpers;
1539 MenuList& edit_items = track_context_menu.items();
1542 add_dstream_context_items (edit_items);
1543 return &track_context_menu;
1547 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1549 using namespace Menu_Helpers;
1551 MenuList& edit_items = track_context_menu.items();
1554 add_bus_context_items (edit_items);
1555 return &track_context_menu;
1559 Editor::build_track_region_context_menu (jack_nframes_t frame)
1561 using namespace Menu_Helpers;
1562 MenuList& edit_items = track_region_context_menu.items();
1565 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1571 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1572 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1573 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1574 add_region_context_items (atv->view, (*i), edit_items);
1580 add_dstream_context_items (edit_items);
1582 return &track_region_context_menu;
1586 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1588 using namespace Menu_Helpers;
1589 MenuList& edit_items = track_crossfade_context_menu.items();
1590 edit_items.clear ();
1592 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1599 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
1601 Playlist::RegionList* regions = pl->regions_at (frame);
1602 AudioPlaylist::Crossfades xfades;
1604 apl->crossfades_at (frame, xfades);
1606 bool many = xfades.size() > 1;
1608 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
1609 add_crossfade_context_items (atv->view, (*i), edit_items, many);
1612 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1613 add_region_context_items (atv->view, (*i), edit_items);
1620 add_dstream_context_items (edit_items);
1622 return &track_crossfade_context_menu;
1626 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
1628 using namespace Menu_Helpers;
1629 MenuList& edit_items = track_selection_context_menu.items();
1630 edit_items.clear ();
1632 add_selection_context_items (edit_items);
1633 add_dstream_context_items (edit_items);
1635 return &track_selection_context_menu;
1639 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
1641 using namespace Menu_Helpers;
1642 Menu *xfade_menu = manage (new Menu);
1643 MenuList& items = xfade_menu->items();
1644 xfade_menu->set_name ("ArdourContextMenu");
1647 if (xfade->active()) {
1653 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
1654 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
1656 if (xfade->can_follow_overlap()) {
1658 if (xfade->following_overlap()) {
1659 str = _("Convert to short");
1661 str = _("Convert to full");
1664 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
1668 str = xfade->out().name();
1670 str += xfade->in().name();
1672 str = _("Crossfade");
1675 edit_items.push_back (MenuElem (str, *xfade_menu));
1676 edit_items.push_back (SeparatorElem());
1680 Editor::xfade_edit_left_region ()
1682 if (clicked_crossfadeview) {
1683 clicked_crossfadeview->left_view.show_region_editor ();
1688 Editor::xfade_edit_right_region ()
1690 if (clicked_crossfadeview) {
1691 clicked_crossfadeview->right_view.show_region_editor ();
1696 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
1698 using namespace Menu_Helpers;
1699 Menu *region_menu = manage (new Menu);
1700 MenuList& items = region_menu->items();
1701 region_menu->set_name ("ArdourContextMenu");
1703 AudioRegion* ar = 0;
1706 ar = dynamic_cast<AudioRegion*> (region);
1709 /* when this particular menu pops up, make the relevant region
1713 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
1715 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
1716 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
1717 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
1718 items.push_back (SeparatorElem());
1719 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
1720 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
1721 items.push_back (SeparatorElem());
1723 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
1724 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
1725 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
1726 items.push_back (SeparatorElem());
1728 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
1729 might be able to figure out which overloaded member function to use in
1733 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
1735 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
1736 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
1737 items.push_back (SeparatorElem());
1739 if (region->muted()) {
1740 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
1742 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
1744 items.push_back (SeparatorElem());
1746 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
1747 items.push_back (SeparatorElem());
1752 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
1753 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
1754 items.push_back (SeparatorElem());
1756 if (ar->scale_amplitude() != 1.0f) {
1757 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
1759 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
1762 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
1763 items.push_back (SeparatorElem());
1767 Menu *nudge_menu = manage (new Menu());
1768 MenuList& nudge_items = nudge_menu->items();
1769 nudge_menu->set_name ("ArdourContextMenu");
1771 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
1772 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
1773 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
1774 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
1776 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1777 items.push_back (SeparatorElem());
1779 Menu *trim_menu = manage (new Menu);
1780 MenuList& trim_items = trim_menu->items();
1781 trim_menu->set_name ("ArdourContextMenu");
1783 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
1784 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
1786 items.push_back (MenuElem (_("Trim"), *trim_menu));
1787 items.push_back (SeparatorElem());
1789 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
1790 region_edit_menu_split_item = &items.back();
1792 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
1793 region_edit_menu_split_multichannel_item = &items.back();
1795 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
1796 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
1797 items.push_back (SeparatorElem());
1798 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
1799 items.push_back (SeparatorElem());
1800 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
1802 /* OK, stick the region submenu at the top of the list, and then add
1806 /* we have to hack up the region name because "_" has a special
1807 meaning for menu titles.
1810 string::size_type pos = 0;
1811 string menu_item_name = region->name();
1813 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1814 menu_item_name.replace (pos, 1, "__");
1818 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
1819 edit_items.push_back (SeparatorElem());
1823 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1825 using namespace Menu_Helpers;
1826 Menu *selection_menu = manage (new Menu);
1827 MenuList& items = selection_menu->items();
1828 selection_menu->set_name ("ArdourContextMenu");
1830 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
1831 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
1832 items.push_back (SeparatorElem());
1833 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
1834 items.push_back (SeparatorElem());
1835 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
1836 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
1837 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
1838 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
1839 items.push_back (SeparatorElem());
1840 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
1841 items.push_back (SeparatorElem());
1842 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
1843 items.push_back (SeparatorElem());
1844 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
1846 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
1847 edit_items.push_back (SeparatorElem());
1851 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1853 using namespace Menu_Helpers;
1857 Menu *play_menu = manage (new Menu);
1858 MenuList& play_items = play_menu->items();
1859 play_menu->set_name ("ArdourContextMenu");
1861 play_items.push_back (MenuElem (_("Play from edit cursor")));
1862 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1863 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
1864 play_items.push_back (SeparatorElem());
1865 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
1867 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1871 Menu *select_menu = manage (new Menu);
1872 MenuList& select_items = select_menu->items();
1873 select_menu->set_name ("ArdourContextMenu");
1875 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
1876 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
1877 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1878 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
1879 select_items.push_back (SeparatorElem());
1880 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1881 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1882 select_items.push_back (SeparatorElem());
1884 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1888 Menu *cutnpaste_menu = manage (new Menu);
1889 MenuList& cutnpaste_items = cutnpaste_menu->items();
1890 cutnpaste_menu->set_name ("ArdourContextMenu");
1892 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
1893 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
1894 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
1895 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
1897 cutnpaste_items.push_back (SeparatorElem());
1899 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
1900 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
1902 cutnpaste_items.push_back (SeparatorElem());
1904 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
1906 cutnpaste_items.push_back (SeparatorElem());
1908 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
1909 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
1911 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1913 /* Adding new material */
1915 Menu *import_menu = manage (new Menu());
1916 MenuList& import_items = import_menu->items();
1917 import_menu->set_name ("ArdourContextMenu");
1919 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1920 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
1922 edit_items.push_back (MenuElem (_("Import"), *import_menu));
1926 Menu *nudge_menu = manage (new Menu());
1927 MenuList& nudge_items = nudge_menu->items();
1928 nudge_menu->set_name ("ArdourContextMenu");
1930 edit_items.push_back (SeparatorElem());
1931 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
1932 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
1933 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
1934 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
1936 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1940 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1942 using namespace Menu_Helpers;
1946 Menu *play_menu = manage (new Menu);
1947 MenuList& play_items = play_menu->items();
1948 play_menu->set_name ("ArdourContextMenu");
1950 play_items.push_back (MenuElem (_("Play from edit cursor")));
1951 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1952 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1956 Menu *select_menu = manage (new Menu);
1957 MenuList& select_items = select_menu->items();
1958 select_menu->set_name ("ArdourContextMenu");
1960 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
1961 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
1962 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1963 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
1964 select_items.push_back (SeparatorElem());
1965 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1966 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1967 select_items.push_back (SeparatorElem());
1969 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1973 Menu *cutnpaste_menu = manage (new Menu);
1974 MenuList& cutnpaste_items = cutnpaste_menu->items();
1975 cutnpaste_menu->set_name ("ArdourContextMenu");
1977 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
1978 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
1979 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
1981 Menu *nudge_menu = manage (new Menu());
1982 MenuList& nudge_items = nudge_menu->items();
1983 nudge_menu->set_name ("ArdourContextMenu");
1985 edit_items.push_back (SeparatorElem());
1986 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
1987 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
1988 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
1989 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
1991 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1994 /* CURSOR SETTING AND MARKS AND STUFF */
1997 Editor::set_snap_to (SnapType st)
2000 vector<string> txt = internationalize (snap_type_strings);
2001 snap_type_selector.set_active_text (txt[(int)st]);
2005 switch (snap_type) {
2006 case SnapToAThirtysecondBeat:
2007 case SnapToASixteenthBeat:
2008 case SnapToAEighthBeat:
2009 case SnapToAQuarterBeat:
2010 case SnapToAThirdBeat:
2011 update_tempo_based_rulers ();
2019 Editor::set_snap_mode (SnapMode mode)
2022 vector<string> txt = internationalize (snap_mode_strings);
2023 snap_mode_selector.set_active_text (txt[(int)mode]);
2029 Editor::add_location_from_selection ()
2031 if (selection->time.empty()) {
2035 if (session == 0 || clicked_trackview == 0) {
2039 jack_nframes_t start = selection->time[clicked_selection].start;
2040 jack_nframes_t end = selection->time[clicked_selection].end;
2042 Location *location = new Location (start, end, "selection");
2044 session->begin_reversible_command (_("add marker"));
2045 session->add_undo (session->locations()->get_memento());
2046 session->locations()->add (location, true);
2047 session->add_redo_no_execute (session->locations()->get_memento());
2048 session->commit_reversible_command ();
2052 Editor::add_location_from_playhead_cursor ()
2054 jack_nframes_t where = session->audible_frame();
2056 Location *location = new Location (where, where, "mark", Location::IsMark);
2057 session->begin_reversible_command (_("add marker"));
2058 session->add_undo (session->locations()->get_memento());
2059 session->locations()->add (location, true);
2060 session->add_redo_no_execute (session->locations()->get_memento());
2061 session->commit_reversible_command ();
2066 Editor::set_state (const XMLNode& node)
2068 const XMLProperty* prop;
2070 int x, y, width, height, xoff, yoff;
2072 if ((geometry = find_named_node (node, "geometry")) == 0) {
2074 width = default_width;
2075 height = default_height;
2083 width = atoi(geometry->property("x_size")->value());
2084 height = atoi(geometry->property("y_size")->value());
2085 x = atoi(geometry->property("x_pos")->value());
2086 y = atoi(geometry->property("y_pos")->value());
2087 xoff = atoi(geometry->property("x_off")->value());
2088 yoff = atoi(geometry->property("y_off")->value());
2091 set_default_size(width, height);
2094 if ((prop = node.property ("zoom-focus"))) {
2095 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2098 if ((prop = node.property ("zoom"))) {
2099 set_frames_per_unit (atof (prop->value()));
2102 if ((prop = node.property ("snap-to"))) {
2103 set_snap_to ((SnapType) atoi (prop->value()));
2106 if ((prop = node.property ("snap-mode"))) {
2107 set_snap_mode ((SnapMode) atoi (prop->value()));
2110 if ((prop = node.property ("show-waveforms"))) {
2111 bool yn = (prop->value() == "yes");
2112 _show_waveforms = !yn;
2113 set_show_waveforms (yn);
2116 if ((prop = node.property ("show-waveforms-recording"))) {
2117 bool yn = (prop->value() == "yes");
2118 _show_waveforms_recording = !yn;
2119 set_show_waveforms_recording (yn);
2122 if ((prop = node.property ("show-measures"))) {
2123 bool yn = (prop->value() == "yes");
2124 _show_measures = !yn;
2125 set_show_measures (yn);
2128 if ((prop = node.property ("follow-playhead"))) {
2129 bool yn = (prop->value() == "yes");
2130 _follow_playhead = !yn;
2131 set_follow_playhead (yn);
2134 if ((prop = node.property ("xfades-visible"))) {
2135 bool yn = (prop->value() == "yes");
2136 _xfade_visibility = !yn;
2137 set_xfade_visibility (yn);
2140 if ((prop = node.property ("region-list-sort-type"))) {
2141 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2142 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2145 if ((prop = node.property ("mouse-mode"))) {
2146 MouseMode m = str2mousemode(prop->value());
2147 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2148 set_mouse_mode (m, true);
2150 mouse_mode = MouseGain; /* lie, to force the mode switch */
2151 set_mouse_mode (MouseObject, true);
2154 if ((prop = node.property ("editor-mixer-button"))) {
2155 editor_mixer_button.set_active(prop->value() == "yes");
2162 Editor::get_state ()
2164 XMLNode* node = new XMLNode ("Editor");
2167 if (is_realized()) {
2168 Glib::RefPtr<Gdk::Window> win = get_window();
2170 int x, y, xoff, yoff, width, height;
2171 win->get_root_origin(x, y);
2172 win->get_position(xoff, yoff);
2173 win->get_size(width, height);
2175 XMLNode* geometry = new XMLNode ("geometry");
2177 snprintf(buf, sizeof(buf), "%d", width);
2178 geometry->add_property("x_size", string(buf));
2179 snprintf(buf, sizeof(buf), "%d", height);
2180 geometry->add_property("y_size", string(buf));
2181 snprintf(buf, sizeof(buf), "%d", x);
2182 geometry->add_property("x_pos", string(buf));
2183 snprintf(buf, sizeof(buf), "%d", y);
2184 geometry->add_property("y_pos", string(buf));
2185 snprintf(buf, sizeof(buf), "%d", xoff);
2186 geometry->add_property("x_off", string(buf));
2187 snprintf(buf, sizeof(buf), "%d", yoff);
2188 geometry->add_property("y_off", string(buf));
2189 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2190 geometry->add_property("edit_pane_pos", string(buf));
2192 node->add_child_nocopy (*geometry);
2195 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2196 node->add_property ("zoom-focus", buf);
2197 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2198 node->add_property ("zoom", buf);
2199 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2200 node->add_property ("snap-to", buf);
2201 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2202 node->add_property ("snap-mode", buf);
2204 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2205 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2206 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2207 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2208 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2209 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2210 node->add_property ("mouse-mode", enum2str(mouse_mode));
2211 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2219 Editor::trackview_by_y_position (double y)
2221 TrackViewList::iterator iter;
2224 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2232 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2241 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2243 Location* before = 0;
2244 Location* after = 0;
2250 const jack_nframes_t one_second = session->frame_rate();
2251 const jack_nframes_t one_minute = session->frame_rate() * 60;
2253 jack_nframes_t presnap = start;
2255 switch (snap_type) {
2261 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2263 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2266 case SnapToSMPTEFrame:
2268 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2270 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2274 case SnapToSMPTESeconds:
2275 if (session->smpte_offset_negative())
2277 start += session->smpte_offset ();
2279 start -= session->smpte_offset ();
2281 if (direction > 0) {
2282 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2284 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2287 if (session->smpte_offset_negative())
2289 start -= session->smpte_offset ();
2291 start += session->smpte_offset ();
2295 case SnapToSMPTEMinutes:
2296 if (session->smpte_offset_negative())
2298 start += session->smpte_offset ();
2300 start -= session->smpte_offset ();
2303 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2305 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2307 if (session->smpte_offset_negative())
2309 start -= session->smpte_offset ();
2311 start += session->smpte_offset ();
2317 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2319 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2325 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2327 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2332 start = session->tempo_map().round_to_bar (start, direction);
2336 start = session->tempo_map().round_to_beat (start, direction);
2339 case SnapToAThirtysecondBeat:
2340 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2343 case SnapToASixteenthBeat:
2344 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2347 case SnapToAEighthBeat:
2348 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2351 case SnapToAQuarterBeat:
2352 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2355 case SnapToAThirdBeat:
2356 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2359 case SnapToEditCursor:
2360 start = edit_cursor->current_frame;
2368 before = session->locations()->first_location_before (start);
2369 after = session->locations()->first_location_after (start);
2371 if (direction < 0) {
2373 start = before->start();
2377 } else if (direction > 0) {
2379 start = after->start();
2381 start = session->current_end_frame();
2386 /* find nearest of the two */
2387 if ((start - before->start()) < (after->start() - start)) {
2388 start = before->start();
2390 start = after->start();
2393 start = before->start();
2396 start = after->start();
2403 case SnapToRegionStart:
2404 case SnapToRegionEnd:
2405 case SnapToRegionSync:
2406 case SnapToRegionBoundary:
2407 if (!region_boundary_cache.empty()) {
2408 vector<jack_nframes_t>::iterator i;
2410 if (direction > 0) {
2411 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2413 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2416 if (i != region_boundary_cache.end()) {
2419 start = region_boundary_cache.back();
2425 switch (snap_mode) {
2431 if (presnap > start) {
2432 if (presnap > (start + unit_to_frame(snap_threshold))) {
2436 } else if (presnap < start) {
2437 if (presnap < (start - unit_to_frame(snap_threshold))) {
2449 Editor::setup_toolbar ()
2452 vector<ToggleButton *> mouse_mode_buttons;
2454 mouse_mode_buttons.push_back (&mouse_move_button);
2455 mouse_mode_buttons.push_back (&mouse_select_button);
2456 mouse_mode_buttons.push_back (&mouse_gain_button);
2457 mouse_mode_buttons.push_back (&mouse_zoom_button);
2458 mouse_mode_buttons.push_back (&mouse_timefx_button);
2459 mouse_mode_buttons.push_back (&mouse_audition_button);
2460 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2462 mouse_mode_button_table.set_homogeneous (true);
2463 mouse_mode_button_table.set_col_spacings (2);
2464 mouse_mode_button_table.set_row_spacings (2);
2465 mouse_mode_button_table.set_border_width (5);
2467 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2468 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2469 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2471 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2472 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2473 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2475 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2476 mouse_mode_tearoff->set_name ("MouseModeBase");
2478 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2479 mouse_mode_tearoff->tearoff_window()));
2480 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2481 mouse_mode_tearoff->tearoff_window(), 1));
2483 mouse_move_button.set_name ("MouseModeButton");
2484 mouse_select_button.set_name ("MouseModeButton");
2485 mouse_gain_button.set_name ("MouseModeButton");
2486 mouse_zoom_button.set_name ("MouseModeButton");
2487 mouse_timefx_button.set_name ("MouseModeButton");
2488 mouse_audition_button.set_name ("MouseModeButton");
2490 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2491 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2492 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2493 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2494 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2495 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2497 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2498 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2499 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2500 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2501 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2502 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2504 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2505 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2507 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2508 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2509 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2510 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2511 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2513 // mouse_move_button.set_active (true);
2515 /* automation control */
2517 global_automation_button.set_name ("MouseModeButton");
2518 automation_mode_button.set_name ("MouseModeButton");
2520 automation_box.set_spacing (2);
2521 automation_box.set_border_width (2);
2522 automation_box.pack_start (global_automation_button, false, false);
2523 automation_box.pack_start (automation_mode_button, false, false);
2527 edit_mode_label.set_name ("ToolBarLabel");
2529 edit_mode_selector.set_name ("EditModeSelector");
2531 edit_mode_box.set_spacing (3);
2532 edit_mode_box.set_border_width (3);
2534 /* XXX another disgusting hack because of the way combo boxes size themselves */
2536 const guint32 FUDGE = 20; // Combo's are stupid - they steal space from the entry for the button
2537 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2+FUDGE, 10);
2538 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2539 edit_mode_box.pack_start (edit_mode_label, false, false);
2540 edit_mode_box.pack_start (edit_mode_selector, false, false);
2542 edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2546 snap_type_label.set_name ("ToolBarLabel");
2548 snap_type_selector.set_name ("SnapTypeSelector");
2550 snap_type_box.set_spacing (3);
2551 snap_type_box.set_border_width (3);
2553 /* XXX another disgusting hack because of the way combo boxes size themselves */
2555 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "SMPTE Seconds", 2+FUDGE, 10);
2556 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2558 snap_type_box.pack_start (snap_type_label, false, false);
2559 snap_type_box.pack_start (snap_type_selector, false, false);
2561 snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2563 /* Snap mode, not snap type */
2565 snap_mode_label.set_name ("ToolBarLabel");
2567 snap_mode_selector.set_name ("SnapModeSelector");
2569 snap_mode_box.set_spacing (3);
2570 snap_mode_box.set_border_width (3);
2572 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2+FUDGE, 10);
2573 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2575 snap_mode_box.pack_start (snap_mode_label, false, false);
2576 snap_mode_box.pack_start (snap_mode_selector, false, false);
2578 snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2580 /* Zoom focus mode */
2582 zoom_focus_label.set_name ("ToolBarLabel");
2584 zoom_focus_selector.set_name ("ZoomFocusSelector");
2586 zoom_focus_box.set_spacing (3);
2587 zoom_focus_box.set_border_width (3);
2589 /* XXX another disgusting hack because of the way combo boxes size themselves */
2591 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2+FUDGE, 10);
2592 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
2594 zoom_focus_box.pack_start (zoom_focus_label, false, false);
2595 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
2597 zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
2599 /* selection/cursor clocks */
2601 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
2602 selection_start_clock_label.set_name ("ToolBarLabel");
2603 selection_end_clock_label.set_name ("ToolBarLabel");
2604 edit_cursor_clock_label.set_name ("ToolBarLabel");
2606 selection_start_clock_label.set_text (_("Start:"));
2607 selection_end_clock_label.set_text (_("End:"));
2608 edit_cursor_clock_label.set_text (_("Edit:"));
2610 toolbar_selection_clock_table.set_border_width (5);
2611 toolbar_selection_clock_table.set_col_spacings (2);
2612 toolbar_selection_clock_table.set_homogeneous (false);
2614 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
2615 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
2616 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
2618 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
2619 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
2620 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
2623 // toolbar_clock_vbox.set_spacing (2);
2624 // toolbar_clock_vbox.set_border_width (10);
2625 /* the editor/mixer button will be enabled at session connect */
2627 editor_mixer_button.set_active(false);
2628 editor_mixer_button.set_sensitive(false);
2630 HBox* hbox = new HBox;
2632 hbox->pack_start (editor_mixer_button, false, false);
2633 hbox->pack_start (toolbar_selection_clock_table, false, false);
2634 hbox->pack_start (zoom_indicator_vbox, false, false);
2635 hbox->pack_start (zoom_focus_box, false, false);
2636 hbox->pack_start (snap_type_box, false, false);
2637 hbox->pack_start (snap_mode_box, false, false);
2638 hbox->pack_start (edit_mode_box, false, false);
2640 VBox *vbox = manage (new VBox);
2642 vbox->set_spacing (3);
2643 vbox->set_border_width (3);
2645 HBox *nbox = manage (new HBox);
2647 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
2648 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
2650 nbox->pack_start (nudge_backward_button, false, false);
2651 nbox->pack_start (nudge_forward_button, false, false);
2652 nbox->pack_start (nudge_clock, false, false, 5);
2654 nudge_label.set_name ("ToolBarLabel");
2656 vbox->pack_start (nudge_label, false, false);
2657 vbox->pack_start (*nbox, false, false);
2659 hbox->pack_start (*vbox, false, false);
2663 tools_tearoff = new TearOff (*hbox);
2664 tools_tearoff->set_name ("MouseModeBase");
2666 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2667 tools_tearoff->tearoff_window()));
2668 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2669 tools_tearoff->tearoff_window(), 0));
2672 toolbar_hbox.set_spacing (8);
2673 toolbar_hbox.set_border_width (2);
2675 toolbar_hbox.pack_start (*tools_tearoff, false, false);
2676 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
2678 toolbar_base.set_name ("ToolBarBase");
2679 toolbar_base.add (toolbar_hbox);
2681 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
2682 toolbar_frame.set_name ("BaseFrame");
2683 toolbar_frame.add (toolbar_base);
2687 Editor::_autoscroll_canvas (void *arg)
2689 return ((Editor *) arg)->autoscroll_canvas ();
2693 Editor::autoscroll_canvas ()
2695 jack_nframes_t new_frame;
2696 bool keep_calling = true;
2698 if (autoscroll_direction < 0) {
2699 if (leftmost_frame < autoscroll_distance) {
2702 new_frame = leftmost_frame - autoscroll_distance;
2705 if (leftmost_frame > max_frames - autoscroll_distance) {
2706 new_frame = max_frames;
2708 new_frame = leftmost_frame + autoscroll_distance;
2712 if (new_frame != leftmost_frame) {
2713 reposition_x_origin (new_frame);
2716 if (new_frame == 0 || new_frame == max_frames) {
2723 if (autoscroll_cnt == 1) {
2725 /* connect the timeout so that we get called repeatedly */
2727 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
2728 keep_calling = false;
2730 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
2732 /* after about a while, speed up a bit by changing the timeout interval */
2734 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
2735 keep_calling = false;
2737 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
2739 /* after about another while, speed up some more */
2741 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
2742 keep_calling = false;
2744 } else if (autoscroll_cnt >= 30) {
2746 /* we've been scrolling for a while ... crank it up */
2748 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
2751 return keep_calling;
2755 Editor::start_canvas_autoscroll (int dir)
2761 stop_canvas_autoscroll ();
2763 autoscroll_direction = dir;
2764 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
2767 /* do it right now, which will start the repeated callbacks */
2769 autoscroll_canvas ();
2773 Editor::stop_canvas_autoscroll ()
2775 if (autoscroll_timeout_tag >= 0) {
2776 gtk_timeout_remove (autoscroll_timeout_tag);
2777 autoscroll_timeout_tag = -1;
2782 Editor::convert_drop_to_paths (vector<string>& paths,
2783 GdkDragContext *context,
2786 GtkSelectionData *data,
2794 gchar *tname = gdk_atom_name (data->type);
2796 if (session == 0 || strcmp (tname, "text/plain") != 0) {
2800 /* Parse the "uri-list" format that Nautilus provides,
2801 where each pathname is delimited by \r\n
2804 path = (char *) data->data;
2807 for (int n = 0; n < data->length; ++n) {
2811 if (path[n] == '\r') {
2818 if (path[n] == '\n') {
2819 paths.push_back (spath);
2823 warning << _("incorrectly formatted URI list, ignored")
2831 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
2833 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
2835 // cerr << "dropped text was " << *p << endl;
2839 // cerr << "decoded was " << *p << endl;
2841 if ((*p).substr (0,7) == "file://") {
2842 (*p) = (*p).substr (7);
2850 Editor::track_canvas_drag_data_received (GdkDragContext *context,
2853 GtkSelectionData *data,
2858 AudioTimeAxisView* tv;
2860 vector<string> paths;
2863 jack_nframes_t frame;
2865 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
2869 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
2875 track_canvas.c2w( x, y, wx, wy);
2877 ev.type = GDK_BUTTON_RELEASE;
2881 frame = event_frame (&ev, 0, &cy);
2885 if ((tvp = trackview_by_y_position (cy)) == 0) {
2887 /* drop onto canvas background: create a new track */
2889 insert_paths_as_new_tracks (paths, false);
2892 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
2894 /* check that its an audio track, not a bus */
2896 if (tv->get_diskstream()) {
2898 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
2899 insert_sndfile_into (*p, true, tv, frame);
2906 gtk_drag_finish (context, TRUE, FALSE, time);
2910 Editor::new_tempo_section ()
2916 Editor::map_transport_state ()
2918 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
2920 if (session->transport_stopped()) {
2921 have_pending_keyboard_selection = false;
2927 Editor::State::State ()
2929 selection = new Selection;
2932 Editor::State::~State ()
2938 Editor::get_memento () const
2940 State *state = new State;
2942 store_state (*state);
2943 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
2947 Editor::store_state (State& state) const
2949 *state.selection = *selection;
2953 Editor::restore_state (State *state)
2955 if (*selection == *state->selection) {
2959 *selection = *state->selection;
2960 time_selection_changed ();
2961 region_selection_changed ();
2963 /* XXX other selection change handlers? */
2967 Editor::begin_reversible_command (string name)
2970 UndoAction ua = get_memento();
2971 session->begin_reversible_command (name, &ua);
2976 Editor::commit_reversible_command ()
2979 UndoAction ua = get_memento();
2980 session->commit_reversible_command (&ua);
2985 Editor::flush_track_canvas ()
2987 /* I don't think this is necessary, and only causes more problems.
2988 I'm commenting it out
2989 and if the imageframe folks don't have any issues, we can take
2990 out this method entirely
2993 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
2994 //gtk_main_iteration ();
2998 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3000 if (!clicked_trackview) {
3005 begin_reversible_command (_("set selected trackview"));
3010 if (selection->selected (clicked_trackview)) {
3012 selection->remove (clicked_trackview);
3015 selection->add (clicked_trackview);
3020 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3021 /* no commit necessary */
3025 selection->set (clicked_trackview);
3029 commit_reversible_command ();
3034 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3036 if (!clicked_control_point) {
3041 begin_reversible_command (_("set selected control point"));
3051 commit_reversible_command ();
3056 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3058 if (!clicked_regionview) {
3062 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3068 RouteGroup* group = atv->route().edit_group();
3069 vector<AudioRegionView*> all_equivalent_regions;
3071 if (group && group->is_active()) {
3073 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3075 AudioTimeAxisView* tatv;
3077 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3079 if (tatv->route().edit_group() != group) {
3084 vector<AudioRegion*> results;
3085 AudioRegionView* marv;
3088 if ((ds = tatv->get_diskstream()) == 0) {
3093 if ((pl = ds->playlist()) != 0) {
3094 pl->get_equivalent_regions (clicked_regionview->region,
3098 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3099 if ((marv = tatv->view->find_view (**ir)) != 0) {
3100 all_equivalent_regions.push_back (marv);
3109 all_equivalent_regions.push_back (clicked_regionview);
3113 begin_reversible_command (_("set selected regionview"));
3117 if (clicked_regionview->get_selected()) {
3118 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3119 /* reduce selection down to just the one clicked */
3120 selection->set (clicked_regionview);
3122 selection->remove (clicked_regionview);
3125 selection->add (all_equivalent_regions);
3128 set_selected_track_from_click (add, false, no_track_remove);
3132 // karsten wiese suggested these two lines to make
3133 // a selected region rise to the top. but this
3134 // leads to a mismatch between actual layering
3135 // and visual layering. resolution required ....
3137 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3138 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3140 if (clicked_regionview->get_selected()) {
3141 /* no commit necessary: we are the one selected. */
3146 selection->set (all_equivalent_regions);
3147 set_selected_track_from_click (add, false, false);
3151 commit_reversible_command () ;
3155 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3157 vector<AudioRegionView*> all_equivalent_regions;
3158 AudioRegion* region;
3160 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3164 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3166 AudioTimeAxisView* tatv;
3168 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3171 vector<AudioRegion*> results;
3172 AudioRegionView* marv;
3175 if ((ds = tatv->get_diskstream()) == 0) {
3180 if ((pl = ds->playlist()) != 0) {
3181 pl->get_region_list_equivalent_regions (*region, results);
3184 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3185 if ((marv = tatv->view->find_view (**ir)) != 0) {
3186 all_equivalent_regions.push_back (marv);
3193 begin_reversible_command (_("set selected regions"));
3197 selection->add (all_equivalent_regions);
3201 selection->set (all_equivalent_regions);
3204 commit_reversible_command () ;
3208 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3210 AudioRegionView* rv;
3213 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3217 if ((rv = sv->find_view (*ar)) == 0) {
3221 /* don't reset the selection if its something other than
3222 a single other region.
3225 if (selection->audio_regions.size() > 1) {
3229 begin_reversible_command (_("set selected regions"));
3231 selection->set (rv);
3233 commit_reversible_command () ;
3239 Editor::set_edit_group_solo (Route& route, bool yn)
3241 RouteGroup *edit_group;
3243 if ((edit_group = route.edit_group()) != 0) {
3244 edit_group->apply (&Route::set_solo, yn, this);
3246 route.set_solo (yn, this);
3251 Editor::set_edit_group_mute (Route& route, bool yn)
3253 RouteGroup *edit_group = 0;
3255 if ((edit_group == route.edit_group()) != 0) {
3256 edit_group->apply (&Route::set_mute, yn, this);
3258 route.set_mute (yn, this);
3263 Editor::set_edit_menu (Menu& menu)
3266 edit_menu->signal_map_event().connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3270 Editor::edit_menu_map_handler (GdkEventAny* ev)
3272 using namespace Menu_Helpers;
3273 MenuList& edit_items = edit_menu->items();
3276 /* Nuke all the old items */
3278 edit_items.clear ();
3284 if (session->undo_depth() == 0) {
3287 label = string_compose(_("Undo (%1)"), session->next_undo());
3290 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3292 if (session->undo_depth() == 0) {
3293 edit_items.back().set_sensitive (false);
3296 if (session->redo_depth() == 0) {
3299 label = string_compose(_("Redo (%1)"), session->next_redo());
3302 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3303 if (session->redo_depth() == 0) {
3304 edit_items.back().set_sensitive (false);
3307 vector<MenuItem*> mitems;
3309 edit_items.push_back (SeparatorElem());
3310 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3311 mitems.push_back (&edit_items.back());
3312 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3313 mitems.push_back (&edit_items.back());
3314 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3315 mitems.push_back (&edit_items.back());
3316 edit_items.push_back (SeparatorElem());
3317 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3318 mitems.push_back (&edit_items.back());
3319 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3320 mitems.push_back (&edit_items.back());
3321 edit_items.push_back (SeparatorElem());
3323 if (selection->empty()) {
3324 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3325 (*i)->set_sensitive (false);
3329 Menu* import_menu = manage (new Menu());
3330 import_menu->set_name ("ArdourContextMenu");
3331 MenuList& import_items = import_menu->items();
3333 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3334 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3336 Menu* embed_menu = manage (new Menu());
3337 embed_menu->set_name ("ArdourContextMenu");
3338 MenuList& embed_items = embed_menu->items();
3340 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3341 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3343 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3344 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3345 edit_items.push_back (SeparatorElem());
3347 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3348 if (!session->have_captured()) {
3349 edit_items.back().set_sensitive (false);
3356 Editor::duplicate_dialog (bool dup_region)
3359 if (clicked_regionview == 0) {
3363 if (selection->time.length() == 0) {
3368 ArdourDialog win ("duplicate dialog");
3370 Label label (_("Duplicate how many times?"));
3372 win.get_vbox()->pack_start (label);
3373 win.add_action_widget (entry, RESPONSE_ACCEPT);
3374 win.add_button (Stock::OK, RESPONSE_ACCEPT);
3375 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3377 win.set_position (Gtk::WIN_POS_MOUSE);
3379 entry.set_text ("1");
3380 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3381 entry.select_region (0, entry.get_text_length());
3382 entry.grab_focus ();
3385 // win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3388 switch (win.run ()) {
3389 case RESPONSE_ACCEPT:
3395 string text = entry.get_text();
3398 if (sscanf (text.c_str(), "%f", ×) == 1) {
3400 AudioRegionSelection regions;
3401 regions.add (clicked_regionview);
3402 duplicate_some_regions (regions, times);
3404 duplicate_selection (times);
3410 Editor::show_verbose_canvas_cursor ()
3412 verbose_canvas_cursor->raise_to_top();
3413 verbose_canvas_cursor->show();
3414 verbose_cursor_visible = true;
3418 Editor::hide_verbose_canvas_cursor ()
3420 verbose_canvas_cursor->hide();
3421 verbose_cursor_visible = false;
3425 Editor::set_verbose_canvas_cursor (stringcr_t txt, double x, double y)
3427 /* XXX get origin of canvas relative to root window,
3428 add x and y and check compared to gdk_screen_{width,height}
3430 verbose_canvas_cursor->property_text() = txt.c_str();
3431 verbose_canvas_cursor->property_x() = x;
3432 verbose_canvas_cursor->property_y() = y;
3436 Editor::set_verbose_canvas_cursor_text (stringcr_t txt)
3438 verbose_canvas_cursor->property_text() = txt.c_str();
3442 Editor::edit_mode_selection_done ()
3448 string choice = edit_mode_selector.get_active_text();
3449 EditMode mode = Slide;
3451 if (choice == _("Splice")) {
3453 } else if (choice == _("Slide")) {
3457 session->set_edit_mode (mode);
3461 Editor::snap_type_selection_done ()
3467 string choice = snap_type_selector.get_active_text();
3468 SnapType snaptype = SnapToFrame;
3470 if (choice == _("Beats/3")) {
3471 snaptype = SnapToAThirdBeat;
3472 } else if (choice == _("Beats/4")) {
3473 snaptype = SnapToAQuarterBeat;
3474 } else if (choice == _("Beats/8")) {
3475 snaptype = SnapToAEighthBeat;
3476 } else if (choice == _("Beats/16")) {
3477 snaptype = SnapToASixteenthBeat;
3478 } else if (choice == _("Beats/32")) {
3479 snaptype = SnapToAThirtysecondBeat;
3480 } else if (choice == _("Beats")) {
3481 snaptype = SnapToBeat;
3482 } else if (choice == _("Bars")) {
3483 snaptype = SnapToBar;
3484 } else if (choice == _("Marks")) {
3485 snaptype = SnapToMark;
3486 } else if (choice == _("Edit Cursor")) {
3487 snaptype = SnapToEditCursor;
3488 } else if (choice == _("Region starts")) {
3489 snaptype = SnapToRegionStart;
3490 } else if (choice == _("Region ends")) {
3491 snaptype = SnapToRegionEnd;
3492 } else if (choice == _("Region bounds")) {
3493 snaptype = SnapToRegionBoundary;
3494 } else if (choice == _("Region syncs")) {
3495 snaptype = SnapToRegionSync;
3496 } else if (choice == _("CD Frames")) {
3497 snaptype = SnapToCDFrame;
3498 } else if (choice == _("SMPTE Frames")) {
3499 snaptype = SnapToSMPTEFrame;
3500 } else if (choice == _("SMPTE Seconds")) {
3501 snaptype = SnapToSMPTESeconds;
3502 } else if (choice == _("SMPTE Minutes")) {
3503 snaptype = SnapToSMPTEMinutes;
3504 } else if (choice == _("Seconds")) {
3505 snaptype = SnapToSeconds;
3506 } else if (choice == _("Minutes")) {
3507 snaptype = SnapToMinutes;
3508 } else if (choice == _("None")) {
3509 snaptype = SnapToFrame;
3512 set_snap_to (snaptype);
3516 Editor::snap_mode_selection_done ()
3522 string choice = snap_mode_selector.get_active_text();
3523 SnapMode mode = SnapNormal;
3525 if (choice == _("Normal")) {
3527 } else if (choice == _("Magnetic")) {
3528 mode = SnapMagnetic;
3531 set_snap_mode (mode);
3535 Editor::zoom_focus_selection_done ()
3541 string choice = zoom_focus_selector.get_active_text();
3542 ZoomFocus focus_type = ZoomFocusLeft;
3544 if (choice == _("Left")) {
3545 focus_type = ZoomFocusLeft;
3546 } else if (choice == _("Right")) {
3547 focus_type = ZoomFocusRight;
3548 } else if (choice == _("Center")) {
3549 focus_type = ZoomFocusCenter;
3550 } else if (choice == _("Playhead")) {
3551 focus_type = ZoomFocusPlayhead;
3552 } else if (choice == _("Edit Cursor")) {
3553 focus_type = ZoomFocusEdit;
3556 set_zoom_focus (focus_type);
3560 Editor::edit_controls_button_release (GdkEventButton* ev)
3562 if (Keyboard::is_context_menu_event (ev)) {
3563 ARDOUR_UI::instance()->add_route ();
3569 Editor::track_selection_changed ()
3571 switch (selection->tracks.size()){
3575 set_selected_mixer_strip (*(selection->tracks.front()));
3579 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3580 (*i)->set_selected (false);
3581 if (mouse_mode == MouseRange) {
3582 (*i)->hide_selection ();
3586 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3587 (*i)->set_selected (true);
3588 if (mouse_mode == MouseRange) {
3589 (*i)->show_selection (selection->time);
3595 Editor::time_selection_changed ()
3597 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3598 (*i)->hide_selection ();
3601 if (selection->tracks.empty()) {
3602 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3603 (*i)->show_selection (selection->time);
3606 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3607 (*i)->show_selection (selection->time);
3613 Editor::region_selection_changed ()
3615 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3616 (*i)->set_selected_regionviews (selection->audio_regions);
3621 Editor::point_selection_changed ()
3623 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3624 (*i)->set_selected_points (selection->points);
3629 Editor::mouse_select_button_release (GdkEventButton* ev)
3631 /* this handles just right-clicks */
3633 if (ev->button != 3) {
3640 Editor::TrackViewList *
3641 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
3644 TrackViewList::iterator i;
3646 v = new TrackViewList;
3648 if (track == 0 && group == 0) {
3652 for (i = track_views.begin(); i != track_views.end (); ++i) {
3656 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
3658 /* just the view for this track
3661 v->push_back (track);
3665 /* views for all tracks in the edit group */
3667 for (i = track_views.begin(); i != track_views.end (); ++i) {
3669 if (group == 0 || (*i)->edit_group() == group) {
3679 Editor::set_zoom_focus (ZoomFocus f)
3681 if (zoom_focus != f) {
3683 vector<string> txt = internationalize (zoom_focus_strings);
3684 zoom_focus_selector.set_active_text (txt[(int)f]);
3685 ZoomFocusChanged (); /* EMIT_SIGNAL */
3692 Editor::ensure_float (Window& win)
3694 win.set_transient_for (*this);
3698 Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which)
3700 /* recover or initialize pane positions. do this here rather than earlier because
3701 we don't want the positions to change the child allocations, which they seem to do.
3707 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3709 static int32_t done[4] = { 0, 0, 0, 0 };
3712 if ((geometry = find_named_node (*node, "geometry")) == 0) {
3713 width = default_width;
3714 height = default_height;
3716 width = atoi(geometry->property("x_size")->value());
3717 height = atoi(geometry->property("y_size")->value());
3720 if (which == static_cast<Gtk::Paned*> (&edit_pane)) {
3726 if (!geometry || (prop = geometry->property ("edit_pane_pos")) == 0) {
3728 snprintf (buf, sizeof(buf), "%d", pos);
3730 pos = atoi (prop->value());
3733 if ((done[0] = GTK_WIDGET(edit_pane.gobj())->allocation.width > pos)) {
3734 edit_pane.set_position (pos);
3740 Editor::detach_tearoff (Gtk::Box* b, Gtk::Window* w)
3742 if (tools_tearoff->torn_off() &&
3743 mouse_mode_tearoff->torn_off()) {
3744 top_hbox.remove (toolbar_frame);
3751 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Window* w, int32_t n)
3753 if (toolbar_frame.get_parent() == 0) {
3754 top_hbox.pack_end (toolbar_frame);
3759 Editor::set_show_measures (bool yn)
3761 if (_show_measures != yn) {
3764 if ((_show_measures = yn) == true) {
3767 DisplayControlChanged (ShowMeasures);
3773 Editor::set_follow_playhead (bool yn)
3775 if (_follow_playhead != yn) {
3776 if ((_follow_playhead = yn) == true) {
3778 update_current_screen ();
3780 DisplayControlChanged (FollowPlayhead);
3786 Editor::toggle_xfade_active (Crossfade* xfade)
3788 xfade->set_active (!xfade->active());
3792 Editor::toggle_xfade_length (Crossfade* xfade)
3794 xfade->set_follow_overlap (!xfade->following_overlap());
3798 Editor::edit_xfade (Crossfade* xfade)
3800 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
3805 // cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
3807 switch (cew.run ()) {
3808 case RESPONSE_ACCEPT:
3815 xfade->StateChanged (Change (~0));
3819 Editor::playlist_selector () const
3821 return *_playlist_selector;
3825 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
3829 ret = nudge_clock.current_duration (pos);
3830 next = ret + 1; /* XXXX fix me */
3836 Editor::end_location_changed (Location* location)
3838 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
3839 horizontal_adjustment.set_upper (location->end() / frames_per_unit);
3843 Editor::playlist_deletion_dialog (Playlist* pl)
3845 ArdourDialog dialog ("playlist deletion dialog");
3846 Label label (string_compose (_("Playlist %1 is currently unused.\n"
3847 "If left alone, no audio files used by it will be cleaned.\n"
3848 "If deleted, audio files used by it alone by will cleaned."),
3851 dialog.set_position (Gtk::WIN_POS_CENTER);
3852 dialog.get_vbox()->pack_start (label);
3854 dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT);
3855 dialog.add_button (_("Keep playlist"), RESPONSE_CANCEL);
3856 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3858 switch (dialog.run ()) {
3859 case RESPONSE_ACCEPT:
3860 /* delete the playlist */
3864 case RESPONSE_REJECT:
3865 /* keep the playlist */
3877 Editor::audio_region_selection_covers (jack_nframes_t where)
3879 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
3880 if ((*a)->region.covers (where)) {
3889 Editor::prepare_for_cleanup ()
3891 cut_buffer->clear_audio_regions ();
3892 cut_buffer->clear_playlists ();
3894 selection->clear_audio_regions ();
3895 selection->clear_playlists ();
3899 Editor::init_colormap ()
3901 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
3902 pair<ColorID,int> newpair;
3904 newpair.first = (ColorID) x;
3905 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
3906 color_map.insert (newpair);
3911 Editor::transport_loop_location()
3914 return session->locations()->auto_loop_location();
3921 Editor::transport_punch_location()
3924 return session->locations()->auto_punch_location();
3931 Editor::set_layout_width(Gtk::Requisition *r)
3933 edit_controls_vbox.check_resize();
3934 int w = edit_controls_vbox.get_width();
3935 cerr << "set_layout_width() called w = " << w << endl;
3936 controls_layout.set_size_request (w, -1);