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->property_activatable() = true;
544 active_cell->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->property_font_desc() = font;
831 // verbose_canvas_cursor->property_anchor() = GTK_ANCHOR_NW;
832 verbose_canvas_cursor->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->property_fill_color_rgba() = color_map[cTempoBar];
852 tempo_bar->property_outline_pixels() = 0;
854 meter_bar = new ArdourCanvas::SimpleRect (*meter_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
855 meter_bar->property_fill_color_rgba() = color_map[cMeterBar];
856 meter_bar->property_outline_pixels() = 0;
858 marker_bar = new ArdourCanvas::SimpleRect (*marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
859 marker_bar->property_fill_color_rgba() = color_map[cMarkerBar];
860 marker_bar->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->property_fill_color_rgba() = color_map[cRangeMarkerBar];
864 range_marker_bar->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->property_fill_color_rgba() = color_map[cTransportMarkerBar];
868 transport_marker_bar->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->property_fill_color_rgba() = color_map[cRangeDragBarRectFill];
872 range_bar_drag_rect->property_outline_color_rgba() = color_map[cRangeDragBarRect];
873 range_bar_drag_rect->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 ->property_fill_color_rgba() = color_map[cTransportDragRectFill];
878 transport_bar_drag_rect->property_outline_color_rgba() = color_map[cTransportDragRect];
879 transport_bar_drag_rect->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->property_width_pixels() = 1;
887 marker_drag_line->property_fill_color_rgba() = color_map[cMarkerDragLine];
888 marker_drag_line->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->property_fill_color_rgba() = color_map[cRangeDragRectFill];
893 range_marker_drag_rect->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->property_fill_color_rgba() = color_map[cTransportLoopRectFill];
898 transport_loop_range_rect->property_outline_color_rgba() = color_map[cTransportLoopRect];
899 transport_loop_range_rect->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->property_fill_color_rgba() = color_map[cTransportPunchRectFill];
904 transport_punch_range_rect->property_outline_color_rgba() = color_map[cTransportPunchRect];
905 transport_punch_range_rect->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->property_x1() = 0.0;
912 transport_punchin_line->property_y1() = 0.0;
913 transport_punchin_line->property_x2() = 0.0;
914 transport_punchin_line->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->property_x1() = 0.0;
920 transport_punchout_line->property_y1() = 0.0;
921 transport_punchout_line->property_x2() = 0.0;
922 transport_punchout_line->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->property_fill_color_rgba() = color_map[cZoomRectFill];
929 zoom_rect->property_outline_color_rgba() = color_map[cZoomRect];
930 zoom_rect->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->property_outline_color_rgba() = color_map[cRubberBandRect];
938 rubberband_rect->property_fill_color_rgba() = (guint32) color_map[cRubberBandRectFill];
939 rubberband_rect->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->property_font_desc() = font;
1246 first_action_message->property_fill_color_rgba() = color_map[cFirstActionMessage];
1247 first_action_message->property_x() = (gdouble) (canvas_width - pixel_width) / 2.0;
1248 first_action_message->property_y() = (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height));
1249 first_action_message->property_anchor() = ANCHOR_NORTH_WEST;
1250 first_action_message->property_text() = ustring (txt);
1255 first_action_message->property_x() = (gdouble) (canvas_width - pixel_width) / 2.0;
1256 first_action_message->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->property_points() = marker_drag_line_points;
1330 if (range_marker_drag_rect) {
1331 range_marker_drag_rect->property_y1() = 0.0;
1332 range_marker_drag_rect->property_y2() = (double) canvas_height;
1335 if (transport_loop_range_rect) {
1336 transport_loop_range_rect->property_y1() = 0.0;
1337 transport_loop_range_rect->property_y2() = (double) canvas_height;
1340 if (transport_punch_range_rect) {
1341 transport_punch_range_rect->property_y1() = 0.0;
1342 transport_punch_range_rect->property_y2() = (double) canvas_height;
1345 if (transport_punchin_line) {
1346 transport_punchin_line->property_y1() = 0.0;
1347 transport_punchin_line->property_y2() = (double) canvas_height;
1350 if (transport_punchout_line) {
1351 transport_punchout_line->property_y1() = 0.0;
1352 transport_punchout_line->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 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1638 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1641 /* ::reposition_x_origin() doesn't work right here, since the old
1642 position may be zero already, and it does nothing in such
1648 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1649 track_canvas_scroller.get_hadjustment()->set_value (0);
1651 update_hscroller ();
1652 restore_ruler_visibility ();
1653 tempo_map_changed (Change (0));
1655 edit_cursor->set_position (0);
1656 playhead_cursor->set_position (0);
1660 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1663 /* don't show master bus in a new session */
1665 if (ARDOUR_UI::instance()->session_is_new ()) {
1667 TreeModel::Children rows = route_display_model->children();
1668 TreeModel::Children::iterator i;
1670 //route_list.freeze ();
1672 for (i = rows.begin(); i != rows.end(); ++i) {
1673 TimeAxisView *tv = (*i)[route_display_columns.tv];
1674 AudioTimeAxisView *atv;
1676 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1677 if (atv->route().master()) {
1678 route_list.get_selection()->unselect (i);
1679 //(*i)->unselect ();
1684 //route_list.thaw ();
1689 Editor::build_cursors ()
1691 using namespace Gdk;
1693 Gdk::Color fg ("#ff0000"); /* Red. */
1694 Gdk::Color bg ("#0000ff"); /* Blue. */
1697 RefPtr<Bitmap> source, mask;
1698 source = Bitmap::create (hand_bits, hand_width, hand_height);
1699 mask = Bitmap::create (handmask_bits, handmask_width, handmask_height);
1700 grabber_cursor = new Gdk::Cursor (source, mask, fg, bg, hand_x_hot, hand_y_hot);
1703 Gdk::Color mbg ("#000000" ); /* Black */
1704 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1707 RefPtr<Bitmap> source, mask;
1708 source = Bitmap::create (mag_bits, mag_width, mag_height);
1709 mask = Bitmap::create (magmask_bits, mag_width, mag_height);
1710 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1713 Gdk::Color fbg ("#ffffff" );
1714 Gdk::Color ffg ("#000000" );
1717 RefPtr<Bitmap> source, mask;
1719 source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
1720 mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
1721 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1725 RefPtr<Bitmap> source, mask;
1726 source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
1727 mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
1728 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1731 cross_hair_cursor = new Gdk::Cursor (Gdk::CROSSHAIR);
1732 trimmer_cursor = new Gdk::Cursor (Gdk::SB_H_DOUBLE_ARROW);
1733 selector_cursor = new Gdk::Cursor (Gdk::XTERM);
1734 time_fx_cursor = new Gdk::Cursor (Gdk::SIZING);
1735 wait_cursor = new Gdk::Cursor (Gdk::WATCH);
1736 timebar_cursor = new Gdk::Cursor(Gdk::LEFT_PTR);
1740 Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
1742 using namespace Menu_Helpers;
1743 AudioRegionView* arv = static_cast<AudioRegionView*> (gtk_object_get_data (GTK_OBJECT(item), "regionview"));
1746 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1750 MenuList& items (fade_context_menu.items());
1754 switch (item_type) {
1756 case FadeInHandleItem:
1757 if (arv->region.fade_in_active()) {
1758 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1760 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1763 items.push_back (SeparatorElem());
1765 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1766 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1767 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1768 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1769 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1773 case FadeOutHandleItem:
1774 if (arv->region.fade_out_active()) {
1775 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1777 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1780 items.push_back (SeparatorElem());
1782 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1783 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1784 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1785 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1786 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1790 fatal << _("programming error: ")
1791 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1796 fade_context_menu.popup (button, time);
1800 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1802 using namespace Menu_Helpers;
1803 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1806 switch (item_type) {
1808 case AudioRegionViewName:
1809 case AudioRegionViewNameHighlight:
1810 if (with_selection) {
1811 build_menu_function = &Editor::build_track_selection_context_menu;
1813 build_menu_function = &Editor::build_track_region_context_menu;
1818 if (with_selection) {
1819 build_menu_function = &Editor::build_track_selection_context_menu;
1821 build_menu_function = &Editor::build_track_context_menu;
1825 case CrossfadeViewItem:
1826 build_menu_function = &Editor::build_track_crossfade_context_menu;
1830 if (clicked_audio_trackview->get_diskstream()) {
1831 build_menu_function = &Editor::build_track_context_menu;
1833 build_menu_function = &Editor::build_track_bus_context_menu;
1838 /* probably shouldn't happen but if it does, we don't care */
1842 menu = (this->*build_menu_function)(frame);
1843 menu->set_name ("ArdourContextMenu");
1845 /* now handle specific situations */
1847 switch (item_type) {
1849 case AudioRegionViewName:
1850 case AudioRegionViewNameHighlight:
1851 if (!with_selection) {
1852 if (region_edit_menu_split_item) {
1853 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1854 // GTK2FIX find the action, change its sensitivity
1855 // region_edit_menu_split_item->set_sensitive (true);
1857 // GTK2FIX see above
1858 // region_edit_menu_split_item->set_sensitive (false);
1861 if (region_edit_menu_split_multichannel_item) {
1862 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1863 // GTK2FIX find the action, change its sensitivity
1864 // region_edit_menu_split_multichannel_item->set_sensitive (true);
1866 // GTK2FIX see above
1867 // region_edit_menu_split_multichannel_item->set_sensitive (false);
1876 case CrossfadeViewItem:
1883 /* probably shouldn't happen but if it does, we don't care */
1887 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1889 /* Bounce to disk */
1891 using namespace Menu_Helpers;
1892 MenuList& edit_items = menu->items();
1894 edit_items.push_back (SeparatorElem());
1896 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1897 case AudioTrack::NoFreeze:
1898 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1901 case AudioTrack::Frozen:
1902 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1905 case AudioTrack::UnFrozen:
1906 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1912 menu->popup (button, time);
1916 Editor::build_track_context_menu (jack_nframes_t ignored)
1918 using namespace Menu_Helpers;
1920 MenuList& edit_items = track_context_menu.items();
1923 add_dstream_context_items (edit_items);
1924 return &track_context_menu;
1928 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1930 using namespace Menu_Helpers;
1932 MenuList& edit_items = track_context_menu.items();
1935 add_bus_context_items (edit_items);
1936 return &track_context_menu;
1940 Editor::build_track_region_context_menu (jack_nframes_t frame)
1942 using namespace Menu_Helpers;
1943 MenuList& edit_items = track_region_context_menu.items();
1946 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1952 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1953 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1954 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1955 add_region_context_items (atv->view, (*i), edit_items);
1961 add_dstream_context_items (edit_items);
1963 return &track_region_context_menu;
1967 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1969 using namespace Menu_Helpers;
1970 MenuList& edit_items = track_crossfade_context_menu.items();
1971 edit_items.clear ();
1973 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1980 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
1982 Playlist::RegionList* regions = pl->regions_at (frame);
1983 AudioPlaylist::Crossfades xfades;
1985 apl->crossfades_at (frame, xfades);
1987 bool many = xfades.size() > 1;
1989 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
1990 add_crossfade_context_items (atv->view, (*i), edit_items, many);
1993 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1994 add_region_context_items (atv->view, (*i), edit_items);
2001 add_dstream_context_items (edit_items);
2003 return &track_crossfade_context_menu;
2007 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
2009 using namespace Menu_Helpers;
2010 MenuList& edit_items = track_selection_context_menu.items();
2011 edit_items.clear ();
2013 add_selection_context_items (edit_items);
2014 add_dstream_context_items (edit_items);
2016 return &track_selection_context_menu;
2020 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
2022 using namespace Menu_Helpers;
2023 Menu *xfade_menu = manage (new Menu);
2024 MenuList& items = xfade_menu->items();
2025 xfade_menu->set_name ("ArdourContextMenu");
2028 if (xfade->active()) {
2034 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
2035 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
2037 if (xfade->can_follow_overlap()) {
2039 if (xfade->following_overlap()) {
2040 str = _("Convert to short");
2042 str = _("Convert to full");
2045 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
2049 str = xfade->out().name();
2051 str += xfade->in().name();
2053 str = _("Crossfade");
2056 edit_items.push_back (MenuElem (str, *xfade_menu));
2057 edit_items.push_back (SeparatorElem());
2061 Editor::xfade_edit_left_region ()
2063 if (clicked_crossfadeview) {
2064 clicked_crossfadeview->left_view.show_region_editor ();
2069 Editor::xfade_edit_right_region ()
2071 if (clicked_crossfadeview) {
2072 clicked_crossfadeview->right_view.show_region_editor ();
2077 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
2079 using namespace Menu_Helpers;
2080 Menu *region_menu = manage (new Menu);
2081 MenuList& items = region_menu->items();
2082 region_menu->set_name ("ArdourContextMenu");
2084 AudioRegion* ar = 0;
2087 ar = dynamic_cast<AudioRegion*> (region);
2090 /* when this particular menu pops up, make the relevant region
2094 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
2096 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
2097 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
2098 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
2099 items.push_back (SeparatorElem());
2100 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
2101 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
2102 items.push_back (SeparatorElem());
2104 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
2105 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
2106 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
2107 items.push_back (SeparatorElem());
2109 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
2110 might be able to figure out which overloaded member function to use in
2114 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
2116 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
2117 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
2118 items.push_back (SeparatorElem());
2120 if (region->muted()) {
2121 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
2123 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
2125 items.push_back (SeparatorElem());
2127 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
2128 items.push_back (SeparatorElem());
2133 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
2134 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
2135 items.push_back (SeparatorElem());
2137 if (ar->scale_amplitude() != 1.0f) {
2138 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
2140 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
2143 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
2144 items.push_back (SeparatorElem());
2148 Menu *nudge_menu = manage (new Menu());
2149 MenuList& nudge_items = nudge_menu->items();
2150 nudge_menu->set_name ("ArdourContextMenu");
2152 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
2153 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
2154 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
2155 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
2157 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2158 items.push_back (SeparatorElem());
2160 Menu *trim_menu = manage (new Menu);
2161 MenuList& trim_items = trim_menu->items();
2162 trim_menu->set_name ("ArdourContextMenu");
2164 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
2165 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
2167 items.push_back (MenuElem (_("Trim"), *trim_menu));
2168 items.push_back (SeparatorElem());
2170 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
2171 region_edit_menu_split_item = &items.back();
2173 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
2174 region_edit_menu_split_multichannel_item = &items.back();
2176 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
2177 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
2178 items.push_back (SeparatorElem());
2179 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
2180 items.push_back (SeparatorElem());
2181 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
2183 /* OK, stick the region submenu at the top of the list, and then add
2187 /* we have to hack up the region name because "_" has a special
2188 meaning for menu titles.
2191 string::size_type pos = 0;
2192 string menu_item_name = region->name();
2194 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
2195 menu_item_name.replace (pos, 1, "__");
2199 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
2200 edit_items.push_back (SeparatorElem());
2204 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
2206 using namespace Menu_Helpers;
2207 Menu *selection_menu = manage (new Menu);
2208 MenuList& items = selection_menu->items();
2209 selection_menu->set_name ("ArdourContextMenu");
2211 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
2212 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
2213 items.push_back (SeparatorElem());
2214 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
2215 items.push_back (SeparatorElem());
2216 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
2217 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
2218 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
2219 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
2220 items.push_back (SeparatorElem());
2221 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
2222 items.push_back (SeparatorElem());
2223 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
2224 items.push_back (SeparatorElem());
2225 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
2227 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
2228 edit_items.push_back (SeparatorElem());
2232 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
2234 using namespace Menu_Helpers;
2238 Menu *play_menu = manage (new Menu);
2239 MenuList& play_items = play_menu->items();
2240 play_menu->set_name ("ArdourContextMenu");
2242 play_items.push_back (MenuElem (_("Play from edit cursor")));
2243 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2244 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
2245 play_items.push_back (SeparatorElem());
2246 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
2248 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2252 Menu *select_menu = manage (new Menu);
2253 MenuList& select_items = select_menu->items();
2254 select_menu->set_name ("ArdourContextMenu");
2256 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2257 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2258 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2259 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2260 select_items.push_back (SeparatorElem());
2261 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2262 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2263 select_items.push_back (SeparatorElem());
2265 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2269 Menu *cutnpaste_menu = manage (new Menu);
2270 MenuList& cutnpaste_items = cutnpaste_menu->items();
2271 cutnpaste_menu->set_name ("ArdourContextMenu");
2273 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2274 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2275 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2276 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
2278 cutnpaste_items.push_back (SeparatorElem());
2280 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
2281 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
2283 cutnpaste_items.push_back (SeparatorElem());
2285 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
2287 cutnpaste_items.push_back (SeparatorElem());
2289 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
2290 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
2292 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2294 /* Adding new material */
2296 Menu *import_menu = manage (new Menu());
2297 MenuList& import_items = import_menu->items();
2298 import_menu->set_name ("ArdourContextMenu");
2300 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2301 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
2303 edit_items.push_back (MenuElem (_("Import"), *import_menu));
2307 Menu *nudge_menu = manage (new Menu());
2308 MenuList& nudge_items = nudge_menu->items();
2309 nudge_menu->set_name ("ArdourContextMenu");
2311 edit_items.push_back (SeparatorElem());
2312 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2313 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2314 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2315 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2317 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2321 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2323 using namespace Menu_Helpers;
2327 Menu *play_menu = manage (new Menu);
2328 MenuList& play_items = play_menu->items();
2329 play_menu->set_name ("ArdourContextMenu");
2331 play_items.push_back (MenuElem (_("Play from edit cursor")));
2332 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2333 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2337 Menu *select_menu = manage (new Menu);
2338 MenuList& select_items = select_menu->items();
2339 select_menu->set_name ("ArdourContextMenu");
2341 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2342 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2343 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2344 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2345 select_items.push_back (SeparatorElem());
2346 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2347 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2348 select_items.push_back (SeparatorElem());
2350 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2354 Menu *cutnpaste_menu = manage (new Menu);
2355 MenuList& cutnpaste_items = cutnpaste_menu->items();
2356 cutnpaste_menu->set_name ("ArdourContextMenu");
2358 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2359 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2360 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2362 Menu *nudge_menu = manage (new Menu());
2363 MenuList& nudge_items = nudge_menu->items();
2364 nudge_menu->set_name ("ArdourContextMenu");
2366 edit_items.push_back (SeparatorElem());
2367 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2368 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2369 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2370 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2372 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2375 /* CURSOR SETTING AND MARKS AND STUFF */
2378 Editor::set_snap_to (SnapType st)
2381 vector<string> txt = internationalize (snap_type_strings);
2382 snap_type_selector.set_active_text (txt[(int)st]);
2386 switch (snap_type) {
2387 case SnapToAThirtysecondBeat:
2388 case SnapToASixteenthBeat:
2389 case SnapToAEighthBeat:
2390 case SnapToAQuarterBeat:
2391 case SnapToAThirdBeat:
2392 update_tempo_based_rulers ();
2400 Editor::set_snap_mode (SnapMode mode)
2403 vector<string> txt = internationalize (snap_mode_strings);
2404 snap_mode_selector.set_active_text (txt[(int)mode]);
2410 Editor::add_location_from_selection ()
2412 if (selection->time.empty()) {
2416 if (session == 0 || clicked_trackview == 0) {
2420 jack_nframes_t start = selection->time[clicked_selection].start;
2421 jack_nframes_t end = selection->time[clicked_selection].end;
2423 Location *location = new Location (start, end, "selection");
2425 session->begin_reversible_command (_("add marker"));
2426 session->add_undo (session->locations()->get_memento());
2427 session->locations()->add (location, true);
2428 session->add_redo_no_execute (session->locations()->get_memento());
2429 session->commit_reversible_command ();
2433 Editor::add_location_from_playhead_cursor ()
2435 jack_nframes_t where = session->audible_frame();
2437 Location *location = new Location (where, where, "mark", Location::IsMark);
2438 session->begin_reversible_command (_("add marker"));
2439 session->add_undo (session->locations()->get_memento());
2440 session->locations()->add (location, true);
2441 session->add_redo_no_execute (session->locations()->get_memento());
2442 session->commit_reversible_command ();
2447 Editor::set_state (const XMLNode& node)
2449 const XMLProperty* prop;
2451 int x, y, width, height, xoff, yoff;
2453 if ((geometry = find_named_node (node, "geometry")) == 0) {
2455 width = default_width;
2456 height = default_height;
2464 width = atoi(geometry->property("x_size")->value());
2465 height = atoi(geometry->property("y_size")->value());
2466 x = atoi(geometry->property("x_pos")->value());
2467 y = atoi(geometry->property("y_pos")->value());
2468 xoff = atoi(geometry->property("x_off")->value());
2469 yoff = atoi(geometry->property("y_off")->value());
2472 set_default_size(width, height);
2474 // set_position(x, y-yoff);
2476 if ((prop = node.property ("zoom-focus"))) {
2477 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2480 if ((prop = node.property ("zoom"))) {
2481 set_frames_per_unit (atof (prop->value()));
2484 if ((prop = node.property ("snap-to"))) {
2485 set_snap_to ((SnapType) atoi (prop->value()));
2488 if ((prop = node.property ("snap-mode"))) {
2489 set_snap_mode ((SnapMode) atoi (prop->value()));
2492 if ((prop = node.property ("show-waveforms"))) {
2493 bool yn = (prop->value() == "yes");
2494 _show_waveforms = !yn;
2495 set_show_waveforms (yn);
2498 if ((prop = node.property ("show-waveforms-recording"))) {
2499 bool yn = (prop->value() == "yes");
2500 _show_waveforms_recording = !yn;
2501 set_show_waveforms_recording (yn);
2504 if ((prop = node.property ("show-measures"))) {
2505 bool yn = (prop->value() == "yes");
2506 _show_measures = !yn;
2507 set_show_measures (yn);
2510 if ((prop = node.property ("follow-playhead"))) {
2511 bool yn = (prop->value() == "yes");
2512 _follow_playhead = !yn;
2513 set_follow_playhead (yn);
2516 if ((prop = node.property ("xfades-visible"))) {
2517 bool yn = (prop->value() == "yes");
2518 _xfade_visibility = !yn;
2519 set_xfade_visibility (yn);
2522 if ((prop = node.property ("region-list-sort-type"))) {
2523 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2524 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2527 if ((prop = node.property ("mouse-mode"))) {
2528 MouseMode m = str2mousemode(prop->value());
2529 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2530 set_mouse_mode (m, true);
2532 mouse_mode = MouseGain; /* lie, to force the mode switch */
2533 set_mouse_mode (MouseObject, true);
2536 if ((prop = node.property ("editor-mixer-button"))) {
2537 editor_mixer_button.set_active(prop->value() == "yes");
2544 Editor::get_state ()
2546 XMLNode* node = new XMLNode ("Editor");
2549 if (is_realized()) {
2550 Glib::RefPtr<Gdk::Window> win = get_window();
2552 int x, y, xoff, yoff, width, height;
2553 win->get_root_origin(x, y);
2554 win->get_position(xoff, yoff);
2555 win->get_size(width, height);
2557 XMLNode* geometry = new XMLNode ("geometry");
2559 snprintf(buf, sizeof(buf), "%d", width);
2560 geometry->add_property("x_size", string(buf));
2561 snprintf(buf, sizeof(buf), "%d", height);
2562 geometry->add_property("y_size", string(buf));
2563 snprintf(buf, sizeof(buf), "%d", x);
2564 geometry->add_property("x_pos", string(buf));
2565 snprintf(buf, sizeof(buf), "%d", y);
2566 geometry->add_property("y_pos", string(buf));
2567 snprintf(buf, sizeof(buf), "%d", xoff);
2568 geometry->add_property("x_off", string(buf));
2569 snprintf(buf, sizeof(buf), "%d", yoff);
2570 geometry->add_property("y_off", string(buf));
2571 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gobj()));
2572 geometry->add_property("canvas_region_list_pane_pos", string(buf));
2573 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gobj()));
2574 geometry->add_property("track_list_canvas_pane_pos", string(buf));
2575 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(®ion_selection_vpane)->gobj()));
2576 geometry->add_property("region_selection_pane_pos", string(buf));
2577 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gobj()));
2578 geometry->add_property("route_group_pane_pos", string(buf));
2580 node->add_child_nocopy (*geometry);
2583 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2584 node->add_property ("zoom-focus", buf);
2585 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2586 node->add_property ("zoom", buf);
2587 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2588 node->add_property ("snap-to", buf);
2589 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2590 node->add_property ("snap-mode", buf);
2592 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2593 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2594 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2595 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2596 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2597 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2598 node->add_property ("mouse-mode", enum2str(mouse_mode));
2599 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2607 Editor::trackview_by_y_position (double y)
2609 TrackViewList::iterator iter;
2612 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2620 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2629 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2631 Location* before = 0;
2632 Location* after = 0;
2638 const jack_nframes_t one_second = session->frame_rate();
2639 const jack_nframes_t one_minute = session->frame_rate() * 60;
2641 jack_nframes_t presnap = start;
2643 switch (snap_type) {
2649 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2651 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2654 case SnapToSMPTEFrame:
2656 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2658 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2662 case SnapToSMPTESeconds:
2663 if (session->smpte_offset_negative())
2665 start += session->smpte_offset ();
2667 start -= session->smpte_offset ();
2669 if (direction > 0) {
2670 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2672 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2675 if (session->smpte_offset_negative())
2677 start -= session->smpte_offset ();
2679 start += session->smpte_offset ();
2683 case SnapToSMPTEMinutes:
2684 if (session->smpte_offset_negative())
2686 start += session->smpte_offset ();
2688 start -= session->smpte_offset ();
2691 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2693 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2695 if (session->smpte_offset_negative())
2697 start -= session->smpte_offset ();
2699 start += session->smpte_offset ();
2705 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2707 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2713 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2715 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2720 start = session->tempo_map().round_to_bar (start, direction);
2724 start = session->tempo_map().round_to_beat (start, direction);
2727 case SnapToAThirtysecondBeat:
2728 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2731 case SnapToASixteenthBeat:
2732 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2735 case SnapToAEighthBeat:
2736 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2739 case SnapToAQuarterBeat:
2740 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2743 case SnapToAThirdBeat:
2744 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2747 case SnapToEditCursor:
2748 start = edit_cursor->current_frame;
2756 before = session->locations()->first_location_before (start);
2757 after = session->locations()->first_location_after (start);
2759 if (direction < 0) {
2761 start = before->start();
2765 } else if (direction > 0) {
2767 start = after->start();
2769 start = session->current_end_frame();
2774 /* find nearest of the two */
2775 if ((start - before->start()) < (after->start() - start)) {
2776 start = before->start();
2778 start = after->start();
2781 start = before->start();
2784 start = after->start();
2791 case SnapToRegionStart:
2792 case SnapToRegionEnd:
2793 case SnapToRegionSync:
2794 case SnapToRegionBoundary:
2795 if (!region_boundary_cache.empty()) {
2796 vector<jack_nframes_t>::iterator i;
2798 if (direction > 0) {
2799 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2801 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2804 if (i != region_boundary_cache.end()) {
2807 start = region_boundary_cache.back();
2813 switch (snap_mode) {
2819 if (presnap > start) {
2820 if (presnap > (start + unit_to_frame(snap_threshold))) {
2824 } else if (presnap < start) {
2825 if (presnap < (start - unit_to_frame(snap_threshold))) {
2837 Editor::setup_toolbar ()
2840 vector<ToggleButton *> mouse_mode_buttons;
2842 mouse_mode_buttons.push_back (&mouse_move_button);
2843 mouse_mode_buttons.push_back (&mouse_select_button);
2844 mouse_mode_buttons.push_back (&mouse_gain_button);
2845 mouse_mode_buttons.push_back (&mouse_zoom_button);
2846 mouse_mode_buttons.push_back (&mouse_timefx_button);
2847 mouse_mode_buttons.push_back (&mouse_audition_button);
2848 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2850 mouse_mode_button_table.set_homogeneous (true);
2851 mouse_mode_button_table.set_col_spacings (2);
2852 mouse_mode_button_table.set_row_spacings (2);
2853 mouse_mode_button_table.set_border_width (5);
2855 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2856 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2857 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2859 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2860 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2861 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2863 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2864 mouse_mode_tearoff->set_name ("MouseModeBase");
2866 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2867 mouse_mode_tearoff->tearoff_window()));
2868 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2869 mouse_mode_tearoff->tearoff_window(), 1));
2871 mouse_move_button.set_name ("MouseModeButton");
2872 mouse_select_button.set_name ("MouseModeButton");
2873 mouse_gain_button.set_name ("MouseModeButton");
2874 mouse_zoom_button.set_name ("MouseModeButton");
2875 mouse_timefx_button.set_name ("MouseModeButton");
2876 mouse_audition_button.set_name ("MouseModeButton");
2878 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2879 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2880 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2881 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2882 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2883 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2885 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2886 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2887 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2888 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2889 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2890 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2892 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2893 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2895 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2896 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2897 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2898 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2899 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2901 // mouse_move_button.set_active (true);
2903 /* automation control */
2905 global_automation_button.set_name ("MouseModeButton");
2906 automation_mode_button.set_name ("MouseModeButton");
2908 automation_box.set_spacing (2);
2909 automation_box.set_border_width (2);
2910 automation_box.pack_start (global_automation_button, false, false);
2911 automation_box.pack_start (automation_mode_button, false, false);
2915 edit_mode_label.set_name ("ToolBarLabel");
2917 edit_mode_selector.set_name ("EditModeSelector");
2919 edit_mode_box.set_spacing (3);
2920 edit_mode_box.set_border_width (3);
2922 /* XXX another disgusting hack because of the way combo boxes size themselves */
2924 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2, 10);
2925 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2926 edit_mode_box.pack_start (edit_mode_label, false, false);
2927 edit_mode_box.pack_start (edit_mode_selector, false, false);
2929 edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2933 snap_type_label.set_name ("ToolBarLabel");
2935 snap_type_selector.set_name ("SnapTypeSelector");
2937 snap_type_box.set_spacing (3);
2938 snap_type_box.set_border_width (3);
2940 /* XXX another disgusting hack because of the way combo boxes size themselves */
2942 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2943 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "Region bounds", 2+FUDGE, 10);
2944 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2946 snap_type_box.pack_start (snap_type_label, false, false);
2947 snap_type_box.pack_start (snap_type_selector, false, false);
2949 snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2951 /* Snap mode, not snap type */
2953 snap_mode_label.set_name ("ToolBarLabel");
2955 snap_mode_selector.set_name ("SnapModeSelector");
2957 snap_mode_box.set_spacing (3);
2958 snap_mode_box.set_border_width (3);
2960 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2, 10);
2961 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2963 snap_mode_box.pack_start (snap_mode_label, false, false);
2964 snap_mode_box.pack_start (snap_mode_selector, false, false);
2966 snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2968 /* Zoom focus mode */
2970 zoom_focus_label.set_name ("ToolBarLabel");
2972 zoom_focus_selector.set_name ("ZoomFocusSelector");
2974 zoom_focus_box.set_spacing (3);
2975 zoom_focus_box.set_border_width (3);
2977 /* XXX another disgusting hack because of the way combo boxes size themselves */
2979 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2, 10);
2980 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
2982 zoom_focus_box.pack_start (zoom_focus_label, false, false);
2983 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
2985 zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
2987 /* selection/cursor clocks */
2989 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
2990 selection_start_clock_label.set_name ("ToolBarLabel");
2991 selection_end_clock_label.set_name ("ToolBarLabel");
2992 edit_cursor_clock_label.set_name ("ToolBarLabel");
2994 selection_start_clock_label.set_text (_("Start:"));
2995 selection_end_clock_label.set_text (_("End:"));
2996 edit_cursor_clock_label.set_text (_("Edit:"));
2998 toolbar_selection_clock_table.set_border_width (5);
2999 toolbar_selection_clock_table.set_col_spacings (2);
3000 toolbar_selection_clock_table.set_homogeneous (false);
3002 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
3003 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
3004 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
3006 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
3007 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
3008 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
3011 // toolbar_clock_vbox.set_spacing (2);
3012 // toolbar_clock_vbox.set_border_width (10);
3013 /* the editor/mixer button will be enabled at session connect */
3015 editor_mixer_button.set_active(false);
3016 editor_mixer_button.set_sensitive(false);
3018 HBox* hbox = new HBox;
3020 hbox->pack_start (editor_mixer_button, false, false);
3021 hbox->pack_start (toolbar_selection_clock_table, false, false);
3022 hbox->pack_start (zoom_indicator_vbox, false, false);
3023 hbox->pack_start (zoom_focus_box, false, false);
3024 hbox->pack_start (snap_type_box, false, false);
3025 hbox->pack_start (snap_mode_box, false, false);
3026 hbox->pack_start (edit_mode_box, false, false);
3028 VBox *vbox = manage (new VBox);
3030 vbox->set_spacing (3);
3031 vbox->set_border_width (3);
3033 HBox *nbox = manage (new HBox);
3035 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
3036 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
3038 nbox->pack_start (nudge_backward_button, false, false);
3039 nbox->pack_start (nudge_forward_button, false, false);
3040 nbox->pack_start (nudge_clock, false, false, 5);
3042 nudge_label.set_name ("ToolBarLabel");
3044 vbox->pack_start (nudge_label, false, false);
3045 vbox->pack_start (*nbox, false, false);
3047 hbox->pack_start (*vbox, false, false);
3051 tools_tearoff = new TearOff (*hbox);
3052 tools_tearoff->set_name ("MouseModeBase");
3054 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
3055 tools_tearoff->tearoff_window()));
3056 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
3057 tools_tearoff->tearoff_window(), 0));
3060 toolbar_hbox.set_spacing (8);
3061 toolbar_hbox.set_border_width (2);
3063 toolbar_hbox.pack_start (*tools_tearoff, false, false);
3064 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
3066 toolbar_base.set_name ("ToolBarBase");
3067 toolbar_base.add (toolbar_hbox);
3069 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
3070 toolbar_frame.set_name ("BaseFrame");
3071 toolbar_frame.add (toolbar_base);
3075 Editor::_autoscroll_canvas (void *arg)
3077 return ((Editor *) arg)->autoscroll_canvas ();
3081 Editor::autoscroll_canvas ()
3083 jack_nframes_t new_frame;
3084 bool keep_calling = true;
3086 if (autoscroll_direction < 0) {
3087 if (leftmost_frame < autoscroll_distance) {
3090 new_frame = leftmost_frame - autoscroll_distance;
3093 if (leftmost_frame > max_frames - autoscroll_distance) {
3094 new_frame = max_frames;
3096 new_frame = leftmost_frame + autoscroll_distance;
3100 if (new_frame != leftmost_frame) {
3101 reposition_x_origin (new_frame);
3104 if (new_frame == 0 || new_frame == max_frames) {
3111 if (autoscroll_cnt == 1) {
3113 /* connect the timeout so that we get called repeatedly */
3115 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
3116 keep_calling = false;
3118 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
3120 /* after about a while, speed up a bit by changing the timeout interval */
3122 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
3123 keep_calling = false;
3125 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
3127 /* after about another while, speed up some more */
3129 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
3130 keep_calling = false;
3132 } else if (autoscroll_cnt >= 30) {
3134 /* we've been scrolling for a while ... crank it up */
3136 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
3139 return keep_calling;
3143 Editor::start_canvas_autoscroll (int dir)
3149 stop_canvas_autoscroll ();
3151 autoscroll_direction = dir;
3152 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
3155 /* do it right now, which will start the repeated callbacks */
3157 autoscroll_canvas ();
3161 Editor::stop_canvas_autoscroll ()
3163 if (autoscroll_timeout_tag >= 0) {
3164 gtk_timeout_remove (autoscroll_timeout_tag);
3165 autoscroll_timeout_tag = -1;
3170 Editor::convert_drop_to_paths (vector<string>& paths,
3171 GdkDragContext *context,
3174 GtkSelectionData *data,
3182 gchar *tname = gdk_atom_name (data->type);
3184 if (session == 0 || strcmp (tname, "text/plain") != 0) {
3188 /* Parse the "uri-list" format that Nautilus provides,
3189 where each pathname is delimited by \r\n
3192 path = (char *) data->data;
3195 for (int n = 0; n < data->length; ++n) {
3199 if (path[n] == '\r') {
3206 if (path[n] == '\n') {
3207 paths.push_back (spath);
3211 warning << _("incorrectly formatted URI list, ignored")
3219 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
3221 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3223 // cerr << "dropped text was " << *p << endl;
3227 // cerr << "decoded was " << *p << endl;
3229 if ((*p).substr (0,7) == "file://") {
3230 (*p) = (*p).substr (7);
3238 Editor::track_canvas_drag_data_received (GdkDragContext *context,
3241 GtkSelectionData *data,
3246 AudioTimeAxisView* tv;
3248 vector<string> paths;
3251 jack_nframes_t frame;
3253 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
3257 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
3263 track_canvas.c2w( x, y, wx, wy);
3265 ev.type = GDK_BUTTON_RELEASE;
3269 frame = event_frame (&ev, 0, &cy);
3273 if ((tvp = trackview_by_y_position (cy)) == 0) {
3275 /* drop onto canvas background: create a new track */
3277 insert_paths_as_new_tracks (paths, false);
3280 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
3282 /* check that its an audio track, not a bus */
3284 if (tv->get_diskstream()) {
3286 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3287 insert_sndfile_into (*p, true, tv, frame);
3294 gtk_drag_finish (context, TRUE, FALSE, time);
3298 Editor::new_tempo_section ()
3304 Editor::map_transport_state ()
3306 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3308 if (session->transport_stopped()) {
3309 have_pending_keyboard_selection = false;
3315 Editor::State::State ()
3317 selection = new Selection;
3320 Editor::State::~State ()
3326 Editor::get_memento () const
3328 State *state = new State;
3330 store_state (*state);
3331 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3335 Editor::store_state (State& state) const
3337 *state.selection = *selection;
3341 Editor::restore_state (State *state)
3343 if (*selection == *state->selection) {
3347 *selection = *state->selection;
3348 time_selection_changed ();
3349 region_selection_changed ();
3351 /* XXX other selection change handlers? */
3355 Editor::begin_reversible_command (string name)
3358 UndoAction ua = get_memento();
3359 session->begin_reversible_command (name, &ua);
3364 Editor::commit_reversible_command ()
3367 UndoAction ua = get_memento();
3368 session->commit_reversible_command (&ua);
3373 Editor::flush_track_canvas ()
3375 /* I don't think this is necessary, and only causes more problems.
3376 I'm commenting it out
3377 and if the imageframe folks don't have any issues, we can take
3378 out this method entirely
3381 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
3382 //gtk_main_iteration ();
3386 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3388 if (!clicked_trackview) {
3393 begin_reversible_command (_("set selected trackview"));
3398 if (selection->selected (clicked_trackview)) {
3400 selection->remove (clicked_trackview);
3403 selection->add (clicked_trackview);
3408 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3409 /* no commit necessary */
3413 selection->set (clicked_trackview);
3417 commit_reversible_command ();
3422 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3424 if (!clicked_control_point) {
3429 begin_reversible_command (_("set selected control point"));
3439 commit_reversible_command ();
3444 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3446 if (!clicked_regionview) {
3450 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3456 RouteGroup* group = atv->route().edit_group();
3457 vector<AudioRegionView*> all_equivalent_regions;
3459 if (group && group->is_active()) {
3461 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3463 AudioTimeAxisView* tatv;
3465 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3467 if (tatv->route().edit_group() != group) {
3472 vector<AudioRegion*> results;
3473 AudioRegionView* marv;
3476 if ((ds = tatv->get_diskstream()) == 0) {
3481 if ((pl = ds->playlist()) != 0) {
3482 pl->get_equivalent_regions (clicked_regionview->region,
3486 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3487 if ((marv = tatv->view->find_view (**ir)) != 0) {
3488 all_equivalent_regions.push_back (marv);
3497 all_equivalent_regions.push_back (clicked_regionview);
3501 begin_reversible_command (_("set selected regionview"));
3505 if (clicked_regionview->get_selected()) {
3506 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3507 /* reduce selection down to just the one clicked */
3508 selection->set (clicked_regionview);
3510 selection->remove (clicked_regionview);
3513 selection->add (all_equivalent_regions);
3516 set_selected_track_from_click (add, false, no_track_remove);
3520 // karsten wiese suggested these two lines to make
3521 // a selected region rise to the top. but this
3522 // leads to a mismatch between actual layering
3523 // and visual layering. resolution required ....
3525 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3526 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3528 if (clicked_regionview->get_selected()) {
3529 /* no commit necessary: we are the one selected. */
3534 selection->set (all_equivalent_regions);
3535 set_selected_track_from_click (add, false, false);
3539 commit_reversible_command () ;
3543 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3545 vector<AudioRegionView*> all_equivalent_regions;
3546 AudioRegion* region;
3548 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3552 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3554 AudioTimeAxisView* tatv;
3556 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3559 vector<AudioRegion*> results;
3560 AudioRegionView* marv;
3563 if ((ds = tatv->get_diskstream()) == 0) {
3568 if ((pl = ds->playlist()) != 0) {
3569 pl->get_region_list_equivalent_regions (*region, results);
3572 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3573 if ((marv = tatv->view->find_view (**ir)) != 0) {
3574 all_equivalent_regions.push_back (marv);
3581 begin_reversible_command (_("set selected regions"));
3585 selection->add (all_equivalent_regions);
3589 selection->set (all_equivalent_regions);
3592 commit_reversible_command () ;
3596 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3598 AudioRegionView* rv;
3601 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3605 if ((rv = sv->find_view (*ar)) == 0) {
3609 /* don't reset the selection if its something other than
3610 a single other region.
3613 if (selection->audio_regions.size() > 1) {
3617 begin_reversible_command (_("set selected regions"));
3619 selection->set (rv);
3621 commit_reversible_command () ;
3627 Editor::set_edit_group_solo (Route& route, bool yn)
3629 RouteGroup *edit_group;
3631 if ((edit_group = route.edit_group()) != 0) {
3632 edit_group->apply (&Route::set_solo, yn, this);
3634 route.set_solo (yn, this);
3639 Editor::set_edit_group_mute (Route& route, bool yn)
3641 RouteGroup *edit_group = 0;
3643 if ((edit_group == route.edit_group()) != 0) {
3644 edit_group->apply (&Route::set_mute, yn, this);
3646 route.set_mute (yn, this);
3651 Editor::set_edit_menu (Menu& menu)
3654 edit_menu->signal_map_event().connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3658 Editor::edit_menu_map_handler (GdkEventAny* ev)
3660 using namespace Menu_Helpers;
3661 MenuList& edit_items = edit_menu->items();
3664 /* Nuke all the old items */
3666 edit_items.clear ();
3672 if (session->undo_depth() == 0) {
3675 label = string_compose(_("Undo (%1)"), session->next_undo());
3678 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3680 if (session->undo_depth() == 0) {
3681 edit_items.back().set_sensitive (false);
3684 if (session->redo_depth() == 0) {
3687 label = string_compose(_("Redo (%1)"), session->next_redo());
3690 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3691 if (session->redo_depth() == 0) {
3692 edit_items.back().set_sensitive (false);
3695 vector<MenuItem*> mitems;
3697 edit_items.push_back (SeparatorElem());
3698 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3699 mitems.push_back (&edit_items.back());
3700 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3701 mitems.push_back (&edit_items.back());
3702 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3703 mitems.push_back (&edit_items.back());
3704 edit_items.push_back (SeparatorElem());
3705 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3706 mitems.push_back (&edit_items.back());
3707 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3708 mitems.push_back (&edit_items.back());
3709 edit_items.push_back (SeparatorElem());
3711 if (selection->empty()) {
3712 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3713 (*i)->set_sensitive (false);
3717 Menu* import_menu = manage (new Menu());
3718 import_menu->set_name ("ArdourContextMenu");
3719 MenuList& import_items = import_menu->items();
3721 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3722 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3724 Menu* embed_menu = manage (new Menu());
3725 embed_menu->set_name ("ArdourContextMenu");
3726 MenuList& embed_items = embed_menu->items();
3728 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3729 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3731 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3732 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3733 edit_items.push_back (SeparatorElem());
3735 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3736 if (!session->have_captured()) {
3737 edit_items.back().set_sensitive (false);
3744 Editor::duplicate_dialog (bool dup_region)
3747 if (clicked_regionview == 0) {
3751 if (selection->time.length() == 0) {
3756 ArdourDialog win ("duplicate dialog");
3758 Label label (_("Duplicate how many times?"));
3760 win.get_vbox()->pack_start (label);
3761 win.add_action_widget (entry, RESPONSE_ACCEPT);
3762 win.add_button (Stock::OK, RESPONSE_ACCEPT);
3763 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3765 win.set_position (Gtk::WIN_POS_MOUSE);
3767 entry.set_text ("1");
3768 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3769 entry.select_region (0, entry.get_text_length());
3770 entry.grab_focus ();
3773 // win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3776 switch (win.run ()) {
3777 case RESPONSE_ACCEPT:
3783 string text = entry.get_text();
3786 if (sscanf (text.c_str(), "%f", ×) == 1) {
3788 AudioRegionSelection regions;
3789 regions.add (clicked_regionview);
3790 duplicate_some_regions (regions, times);
3792 duplicate_selection (times);
3798 Editor::show_verbose_canvas_cursor ()
3800 verbose_canvas_cursor->raise_to_top();
3801 verbose_canvas_cursor->show();
3802 verbose_cursor_visible = true;
3806 Editor::hide_verbose_canvas_cursor ()
3808 verbose_canvas_cursor->hide();
3809 verbose_cursor_visible = false;
3813 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3815 /* XXX get origin of canvas relative to root window,
3816 add x and y and check compared to gdk_screen_{width,height}
3818 verbose_canvas_cursor->property_text() = txt.c_str();
3819 verbose_canvas_cursor->property_x() = x;
3820 verbose_canvas_cursor->property_y() = y;
3824 Editor::set_verbose_canvas_cursor_text (string txt)
3826 verbose_canvas_cursor->property_text() = txt.c_str();
3830 Editor::edit_mode_selection_done ()
3836 string choice = edit_mode_selector.get_active_text();
3837 EditMode mode = Slide;
3839 if (choice == _("Splice")) {
3841 } else if (choice == _("Slide")) {
3845 session->set_edit_mode (mode);
3849 Editor::snap_type_selection_done ()
3855 string choice = snap_type_selector.get_active_text();
3856 SnapType snaptype = SnapToFrame;
3858 if (choice == _("Beats/3")) {
3859 snaptype = SnapToAThirdBeat;
3860 } else if (choice == _("Beats/4")) {
3861 snaptype = SnapToAQuarterBeat;
3862 } else if (choice == _("Beats/8")) {
3863 snaptype = SnapToAEighthBeat;
3864 } else if (choice == _("Beats/16")) {
3865 snaptype = SnapToASixteenthBeat;
3866 } else if (choice == _("Beats/32")) {
3867 snaptype = SnapToAThirtysecondBeat;
3868 } else if (choice == _("Beats")) {
3869 snaptype = SnapToBeat;
3870 } else if (choice == _("Bars")) {
3871 snaptype = SnapToBar;
3872 } else if (choice == _("Marks")) {
3873 snaptype = SnapToMark;
3874 } else if (choice == _("Edit Cursor")) {
3875 snaptype = SnapToEditCursor;
3876 } else if (choice == _("Region starts")) {
3877 snaptype = SnapToRegionStart;
3878 } else if (choice == _("Region ends")) {
3879 snaptype = SnapToRegionEnd;
3880 } else if (choice == _("Region bounds")) {
3881 snaptype = SnapToRegionBoundary;
3882 } else if (choice == _("Region syncs")) {
3883 snaptype = SnapToRegionSync;
3884 } else if (choice == _("CD Frames")) {
3885 snaptype = SnapToCDFrame;
3886 } else if (choice == _("SMPTE Frames")) {
3887 snaptype = SnapToSMPTEFrame;
3888 } else if (choice == _("SMPTE Seconds")) {
3889 snaptype = SnapToSMPTESeconds;
3890 } else if (choice == _("SMPTE Minutes")) {
3891 snaptype = SnapToSMPTEMinutes;
3892 } else if (choice == _("Seconds")) {
3893 snaptype = SnapToSeconds;
3894 } else if (choice == _("Minutes")) {
3895 snaptype = SnapToMinutes;
3896 } else if (choice == _("None")) {
3897 snaptype = SnapToFrame;
3900 set_snap_to (snaptype);
3904 Editor::snap_mode_selection_done ()
3910 string choice = snap_mode_selector.get_active_text();
3911 SnapMode mode = SnapNormal;
3913 if (choice == _("Normal")) {
3915 } else if (choice == _("Magnetic")) {
3916 mode = SnapMagnetic;
3919 set_snap_mode (mode);
3923 Editor::zoom_focus_selection_done ()
3929 string choice = zoom_focus_selector.get_active_text();
3930 ZoomFocus focus_type = ZoomFocusLeft;
3932 if (choice == _("Left")) {
3933 focus_type = ZoomFocusLeft;
3934 } else if (choice == _("Right")) {
3935 focus_type = ZoomFocusRight;
3936 } else if (choice == _("Center")) {
3937 focus_type = ZoomFocusCenter;
3938 } else if (choice == _("Playhead")) {
3939 focus_type = ZoomFocusPlayhead;
3940 } else if (choice == _("Edit Cursor")) {
3941 focus_type = ZoomFocusEdit;
3944 set_zoom_focus (focus_type);
3948 Editor::edit_controls_button_release (GdkEventButton* ev)
3950 if (Keyboard::is_context_menu_event (ev)) {
3951 ARDOUR_UI::instance()->add_route ();
3957 Editor::track_selection_changed ()
3959 switch (selection->tracks.size()){
3963 set_selected_mixer_strip (*(selection->tracks.front()));
3967 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3968 (*i)->set_selected (false);
3969 if (mouse_mode == MouseRange) {
3970 (*i)->hide_selection ();
3974 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3975 (*i)->set_selected (true);
3976 if (mouse_mode == MouseRange) {
3977 (*i)->show_selection (selection->time);
3983 Editor::time_selection_changed ()
3985 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3986 (*i)->hide_selection ();
3989 if (selection->tracks.empty()) {
3990 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3991 (*i)->show_selection (selection->time);
3994 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3995 (*i)->show_selection (selection->time);
4001 Editor::region_selection_changed ()
4003 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4004 (*i)->set_selected_regionviews (selection->audio_regions);
4009 Editor::point_selection_changed ()
4011 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4012 (*i)->set_selected_points (selection->points);
4017 Editor::run_sub_event_loop ()
4019 sub_event_loop_status = 0;
4024 Editor::finish_sub_event_loop (int status)
4027 sub_event_loop_status = status;
4031 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
4033 finish_sub_event_loop (status);
4038 Editor::mouse_select_button_release (GdkEventButton* ev)
4040 /* this handles just right-clicks */
4042 if (ev->button != 3) {
4049 Editor::TrackViewList *
4050 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
4053 TrackViewList::iterator i;
4055 v = new TrackViewList;
4057 if (track == 0 && group == 0) {
4061 for (i = track_views.begin(); i != track_views.end (); ++i) {
4065 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
4067 /* just the view for this track
4070 v->push_back (track);
4074 /* views for all tracks in the edit group */
4076 for (i = track_views.begin(); i != track_views.end (); ++i) {
4078 if (group == 0 || (*i)->edit_group() == group) {
4088 Editor::set_zoom_focus (ZoomFocus f)
4090 if (zoom_focus != f) {
4092 vector<string> txt = internationalize (zoom_focus_strings);
4093 zoom_focus_selector.set_active_text (txt[(int)f]);
4094 ZoomFocusChanged (); /* EMIT_SIGNAL */
4101 Editor::ensure_float (Window& win)
4103 win.set_transient_for (*this);
4107 Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which)
4109 /* recover or initialize pane positions. do this here rather than earlier because
4110 we don't want the positions to change the child allocations, which they seem to do.
4116 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
4118 static int32_t done[4] = { 0, 0, 0, 0 };
4121 if ((geometry = find_named_node (*node, "geometry")) == 0) {
4122 width = default_width;
4123 height = default_height;
4125 width = atoi(geometry->property("x_size")->value());
4126 height = atoi(geometry->property("y_size")->value());
4129 if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
4135 if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
4137 snprintf (buf, sizeof(buf), "%d", pos);
4139 pos = atoi (prop->value());
4142 if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gobj())->allocation.width > pos)) {
4143 track_list_canvas_pane.set_position (pos);
4146 } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
4152 if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
4153 pos = width - (95 * 2);
4154 snprintf (buf, sizeof(buf), "%d", pos);
4156 pos = atoi (prop->value());
4159 if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gobj())->allocation.width > pos)) {
4160 canvas_region_list_pane.set_position (pos);
4163 } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
4169 if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
4170 pos = width - (95 * 2);
4171 snprintf (buf, sizeof(buf), "%d", pos);
4173 pos = atoi (prop->value());
4176 if ((done[2] = GTK_WIDGET(route_group_vpane.gobj())->allocation.height > pos)) {
4177 route_group_vpane.set_position (pos);
4180 } else if (which == static_cast<Gtk::Paned*> (®ion_selection_vpane)) {
4186 if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
4187 pos = width - (95 * 2);
4188 snprintf (buf, sizeof(buf), "%d", pos);
4190 pos = atoi (prop->value());
4193 if ((done[3] = GTK_WIDGET(region_selection_vpane.gobj())->allocation.height > pos)) {
4194 region_selection_vpane.set_position (pos);
4200 Editor::detach_tearoff (Gtk::Box* b, Gtk::Window* w)
4202 if (tools_tearoff->torn_off() &&
4203 mouse_mode_tearoff->torn_off()) {
4204 top_hbox.remove (toolbar_frame);
4211 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Window* w, int32_t n)
4213 if (toolbar_frame.get_parent() == 0) {
4214 top_hbox.pack_end (toolbar_frame);
4219 Editor::set_show_measures (bool yn)
4221 if (_show_measures != yn) {
4224 if ((_show_measures = yn) == true) {
4227 DisplayControlChanged (ShowMeasures);
4233 Editor::set_follow_playhead (bool yn)
4235 if (_follow_playhead != yn) {
4236 if ((_follow_playhead = yn) == true) {
4238 update_current_screen ();
4240 DisplayControlChanged (FollowPlayhead);
4246 Editor::toggle_xfade_active (Crossfade* xfade)
4248 xfade->set_active (!xfade->active());
4252 Editor::toggle_xfade_length (Crossfade* xfade)
4254 xfade->set_follow_overlap (!xfade->following_overlap());
4258 Editor::edit_xfade (Crossfade* xfade)
4260 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
4265 // cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
4267 switch (cew.run ()) {
4268 case RESPONSE_ACCEPT:
4275 xfade->StateChanged (Change (~0));
4279 Editor::playlist_selector () const
4281 return *_playlist_selector;
4285 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
4289 ret = nudge_clock.current_duration (pos);
4290 next = ret + 1; /* XXXX fix me */
4296 Editor::end_location_changed (Location* location)
4298 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
4299 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
4303 Editor::playlist_deletion_dialog (Playlist* pl)
4305 ArdourDialog dialog ("playlist deletion dialog");
4306 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4307 "If left alone, no audio files used by it will be cleaned.\n"
4308 "If deleted, audio files used by it alone by will cleaned."),
4311 dialog.set_position (Gtk::WIN_POS_CENTER);
4312 dialog.get_vbox()->pack_start (label);
4314 dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT);
4315 dialog.add_button (_("Keep playlist"), RESPONSE_CANCEL);
4316 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4318 switch (dialog.run ()) {
4319 case RESPONSE_ACCEPT:
4320 /* delete the playlist */
4324 case RESPONSE_REJECT:
4325 /* keep the playlist */
4337 Editor::audio_region_selection_covers (jack_nframes_t where)
4339 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
4340 if ((*a)->region.covers (where)) {
4349 Editor::prepare_for_cleanup ()
4351 cut_buffer->clear_audio_regions ();
4352 cut_buffer->clear_playlists ();
4354 selection->clear_audio_regions ();
4355 selection->clear_playlists ();
4359 Editor::init_colormap ()
4361 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
4362 pair<ColorID,int> newpair;
4364 newpair.first = (ColorID) x;
4365 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
4366 color_map.insert (newpair);
4371 Editor::transport_loop_location()
4374 return session->locations()->auto_loop_location();
4381 Editor::transport_punch_location()
4384 return session->locations()->auto_punch_location();