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 <libgnomecanvasmm/init.h>
31 #include <pbd/error.h>
33 #include <gtkmm/image.h>
34 #include <gdkmm/color.h>
35 #include <gdkmm/bitmap.h>
37 #include <gtkmm2ext/gtk_ui.h>
38 #include <gtkmm2ext/tearoff.h>
39 #include <gtkmm2ext/utils.h>
41 #include <ardour/audio_track.h>
42 #include <ardour/diskstream.h>
43 #include <ardour/plugin_manager.h>
44 #include <ardour/location.h>
45 #include <ardour/audioplaylist.h>
46 #include <ardour/audioregion.h>
47 #include <ardour/region.h>
48 #include <ardour/session_route.h>
49 #include <ardour/tempo.h>
50 #include <ardour/utils.h>
52 #include "ardour_ui.h"
53 #include "check_mark.h"
55 #include "grouped_buttons.h"
58 #include "playlist_selector.h"
59 #include "regionview.h"
60 #include "rgb_macros.h"
61 #include "selection.h"
62 #include "streamview.h"
63 #include "simpleline.h"
64 #include "time_axis_view.h"
66 #include "crossfade_view.h"
68 #include "public_editor.h"
69 #include "crossfade_edit.h"
70 #include "audio_time_axis.h"
71 #include "canvas_impl.h"
72 #include "gui_thread.h"
77 #include "imageframe_socket_handler.h"
78 /* </CMT Additions> */
82 using namespace ARDOUR;
85 using namespace Gtkmm2ext;
86 using namespace Editing;
88 /* XXX this is a hack. it ought to be the maximum value of an jack_nframes_t */
90 const double max_canvas_coordinate = 100000000.0;
91 const double Editor::timebar_height = 15.0;
93 #include "editor_xpms"
95 static const int32_t slide_index = 0;
96 static const int32_t splice_index = 1;
98 static const gchar *edit_mode_strings[] = {
104 static const gchar *snap_type_strings[] = {
128 static const gchar *snap_mode_strings[] = {
134 static const gchar *zoom_focus_strings[] = {
143 /* Soundfile drag-n-drop */
145 Gdk::Cursor* Editor::cross_hair_cursor = 0;
146 Gdk::Cursor* Editor::selector_cursor = 0;
147 Gdk::Cursor* Editor::trimmer_cursor = 0;
148 Gdk::Cursor* Editor::grabber_cursor = 0;
149 Gdk::Cursor* Editor::zoom_cursor = 0;
150 Gdk::Cursor* Editor::time_fx_cursor = 0;
151 Gdk::Cursor* Editor::fader_cursor = 0;
152 Gdk::Cursor* Editor::speaker_cursor = 0;
153 Gdk::Cursor* Editor::null_cursor = 0;
154 Gdk::Cursor* Editor::wait_cursor = 0;
155 Gdk::Cursor* Editor::timebar_cursor = 0;
157 GdkPixmap *Editor::check_pixmap = 0;
158 GdkBitmap *Editor::check_mask = 0;
159 GdkPixmap *Editor::empty_pixmap = 0;
160 GdkBitmap *Editor::empty_mask = 0;
162 Editor::Editor (AudioEngine& eng)
165 /* time display buttons */
167 minsec_label (_("Mins:Secs")),
168 bbt_label (_("Bars:Beats")),
169 smpte_label (_("SMPTE")),
170 frame_label (_("Frames")),
171 tempo_label (_("Tempo")),
172 meter_label (_("Meter")),
173 mark_label (_("Location Markers")),
174 range_mark_label (_("Range Markers")),
175 transport_mark_label (_("Loop/Punch Ranges")),
177 edit_packer (3, 3, false),
178 edit_hscroll_left_arrow (Gtk::ARROW_LEFT, Gtk::SHADOW_OUT),
179 edit_hscroll_right_arrow (Gtk::ARROW_RIGHT, Gtk::SHADOW_OUT),
181 /* tool bar related */
183 editor_mixer_button (_("editor\nmixer")),
185 selection_start_clock (X_("SelectionStartClock"), true),
186 selection_end_clock (X_("SelectionEndClock"), true),
187 edit_cursor_clock (X_("EditCursorClock"), true),
188 zoom_range_clock (X_("ZoomRangeClock"), true, true),
190 toolbar_selection_clock_table (2,3),
192 mouse_mode_button_table (2, 3),
194 mouse_select_button (_("range")),
195 mouse_move_button (_("object")),
196 mouse_gain_button (_("gain")),
197 mouse_zoom_button (_("zoom")),
198 mouse_timefx_button (_("timefx")),
199 mouse_audition_button (_("listen")),
201 automation_mode_button (_("mode")),
202 global_automation_button (_("automation")),
204 edit_mode_label (_("Edit Mode")),
205 snap_type_label (_("Snap To")),
206 snap_mode_label(_("Snap Mode")),
207 zoom_focus_label (_("Zoom Focus")),
209 /* <CMT Additions> */
210 image_socket_listener(0),
211 /* </CMT Additions> */
215 nudge_label (_("Nudge")),
216 nudge_clock (X_("NudgeClock"), true, true)
221 /* we are a singleton */
223 PublicEditor::_instance = this;
227 check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
228 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
229 &check_mask, NULL, (gchar **) check_xpm);
230 empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
231 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
232 &empty_mask, NULL, (gchar **) empty_xpm);
236 selection = new Selection;
237 cut_buffer = new Selection;
239 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
240 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
241 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
242 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
244 clicked_regionview = 0;
245 clicked_trackview = 0;
246 clicked_audio_trackview = 0;
247 clicked_crossfadeview = 0;
248 clicked_control_point = 0;
249 latest_regionview = 0;
250 last_update_frame = 0;
252 last_audition_region = 0;
253 current_mixer_strip = 0;
254 current_bbt_points = 0;
256 snap_type = SnapToFrame;
257 set_snap_to (snap_type);
258 snap_mode = SnapNormal;
259 set_snap_mode (snap_mode);
260 snap_threshold = 5.0;
261 bbt_beat_subdivision = 4;
264 autoscroll_timeout_tag = -1;
265 interthread_progress_window = 0;
266 current_interthread_info = 0;
267 _show_measures = true;
268 _show_waveforms = true;
269 _show_waveforms_recording = true;
270 first_action_message = 0;
272 show_gain_after_trim = false;
273 no_zoom_repos_update = false;
274 ignore_route_list_reorder = false;
275 verbose_cursor_on = true;
276 route_removal = false;
278 show_automatic_regions_in_region_list = true;
279 have_pending_keyboard_selection = false;
280 _follow_playhead = true;
281 _xfade_visibility = true;
282 editor_ruler_menu = 0;
283 no_ruler_shown_update = false;
284 edit_group_list_menu = 0;
286 region_list_menu = 0;
288 marker_menu_item = 0;
290 transport_marker_menu = 0;
291 new_transport_marker_menu = 0;
292 editor_mixer_strip_width = Wide;
293 repos_zoom_queued = false;
294 import_audio_item = 0;
295 embed_audio_item = 0;
296 region_edit_menu_split_item = 0;
298 region_edit_menu_split_multichannel_item = 0;
299 edit_hscroll_dragging = false;
301 ignore_mouse_mode_toggle = false;
302 current_stepping_trackview = 0;
304 entered_regionview = 0;
305 clear_entered_track = false;
306 _new_regionviews_show_envelope = false;
307 current_timestretch = 0;
312 location_marker_color = color_map[cLocationMarker];
313 location_range_color = color_map[cLocationRange];
314 location_cd_marker_color = color_map[cLocationCDMarker];
315 location_loop_color = color_map[cLocationLoop];
316 location_punch_color = color_map[cLocationPunch];
318 range_marker_drag_rect = 0;
319 marker_drag_line = 0;
321 mouse_mode = MouseZoom; /* force change in next call */
322 set_mouse_mode (MouseObject, true);
324 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
325 zoom_focus = ZoomFocusLeft;
326 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
328 initialize_rulers ();
329 initialize_canvas ();
331 track_canvas_scroller.add (track_canvas);
332 track_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
333 track_canvas_scroller.set_name ("TrackCanvasScroller");
335 track_canvas_scroller.get_vadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
336 track_canvas_scroller.get_vadjustment()->set_step_increment (10.0);
338 track_canvas_scroller.get_hadjustment()->set_lower (0.0);
339 track_canvas_scroller.get_hadjustment()->set_upper (1200.0);
340 track_canvas_scroller.get_hadjustment()->set_step_increment (20.0);
341 track_canvas_scroller.get_hadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
343 edit_vscrollbar.set_adjustment(*track_canvas_scroller.get_vadjustment());
344 edit_hscrollbar.set_adjustment(*track_canvas_scroller.get_hadjustment());
346 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_press));
347 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_release));
348 edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscroll_slider_allocate));
350 time_canvas_scroller.add (time_canvas);
351 time_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
352 time_canvas_scroller.set_hadjustment (*track_canvas_scroller.get_hadjustment());
353 time_canvas_scroller.set_name ("TimeCanvasScroller");
355 edit_controls_vbox.set_spacing (track_spacing);
356 edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
357 edit_controls_scroller.add (edit_controls_hbox);
358 edit_controls_scroller.set_name ("EditControlsBase");
359 edit_controls_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
361 Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
363 viewport->set_shadow_type (Gtk::SHADOW_NONE);
364 viewport->set_name ("EditControlsBase");
365 viewport->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
366 viewport->signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
371 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
373 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
374 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
375 time_canvas_vbox.pack_start (*frames_ruler, false, false);
376 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
377 time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
378 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
380 bbt_label.set_name ("EditorTimeButton");
381 bbt_label.set_size_request (-1, (int)timebar_height);
382 bbt_label.set_alignment (1.0, 0.5);
383 bbt_label.set_padding (5,0);
384 minsec_label.set_name ("EditorTimeButton");
385 minsec_label.set_size_request (-1, (int)timebar_height);
386 minsec_label.set_alignment (1.0, 0.5);
387 minsec_label.set_padding (5,0);
388 smpte_label.set_name ("EditorTimeButton");
389 smpte_label.set_size_request (-1, (int)timebar_height);
390 smpte_label.set_alignment (1.0, 0.5);
391 smpte_label.set_padding (5,0);
392 frame_label.set_name ("EditorTimeButton");
393 frame_label.set_size_request (-1, (int)timebar_height);
394 frame_label.set_alignment (1.0, 0.5);
395 frame_label.set_padding (5,0);
396 tempo_label.set_name ("EditorTimeButton");
397 tempo_label.set_size_request (-1, (int)timebar_height);
398 tempo_label.set_alignment (1.0, 0.5);
399 tempo_label.set_padding (5,0);
400 meter_label.set_name ("EditorTimeButton");
401 meter_label.set_size_request (-1, (int)timebar_height);
402 meter_label.set_alignment (1.0, 0.5);
403 meter_label.set_padding (5,0);
404 mark_label.set_name ("EditorTimeButton");
405 mark_label.set_size_request (-1, (int)timebar_height);
406 mark_label.set_alignment (1.0, 0.5);
407 mark_label.set_padding (5,0);
408 range_mark_label.set_name ("EditorTimeButton");
409 range_mark_label.set_size_request (-1, (int)timebar_height);
410 range_mark_label.set_alignment (1.0, 0.5);
411 range_mark_label.set_padding (5,0);
412 transport_mark_label.set_name ("EditorTimeButton");
413 transport_mark_label.set_size_request (-1, (int)timebar_height);
414 transport_mark_label.set_alignment (1.0, 0.5);
415 transport_mark_label.set_padding (5,0);
417 time_button_vbox.pack_start (minsec_label, false, false);
418 time_button_vbox.pack_start (smpte_label, false, false);
419 time_button_vbox.pack_start (frame_label, false, false);
420 time_button_vbox.pack_start (bbt_label, false, false);
421 time_button_vbox.pack_start (meter_label, false, false);
422 time_button_vbox.pack_start (tempo_label, false, false);
423 time_button_vbox.pack_start (mark_label, false, false);
425 time_button_event_box.add (time_button_vbox);
427 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
428 time_button_event_box.set_name ("TimebarLabelBase");
429 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
431 /* these enable us to have a dedicated window (for cursor setting, etc.)
432 for the canvas areas.
435 track_canvas_event_box.add (track_canvas_scroller);
437 time_canvas_event_box.add (time_canvas_vbox);
438 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
441 edit_packer.set_col_spacings (0);
442 edit_packer.set_row_spacings (0);
443 edit_packer.set_homogeneous (false);
444 edit_packer.set_name ("EditorWindow");
446 // edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, Gtk::FILL, 0, 0, 0);
447 // edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, 0, 0, 0);
448 // edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, Gtk::FILL, 0, 0, 0);
449 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
451 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
452 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
454 edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
455 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
456 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
458 edit_frame.set_name ("BaseFrame");
459 edit_frame.set_shadow_type (SHADOW_IN);
460 edit_frame.add (edit_packer);
462 zoom_in_button.set_name ("EditorTimeButton");
463 zoom_out_button.set_name ("EditorTimeButton");
464 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
465 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
467 // zoom_onetoone_button.set_name ("EditorTimeButton");
468 zoom_out_full_button.set_name ("EditorTimeButton");
469 // ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1"));
470 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
472 zoom_in_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(zoom_in_button_xpm)))));
473 zoom_out_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_button_xpm)))));
474 zoom_out_full_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_full_button_xpm)))));
475 // zoom_onetoone_button.add (*(manage (new Gtk::Image (zoom_onetoone_button_xpm))));
478 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
479 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
480 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
481 // zoom_onetoone_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom), 1.0));
483 zoom_indicator_box.pack_start (zoom_out_button, false, false);
484 zoom_indicator_box.pack_start (zoom_in_button, false, false);
485 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
486 // zoom_indicator_box.pack_start (zoom_onetoone_button, false, false);
487 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
489 zoom_indicator_label.set_text (_("Zoom Span"));
490 zoom_indicator_label.set_name ("ToolBarLabel");
493 zoom_indicator_vbox.set_spacing (3);
494 zoom_indicator_vbox.set_border_width (3);
495 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
496 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
499 bottom_hbox.set_border_width (3);
500 bottom_hbox.set_spacing (3);
502 route_display_model = ListStore::create(route_display_columns);
503 route_list.set_model (route_display_model);
504 route_list.append_column (_("Tracks"), route_display_columns.text);
505 route_list.set_name ("TrackListDisplay");
506 route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
507 route_list.set_reorderable (true);
509 route_list.set_size_request (75,-1);
510 route_list.set_headers_visible (true);
511 route_list.set_headers_clickable (true);
514 // route_list.signal_rows_reordered().connect (mem_fun (*this, &Editor::queue_route_list_reordered));
517 // route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func));
520 //route_list.set_shadow_type (Gtk::SHADOW_IN);
522 route_list_scroller.add (route_list);
523 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
525 route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed));
526 route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click));
528 edit_group_list_button_label.set_text (_("Edit Groups"));
529 edit_group_list_button_label.set_name ("EditGroupTitleButton");
530 edit_group_list_button.add (edit_group_list_button_label);
531 edit_group_list_button.set_name ("EditGroupTitleButton");
533 group_model = ListStore::create(group_columns);
534 edit_group_list.set_model (group_model);
535 edit_group_list.append_column (_("active"), group_columns.is_active);
536 edit_group_list.append_column (_("groupname"), group_columns.text);
537 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
538 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
540 /* use checkbox for the active column */
542 CellRendererToggle *active_cell = dynamic_cast<CellRendererToggle*>(edit_group_list.get_column_cell_renderer (0));
543 active_cell->set_property ("activatable", true);
544 active_cell->set_property ("radio", false);
546 edit_group_list.set_name ("MixerGroupList");
547 //edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
548 route_list.set_headers_visible (false);
549 edit_group_list.set_reorderable (false);
550 edit_group_list.set_size_request (75, -1);
551 edit_group_list.columns_autosize ();
552 edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
554 edit_group_list_scroller.add (edit_group_list);
555 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
557 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
558 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
559 edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed));
561 TreeModel::Row row = *(group_model->append());
562 row[group_columns.is_active] = false;
563 row[group_columns.text] = (_("-all-"));
564 edit_group_list.get_selection()->select (row);
565 /* GTK2FIX is set_data(0) setting the is_active to false here?
566 list<string> stupid_list;
568 stupid_list.push_back ("*");
569 stupid_list.push_back (_("-all-"));
571 edit_group_list.rows().push_back (stupid_list);
572 edit_group_list.rows().back().set_data (0);
573 edit_group_list.rows().back().select();
576 edit_group_vbox.pack_start (edit_group_list_button, false, false);
577 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
579 route_list_frame.set_name ("BaseFrame");
580 route_list_frame.set_shadow_type (Gtk::SHADOW_IN);
581 route_list_frame.add (route_list_scroller);
583 edit_group_list_frame.set_name ("BaseFrame");
584 edit_group_list_frame.set_shadow_type (Gtk::SHADOW_IN);
585 edit_group_list_frame.add (edit_group_vbox);
587 route_group_vpane.add1 (route_list_frame);
588 route_group_vpane.add2 (edit_group_list_frame);
590 list_vpacker.pack_start (route_group_vpane, true, true);
592 region_list_model = TreeStore::create (region_list_columns);
593 region_list_sort_model = TreeModelSort::create (region_list_model);
594 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
596 region_list_display.set_model (region_list_sort_model);
597 region_list_display.append_column (_("Regions"), region_list_columns.name);
598 region_list_display.set_reorderable (true);
599 region_list_display.set_size_request (100, -1);
600 region_list_display.set_data ("editor", this);
601 region_list_display.set_flags (Gtk::CAN_FOCUS);
602 region_list_display.set_name ("RegionListDisplay");
604 region_list_scroller.add (region_list_display);
605 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
607 list<Gtk::TargetEntry> region_list_target_table;
609 region_list_target_table.push_back (TargetEntry ("STRING"));
610 region_list_target_table.push_back (TargetEntry ("text/plain"));
611 region_list_target_table.push_back (TargetEntry ("text/uri-list"));
612 region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
615 // region_list_display.drag_dest_set (region_list_target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
616 // region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
618 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
619 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
620 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
621 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
622 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
624 //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
625 //region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click));
627 named_selection_scroller.add (named_selection_display);
628 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
630 named_selection_model = TreeStore::create (named_selection_columns);
631 named_selection_display.set_model (named_selection_model);
632 named_selection_display.set_name ("RegionListDisplay");
633 named_selection_display.set_size_request (100, -1);
634 named_selection_display.set_headers_visible (true);
635 named_selection_display.set_headers_clickable (true);
636 named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
637 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
638 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
640 region_selection_vpane.pack1 (region_list_scroller, true, true);
641 region_selection_vpane.pack2 (named_selection_scroller, true, true);
643 canvas_region_list_pane.pack1 (edit_frame, true, true);
644 canvas_region_list_pane.pack2 (region_selection_vpane, true, true);
646 track_list_canvas_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
647 static_cast<Gtk::Paned*> (&track_list_canvas_pane)));
648 canvas_region_list_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
649 static_cast<Gtk::Paned*> (&canvas_region_list_pane)));
650 route_group_vpane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
651 static_cast<Gtk::Paned*> (&route_group_vpane)));
652 region_selection_vpane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
653 static_cast<Gtk::Paned*> (®ion_selection_vpane)));
655 track_list_canvas_pane.pack1 (list_vpacker, true, true);
656 track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true);
658 /* provide special pane-handle event handling for easy "hide" action */
660 /* 0: collapse to show left/upper child
661 1: collapse to show right/lower child
664 route_group_vpane.set_data ("collapse-direction", (gpointer) 0);
665 region_selection_vpane.set_data ("collapse-direction", (gpointer) 0);
666 canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0);
667 track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1);
669 route_group_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&route_group_vpane)));
670 region_selection_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (®ion_selection_vpane)));
671 canvas_region_list_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&canvas_region_list_pane)));
672 track_list_canvas_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&track_list_canvas_pane)));
674 top_hbox.pack_start (toolbar_frame, true, true);
676 HBox *hbox = manage (new HBox);
677 hbox->pack_start (track_list_canvas_pane, true, true);
679 global_vpacker.pack_start (top_hbox, false, false);
680 global_vpacker.pack_start (*hbox, true, true);
682 global_hpacker.pack_start (global_vpacker, true, true);
684 set_name ("EditorWindow");
686 vpacker.pack_end (global_hpacker, true, true);
688 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
691 _playlist_selector = new PlaylistSelector();
692 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
694 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
698 nudge_forward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
699 nudge_backward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
701 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
702 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
704 nudge_forward_button.set_name ("TransportButton");
705 nudge_backward_button.set_name ("TransportButton");
707 fade_context_menu.set_name ("ArdourContextMenu");
709 set_title (_("ardour: editor"));
710 set_wmclass (_("ardour_editor"), "Ardour");
713 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
715 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
716 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
724 /* <CMT Additions> */
725 if(image_socket_listener)
727 if(image_socket_listener->is_connected())
729 image_socket_listener->close_connection() ;
732 delete image_socket_listener ;
733 image_socket_listener = 0 ;
735 /* </CMT Additions> */
739 Editor::add_toplevel_controls (Container& cont)
741 vpacker.pack_start (cont, false, false);
746 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
748 /* note: the selection will take care of the vanishing
749 audioregionview by itself.
752 if (clicked_regionview == rv) {
753 clicked_regionview = 0;
756 if (entered_regionview == rv) {
757 set_entered_regionview (0);
762 Editor::set_entered_regionview (AudioRegionView* rv)
764 if (rv == entered_regionview) {
768 if (entered_regionview) {
769 entered_regionview->exited ();
772 if ((entered_regionview = rv) != 0) {
773 entered_regionview->entered ();
778 Editor::set_entered_track (TimeAxisView* tav)
781 entered_track->exited ();
784 if ((entered_track = tav) != 0) {
785 entered_track->entered ();
790 Editor::left_track_canvas (GdkEventCrossing *ev)
792 set_entered_track (0);
793 set_entered_regionview (0);
799 Editor::initialize_canvas ()
801 ArdourCanvas::init ();
803 /* adjust sensitivity for "picking" items */
805 // GNOME_CANVAS(track_canvas)->close_enough = 2;
807 track_canvas.signal_event().connect (bind (mem_fun (*this, &Editor::track_canvas_event), (ArdourCanvas::Item*) 0));
808 track_canvas.set_name ("EditorMainCanvas");
809 track_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
810 track_canvas.signal_leave_notify_event().connect (mem_fun(*this, &Editor::left_track_canvas));
812 /* set up drag-n-drop */
813 vector<Gtk::TargetEntry> target_table;
815 target_table.push_back (TargetEntry ("STRING"));
816 target_table.push_back (TargetEntry ("text/plain"));
817 target_table.push_back (TargetEntry ("text/uri-list"));
818 target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
821 // track_canvas.drag_dest_set (target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
822 // track_canvas.signal_drag_data_received().connect (mem_fun(*this, &Editor::track_canvas_drag_data_received));
824 /* stuff for the verbose canvas cursor */
826 Pango::FontDescription font = get_font_for_style (N_("VerboseCanvasCursor"));
828 verbose_canvas_cursor = new ArdourCanvas::Text (*track_canvas.root());
829 verbose_canvas_cursor->set_property ("font_desc", font);
831 // verbose_canvas_cursor->set_property ("anchor", GTK_ANCHOR_NW);
832 verbose_canvas_cursor->set_property ("fill_color_rgba", color_map[cVerboseCanvasCursor]);
834 verbose_cursor_visible = false;
836 /* a group to hold time (measure) lines */
838 time_line_group = new ArdourCanvas::Group (*track_canvas.root(), 0.0, 0.0);
839 cursor_group = new ArdourCanvas::Group (*track_canvas.root(), 0.0, 0.0);
841 time_canvas.set_name ("EditorTimeCanvas");
842 time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
844 meter_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, 0.0);
845 tempo_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, 0.0);
846 marker_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, timebar_height * 2.0);
847 range_marker_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, timebar_height * 3.0);
848 transport_marker_group = new ArdourCanvas::Group (*time_canvas.root(), 0.0, timebar_height * 4.0);
850 tempo_bar = new ArdourCanvas::SimpleRect (*tempo_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
851 tempo_bar->set_property ("fill_color_rgba", color_map[cTempoBar]);
852 tempo_bar->set_property ("outline_pixels", 0);
854 meter_bar = new ArdourCanvas::SimpleRect (*meter_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
855 meter_bar->set_property ("fill_color_rgba", color_map[cMeterBar]);
856 meter_bar->set_property ("outline_pixels",0);
858 marker_bar = new ArdourCanvas::SimpleRect (*marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
859 marker_bar->set_property ("fill_color_rgba", color_map[cMarkerBar]);
860 marker_bar->set_property ("outline_pixels", 0);
862 range_marker_bar = new ArdourCanvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
863 range_marker_bar->set_property ("fill_color_rgba", color_map[cRangeMarkerBar]);
864 range_marker_bar->set_property ("outline_pixels", 0);
866 transport_marker_bar = new ArdourCanvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
867 transport_marker_bar->set_property ("fill_color_rgba", color_map[cTransportMarkerBar]);
868 transport_marker_bar->set_property ("outline_pixels", 0);
870 range_bar_drag_rect = new ArdourCanvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
871 range_bar_drag_rect->set_property ("fill_color_rgba", color_map[cRangeDragBarRectFill]);
872 range_bar_drag_rect->set_property ("outline_color_rgba", color_map[cRangeDragBarRect]);
873 range_bar_drag_rect->set_property ("outline_pixels", 0);
874 range_bar_drag_rect->hide ();
876 transport_bar_drag_rect = new ArdourCanvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
877 transport_bar_drag_rect ->set_property ("fill_color_rgba", color_map[cTransportDragRectFill]);
878 transport_bar_drag_rect->set_property ("outline_color_rgba", color_map[cTransportDragRect]);
879 transport_bar_drag_rect->set_property ("outline_pixels", 0);
880 transport_bar_drag_rect->hide ();
882 marker_drag_line_points.push_back(Gnome::Art::Point(0.0, 0.0));
883 marker_drag_line_points.push_back(Gnome::Art::Point(0.0, 0.0));
885 marker_drag_line = new ArdourCanvas::Line (*track_canvas.root());
886 marker_drag_line->set_property ("width_pixels", 1);
887 marker_drag_line->set_property("fill_color_rgba", color_map[cMarkerDragLine]);
888 marker_drag_line->set_property("points", marker_drag_line_points);
889 marker_drag_line->hide();
891 range_marker_drag_rect = new ArdourCanvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
892 range_marker_drag_rect->set_property ("fill_color_rgba", color_map[cRangeDragRectFill]);
893 range_marker_drag_rect->set_property ("outline_color_rgba", color_map[cRangeDragRect]);
894 range_marker_drag_rect->hide ();
896 transport_loop_range_rect = new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
897 transport_loop_range_rect->set_property ("fill_color_rgba", color_map[cTransportLoopRectFill]);
898 transport_loop_range_rect->set_property ("outline_color_rgba", color_map[cTransportLoopRect]);
899 transport_loop_range_rect->set_property ("outline_pixels", 1);
900 transport_loop_range_rect->hide();
902 transport_punch_range_rect = new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
903 transport_punch_range_rect->set_property ("fill_color_rgba", color_map[cTransportPunchRectFill]);
904 transport_punch_range_rect->set_property ("outline_color_rgba", color_map[cTransportPunchRect]);
905 transport_punch_range_rect->set_property ("outline_pixels", 0);
906 transport_punch_range_rect->hide();
908 transport_loop_range_rect->lower_to_bottom (); // loop on the bottom
910 transport_punchin_line = new ArdourCanvas::SimpleLine (*time_line_group);
911 transport_punchin_line->set_property ("x1", 0.0);
912 transport_punchin_line->set_property ("y1", 0.0);
913 transport_punchin_line->set_property ("x2", 0.0);
914 transport_punchin_line->set_property ("y2", 0.0);
915 transport_punchin_line->property_color_rgba() = color_map[cPunchInLine];
916 transport_punchin_line->hide ();
918 transport_punchout_line = new ArdourCanvas::SimpleLine (*time_line_group);
919 transport_punchout_line->set_property ("x1", 0.0);
920 transport_punchout_line->set_property ("y1", 0.0);
921 transport_punchout_line->set_property ("x2", 0.0);
922 transport_punchout_line->set_property ("y2", 0.0);
923 transport_punchout_line->property_color_rgba() = color_map[cPunchOutLine];
924 transport_punchout_line->hide();
926 // used to show zoom mode active zooming
927 zoom_rect = new ArdourCanvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
928 zoom_rect->set_property ("fill_color_rgba", color_map[cZoomRectFill]);
929 zoom_rect->set_property ("outline_color_rgba", color_map[cZoomRect]);
930 zoom_rect->set_property ("outline_pixels", 1);
933 zoom_rect->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_zoom_rect_event), (ArdourCanvas::Item*) 0));
935 // used as rubberband rect
936 rubberband_rect = new ArdourCanvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
937 rubberband_rect->set_property ("outline_color_rgba", color_map[cRubberBandRect]);
938 rubberband_rect->set_property ("fill_color_rgba", (guint32) color_map[cRubberBandRectFill]);
939 rubberband_rect->set_property ("outline_pixels", 1);
940 rubberband_rect->hide();
942 tempo_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_tempo_bar_event), tempo_bar));
943 meter_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_meter_bar_event), meter_bar));
944 marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_marker_bar_event), marker_bar));
945 range_marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_range_marker_bar_event), range_marker_bar));
946 transport_marker_bar->signal_event().connect (bind (mem_fun (*this, &Editor::canvas_transport_marker_bar_event), transport_marker_bar));
948 /* separator lines */
950 tempo_line = new ArdourCanvas::SimpleLine (*tempo_group, 0, timebar_height, max_canvas_coordinate, timebar_height);
951 tempo_line->property_color_rgba() = RGBA_TO_UINT (0,0,0,255);
953 meter_line = new ArdourCanvas::SimpleLine (*meter_group, 0, timebar_height, max_canvas_coordinate, timebar_height);
954 meter_line->property_color_rgba() = RGBA_TO_UINT (0,0,0,255);
956 marker_line = new ArdourCanvas::SimpleLine (*marker_group, 0, timebar_height, max_canvas_coordinate, timebar_height);
957 marker_line->property_color_rgba() = RGBA_TO_UINT (0,0,0,255);
959 range_marker_line = new ArdourCanvas::SimpleLine (*range_marker_group, 0, timebar_height, max_canvas_coordinate, timebar_height);
960 range_marker_line->property_color_rgba() = RGBA_TO_UINT (0,0,0,255);
962 transport_marker_line = new ArdourCanvas::SimpleLine (*transport_marker_group, 0, timebar_height, max_canvas_coordinate, timebar_height);
963 transport_marker_line->property_color_rgba() = RGBA_TO_UINT (0,0,0,255);
965 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_loop_range_view), false));
966 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_punch_range_view), false));
968 double time_height = timebar_height * 5;
969 double time_width = FLT_MAX/frames_per_unit;
970 time_canvas.set_scroll_region(0.0, 0.0, time_width, time_height);
972 edit_cursor = new Cursor (*this, "blue", &Editor::canvas_edit_cursor_event);
973 playhead_cursor = new Cursor (*this, "red", &Editor::canvas_playhead_cursor_event);
975 track_canvas.signal_size_allocate().connect (mem_fun(*this, &Editor::track_canvas_allocate));
979 Editor::show_window ()
983 /* now reset all audio_time_axis heights, because widgets might need
989 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
990 tv = (static_cast<TimeAxisView*>(*i));
996 Editor::tie_vertical_scrolling ()
998 edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
1000 float y1 = track_canvas_scroller.get_vadjustment()->get_value();
1001 playhead_cursor->set_y_axis(y1);
1002 edit_cursor->set_y_axis(y1);
1006 Editor::set_frames_per_unit (double fpu)
1008 jack_nframes_t frames;
1010 if (fpu == frames_per_unit) {
1018 // convert fpu to frame count
1020 frames = (jack_nframes_t) (fpu * canvas_width);
1022 /* don't allow zooms that fit more than the maximum number
1023 of frames into an 800 pixel wide space.
1026 if (max_frames / fpu < 800.0) {
1030 frames_per_unit = fpu;
1032 if (frames != zoom_range_clock.current_duration()) {
1033 zoom_range_clock.set (frames);
1036 /* only update these if we not about to call reposition_x_origin,
1037 which will do the same updates.
1041 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1044 if (!no_zoom_repos_update) {
1045 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1046 update_hscroller ();
1047 update_fixed_rulers ();
1048 tempo_map_changed (Change (0));
1051 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
1052 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1053 (*i)->reshow_selection (selection->time);
1057 ZoomChanged (); /* EMIT_SIGNAL */
1059 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
1060 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
1067 Editor::instant_save ()
1069 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
1074 session->add_instant_xml(get_state(), session->path());
1076 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
1081 Editor::reposition_x_origin (jack_nframes_t frame)
1083 if (frame != leftmost_frame) {
1084 leftmost_frame = frame;
1085 double pixel = frame_to_pixel (frame);
1086 if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
1087 track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
1089 track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
1090 XOriginChanged (); /* EMIT_SIGNAL */
1095 Editor::edit_cursor_clock_changed()
1097 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
1098 edit_cursor->set_position (edit_cursor_clock.current_time());
1104 Editor::zoom_adjustment_changed ()
1106 if (session == 0 || no_zoom_repos_update) {
1110 double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width;
1114 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1116 else if (fpu > session->current_end_frame() / (double) canvas_width) {
1117 fpu = session->current_end_frame() / (double) canvas_width;
1118 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1121 temporal_zoom (fpu);
1125 Editor::canvas_horizontally_scrolled ()
1127 /* XXX note the potential loss of accuracy here caused by
1128 adjustments being 32bit floats with only a 24 bit mantissa,
1129 whereas jack_nframes_t is at least a 32 bit uint32_teger.
1132 leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
1134 update_hscroller ();
1135 update_fixed_rulers ();
1137 if (!edit_hscroll_dragging) {
1138 tempo_map_changed (Change (0));
1140 update_tempo_based_rulers();
1145 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
1147 if (!repos_zoom_queued) {
1148 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
1149 repos_zoom_queued = true;
1154 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
1156 /* if we need to force an update to the hscroller stuff,
1157 don't set no_zoom_repos_update.
1160 no_zoom_repos_update = (frame != leftmost_frame);
1162 set_frames_per_unit (nfpu);
1163 if (no_zoom_repos_update) {
1164 reposition_x_origin (frame);
1166 no_zoom_repos_update = false;
1167 repos_zoom_queued = false;
1173 Editor::on_realize ()
1175 Window::on_realize ();
1177 /* Even though we're not using acceleration, we want the
1181 track_context_menu.accelerate (*this->get_toplevel());
1182 track_region_context_menu.accelerate (*this->get_toplevel());
1184 Glib::RefPtr<Gdk::Pixmap> empty_pixmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1185 Glib::RefPtr<Gdk::Pixmap> empty_bitmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1186 Gdk::Color white ("#ffffff" );
1188 null_cursor = new Gdk::Cursor(empty_pixmap, empty_bitmap, white, white, 0, 0);
1196 track_canvas_scroller.get_window()->set_cursor (*current_canvas_cursor);
1197 time_canvas_scroller.get_window()->set_cursor (*timebar_cursor);
1201 Editor::track_canvas_allocate (Gtk::Allocation alloc)
1203 canvas_width = alloc.get_width();
1204 canvas_height = alloc.get_height();
1206 if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) {
1208 Pango::FontDescription font = get_font_for_style (N_("FirstActionMessage"));
1210 const char *txt1 = _("Start a new session\n");
1211 const char *txt2 = _("via Session menu");
1213 /* this mess of code is here to find out how wide this text is and
1214 position the message in the center of the editor window. there
1215 are two lines, so we use the longer of the the lines to
1216 compute width, and multiply the height by 2.
1222 /* this is a dummy widget that exists so that we can get the
1223 style from the RC file.
1226 Label foo (_(txt2));
1227 Glib::RefPtr<Pango::Layout> layout;
1228 foo.set_name ("NoSessionMessage");
1229 foo.ensure_style ();
1231 layout = foo.create_pango_layout (_(txt2));
1232 layout->set_font_description (font);
1233 layout->get_pixel_size (pixel_width, pixel_height);
1235 if (first_action_message == 0) {
1237 char txt[strlen(txt1)+strlen(txt2)+1];
1239 /* merge both lines */
1241 strcpy (txt, _(txt1));
1242 strcat (txt, _(txt2));
1244 first_action_message = new ArdourCanvas::Text (*track_canvas.root());
1245 first_action_message->set_property ("font_desc", font);
1246 first_action_message->set_property ("fill_color_rgba", color_map[cFirstActionMessage]);
1247 first_action_message->set_property ("x", (gdouble) (canvas_width - pixel_width) / 2.0);
1248 first_action_message->set_property ("y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)));
1249 first_action_message->set_property ("anchor", GTK_ANCHOR_NORTH_WEST);
1250 first_action_message->set_property ("text", ustring (txt));
1255 first_action_message->set_property ("x", (gdouble) (canvas_width - pixel_width) / 2.0),
1256 first_action_message->set_property ("y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)));
1260 zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit));
1261 edit_cursor->set_position (edit_cursor->current_frame);
1262 playhead_cursor->set_position (playhead_cursor->current_frame);
1263 reset_scrolling_region (&alloc);
1265 Resized (); /* EMIT_SIGNAL */
1269 Editor::reset_scrolling_region (Gtk::Allocation* alloc)
1271 guint32 last_canvas_unit;
1273 guint32 canvas_alloc_height, canvas_alloc_width;
1274 TrackViewList::iterator i;
1275 static bool first_time = true;
1277 /* We need to make sure that the canvas always has its
1278 scrolling region set to larger of:
1280 - the size allocated for it (within the container its packed in)
1281 - the size required to see the entire session
1283 If we don't ensure at least the first of these, the canvas
1284 does some wierd and in my view unnecessary stuff to center
1285 itself within the allocated area, which causes bad, bad
1288 XXX GnomeCanvas has fixed this, and has an option to
1289 control the centering behaviour.
1292 last_canvas_unit = (guint32) ceil ((float) max_frames / frames_per_unit);
1297 for (i = track_views.begin(); i != track_views.end(); ++i) {
1298 if ((*i)->control_parent) {
1299 height += (*i)->effective_height;
1300 height += track_spacing;
1305 height -= track_spacing;
1309 canvas_height = (guint32) height;
1312 canvas_alloc_height = alloc->get_height();
1313 canvas_alloc_width = alloc->get_width();
1315 canvas_alloc_height = track_canvas.get_height();
1316 canvas_alloc_width = track_canvas.get_width();
1319 canvas_height = max (canvas_height, canvas_alloc_height);
1320 track_canvas.set_scroll_region ( 0.0, 0.0, max (last_canvas_unit, canvas_alloc_width), canvas_height);
1322 if (edit_cursor) edit_cursor->set_length (canvas_alloc_height);
1323 if (playhead_cursor) playhead_cursor->set_length (canvas_alloc_height);
1325 if (marker_drag_line) {
1326 marker_drag_line_points.back().set_x(canvas_height);
1327 // cerr << "set mlA points, nc = " << marker_drag_line_points.num_points << endl;
1328 marker_drag_line->set_property("points", marker_drag_line_points);
1330 if (range_marker_drag_rect) {
1331 range_marker_drag_rect->set_property("y1", 0.0);
1332 range_marker_drag_rect->set_property("y2", (double) canvas_height);
1335 if (transport_loop_range_rect) {
1336 transport_loop_range_rect->set_property("y1", 0.0);
1337 transport_loop_range_rect->set_property("y2", (double) canvas_height);
1340 if (transport_punch_range_rect) {
1341 transport_punch_range_rect->set_property("y1", 0.0);
1342 transport_punch_range_rect->set_property("y2", (double) canvas_height);
1345 if (transport_punchin_line) {
1346 transport_punchin_line->set_property("y1", 0.0);
1347 transport_punchin_line->set_property("y2", (double) canvas_height);
1350 if (transport_punchout_line) {
1351 transport_punchout_line->set_property("y1", 0.0);
1352 transport_punchout_line->set_property("y2", (double) canvas_height);
1355 update_fixed_rulers ();
1357 if (is_visible() && first_time) {
1358 tempo_map_changed (Change (0));
1366 Editor::queue_session_control_changed (Session::ControlType t)
1368 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1372 Editor::session_control_changed (Session::ControlType t)
1374 // right now we're only tracking the loop and punch state
1377 case Session::AutoLoop:
1378 update_loop_range_view (true);
1380 case Session::PunchIn:
1381 case Session::PunchOut:
1382 update_punch_range_view (true);
1391 Editor::fake_add_edit_group (RouteGroup *group)
1393 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1397 Editor::fake_handle_new_audio_region (AudioRegion *region)
1399 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1403 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1405 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1409 Editor::fake_handle_new_duration ()
1411 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1415 Editor::start_scrolling ()
1417 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1418 (mem_fun(*this, &Editor::update_current_screen));
1420 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1421 (mem_fun(*this, &Editor::update_slower));
1425 Editor::stop_scrolling ()
1427 scroll_connection.disconnect ();
1428 slower_update_connection.disconnect ();
1432 Editor::map_position_change (jack_nframes_t frame)
1434 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1436 if (session == 0 || !_follow_playhead) {
1440 center_screen (frame);
1441 playhead_cursor->set_position (frame);
1445 Editor::center_screen (jack_nframes_t frame)
1447 float page = canvas_width * frames_per_unit;
1449 /* if we're off the page, then scroll.
1452 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1453 center_screen_internal (frame,page);
1458 Editor::center_screen_internal (jack_nframes_t frame, float page)
1463 frame -= (jack_nframes_t) page;
1468 reposition_x_origin (frame);
1472 Editor::handle_new_duration ()
1474 reset_scrolling_region ();
1477 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1478 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1481 update_hscroller ();
1485 Editor::update_title_s (string snap_name)
1487 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1493 Editor::update_title ()
1495 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1498 bool dirty = session->dirty();
1500 string wintitle = _("ardour: editor: ");
1506 wintitle += session->name();
1508 if (session->snap_name() != session->name()) {
1510 wintitle += session->snap_name();
1517 set_title (wintitle);
1522 Editor::connect_to_session (Session *t)
1526 if (first_action_message) {
1527 first_action_message->hide();
1530 flush_track_canvas();
1534 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1536 /* These signals can all be emitted by a non-GUI thread. Therefore the
1537 handlers for them must not attempt to directly interact with the GUI,
1538 but use Gtkmm2ext::UI::instance()->call_slot();
1541 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1542 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1543 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1544 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1545 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1546 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1547 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1548 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1549 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1550 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1551 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1552 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1553 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1555 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1556 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1558 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1560 session->foreach_edit_group(this, &Editor::add_edit_group);
1562 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1563 editor_mixer_button.set_name (X_("EditorMixerButton"));
1565 edit_cursor_clock.set_session (session);
1566 selection_start_clock.set_session (session);
1567 selection_end_clock.set_session (session);
1568 zoom_range_clock.set_session (session);
1569 _playlist_selector->set_session (session);
1570 nudge_clock.set_session (session);
1572 switch (session->get_edit_mode()) {
1574 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1578 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1582 Location* loc = session->locations()->auto_loop_location();
1584 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1585 if (loc->start() == loc->end()) {
1586 loc->set_end (loc->start() + 1);
1588 session->locations()->add (loc, false);
1589 session->set_auto_loop_location (loc);
1593 loc->set_name (_("Loop"));
1596 loc = session->locations()->auto_punch_location();
1598 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1599 if (loc->start() == loc->end()) {
1600 loc->set_end (loc->start() + 1);
1602 session->locations()->add (loc, false);
1603 session->set_auto_punch_location (loc);
1607 loc->set_name (_("Punch"));
1610 update_loop_range_view (true);
1611 update_punch_range_view (true);
1613 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1616 refresh_location_display ();
1617 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1618 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1619 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1620 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1621 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1623 reset_scrolling_region ();
1625 redisplay_regions ();
1626 redisplay_named_selections ();
1628 //route_list.freeze (); GTK2FIX
1629 route_display_model.clear ();
1630 session->foreach_route (this, &Editor::handle_new_route);
1631 // route_list.select_all ();
1633 //route_list.sort ();
1634 route_list_reordered ();
1635 //route_list.thaw ();
1637 if (embed_audio_item) {
1638 embed_audio_item->set_sensitive (true);
1640 if (import_audio_item) {
1641 import_audio_item->set_sensitive (true);
1644 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1645 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1648 /* ::reposition_x_origin() doesn't work right here, since the old
1649 position may be zero already, and it does nothing in such
1655 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1656 track_canvas_scroller.get_hadjustment()->set_value (0);
1658 update_hscroller ();
1659 restore_ruler_visibility ();
1660 tempo_map_changed (Change (0));
1662 edit_cursor->set_position (0);
1663 playhead_cursor->set_position (0);
1667 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1670 /* don't show master bus in a new session */
1672 if (ARDOUR_UI::instance()->session_is_new ()) {
1674 TreeModel::Children rows = route_display_model->children();
1675 TreeModel::Children::iterator i;
1677 //route_list.freeze ();
1679 for (i = rows.begin(); i != rows.end(); ++i) {
1680 TimeAxisView *tv = (*i)[route_display_columns.tv];
1681 AudioTimeAxisView *atv;
1683 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1684 if (atv->route().master()) {
1685 route_list.get_selection()->unselect (i);
1686 //(*i)->unselect ();
1691 //route_list.thaw ();
1696 Editor::build_cursors ()
1698 using namespace Gdk;
1700 Gdk::Color fg ("#ff0000"); /* Red. */
1701 Gdk::Color bg ("#0000ff"); /* Blue. */
1704 RefPtr<Bitmap> source, mask;
1705 source = Bitmap::create (hand_bits, hand_width, hand_height);
1706 mask = Bitmap::create (handmask_bits, handmask_width, handmask_height);
1707 grabber_cursor = new Gdk::Cursor (source, mask, fg, bg, hand_x_hot, hand_y_hot);
1710 Gdk::Color mbg ("#000000" ); /* Black */
1711 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1714 RefPtr<Bitmap> source, mask;
1715 source = Bitmap::create (mag_bits, mag_width, mag_height);
1716 mask = Bitmap::create (magmask_bits, mag_width, mag_height);
1717 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1720 Gdk::Color fbg ("#ffffff" );
1721 Gdk::Color ffg ("#000000" );
1724 RefPtr<Bitmap> source, mask;
1726 source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
1727 mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
1728 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1732 RefPtr<Bitmap> source, mask;
1733 source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
1734 mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
1735 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1738 cross_hair_cursor = new Gdk::Cursor (Gdk::CROSSHAIR);
1739 trimmer_cursor = new Gdk::Cursor (Gdk::SB_H_DOUBLE_ARROW);
1740 selector_cursor = new Gdk::Cursor (Gdk::XTERM);
1741 time_fx_cursor = new Gdk::Cursor (Gdk::SIZING);
1742 wait_cursor = new Gdk::Cursor (Gdk::WATCH);
1743 timebar_cursor = new Gdk::Cursor(Gdk::LEFT_PTR);
1747 Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
1749 using namespace Menu_Helpers;
1750 AudioRegionView* arv = static_cast<AudioRegionView*> (gtk_object_get_data (GTK_OBJECT(item), "regionview"));
1753 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1757 MenuList& items (fade_context_menu.items());
1761 switch (item_type) {
1763 case FadeInHandleItem:
1764 if (arv->region.fade_in_active()) {
1765 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1767 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1770 items.push_back (SeparatorElem());
1772 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1773 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1774 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1775 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1776 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1780 case FadeOutHandleItem:
1781 if (arv->region.fade_out_active()) {
1782 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1784 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1787 items.push_back (SeparatorElem());
1789 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1790 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1791 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1792 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1793 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1797 fatal << _("programming error: ")
1798 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1803 fade_context_menu.popup (button, time);
1807 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1809 using namespace Menu_Helpers;
1810 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1813 switch (item_type) {
1815 case AudioRegionViewName:
1816 case AudioRegionViewNameHighlight:
1817 if (with_selection) {
1818 build_menu_function = &Editor::build_track_selection_context_menu;
1820 build_menu_function = &Editor::build_track_region_context_menu;
1825 if (with_selection) {
1826 build_menu_function = &Editor::build_track_selection_context_menu;
1828 build_menu_function = &Editor::build_track_context_menu;
1832 case CrossfadeViewItem:
1833 build_menu_function = &Editor::build_track_crossfade_context_menu;
1837 if (clicked_audio_trackview->get_diskstream()) {
1838 build_menu_function = &Editor::build_track_context_menu;
1840 build_menu_function = &Editor::build_track_bus_context_menu;
1845 /* probably shouldn't happen but if it does, we don't care */
1849 menu = (this->*build_menu_function)(frame);
1850 menu->set_name ("ArdourContextMenu");
1852 /* now handle specific situations */
1854 switch (item_type) {
1856 case AudioRegionViewName:
1857 case AudioRegionViewNameHighlight:
1858 if (!with_selection) {
1859 if (region_edit_menu_split_item) {
1860 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1861 region_edit_menu_split_item->set_sensitive (true);
1863 region_edit_menu_split_item->set_sensitive (false);
1866 if (region_edit_menu_split_multichannel_item) {
1867 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1868 region_edit_menu_split_multichannel_item->set_sensitive (true);
1870 region_edit_menu_split_multichannel_item->set_sensitive (false);
1879 case CrossfadeViewItem:
1886 /* probably shouldn't happen but if it does, we don't care */
1890 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1892 /* Bounce to disk */
1894 using namespace Menu_Helpers;
1895 MenuList& edit_items = menu->items();
1897 edit_items.push_back (SeparatorElem());
1899 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1900 case AudioTrack::NoFreeze:
1901 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1904 case AudioTrack::Frozen:
1905 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1908 case AudioTrack::UnFrozen:
1909 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1915 menu->popup (button, time);
1919 Editor::build_track_context_menu (jack_nframes_t ignored)
1921 using namespace Menu_Helpers;
1923 MenuList& edit_items = track_context_menu.items();
1926 add_dstream_context_items (edit_items);
1927 return &track_context_menu;
1931 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1933 using namespace Menu_Helpers;
1935 MenuList& edit_items = track_context_menu.items();
1938 add_bus_context_items (edit_items);
1939 return &track_context_menu;
1943 Editor::build_track_region_context_menu (jack_nframes_t frame)
1945 using namespace Menu_Helpers;
1946 MenuList& edit_items = track_region_context_menu.items();
1949 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1955 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1956 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1957 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1958 add_region_context_items (atv->view, (*i), edit_items);
1964 add_dstream_context_items (edit_items);
1966 return &track_region_context_menu;
1970 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1972 using namespace Menu_Helpers;
1973 MenuList& edit_items = track_crossfade_context_menu.items();
1974 edit_items.clear ();
1976 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1983 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
1985 Playlist::RegionList* regions = pl->regions_at (frame);
1986 AudioPlaylist::Crossfades xfades;
1988 apl->crossfades_at (frame, xfades);
1990 bool many = xfades.size() > 1;
1992 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
1993 add_crossfade_context_items (atv->view, (*i), edit_items, many);
1996 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1997 add_region_context_items (atv->view, (*i), edit_items);
2004 add_dstream_context_items (edit_items);
2006 return &track_crossfade_context_menu;
2010 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
2012 using namespace Menu_Helpers;
2013 MenuList& edit_items = track_selection_context_menu.items();
2014 edit_items.clear ();
2016 add_selection_context_items (edit_items);
2017 add_dstream_context_items (edit_items);
2019 return &track_selection_context_menu;
2023 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
2025 using namespace Menu_Helpers;
2026 Menu *xfade_menu = manage (new Menu);
2027 MenuList& items = xfade_menu->items();
2028 xfade_menu->set_name ("ArdourContextMenu");
2031 if (xfade->active()) {
2037 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
2038 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
2040 if (xfade->can_follow_overlap()) {
2042 if (xfade->following_overlap()) {
2043 str = _("Convert to short");
2045 str = _("Convert to full");
2048 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
2052 str = xfade->out().name();
2054 str += xfade->in().name();
2056 str = _("Crossfade");
2059 edit_items.push_back (MenuElem (str, *xfade_menu));
2060 edit_items.push_back (SeparatorElem());
2064 Editor::xfade_edit_left_region ()
2066 if (clicked_crossfadeview) {
2067 clicked_crossfadeview->left_view.show_region_editor ();
2072 Editor::xfade_edit_right_region ()
2074 if (clicked_crossfadeview) {
2075 clicked_crossfadeview->right_view.show_region_editor ();
2080 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
2082 using namespace Menu_Helpers;
2083 Menu *region_menu = manage (new Menu);
2084 MenuList& items = region_menu->items();
2085 region_menu->set_name ("ArdourContextMenu");
2087 AudioRegion* ar = 0;
2090 ar = dynamic_cast<AudioRegion*> (region);
2093 /* when this particular menu pops up, make the relevant region
2097 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
2099 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
2100 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
2101 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
2102 items.push_back (SeparatorElem());
2103 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
2104 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
2105 items.push_back (SeparatorElem());
2107 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
2108 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
2109 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
2110 items.push_back (SeparatorElem());
2112 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
2113 might be able to figure out which overloaded member function to use in
2117 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
2119 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
2120 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
2121 items.push_back (SeparatorElem());
2123 if (region->muted()) {
2124 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
2126 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
2128 items.push_back (SeparatorElem());
2130 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
2131 items.push_back (SeparatorElem());
2136 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
2137 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
2138 items.push_back (SeparatorElem());
2140 if (ar->scale_amplitude() != 1.0f) {
2141 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
2143 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
2146 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
2147 items.push_back (SeparatorElem());
2151 Menu *nudge_menu = manage (new Menu());
2152 MenuList& nudge_items = nudge_menu->items();
2153 nudge_menu->set_name ("ArdourContextMenu");
2155 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
2156 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
2157 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
2158 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
2160 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2161 items.push_back (SeparatorElem());
2163 Menu *trim_menu = manage (new Menu);
2164 MenuList& trim_items = trim_menu->items();
2165 trim_menu->set_name ("ArdourContextMenu");
2167 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
2168 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
2170 items.push_back (MenuElem (_("Trim"), *trim_menu));
2171 items.push_back (SeparatorElem());
2173 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
2174 region_edit_menu_split_item = &items.back();
2176 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
2177 region_edit_menu_split_multichannel_item = &items.back();
2179 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
2180 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
2181 items.push_back (SeparatorElem());
2182 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
2183 items.push_back (SeparatorElem());
2184 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
2186 /* OK, stick the region submenu at the top of the list, and then add
2190 /* we have to hack up the region name because "_" has a special
2191 meaning for menu titles.
2194 string::size_type pos = 0;
2195 string menu_item_name = region->name();
2197 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
2198 menu_item_name.replace (pos, 1, "__");
2202 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
2203 edit_items.push_back (SeparatorElem());
2207 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
2209 using namespace Menu_Helpers;
2210 Menu *selection_menu = manage (new Menu);
2211 MenuList& items = selection_menu->items();
2212 selection_menu->set_name ("ArdourContextMenu");
2214 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
2215 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
2216 items.push_back (SeparatorElem());
2217 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
2218 items.push_back (SeparatorElem());
2219 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
2220 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
2221 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
2222 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
2223 items.push_back (SeparatorElem());
2224 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
2225 items.push_back (SeparatorElem());
2226 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
2227 items.push_back (SeparatorElem());
2228 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
2230 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
2231 edit_items.push_back (SeparatorElem());
2235 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
2237 using namespace Menu_Helpers;
2241 Menu *play_menu = manage (new Menu);
2242 MenuList& play_items = play_menu->items();
2243 play_menu->set_name ("ArdourContextMenu");
2245 play_items.push_back (MenuElem (_("Play from edit cursor")));
2246 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2247 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
2248 play_items.push_back (SeparatorElem());
2249 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
2251 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2255 Menu *select_menu = manage (new Menu);
2256 MenuList& select_items = select_menu->items();
2257 select_menu->set_name ("ArdourContextMenu");
2259 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2260 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2261 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2262 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2263 select_items.push_back (SeparatorElem());
2264 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2265 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2266 select_items.push_back (SeparatorElem());
2268 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2272 Menu *cutnpaste_menu = manage (new Menu);
2273 MenuList& cutnpaste_items = cutnpaste_menu->items();
2274 cutnpaste_menu->set_name ("ArdourContextMenu");
2276 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2277 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2278 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2279 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
2281 cutnpaste_items.push_back (SeparatorElem());
2283 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
2284 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
2286 cutnpaste_items.push_back (SeparatorElem());
2288 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
2290 cutnpaste_items.push_back (SeparatorElem());
2292 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
2293 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
2295 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2297 /* Adding new material */
2299 Menu *import_menu = manage (new Menu());
2300 MenuList& import_items = import_menu->items();
2301 import_menu->set_name ("ArdourContextMenu");
2303 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2304 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
2306 edit_items.push_back (MenuElem (_("Import"), *import_menu));
2310 Menu *nudge_menu = manage (new Menu());
2311 MenuList& nudge_items = nudge_menu->items();
2312 nudge_menu->set_name ("ArdourContextMenu");
2314 edit_items.push_back (SeparatorElem());
2315 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2316 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2317 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2318 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2320 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2324 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2326 using namespace Menu_Helpers;
2330 Menu *play_menu = manage (new Menu);
2331 MenuList& play_items = play_menu->items();
2332 play_menu->set_name ("ArdourContextMenu");
2334 play_items.push_back (MenuElem (_("Play from edit cursor")));
2335 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2336 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2340 Menu *select_menu = manage (new Menu);
2341 MenuList& select_items = select_menu->items();
2342 select_menu->set_name ("ArdourContextMenu");
2344 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2345 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2346 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2347 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2348 select_items.push_back (SeparatorElem());
2349 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2350 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2351 select_items.push_back (SeparatorElem());
2353 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2357 Menu *cutnpaste_menu = manage (new Menu);
2358 MenuList& cutnpaste_items = cutnpaste_menu->items();
2359 cutnpaste_menu->set_name ("ArdourContextMenu");
2361 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2362 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2363 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2365 Menu *nudge_menu = manage (new Menu());
2366 MenuList& nudge_items = nudge_menu->items();
2367 nudge_menu->set_name ("ArdourContextMenu");
2369 edit_items.push_back (SeparatorElem());
2370 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2371 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2372 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2373 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2375 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2378 /* CURSOR SETTING AND MARKS AND STUFF */
2381 Editor::set_snap_to (SnapType st)
2384 vector<string> txt = internationalize (snap_type_strings);
2385 snap_type_selector.set_active_text (txt[(int)st]);
2389 switch (snap_type) {
2390 case SnapToAThirtysecondBeat:
2391 case SnapToASixteenthBeat:
2392 case SnapToAEighthBeat:
2393 case SnapToAQuarterBeat:
2394 case SnapToAThirdBeat:
2395 update_tempo_based_rulers ();
2403 Editor::set_snap_mode (SnapMode mode)
2406 vector<string> txt = internationalize (snap_mode_strings);
2407 snap_mode_selector.set_active_text (txt[(int)mode]);
2413 Editor::add_location_from_selection ()
2415 if (selection->time.empty()) {
2419 if (session == 0 || clicked_trackview == 0) {
2423 jack_nframes_t start = selection->time[clicked_selection].start;
2424 jack_nframes_t end = selection->time[clicked_selection].end;
2426 Location *location = new Location (start, end, "selection");
2428 session->begin_reversible_command (_("add marker"));
2429 session->add_undo (session->locations()->get_memento());
2430 session->locations()->add (location, true);
2431 session->add_redo_no_execute (session->locations()->get_memento());
2432 session->commit_reversible_command ();
2436 Editor::add_location_from_playhead_cursor ()
2438 jack_nframes_t where = session->audible_frame();
2440 Location *location = new Location (where, where, "mark", Location::IsMark);
2441 session->begin_reversible_command (_("add marker"));
2442 session->add_undo (session->locations()->get_memento());
2443 session->locations()->add (location, true);
2444 session->add_redo_no_execute (session->locations()->get_memento());
2445 session->commit_reversible_command ();
2450 Editor::set_state (const XMLNode& node)
2452 const XMLProperty* prop;
2454 int x, y, width, height, xoff, yoff;
2456 if ((geometry = find_named_node (node, "geometry")) == 0) {
2458 width = default_width;
2459 height = default_height;
2467 width = atoi(geometry->property("x_size")->value());
2468 height = atoi(geometry->property("y_size")->value());
2469 x = atoi(geometry->property("x_pos")->value());
2470 y = atoi(geometry->property("y_pos")->value());
2471 xoff = atoi(geometry->property("x_off")->value());
2472 yoff = atoi(geometry->property("y_off")->value());
2475 set_default_size(width, height);
2477 // set_position(x, y-yoff);
2479 if ((prop = node.property ("zoom-focus"))) {
2480 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2483 if ((prop = node.property ("zoom"))) {
2484 set_frames_per_unit (atof (prop->value()));
2487 if ((prop = node.property ("snap-to"))) {
2488 set_snap_to ((SnapType) atoi (prop->value()));
2491 if ((prop = node.property ("snap-mode"))) {
2492 set_snap_mode ((SnapMode) atoi (prop->value()));
2495 if ((prop = node.property ("show-waveforms"))) {
2496 bool yn = (prop->value() == "yes");
2497 _show_waveforms = !yn;
2498 set_show_waveforms (yn);
2501 if ((prop = node.property ("show-waveforms-recording"))) {
2502 bool yn = (prop->value() == "yes");
2503 _show_waveforms_recording = !yn;
2504 set_show_waveforms_recording (yn);
2507 if ((prop = node.property ("show-measures"))) {
2508 bool yn = (prop->value() == "yes");
2509 _show_measures = !yn;
2510 set_show_measures (yn);
2513 if ((prop = node.property ("follow-playhead"))) {
2514 bool yn = (prop->value() == "yes");
2515 _follow_playhead = !yn;
2516 set_follow_playhead (yn);
2519 if ((prop = node.property ("xfades-visible"))) {
2520 bool yn = (prop->value() == "yes");
2521 _xfade_visibility = !yn;
2522 set_xfade_visibility (yn);
2525 if ((prop = node.property ("region-list-sort-type"))) {
2526 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2527 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2530 if ((prop = node.property ("mouse-mode"))) {
2531 MouseMode m = str2mousemode(prop->value());
2532 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2533 set_mouse_mode (m, true);
2535 mouse_mode = MouseGain; /* lie, to force the mode switch */
2536 set_mouse_mode (MouseObject, true);
2539 if ((prop = node.property ("editor-mixer-button"))) {
2540 editor_mixer_button.set_active(prop->value() == "yes");
2547 Editor::get_state ()
2549 XMLNode* node = new XMLNode ("Editor");
2552 if (is_realized()) {
2553 Glib::RefPtr<Gdk::Window> win = get_window();
2555 int x, y, xoff, yoff, width, height;
2556 win->get_root_origin(x, y);
2557 win->get_position(xoff, yoff);
2558 win->get_size(width, height);
2560 XMLNode* geometry = new XMLNode ("geometry");
2562 snprintf(buf, sizeof(buf), "%d", width);
2563 geometry->add_property("x_size", string(buf));
2564 snprintf(buf, sizeof(buf), "%d", height);
2565 geometry->add_property("y_size", string(buf));
2566 snprintf(buf, sizeof(buf), "%d", x);
2567 geometry->add_property("x_pos", string(buf));
2568 snprintf(buf, sizeof(buf), "%d", y);
2569 geometry->add_property("y_pos", string(buf));
2570 snprintf(buf, sizeof(buf), "%d", xoff);
2571 geometry->add_property("x_off", string(buf));
2572 snprintf(buf, sizeof(buf), "%d", yoff);
2573 geometry->add_property("y_off", string(buf));
2574 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gobj()));
2575 geometry->add_property("canvas_region_list_pane_pos", string(buf));
2576 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gobj()));
2577 geometry->add_property("track_list_canvas_pane_pos", string(buf));
2578 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(®ion_selection_vpane)->gobj()));
2579 geometry->add_property("region_selection_pane_pos", string(buf));
2580 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gobj()));
2581 geometry->add_property("route_group_pane_pos", string(buf));
2583 node->add_child_nocopy (*geometry);
2586 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2587 node->add_property ("zoom-focus", buf);
2588 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2589 node->add_property ("zoom", buf);
2590 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2591 node->add_property ("snap-to", buf);
2592 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2593 node->add_property ("snap-mode", buf);
2595 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2596 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2597 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2598 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2599 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2600 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2601 node->add_property ("mouse-mode", enum2str(mouse_mode));
2602 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2610 Editor::trackview_by_y_position (double y)
2612 TrackViewList::iterator iter;
2615 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2623 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2632 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2634 Location* before = 0;
2635 Location* after = 0;
2641 const jack_nframes_t one_second = session->frame_rate();
2642 const jack_nframes_t one_minute = session->frame_rate() * 60;
2644 jack_nframes_t presnap = start;
2646 switch (snap_type) {
2652 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2654 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2657 case SnapToSMPTEFrame:
2659 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2661 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2665 case SnapToSMPTESeconds:
2666 if (session->smpte_offset_negative())
2668 start += session->smpte_offset ();
2670 start -= session->smpte_offset ();
2672 if (direction > 0) {
2673 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2675 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2678 if (session->smpte_offset_negative())
2680 start -= session->smpte_offset ();
2682 start += session->smpte_offset ();
2686 case SnapToSMPTEMinutes:
2687 if (session->smpte_offset_negative())
2689 start += session->smpte_offset ();
2691 start -= session->smpte_offset ();
2694 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2696 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2698 if (session->smpte_offset_negative())
2700 start -= session->smpte_offset ();
2702 start += session->smpte_offset ();
2708 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2710 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2716 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2718 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2723 start = session->tempo_map().round_to_bar (start, direction);
2727 start = session->tempo_map().round_to_beat (start, direction);
2730 case SnapToAThirtysecondBeat:
2731 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2734 case SnapToASixteenthBeat:
2735 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2738 case SnapToAEighthBeat:
2739 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2742 case SnapToAQuarterBeat:
2743 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2746 case SnapToAThirdBeat:
2747 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2750 case SnapToEditCursor:
2751 start = edit_cursor->current_frame;
2759 before = session->locations()->first_location_before (start);
2760 after = session->locations()->first_location_after (start);
2762 if (direction < 0) {
2764 start = before->start();
2768 } else if (direction > 0) {
2770 start = after->start();
2772 start = session->current_end_frame();
2777 /* find nearest of the two */
2778 if ((start - before->start()) < (after->start() - start)) {
2779 start = before->start();
2781 start = after->start();
2784 start = before->start();
2787 start = after->start();
2794 case SnapToRegionStart:
2795 case SnapToRegionEnd:
2796 case SnapToRegionSync:
2797 case SnapToRegionBoundary:
2798 if (!region_boundary_cache.empty()) {
2799 vector<jack_nframes_t>::iterator i;
2801 if (direction > 0) {
2802 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2804 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2807 if (i != region_boundary_cache.end()) {
2810 start = region_boundary_cache.back();
2816 switch (snap_mode) {
2822 if (presnap > start) {
2823 if (presnap > (start + unit_to_frame(snap_threshold))) {
2827 } else if (presnap < start) {
2828 if (presnap < (start - unit_to_frame(snap_threshold))) {
2840 Editor::setup_toolbar ()
2843 vector<ToggleButton *> mouse_mode_buttons;
2845 mouse_mode_buttons.push_back (&mouse_move_button);
2846 mouse_mode_buttons.push_back (&mouse_select_button);
2847 mouse_mode_buttons.push_back (&mouse_gain_button);
2848 mouse_mode_buttons.push_back (&mouse_zoom_button);
2849 mouse_mode_buttons.push_back (&mouse_timefx_button);
2850 mouse_mode_buttons.push_back (&mouse_audition_button);
2851 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2853 mouse_mode_button_table.set_homogeneous (true);
2854 mouse_mode_button_table.set_col_spacings (2);
2855 mouse_mode_button_table.set_row_spacings (2);
2856 mouse_mode_button_table.set_border_width (5);
2858 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2859 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2860 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2862 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2863 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2864 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2866 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2867 mouse_mode_tearoff->set_name ("MouseModeBase");
2869 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2870 mouse_mode_tearoff->tearoff_window()));
2871 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2872 mouse_mode_tearoff->tearoff_window(), 1));
2874 mouse_move_button.set_name ("MouseModeButton");
2875 mouse_select_button.set_name ("MouseModeButton");
2876 mouse_gain_button.set_name ("MouseModeButton");
2877 mouse_zoom_button.set_name ("MouseModeButton");
2878 mouse_timefx_button.set_name ("MouseModeButton");
2879 mouse_audition_button.set_name ("MouseModeButton");
2881 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2882 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2883 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2884 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2885 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2886 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2888 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2889 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2890 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2891 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2892 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2893 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2895 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2896 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2898 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2899 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2900 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2901 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2902 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2904 // mouse_move_button.set_active (true);
2906 /* automation control */
2908 global_automation_button.set_name ("MouseModeButton");
2909 automation_mode_button.set_name ("MouseModeButton");
2911 automation_box.set_spacing (2);
2912 automation_box.set_border_width (2);
2913 automation_box.pack_start (global_automation_button, false, false);
2914 automation_box.pack_start (automation_mode_button, false, false);
2918 edit_mode_label.set_name ("ToolBarLabel");
2920 edit_mode_selector.set_name ("EditModeSelector");
2922 edit_mode_box.set_spacing (3);
2923 edit_mode_box.set_border_width (3);
2925 /* XXX another disgusting hack because of the way combo boxes size themselves */
2927 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2, 10);
2928 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2929 edit_mode_box.pack_start (edit_mode_label, false, false);
2930 edit_mode_box.pack_start (edit_mode_selector, false, false);
2932 edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2936 snap_type_label.set_name ("ToolBarLabel");
2938 snap_type_selector.set_name ("SnapTypeSelector");
2940 snap_type_box.set_spacing (3);
2941 snap_type_box.set_border_width (3);
2943 /* XXX another disgusting hack because of the way combo boxes size themselves */
2945 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2946 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "Region bounds", 2+FUDGE, 10);
2947 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2949 snap_type_box.pack_start (snap_type_label, false, false);
2950 snap_type_box.pack_start (snap_type_selector, false, false);
2952 snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2954 /* Snap mode, not snap type */
2956 snap_mode_label.set_name ("ToolBarLabel");
2958 snap_mode_selector.set_name ("SnapModeSelector");
2960 snap_mode_box.set_spacing (3);
2961 snap_mode_box.set_border_width (3);
2963 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2, 10);
2964 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2966 snap_mode_box.pack_start (snap_mode_label, false, false);
2967 snap_mode_box.pack_start (snap_mode_selector, false, false);
2969 snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2971 /* Zoom focus mode */
2973 zoom_focus_label.set_name ("ToolBarLabel");
2975 zoom_focus_selector.set_name ("ZoomFocusSelector");
2977 zoom_focus_box.set_spacing (3);
2978 zoom_focus_box.set_border_width (3);
2980 /* XXX another disgusting hack because of the way combo boxes size themselves */
2982 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2, 10);
2983 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
2985 zoom_focus_box.pack_start (zoom_focus_label, false, false);
2986 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
2988 zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
2990 /* selection/cursor clocks */
2992 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
2993 selection_start_clock_label.set_name ("ToolBarLabel");
2994 selection_end_clock_label.set_name ("ToolBarLabel");
2995 edit_cursor_clock_label.set_name ("ToolBarLabel");
2997 selection_start_clock_label.set_text (_("Start:"));
2998 selection_end_clock_label.set_text (_("End:"));
2999 edit_cursor_clock_label.set_text (_("Edit:"));
3001 toolbar_selection_clock_table.set_border_width (5);
3002 toolbar_selection_clock_table.set_col_spacings (2);
3003 toolbar_selection_clock_table.set_homogeneous (false);
3005 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
3006 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
3007 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
3009 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
3010 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
3011 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
3014 // toolbar_clock_vbox.set_spacing (2);
3015 // toolbar_clock_vbox.set_border_width (10);
3016 /* the editor/mixer button will be enabled at session connect */
3018 editor_mixer_button.set_active(false);
3019 editor_mixer_button.set_sensitive(false);
3021 HBox* hbox = new HBox;
3023 hbox->pack_start (editor_mixer_button, false, false);
3024 hbox->pack_start (toolbar_selection_clock_table, false, false);
3025 hbox->pack_start (zoom_indicator_vbox, false, false);
3026 hbox->pack_start (zoom_focus_box, false, false);
3027 hbox->pack_start (snap_type_box, false, false);
3028 hbox->pack_start (snap_mode_box, false, false);
3029 hbox->pack_start (edit_mode_box, false, false);
3031 VBox *vbox = manage (new VBox);
3033 vbox->set_spacing (3);
3034 vbox->set_border_width (3);
3036 HBox *nbox = manage (new HBox);
3038 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
3039 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
3041 nbox->pack_start (nudge_backward_button, false, false);
3042 nbox->pack_start (nudge_forward_button, false, false);
3043 nbox->pack_start (nudge_clock, false, false, 5);
3045 nudge_label.set_name ("ToolBarLabel");
3047 vbox->pack_start (nudge_label, false, false);
3048 vbox->pack_start (*nbox, false, false);
3050 hbox->pack_start (*vbox, false, false);
3054 tools_tearoff = new TearOff (*hbox);
3055 tools_tearoff->set_name ("MouseModeBase");
3057 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
3058 tools_tearoff->tearoff_window()));
3059 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
3060 tools_tearoff->tearoff_window(), 0));
3063 toolbar_hbox.set_spacing (8);
3064 toolbar_hbox.set_border_width (2);
3066 toolbar_hbox.pack_start (*tools_tearoff, false, false);
3067 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
3069 toolbar_base.set_name ("ToolBarBase");
3070 toolbar_base.add (toolbar_hbox);
3072 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
3073 toolbar_frame.set_name ("BaseFrame");
3074 toolbar_frame.add (toolbar_base);
3078 Editor::_autoscroll_canvas (void *arg)
3080 return ((Editor *) arg)->autoscroll_canvas ();
3084 Editor::autoscroll_canvas ()
3086 jack_nframes_t new_frame;
3087 bool keep_calling = true;
3089 if (autoscroll_direction < 0) {
3090 if (leftmost_frame < autoscroll_distance) {
3093 new_frame = leftmost_frame - autoscroll_distance;
3096 if (leftmost_frame > max_frames - autoscroll_distance) {
3097 new_frame = max_frames;
3099 new_frame = leftmost_frame + autoscroll_distance;
3103 if (new_frame != leftmost_frame) {
3104 reposition_x_origin (new_frame);
3107 if (new_frame == 0 || new_frame == max_frames) {
3114 if (autoscroll_cnt == 1) {
3116 /* connect the timeout so that we get called repeatedly */
3118 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
3119 keep_calling = false;
3121 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
3123 /* after about a while, speed up a bit by changing the timeout interval */
3125 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
3126 keep_calling = false;
3128 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
3130 /* after about another while, speed up some more */
3132 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
3133 keep_calling = false;
3135 } else if (autoscroll_cnt >= 30) {
3137 /* we've been scrolling for a while ... crank it up */
3139 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
3142 return keep_calling;
3146 Editor::start_canvas_autoscroll (int dir)
3152 stop_canvas_autoscroll ();
3154 autoscroll_direction = dir;
3155 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
3158 /* do it right now, which will start the repeated callbacks */
3160 autoscroll_canvas ();
3164 Editor::stop_canvas_autoscroll ()
3166 if (autoscroll_timeout_tag >= 0) {
3167 gtk_timeout_remove (autoscroll_timeout_tag);
3168 autoscroll_timeout_tag = -1;
3173 Editor::convert_drop_to_paths (vector<string>& paths,
3174 GdkDragContext *context,
3177 GtkSelectionData *data,
3185 gchar *tname = gdk_atom_name (data->type);
3187 if (session == 0 || strcmp (tname, "text/plain") != 0) {
3191 /* Parse the "uri-list" format that Nautilus provides,
3192 where each pathname is delimited by \r\n
3195 path = (char *) data->data;
3198 for (int n = 0; n < data->length; ++n) {
3202 if (path[n] == '\r') {
3209 if (path[n] == '\n') {
3210 paths.push_back (spath);
3214 warning << _("incorrectly formatted URI list, ignored")
3222 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
3224 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3226 // cerr << "dropped text was " << *p << endl;
3230 // cerr << "decoded was " << *p << endl;
3232 if ((*p).substr (0,7) == "file://") {
3233 (*p) = (*p).substr (7);
3241 Editor::track_canvas_drag_data_received (GdkDragContext *context,
3244 GtkSelectionData *data,
3249 AudioTimeAxisView* tv;
3251 vector<string> paths;
3254 jack_nframes_t frame;
3256 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
3260 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
3266 track_canvas.c2w( x, y, wx, wy);
3268 ev.type = GDK_BUTTON_RELEASE;
3272 frame = event_frame (&ev, 0, &cy);
3276 if ((tvp = trackview_by_y_position (cy)) == 0) {
3278 /* drop onto canvas background: create a new track */
3280 insert_paths_as_new_tracks (paths, false);
3283 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
3285 /* check that its an audio track, not a bus */
3287 if (tv->get_diskstream()) {
3289 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3290 insert_sndfile_into (*p, true, tv, frame);
3297 gtk_drag_finish (context, TRUE, FALSE, time);
3301 Editor::new_tempo_section ()
3307 Editor::map_transport_state ()
3309 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3311 if (session->transport_stopped()) {
3312 have_pending_keyboard_selection = false;
3318 Editor::State::State ()
3320 selection = new Selection;
3323 Editor::State::~State ()
3329 Editor::get_memento () const
3331 State *state = new State;
3333 store_state (*state);
3334 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3338 Editor::store_state (State& state) const
3340 *state.selection = *selection;
3344 Editor::restore_state (State *state)
3346 if (*selection == *state->selection) {
3350 *selection = *state->selection;
3351 time_selection_changed ();
3352 region_selection_changed ();
3354 /* XXX other selection change handlers? */
3358 Editor::begin_reversible_command (string name)
3361 UndoAction ua = get_memento();
3362 session->begin_reversible_command (name, &ua);
3367 Editor::commit_reversible_command ()
3370 UndoAction ua = get_memento();
3371 session->commit_reversible_command (&ua);
3376 Editor::flush_track_canvas ()
3378 /* I don't think this is necessary, and only causes more problems.
3379 I'm commenting it out
3380 and if the imageframe folks don't have any issues, we can take
3381 out this method entirely
3384 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
3385 //gtk_main_iteration ();
3389 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3391 if (!clicked_trackview) {
3396 begin_reversible_command (_("set selected trackview"));
3401 if (selection->selected (clicked_trackview)) {
3403 selection->remove (clicked_trackview);
3406 selection->add (clicked_trackview);
3411 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3412 /* no commit necessary */
3416 selection->set (clicked_trackview);
3420 commit_reversible_command ();
3425 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3427 if (!clicked_control_point) {
3432 begin_reversible_command (_("set selected control point"));
3442 commit_reversible_command ();
3447 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3449 if (!clicked_regionview) {
3453 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3459 RouteGroup* group = atv->route().edit_group();
3460 vector<AudioRegionView*> all_equivalent_regions;
3462 if (group && group->is_active()) {
3464 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3466 AudioTimeAxisView* tatv;
3468 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3470 if (tatv->route().edit_group() != group) {
3475 vector<AudioRegion*> results;
3476 AudioRegionView* marv;
3479 if ((ds = tatv->get_diskstream()) == 0) {
3484 if ((pl = ds->playlist()) != 0) {
3485 pl->get_equivalent_regions (clicked_regionview->region,
3489 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3490 if ((marv = tatv->view->find_view (**ir)) != 0) {
3491 all_equivalent_regions.push_back (marv);
3500 all_equivalent_regions.push_back (clicked_regionview);
3504 begin_reversible_command (_("set selected regionview"));
3508 if (clicked_regionview->get_selected()) {
3509 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3510 /* reduce selection down to just the one clicked */
3511 selection->set (clicked_regionview);
3513 selection->remove (clicked_regionview);
3516 selection->add (all_equivalent_regions);
3519 set_selected_track_from_click (add, false, no_track_remove);
3523 // karsten wiese suggested these two lines to make
3524 // a selected region rise to the top. but this
3525 // leads to a mismatch between actual layering
3526 // and visual layering. resolution required ....
3528 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3529 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3531 if (clicked_regionview->get_selected()) {
3532 /* no commit necessary: we are the one selected. */
3537 selection->set (all_equivalent_regions);
3538 set_selected_track_from_click (add, false, false);
3542 commit_reversible_command () ;
3546 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3548 vector<AudioRegionView*> all_equivalent_regions;
3549 AudioRegion* region;
3551 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3555 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3557 AudioTimeAxisView* tatv;
3559 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3562 vector<AudioRegion*> results;
3563 AudioRegionView* marv;
3566 if ((ds = tatv->get_diskstream()) == 0) {
3571 if ((pl = ds->playlist()) != 0) {
3572 pl->get_region_list_equivalent_regions (*region, results);
3575 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3576 if ((marv = tatv->view->find_view (**ir)) != 0) {
3577 all_equivalent_regions.push_back (marv);
3584 begin_reversible_command (_("set selected regions"));
3588 selection->add (all_equivalent_regions);
3592 selection->set (all_equivalent_regions);
3595 commit_reversible_command () ;
3599 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3601 AudioRegionView* rv;
3604 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3608 if ((rv = sv->find_view (*ar)) == 0) {
3612 /* don't reset the selection if its something other than
3613 a single other region.
3616 if (selection->audio_regions.size() > 1) {
3620 begin_reversible_command (_("set selected regions"));
3622 selection->set (rv);
3624 commit_reversible_command () ;
3630 Editor::set_edit_group_solo (Route& route, bool yn)
3632 RouteGroup *edit_group;
3634 if ((edit_group = route.edit_group()) != 0) {
3635 edit_group->apply (&Route::set_solo, yn, this);
3637 route.set_solo (yn, this);
3642 Editor::set_edit_group_mute (Route& route, bool yn)
3644 RouteGroup *edit_group = 0;
3646 if ((edit_group == route.edit_group()) != 0) {
3647 edit_group->apply (&Route::set_mute, yn, this);
3649 route.set_mute (yn, this);
3654 Editor::set_edit_menu (Menu& menu)
3657 edit_menu->signal_map_event().connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3661 Editor::edit_menu_map_handler (GdkEventAny* ev)
3663 using namespace Menu_Helpers;
3664 MenuList& edit_items = edit_menu->items();
3667 /* Nuke all the old items */
3669 edit_items.clear ();
3675 if (session->undo_depth() == 0) {
3678 label = string_compose(_("Undo (%1)"), session->next_undo());
3681 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3683 if (session->undo_depth() == 0) {
3684 edit_items.back().set_sensitive (false);
3687 if (session->redo_depth() == 0) {
3690 label = string_compose(_("Redo (%1)"), session->next_redo());
3693 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3694 if (session->redo_depth() == 0) {
3695 edit_items.back().set_sensitive (false);
3698 vector<MenuItem*> mitems;
3700 edit_items.push_back (SeparatorElem());
3701 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3702 mitems.push_back (&edit_items.back());
3703 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3704 mitems.push_back (&edit_items.back());
3705 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3706 mitems.push_back (&edit_items.back());
3707 edit_items.push_back (SeparatorElem());
3708 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3709 mitems.push_back (&edit_items.back());
3710 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3711 mitems.push_back (&edit_items.back());
3712 edit_items.push_back (SeparatorElem());
3714 if (selection->empty()) {
3715 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3716 (*i)->set_sensitive (false);
3720 Menu* import_menu = manage (new Menu());
3721 import_menu->set_name ("ArdourContextMenu");
3722 MenuList& import_items = import_menu->items();
3724 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3725 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3727 Menu* embed_menu = manage (new Menu());
3728 embed_menu->set_name ("ArdourContextMenu");
3729 MenuList& embed_items = embed_menu->items();
3731 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3732 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3734 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3735 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3736 edit_items.push_back (SeparatorElem());
3738 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3739 if (!session->have_captured()) {
3740 edit_items.back().set_sensitive (false);
3747 Editor::duplicate_dialog (bool dup_region)
3750 if (clicked_regionview == 0) {
3754 if (selection->time.length() == 0) {
3759 ArdourDialog win ("duplicate dialog");
3761 Label label (_("Duplicate how many times?"));
3763 win.get_vbox()->pack_start (label);
3764 win.add_action_widget (entry, RESPONSE_ACCEPT);
3765 win.add_button (Stock::OK, RESPONSE_ACCEPT);
3766 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3768 win.set_position (Gtk::WIN_POS_MOUSE);
3770 entry.set_text ("1");
3771 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3772 entry.select_region (0, entry.get_text_length());
3773 entry.grab_focus ();
3776 // win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3779 switch (win.run ()) {
3780 case RESPONSE_ACCEPT:
3786 string text = entry.get_text();
3789 if (sscanf (text.c_str(), "%f", ×) == 1) {
3791 AudioRegionSelection regions;
3792 regions.add (clicked_regionview);
3793 duplicate_some_regions (regions, times);
3795 duplicate_selection (times);
3801 Editor::show_verbose_canvas_cursor ()
3803 verbose_canvas_cursor->raise_to_top();
3804 verbose_canvas_cursor->show();
3805 verbose_cursor_visible = true;
3809 Editor::hide_verbose_canvas_cursor ()
3811 verbose_canvas_cursor->hide();
3812 verbose_cursor_visible = false;
3816 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3818 /* XXX get origin of canvas relative to root window,
3819 add x and y and check compared to gdk_screen_{width,height}
3821 verbose_canvas_cursor->set_property("text", txt.c_str());
3822 verbose_canvas_cursor->set_property("x", x);
3823 verbose_canvas_cursor->set_property("y", y);
3827 Editor::set_verbose_canvas_cursor_text (string txt)
3829 verbose_canvas_cursor->set_property("text", txt.c_str());
3833 Editor::edit_mode_selection_done ()
3839 string choice = edit_mode_selector.get_active_text();
3840 EditMode mode = Slide;
3842 if (choice == _("Splice")) {
3844 } else if (choice == _("Slide")) {
3848 session->set_edit_mode (mode);
3852 Editor::snap_type_selection_done ()
3858 string choice = snap_type_selector.get_active_text();
3859 SnapType snaptype = SnapToFrame;
3861 if (choice == _("Beats/3")) {
3862 snaptype = SnapToAThirdBeat;
3863 } else if (choice == _("Beats/4")) {
3864 snaptype = SnapToAQuarterBeat;
3865 } else if (choice == _("Beats/8")) {
3866 snaptype = SnapToAEighthBeat;
3867 } else if (choice == _("Beats/16")) {
3868 snaptype = SnapToASixteenthBeat;
3869 } else if (choice == _("Beats/32")) {
3870 snaptype = SnapToAThirtysecondBeat;
3871 } else if (choice == _("Beats")) {
3872 snaptype = SnapToBeat;
3873 } else if (choice == _("Bars")) {
3874 snaptype = SnapToBar;
3875 } else if (choice == _("Marks")) {
3876 snaptype = SnapToMark;
3877 } else if (choice == _("Edit Cursor")) {
3878 snaptype = SnapToEditCursor;
3879 } else if (choice == _("Region starts")) {
3880 snaptype = SnapToRegionStart;
3881 } else if (choice == _("Region ends")) {
3882 snaptype = SnapToRegionEnd;
3883 } else if (choice == _("Region bounds")) {
3884 snaptype = SnapToRegionBoundary;
3885 } else if (choice == _("Region syncs")) {
3886 snaptype = SnapToRegionSync;
3887 } else if (choice == _("CD Frames")) {
3888 snaptype = SnapToCDFrame;
3889 } else if (choice == _("SMPTE Frames")) {
3890 snaptype = SnapToSMPTEFrame;
3891 } else if (choice == _("SMPTE Seconds")) {
3892 snaptype = SnapToSMPTESeconds;
3893 } else if (choice == _("SMPTE Minutes")) {
3894 snaptype = SnapToSMPTEMinutes;
3895 } else if (choice == _("Seconds")) {
3896 snaptype = SnapToSeconds;
3897 } else if (choice == _("Minutes")) {
3898 snaptype = SnapToMinutes;
3899 } else if (choice == _("None")) {
3900 snaptype = SnapToFrame;
3903 set_snap_to (snaptype);
3907 Editor::snap_mode_selection_done ()
3913 string choice = snap_mode_selector.get_active_text();
3914 SnapMode mode = SnapNormal;
3916 if (choice == _("Normal")) {
3918 } else if (choice == _("Magnetic")) {
3919 mode = SnapMagnetic;
3922 set_snap_mode (mode);
3926 Editor::zoom_focus_selection_done ()
3932 string choice = zoom_focus_selector.get_active_text();
3933 ZoomFocus focus_type = ZoomFocusLeft;
3935 if (choice == _("Left")) {
3936 focus_type = ZoomFocusLeft;
3937 } else if (choice == _("Right")) {
3938 focus_type = ZoomFocusRight;
3939 } else if (choice == _("Center")) {
3940 focus_type = ZoomFocusCenter;
3941 } else if (choice == _("Playhead")) {
3942 focus_type = ZoomFocusPlayhead;
3943 } else if (choice == _("Edit Cursor")) {
3944 focus_type = ZoomFocusEdit;
3947 set_zoom_focus (focus_type);
3951 Editor::edit_controls_button_release (GdkEventButton* ev)
3953 if (Keyboard::is_context_menu_event (ev)) {
3954 ARDOUR_UI::instance()->add_route ();
3960 Editor::track_selection_changed ()
3962 switch (selection->tracks.size()){
3966 set_selected_mixer_strip (*(selection->tracks.front()));
3970 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3971 (*i)->set_selected (false);
3972 if (mouse_mode == MouseRange) {
3973 (*i)->hide_selection ();
3977 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3978 (*i)->set_selected (true);
3979 if (mouse_mode == MouseRange) {
3980 (*i)->show_selection (selection->time);
3986 Editor::time_selection_changed ()
3988 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3989 (*i)->hide_selection ();
3992 if (selection->tracks.empty()) {
3993 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3994 (*i)->show_selection (selection->time);
3997 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3998 (*i)->show_selection (selection->time);
4004 Editor::region_selection_changed ()
4006 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4007 (*i)->set_selected_regionviews (selection->audio_regions);
4012 Editor::point_selection_changed ()
4014 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4015 (*i)->set_selected_points (selection->points);
4020 Editor::run_sub_event_loop ()
4022 sub_event_loop_status = 0;
4027 Editor::finish_sub_event_loop (int status)
4030 sub_event_loop_status = status;
4034 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
4036 finish_sub_event_loop (status);
4041 Editor::mouse_select_button_release (GdkEventButton* ev)
4043 /* this handles just right-clicks */
4045 if (ev->button != 3) {
4052 Editor::TrackViewList *
4053 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
4056 TrackViewList::iterator i;
4058 v = new TrackViewList;
4060 if (track == 0 && group == 0) {
4064 for (i = track_views.begin(); i != track_views.end (); ++i) {
4068 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
4070 /* just the view for this track
4073 v->push_back (track);
4077 /* views for all tracks in the edit group */
4079 for (i = track_views.begin(); i != track_views.end (); ++i) {
4081 if (group == 0 || (*i)->edit_group() == group) {
4091 Editor::set_zoom_focus (ZoomFocus f)
4093 if (zoom_focus != f) {
4095 vector<string> txt = internationalize (zoom_focus_strings);
4096 zoom_focus_selector.set_active_text (txt[(int)f]);
4097 ZoomFocusChanged (); /* EMIT_SIGNAL */
4104 Editor::ensure_float (Window& win)
4106 win.set_transient_for (*this);
4110 Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which)
4112 /* recover or initialize pane positions. do this here rather than earlier because
4113 we don't want the positions to change the child allocations, which they seem to do.
4119 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
4121 static int32_t done[4] = { 0, 0, 0, 0 };
4124 if ((geometry = find_named_node (*node, "geometry")) == 0) {
4125 width = default_width;
4126 height = default_height;
4128 width = atoi(geometry->property("x_size")->value());
4129 height = atoi(geometry->property("y_size")->value());
4132 if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
4138 if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
4140 snprintf (buf, sizeof(buf), "%d", pos);
4142 pos = atoi (prop->value());
4145 if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gobj())->allocation.width > pos)) {
4146 track_list_canvas_pane.set_position (pos);
4149 } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
4155 if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
4156 pos = width - (95 * 2);
4157 snprintf (buf, sizeof(buf), "%d", pos);
4159 pos = atoi (prop->value());
4162 if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gobj())->allocation.width > pos)) {
4163 canvas_region_list_pane.set_position (pos);
4166 } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
4172 if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
4173 pos = width - (95 * 2);
4174 snprintf (buf, sizeof(buf), "%d", pos);
4176 pos = atoi (prop->value());
4179 if ((done[2] = GTK_WIDGET(route_group_vpane.gobj())->allocation.height > pos)) {
4180 route_group_vpane.set_position (pos);
4183 } else if (which == static_cast<Gtk::Paned*> (®ion_selection_vpane)) {
4189 if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
4190 pos = width - (95 * 2);
4191 snprintf (buf, sizeof(buf), "%d", pos);
4193 pos = atoi (prop->value());
4196 if ((done[3] = GTK_WIDGET(region_selection_vpane.gobj())->allocation.height > pos)) {
4197 region_selection_vpane.set_position (pos);
4203 Editor::detach_tearoff (Gtk::Box* b, Gtk::Window* w)
4205 if (tools_tearoff->torn_off() &&
4206 mouse_mode_tearoff->torn_off()) {
4207 top_hbox.remove (toolbar_frame);
4214 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Window* w, int32_t n)
4216 if (toolbar_frame.get_parent() == 0) {
4217 top_hbox.pack_end (toolbar_frame);
4222 Editor::set_show_measures (bool yn)
4224 if (_show_measures != yn) {
4227 if ((_show_measures = yn) == true) {
4230 DisplayControlChanged (ShowMeasures);
4236 Editor::set_follow_playhead (bool yn)
4238 if (_follow_playhead != yn) {
4239 if ((_follow_playhead = yn) == true) {
4241 update_current_screen ();
4243 DisplayControlChanged (FollowPlayhead);
4249 Editor::toggle_xfade_active (Crossfade* xfade)
4251 xfade->set_active (!xfade->active());
4255 Editor::toggle_xfade_length (Crossfade* xfade)
4257 xfade->set_follow_overlap (!xfade->following_overlap());
4261 Editor::edit_xfade (Crossfade* xfade)
4263 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
4268 // cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
4270 switch (cew.run ()) {
4271 case RESPONSE_ACCEPT:
4278 xfade->StateChanged (Change (~0));
4282 Editor::playlist_selector () const
4284 return *_playlist_selector;
4288 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
4292 ret = nudge_clock.current_duration (pos);
4293 next = ret + 1; /* XXXX fix me */
4299 Editor::end_location_changed (Location* location)
4301 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
4302 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
4306 Editor::playlist_deletion_dialog (Playlist* pl)
4308 ArdourDialog dialog ("playlist deletion dialog");
4309 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4310 "If left alone, no audio files used by it will be cleaned.\n"
4311 "If deleted, audio files used by it alone by will cleaned."),
4314 dialog.set_position (Gtk::WIN_POS_CENTER);
4315 dialog.get_vbox()->pack_start (label);
4317 dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT);
4318 dialog.add_button (_("Keep playlist"), RESPONSE_CANCEL);
4319 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4321 switch (dialog.run ()) {
4322 case RESPONSE_ACCEPT:
4323 /* delete the playlist */
4327 case RESPONSE_REJECT:
4328 /* keep the playlist */
4340 Editor::audio_region_selection_covers (jack_nframes_t where)
4342 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
4343 if ((*a)->region.covers (where)) {
4352 Editor::prepare_for_cleanup ()
4354 cut_buffer->clear_audio_regions ();
4355 cut_buffer->clear_playlists ();
4357 selection->clear_audio_regions ();
4358 selection->clear_playlists ();
4362 Editor::init_colormap ()
4364 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
4365 pair<ColorID,int> newpair;
4367 newpair.first = (ColorID) x;
4368 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
4369 color_map.insert (newpair);
4374 Editor::transport_loop_location()
4377 return session->locations()->auto_loop_location();
4384 Editor::transport_punch_location()
4387 return session->locations()->auto_punch_location();