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 <libgnomecanvas/libgnomecanvas.h>
30 #include <pbd/error.h>
32 #include <gtkmm2ext/gtk_ui.h>
33 #include <gtkmm2ext/tearoff.h>
34 #include <gtkmm2ext/utils.h>
36 #include <ardour/audio_track.h>
37 #include <ardour/diskstream.h>
38 #include <ardour/plugin_manager.h>
39 #include <ardour/location.h>
40 #include <ardour/audioplaylist.h>
41 #include <ardour/audioregion.h>
42 #include <ardour/session.h>
43 #include <ardour/session_route.h>
44 #include <ardour/tempo.h>
45 #include <ardour/utils.h>
47 #include "ardour_ui.h"
48 #include "canvas-ruler.h"
49 #include "canvas-simpleline.h"
50 #include "canvas-simplerect.h"
51 #include "canvas-waveview.h"
52 #include "check_mark.h"
54 #include "grouped_buttons.h"
56 #include "library_ui.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 "time_axis_view.h"
65 #include "crossfade_view.h"
67 #include "public_editor.h"
68 #include "crossfade_edit.h"
69 #include "audio_time_axis.h"
70 #include "gui_thread.h"
75 #include "imageframe_socket_handler.h"
76 /* </CMT Additions> */
80 using namespace ARDOUR;
82 using namespace Gtkmm2ext;
83 using namespace Editing;
85 /* XXX this is a hack. it ought to be the maximum value of an jack_nframes_t */
87 const double max_canvas_coordinate = 100000000.0;
88 const double Editor::timebar_height = 15.0;
90 #include "editor_xpms"
92 static const gchar *route_list_titles[] = {
97 static const gchar *edit_group_list_titles[] = {
101 static const gchar *named_selection_display_titles[] = {
106 static const int32_t slide_index = 0;
107 static const int32_t splice_index = 1;
109 static const gchar *edit_mode_strings[] = {
115 static const gchar *snap_type_strings[] = {
139 static const gchar *snap_mode_strings[] = {
145 static const gchar *zoom_focus_strings[] = {
154 /* Soundfile drag-n-drop */
162 static GtkTargetEntry target_table[] = {
163 { "STRING", 0, TARGET_STRING },
164 { "text/plain", 0, TARGET_STRING },
165 { "text/uri-list", 0, TARGET_URL },
166 { "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
169 static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
171 GdkCursor* Editor::cross_hair_cursor = 0;
172 GdkCursor* Editor::selector_cursor = 0;
173 GdkCursor* Editor::trimmer_cursor = 0;
174 GdkCursor* Editor::grabber_cursor = 0;
175 GdkCursor* Editor::zoom_cursor = 0;
176 GdkCursor* Editor::time_fx_cursor = 0;
177 GdkCursor* Editor::fader_cursor = 0;
178 GdkCursor* Editor::speaker_cursor = 0;
179 GdkCursor* Editor::null_cursor = 0;
180 GdkCursor* Editor::wait_cursor = 0;
181 GdkCursor* Editor::timebar_cursor = 0;
183 GdkPixmap *Editor::check_pixmap = 0;
184 GdkBitmap *Editor::check_mask = 0;
185 GdkPixmap *Editor::empty_pixmap = 0;
186 GdkBitmap *Editor::empty_mask = 0;
188 extern gint route_list_compare_func (GtkCList*,gconstpointer,gconstpointer);
190 Editor::Editor (AudioEngine& eng)
193 /* time display buttons */
195 minsec_label (_("Mins:Secs")),
196 bbt_label (_("Bars:Beats")),
197 smpte_label (_("SMPTE")),
198 frame_label (_("Frames")),
199 tempo_label (_("Tempo")),
200 meter_label (_("Meter")),
201 mark_label (_("Location Markers")),
202 range_mark_label (_("Range Markers")),
203 transport_mark_label (_("Loop/Punch Ranges")),
205 edit_packer (3, 3, false),
206 edit_hscroll_left_arrow (Gtk::ARROW_LEFT, Gtk::SHADOW_OUT),
207 edit_hscroll_right_arrow (Gtk::ARROW_RIGHT, Gtk::SHADOW_OUT),
209 named_selection_display (internationalize (named_selection_display_titles)),
211 /* tool bar related */
213 editor_mixer_button (_("editor\nmixer")),
215 selection_start_clock (X_("SelectionStartClock"), true),
216 selection_end_clock (X_("SelectionEndClock"), true),
217 edit_cursor_clock (X_("EditCursorClock"), true),
218 zoom_range_clock (X_("ZoomRangeClock"), true, true),
220 toolbar_selection_clock_table (2,3),
222 mouse_mode_button_table (2, 3),
224 mouse_select_button (_("range")),
225 mouse_move_button (_("object")),
226 mouse_gain_button (_("gain")),
227 mouse_zoom_button (_("zoom")),
228 mouse_timefx_button (_("timefx")),
229 mouse_audition_button (_("listen")),
231 automation_mode_button (_("mode")),
232 global_automation_button (_("automation")),
234 edit_mode_label (_("Edit Mode")),
235 snap_type_label (_("Snap To")),
236 snap_mode_label(_("Snap Mode")),
237 zoom_focus_label (_("Zoom Focus")),
239 /* <CMT Additions> */
240 image_socket_listener(0),
241 /* </CMT Additions> */
245 nudge_label (_("Nudge")),
246 nudge_clock (X_("NudgeClock"), true, true)
251 /* we are a singleton */
253 PublicEditor::_instance = this;
257 check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
258 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
259 &check_mask, NULL, (gchar **) check_xpm);
260 empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
261 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
262 &empty_mask, NULL, (gchar **) empty_xpm);
266 selection = new Selection;
267 cut_buffer = new Selection;
269 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
270 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
271 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
272 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
274 clicked_regionview = 0;
275 clicked_trackview = 0;
276 clicked_audio_trackview = 0;
277 clicked_crossfadeview = 0;
278 clicked_control_point = 0;
279 latest_regionview = 0;
280 last_update_frame = 0;
282 last_audition_region = 0;
283 current_mixer_strip = 0;
284 current_bbt_points = 0;
286 snap_type = SnapToFrame;
287 set_snap_to (snap_type);
288 snap_mode = SnapNormal;
289 set_snap_mode (snap_mode);
290 snap_threshold = 5.0;
291 bbt_beat_subdivision = 4;
294 autoscroll_timeout_tag = -1;
295 interthread_progress_window = 0;
296 current_interthread_info = 0;
297 _show_measures = true;
298 _show_waveforms = true;
299 _show_waveforms_recording = true;
300 first_action_message = 0;
302 show_gain_after_trim = false;
303 no_zoom_repos_update = false;
304 ignore_route_list_reorder = false;
305 verbose_cursor_on = true;
306 route_removal = false;
308 show_automatic_regions_in_region_list = true;
309 have_pending_keyboard_selection = false;
310 _follow_playhead = true;
311 _xfade_visibility = true;
312 editor_ruler_menu = 0;
313 no_ruler_shown_update = false;
314 edit_group_list_menu = 0;
316 region_list_menu = 0;
318 marker_menu_item = 0;
320 transport_marker_menu = 0;
321 new_transport_marker_menu = 0;
322 editor_mixer_strip_width = Wide;
323 repos_zoom_queued = false;
324 import_audio_item = 0;
325 embed_audio_item = 0;
326 region_edit_menu_split_item = 0;
328 region_edit_menu_split_multichannel_item = 0;
329 edit_hscroll_dragging = false;
331 ignore_mouse_mode_toggle = false;
332 current_stepping_trackview = 0;
334 entered_regionview = 0;
335 clear_entered_track = false;
336 _new_regionviews_show_envelope = false;
337 current_timestretch = 0;
342 location_marker_color = color_map[cLocationMarker];
343 location_range_color = color_map[cLocationRange];
344 location_cd_marker_color = color_map[cLocationCDMarker];
345 location_loop_color = color_map[cLocationLoop];
346 location_punch_color = color_map[cLocationPunch];
348 range_marker_drag_rect = 0;
349 marker_drag_line = 0;
351 mouse_mode = MouseZoom; /* force change in next call */
352 set_mouse_mode (MouseObject, true);
354 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
355 zoom_focus = ZoomFocusLeft;
356 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
358 initialize_rulers ();
359 initialize_canvas ();
361 track_canvas_scroller.add (*track_canvas);
362 track_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
363 track_canvas_scroller.set_name ("TrackCanvasScroller");
365 track_canvas_scroller.get_vadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
366 track_canvas_scroller.get_vadjustment()->set_step_increment (10.0);
368 track_canvas_scroller.get_hadjustment()->set_lower (0.0);
369 track_canvas_scroller.get_hadjustment()->set_upper (1200.0);
370 track_canvas_scroller.get_hadjustment()->set_step_increment (20.0);
371 track_canvas_scroller.get_hadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
373 edit_vscrollbar.set_adjustment(*track_canvas_scroller.get_vadjustment());
374 edit_hscrollbar.set_adjustment(*track_canvas_scroller.get_hadjustment());
376 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_press));
377 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_release));
378 edit_hscrollbar.size_allocate.connect (mem_fun(*this, &Editor::hscroll_slider_allocate));
380 time_canvas_scroller.add (*time_canvas);
381 time_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
382 time_canvas_scroller.set_hadjustment (*track_canvas_scroller.get_hadjustment());
383 time_canvas_scroller.set_name ("TimeCanvasScroller");
385 edit_controls_vbox.set_spacing (track_spacing);
386 edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
387 edit_controls_scroller.add (edit_controls_hbox);
388 edit_controls_scroller.set_name ("EditControlsBase");
389 edit_controls_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
391 Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
393 viewport->set_shadow_type (Gtk::SHADOW_NONE);
394 viewport->set_name ("EditControlsBase");
395 viewport->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
396 viewport->signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
401 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
404 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
406 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
407 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
408 time_canvas_vbox.pack_start (*frames_ruler, false, false);
409 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
410 time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
411 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
413 bbt_label.set_name ("EditorTimeButton");
414 bbt_label.set_size_request (-1, (int)timebar_height);
415 bbt_label.set_alignment (1.0, 0.5);
416 bbt_label.set_padding (5,0);
417 minsec_label.set_name ("EditorTimeButton");
418 minsec_label.set_size_request (-1, (int)timebar_height);
419 minsec_label.set_alignment (1.0, 0.5);
420 minsec_label.set_padding (5,0);
421 smpte_label.set_name ("EditorTimeButton");
422 smpte_label.set_size_request (-1, (int)timebar_height);
423 smpte_label.set_alignment (1.0, 0.5);
424 smpte_label.set_padding (5,0);
425 frame_label.set_name ("EditorTimeButton");
426 frame_label.set_size_request (-1, (int)timebar_height);
427 frame_label.set_alignment (1.0, 0.5);
428 frame_label.set_padding (5,0);
429 tempo_label.set_name ("EditorTimeButton");
430 tempo_label.set_size_request (-1, (int)timebar_height);
431 tempo_label.set_alignment (1.0, 0.5);
432 tempo_label.set_padding (5,0);
433 meter_label.set_name ("EditorTimeButton");
434 meter_label.set_size_request (-1, (int)timebar_height);
435 meter_label.set_alignment (1.0, 0.5);
436 meter_label.set_padding (5,0);
437 mark_label.set_name ("EditorTimeButton");
438 mark_label.set_size_request (-1, (int)timebar_height);
439 mark_label.set_alignment (1.0, 0.5);
440 mark_label.set_padding (5,0);
441 range_mark_label.set_name ("EditorTimeButton");
442 range_mark_label.set_size_request (-1, (int)timebar_height);
443 range_mark_label.set_alignment (1.0, 0.5);
444 range_mark_label.set_padding (5,0);
445 transport_mark_label.set_name ("EditorTimeButton");
446 transport_mark_label.set_size_request (-1, (int)timebar_height);
447 transport_mark_label.set_alignment (1.0, 0.5);
448 transport_mark_label.set_padding (5,0);
450 time_button_vbox.pack_start (minsec_label, false, false);
451 time_button_vbox.pack_start (smpte_label, false, false);
452 time_button_vbox.pack_start (frame_label, false, false);
453 time_button_vbox.pack_start (bbt_label, false, false);
454 time_button_vbox.pack_start (meter_label, false, false);
455 time_button_vbox.pack_start (tempo_label, false, false);
456 time_button_vbox.pack_start (mark_label, false, false);
458 time_button_event_box.add (time_button_vbox);
460 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
461 time_button_event_box.set_name ("TimebarLabelBase");
462 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
464 /* these enable us to have a dedicated window (for cursor setting, etc.)
465 for the canvas areas.
468 track_canvas_event_box.add (track_canvas_scroller);
470 time_canvas_event_box.add (time_canvas_vbox);
471 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
474 edit_packer.set_col_spacings (0);
475 edit_packer.set_row_spacings (0);
476 edit_packer.set_homogeneous (false);
477 edit_packer.set_name ("EditorWindow");
479 // edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, Gtk::FILL, 0, 0, 0);
480 // edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, 0, 0, 0);
481 // edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, Gtk::FILL, 0, 0, 0);
482 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
484 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
485 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
487 edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
488 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
489 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
491 edit_frame.set_name ("BaseFrame");
492 edit_frame.set_shadow_type (SHADOW_IN);
493 edit_frame.add (edit_packer);
495 zoom_in_button.set_name ("EditorTimeButton");
496 zoom_out_button.set_name ("EditorTimeButton");
497 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
498 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
500 // zoom_onetoone_button.set_name ("EditorTimeButton");
501 zoom_out_full_button.set_name ("EditorTimeButton");
502 // ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1"));
503 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
505 zoom_in_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_in_button_xpm)))));
506 zoom_out_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_button_xpm)))));
507 zoom_out_full_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_full_button_xpm)))));
508 // zoom_onetoone_button.add (*(manage (new Gtk::Image (zoom_onetoone_button_xpm))));
511 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
512 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
513 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
514 // zoom_onetoone_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom), 1.0));
516 zoom_indicator_box.pack_start (zoom_out_button, false, false);
517 zoom_indicator_box.pack_start (zoom_in_button, false, false);
518 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
519 // zoom_indicator_box.pack_start (zoom_onetoone_button, false, false);
520 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
522 zoom_indicator_label.set_text (_("Zoom Span"));
523 zoom_indicator_label.set_name ("ToolBarLabel");
526 zoom_indicator_vbox.set_spacing (3);
527 zoom_indicator_vbox.set_border_width (3);
528 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
529 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
532 bottom_hbox.set_border_width (3);
533 bottom_hbox.set_spacing (3);
535 route_list.set_name ("TrackListDisplay");
536 route_list.set_size_request (75,-1);
537 route_list.column_titles_active();
538 route_list.set_compare_func (route_list_compare_func);
539 route_list.set_shadow_type (Gtk::SHADOW_IN);
540 route_list.set_selection_mode (Gtk::SELECTION_MULTIPLE);
541 route_list.set_reorderable (true);
542 edit_group_list.set_size_request (75, -1);
544 route_list_scroller.add (route_list);
545 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
547 route_list.select_row.connect (mem_fun(*this, &Editor::route_list_selected));
548 route_list.unselect_row.connect (mem_fun(*this, &Editor::route_list_unselected));
549 route_list.row_move.connect (mem_fun(*this, &Editor::queue_route_list_reordered));
550 route_list.click_column.connect (mem_fun(*this, &Editor::route_list_column_click));
552 edit_group_list_button_label.set_text (_("Edit Groups"));
553 edit_group_list_button_label.set_name ("EditGroupTitleButton");
554 edit_group_list_button.add (edit_group_list_button_label);
555 edit_group_list_button.set_name ("EditGroupTitleButton");
557 edit_group_list.column_titles_hide();
558 edit_group_list.set_name ("MixerGroupList");
559 edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
560 edit_group_list.set_selection_mode (Gtk::SELECTION_MULTIPLE);
561 edit_group_list.set_reorderable (false);
562 edit_group_list.set_size_request (75, -1);
563 edit_group_list.set_column_auto_resize (0, true);
564 edit_group_list.columns_autosize ();
566 edit_group_list_scroller.add (edit_group_list);
567 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
569 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
570 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
571 edit_group_list.select_row.connect (mem_fun(*this, &Editor::edit_group_selected));
572 edit_group_list.unselect_row.connect (mem_fun(*this, &Editor::edit_group_unselected));
574 list<string> stupid_list;
576 stupid_list.push_back ("*");
577 stupid_list.push_back (_("-all-"));
579 edit_group_list.rows().push_back (stupid_list);
580 edit_group_list.rows().back().set_data (0);
581 edit_group_list.rows().back().select();
583 edit_group_vbox.pack_start (edit_group_list_button, false, false);
584 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
586 route_list_frame.set_name ("BaseFrame");
587 route_list_frame.set_shadow_type (Gtk::SHADOW_IN);
588 route_list_frame.add (route_list_scroller);
590 edit_group_list_frame.set_name ("BaseFrame");
591 edit_group_list_frame.set_shadow_type (Gtk::SHADOW_IN);
592 edit_group_list_frame.add (edit_group_vbox);
594 route_group_vpane.add1 (route_list_frame);
595 route_group_vpane.add2 (edit_group_list_frame);
597 list_vpacker.pack_start (route_group_vpane, true, true);
599 region_list_model = TreeStore::create (region_list_columns));
600 region_list_sort_model = TreeModelSort::create (region_list_model);
601 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
603 region_list_display.set_model (region_list_sort_model);
604 region_list_display.append_column (_("Regions"), region_list_columns.name);
605 region_list_display.set_reorderable (true);
606 region_list_display.set_size_request (100, -1);
607 region_list_display.set_data ("editor", this);
608 region_list_display.set_flags (Gtk::CAN_FOCUS);
609 region_list_display.set_name ("RegionListDisplay");
611 region_list_scroller.add (region_list_display);
612 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
614 region_list_display.drag_dest_set (GTK_DEST_DEFAULT_ALL,
615 target_table, n_targets - 1,
616 GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
617 region_list_display.drag_data_received.connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
619 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
620 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
621 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
622 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
623 region_list_display.signal_motion_notify_event().connect (mem_fun(*this, &Editor::region_list_display_motion));
624 region_list_display.signal_enter_notify_event().connect (mem_fun(*this, &Editor::region_list_display_enter_notify));
625 region_list_display.signal_leave_notify_event().connect (mem_fun(*this, &Editor::region_list_display_leave_notify));
626 region_list_display.select_row.connect (mem_fun(*this, &Editor::region_list_display_selected));
627 region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
628 region_list_display.click_column.connect (mem_fun(*this, &Editor::region_list_column_click));
630 named_selection_scroller.add (named_selection_display);
631 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
633 named_selection_display.set_name ("RegionListDisplay");
634 named_selection_display.set_size_request (100, -1);
635 named_selection_display.column_titles_active ();
636 named_selection_display.set_selection_mode (Gtk::SELECTION_SINGLE);
638 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
639 named_selection_display.select_row.connect (mem_fun(*this, &Editor::named_selection_display_selected));
640 named_selection_display.unselect_row.connect (mem_fun(*this, &Editor::named_selection_display_unselected));
642 region_selection_vpane.pack1 (region_list_scroller, true, true);
643 region_selection_vpane.pack2 (named_selection_scroller, true, true);
645 canvas_region_list_pane.pack1 (edit_frame, true, true);
646 canvas_region_list_pane.pack2 (region_selection_vpane, true, true);
648 track_list_canvas_pane.signal_size_allocate().connect_after (bind (mem_fun(*this, &Editor::pane_allocation_handler),
649 static_cast<Gtk::Paned*> (&track_list_canvas_pane)));
650 canvas_region_list_pane.signal_size_allocate().connect_after (bind (mem_fun(*this, &Editor::pane_allocation_handler),
651 static_cast<Gtk::Paned*> (&canvas_region_list_pane)));
652 route_group_vpane.signal_size_allocate().connect_after (bind (mem_fun(*this, &Editor::pane_allocation_handler),
653 static_cast<Gtk::Paned*> (&route_group_vpane)));
654 region_selection_vpane.signal_size_allocate().connect_after (bind (mem_fun(*this, &Editor::pane_allocation_handler),
655 static_cast<Gtk::Paned*> (®ion_selection_vpane)));
657 track_list_canvas_pane.pack1 (list_vpacker, true, true);
658 track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true);
660 /* provide special pane-handle event handling for easy "hide" action */
662 /* 0: collapse to show left/upper child
663 1: collapse to show right/lower child
666 route_group_vpane.set_data ("collapse-direction", (gpointer) 0);
667 region_selection_vpane.set_data ("collapse-direction", (gpointer) 0);
668 canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0);
669 track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1);
671 route_group_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&route_group_vpane)));
672 region_selection_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (®ion_selection_vpane)));
673 canvas_region_list_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&canvas_region_list_pane)));
674 track_list_canvas_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&track_list_canvas_pane)));
676 top_hbox.pack_start (toolbar_frame, true, true);
678 HBox *hbox = manage (new HBox);
679 hbox->pack_start (track_list_canvas_pane, true, true);
681 global_vpacker.pack_start (top_hbox, false, false);
682 global_vpacker.pack_start (*hbox, true, true);
684 global_hpacker.pack_start (global_vpacker, true, true);
686 set_name ("EditorWindow");
688 vpacker.pack_end (global_hpacker, true, true);
690 _playlist_selector = new PlaylistSelector();
691 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
693 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
697 nudge_forward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
698 nudge_backward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
700 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
701 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
703 nudge_forward_button.set_name ("TransportButton");
704 nudge_backward_button.set_name ("TransportButton");
706 fade_context_menu.set_name ("ArdourContextMenu");
708 install_keybindings ();
710 set_title (_("ardour: editor"));
711 set_wmclass (_("ardour_editor"), "Ardour");
714 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
716 configure_event.connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
717 delete_event.connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
725 /* <CMT Additions> */
726 if(image_socket_listener)
728 if(image_socket_listener->is_connected())
730 image_socket_listener->close_connection() ;
733 delete image_socket_listener ;
734 image_socket_listener = 0 ;
736 /* </CMT Additions> */
740 Editor::add_toplevel_controls (Container& cont)
742 vpacker.pack_start (cont, false, false);
747 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
749 /* note: the selection will take care of the vanishing
750 audioregionview by itself.
753 if (clicked_regionview == rv) {
754 clicked_regionview = 0;
757 if (entered_regionview == rv) {
758 set_entered_regionview (0);
763 Editor::set_entered_regionview (AudioRegionView* rv)
765 if (rv == entered_regionview) {
769 if (entered_regionview) {
770 entered_regionview->exited ();
773 if ((entered_regionview = rv) != 0) {
774 entered_regionview->entered ();
779 Editor::set_entered_track (TimeAxisView* tav)
782 entered_track->exited ();
785 if ((entered_track = tav) != 0) {
786 entered_track->entered ();
791 Editor::left_track_canvas (GdkEventCrossing *ev)
793 set_entered_track (0);
794 set_entered_regionview (0);
800 Editor::initialize_canvas ()
802 gnome_canvas_init ();
804 /* adjust sensitivity for "picking" items */
806 // GNOME_CANVAS(track_gnome_canvas)->close_enough = 2;
808 track_canvas.signal_event().connect (slot (*this, &Editor::track_canvas_event));
809 track_canvas.set_name ("EditorMainCanvas");
810 track_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
811 track_canvas.signal_event().connect (slot (*this, &Editor::track_canvas_event));
812 track_canvas.signal_leave_notify_event().connect (mem_fun(*this, &Editor::left_track_canvas));
814 /* set up drag-n-drop */
816 track_canvas.drag_dest_set (GTK_DEST_DEFAULT_ALL,
817 target_table, n_targets - 1,
818 GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
819 track_canvas.drag_data_received.connect (mem_fun(*this, &Editor::track_canvas_drag_data_received));
821 /* stuff for the verbose canvas cursor */
823 Pango::FontDescription font = get_font_for_style (N_("VerboseCanvasCursor"));
825 verbose_canvas_cursor = new Canvas::Text (track_canvas.root());
826 verbose_canvas_cursor->property_font_descr() << font;
827 verbose_canvas_cursor->property_anchor() << GTK_ANCHOR_NW;
828 verbose_canvas_cursor->property_fill_color_rgba() << color_map[cVerboseCanvasCursor];
830 verbose_cursor_visible = false;
832 /* a group to hold time (measure) lines */
834 time_line_group = new Canvas::Group (track_canvas.root(), 0.0, 0.0);
835 cursor_group = new Canvas::Group (track_canvas.root(), 0.0, 0.0);
837 time_canvas.set_name ("EditorTimeCanvas");
838 time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
840 meter_group = new Canvas::Group (time_canvas.root(), 0.0, 0.0);
841 tempo_group = new Canvas::Group (time_canvas.root(), 0.0, 0.0);
842 marker_group = new Canvas::Group (time_canvas.root(), 0.0, timebar_height * 2.0);
843 range_marker_group = new Canvas::Group (time_canvas.root(), 0.0, timebar_height * 3.0);
844 transport_marker_group = new Canvas::Group (time_canvas.root(), 0.0, timebar_height * 4.0);
846 tempo_bar = Canvas::SimpleRect (*tempo_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
847 tempo_bar->property_fill_color_rgba() << color_map[cTempoBar];
848 tempo_bar->property_outline_pixels() << 0;
850 meter_bar = Canvas::SimpleRect (*meter_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
851 meter_bar->property_fill_color_rgba() << color_map[cMeterBar];
852 meter_bar->property_outline_pixels() << 0;
854 marker_bar = Canvas::SimpleRect (*marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
855 marker_bar->property_fill_color_rgba() << color_map[cMarkerBar];
856 marker_bar->property_outline_pixels() << 0;
858 range_marker_bar = Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
859 range_marker_bar->property_fill_color_rgba() << color_map[cRangeMarkerBar];
860 range_marker_bar->property_outline_pixels() << 0;
862 transport_marker_bar = Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
863 transport_marker_bar->property_fill_color_rgba() << color_map[cTransportMarkerBar];
864 transport_marker_bar->property_outline_pixels() << 0;
866 range_bar_drag_rect = Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
867 range_bar_drag_rect->property_fill_color_rgba() << color_map[cRangeBarDragRectFill];
868 range_bar_drag_rect->property_outline_color_rgba() << color_map[cRangeBarDragRect];
869 range_bar_drag_rect->property_outline_pixels() << 0;
870 range_bar_drag_rect->hide ();
872 transport_bar_drag_rect = Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
873 transport_bar_drag_rect ->property_fill_color_rgba() << color_map[cTransportBarDragRectFill];
874 transport_bar_drag_rect->property_outline_color_rgba() << color_map[cTransportBarDragRect];
875 transport_bar_drag_rect->property_outline_pixels() << 0;
876 transport_bar_drag_rect->hide ();
878 marker_drag_line_points = new Canvas::Points (2);
879 marker_drag_line_points[0]->set_x (0.0);
880 marker_drag_line_points[0]->set_y (0.0);
881 marker_drag_line_points[1]->set_x (0.0);
882 marker_drag_line_points[1]->set_y (0.0);
884 marker_drag_line = Canvas::Line (track_canvas.root());
885 marker_drag_line->property_width_pixels() << 1;
886 marker_drag_line->property_fill_color_rgba() << color_map[cMarkerDragLine];
887 marker_drag_line->property_points() << marker_drag_line_points;
888 marker_drag_line->hide();
890 range_marker_drag_rect = new Canvas::SimpleRect (track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
891 range_marker_drag_rect->property_fill_color_rgba() << color_map[cRangeDragRectFill];
892 range_marker_drag_rect->property_outline_color_rgba() << color_map[cRangeDragRect];
893 range_marker_drag_rect->hide ();
895 transport_loop_range_rect = new Canvas::Simplerect (group.root(), 0.0, 0.0, 0.0, 0.0);
896 transport_loop_range_rect->property_fill_color_rgba() << color_map[cTransportLoopRectFill];
897 transport_loop_range_rect->property_outline_color_rgba() << color_map[cTransportLoopRect];
898 transport_loop_range_rect->property_outline_pixels() << 1;
899 transport_loop_range_rect->hide();
901 transport_punch_range_rect = new Canvas::Simplerect (group.root(), 0.0, 0.0, 0.0, 0.0);
902 transport_punch_range_rect->property_fill_color_rgba() << color_map[cTransportPunchRectFill];
903 transport_punch_range_rect->property_outline_color_rgba() << color_map[cTransportPunchRect];
904 transport_punch_range_rect->property_outline_pixels() << 0;
905 transport_punch_range_rect->hide();
907 transport_loop_range_rect->lower_to_bottom (); // loop on the bottom
909 transport_punchin_line = new Canvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
910 transport_punchin_line->property_outline_color_rgba() << color_map[cPunchInLine];
911 transport_punchin_line->property_outline_pixels() << 1;
912 transport_punchin_line->hide ();
914 transport_punchout_line = new Canvas::Simplerect (group.root(), 0.0, 0.0, 0.0, 0.0);
915 transport_punchout_line->property_outline_color_rgba() << color_map[cPunchOutLine];
916 transport_punchout_line->property_outline_pixels() << 1;
917 transport_punchout_line->hide();
919 // used to show zoom mode active zooming
920 zoom_rect = new Canvas::Simplerect (track_gnome_canvas.root(), 0.0, 0.0, 0.0, 0.0);
921 zoom_rect->property_fill_color_rgba() << color_map[cZoomRectFill];
922 zoom_rect->property_outline_color_rgba() << color_map[cZoomRect];
923 zoom_rect->property_outline_pixels() << 1;
926 zoom_rect.signal_event().connect (slot (*this, &PublicEditor::canvas_zoom_rect_event));
928 // used as rubberband rect
929 rubberband_rect = new Canvas::Simplerect (track_gnome_canvas.root(), 0.0, 0.0, 0.0, 0.0);
930 rubberband_rect->property_outline_color_rgba() << color_map[cRubberBandRect];
931 rubberband_rect->property_fill_color_rgba() << (guint32) color_map[cRubberBandRectFill];
932 rubberband_rect->property_outline_pixels() << 1;
933 rubberband_rect->hide();
935 tempo_bar.signal_event().connect (slot (*this, &PublicEditor::canvas_tempo_bar_event));
936 meter_bar.signal_event().connect (slot (*this, &PublicEditor::canvas_meter_bar_event));
937 marker_bar.signal_event().connect (slot (*this, &PublicEditor::canvas_marker_bar_event));
938 range_marker_bar.signal_event().connect (slot (*this, &PublicEditor::canvas_range_marker_bar_event));
939 transport_marker_bar.signal_event().connect (slot (*this, &PublicEditor::canvas_transport_marker_bar_event));
941 /* separator lines */
943 tempo_line_points = new Canvas::Points (2);
944 tempo_line_points[0]->set_x (0.0);
945 tempo_line_points[0]->set_y (timebar_height);
946 tempo_line_points[1]->set_x (max_canvas_coordinate);
947 tempo_line_points[1]->set_y (timebar_height);
949 tempo_line = Canvas::Line (*tempo_group, *tempo_line_points);
950 tempo_line->property_width_pixels() << 0;
951 tempo_line->property_fill_color() << "black";
953 meter_line_points = new Canvas::Points (2);
954 meter_line_points[0]->set_x (0);
955 meter_line_points[0]->set_y (timebar_height);
956 meter_line_points[1]->set_x (max_canvas_coordinate);
957 meter_line_points[1]->set_y (timebar_height);
959 meter_line = Canvas::Line (*meter_group, *meter_line_points);
960 meter_line->property_width_pixels() << 0;
961 meter_line->property_fill_color() << "black";
963 marker_line_points = Canvas::Points (2);
964 marker_line_points[0]->set_x (0);
965 marker_line_points[0]->set_y (timebar_height);
966 marker_line_points[1]->set_x (max_canvas_coordinate);
967 marker_line_points[1]->set_y (timebar_height);
969 marker_line = new Canvas::Line (*marker_group, *marker_line_points);
970 marker_line->property_width_pixels() << 0;
971 marker_line->property_fill_color() << "black";
973 range_marker_line = new Canvas::Line (*range_marker_group, marker_line_points);
974 range_marker_line->property_width_pixels() << 0;
975 range_marker_line->property_fill_color() << "black";
977 transport_marker_line = new Canvas::Line (*transport_marker_group, marker_line_points);
978 transport_marker_line->property_width_pixels() << 0;
979 transport_marker_line->property_fill_color() << "black";
981 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_loop_range_view), false));
982 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_punch_range_view), false));
984 double time_height = timebar_height * 5;
985 double time_width = FLT_MAX/frames_per_unit;
986 gnome_canvas_set_scroll_region (GNOME_CANVAS(time_gnome_canvas), 0.0, 0.0, time_width, time_height);
988 edit_cursor = new Cursor (*this, "blue", (GtkSignalFunc) _canvas_edit_cursor_event);
989 playhead_cursor = new Cursor (*this, "red", (GtkSignalFunc) _canvas_playhead_cursor_event);
991 track_canvas.size_allocate.connect (mem_fun(*this, &Editor::track_canvas_allocate));
995 Editor::show_window ()
999 /* now reset all audio_time_axis heights, because widgets might need
1005 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1006 tv = (static_cast<TimeAxisView*>(*i));
1007 tv->reset_height ();
1012 Editor::tie_vertical_scrolling ()
1014 edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
1016 float y1 = track_canvas_scroller.get_vadjustment()->get_value();
1017 playhead_cursor->set_y_axis(y1);
1018 edit_cursor->set_y_axis(y1);
1022 Editor::set_frames_per_unit (double fpu)
1024 jack_nframes_t frames;
1026 if (fpu == frames_per_unit) {
1034 // convert fpu to frame count
1036 frames = (jack_nframes_t) (fpu * canvas_width);
1038 /* don't allow zooms that fit more than the maximum number
1039 of frames into an 800 pixel wide space.
1042 if (max_frames / fpu < 800.0) {
1046 frames_per_unit = fpu;
1048 if (frames != zoom_range_clock.current_duration()) {
1049 zoom_range_clock.set (frames);
1052 /* only update these if we not about to call reposition_x_origin,
1053 which will do the same updates.
1057 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1060 if (!no_zoom_repos_update) {
1061 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1062 update_hscroller ();
1063 update_fixed_rulers ();
1064 tempo_map_changed (Change (0));
1067 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
1068 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1069 (*i)->reshow_selection (selection->time);
1073 ZoomChanged (); /* EMIT_SIGNAL */
1075 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
1076 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
1083 Editor::instant_save ()
1085 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
1090 session->add_instant_xml(get_state(), session->path());
1092 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
1097 Editor::reposition_x_origin (jack_nframes_t frame)
1099 if (frame != leftmost_frame) {
1100 leftmost_frame = frame;
1101 double pixel = frame_to_pixel (frame);
1102 if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
1103 track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
1105 track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
1106 XOriginChanged (); /* EMIT_SIGNAL */
1111 Editor::edit_cursor_clock_changed()
1113 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
1114 edit_cursor->set_position (edit_cursor_clock.current_time());
1120 Editor::zoom_adjustment_changed ()
1122 if (session == 0 || no_zoom_repos_update) {
1126 double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width;
1130 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1132 else if (fpu > session->current_end_frame() / (double) canvas_width) {
1133 fpu = session->current_end_frame() / (double) canvas_width;
1134 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1137 temporal_zoom (fpu);
1141 Editor::canvas_horizontally_scrolled ()
1143 /* XXX note the potential loss of accuracy here caused by
1144 adjustments being 32bit floats with only a 24 bit mantissa,
1145 whereas jack_nframes_t is at least a 32 bit uint32_teger.
1148 leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
1150 update_hscroller ();
1151 update_fixed_rulers ();
1153 if (!edit_hscroll_dragging) {
1154 tempo_map_changed (Change (0));
1156 update_tempo_based_rulers();
1161 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
1163 if (!repos_zoom_queued) {
1164 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
1165 repos_zoom_queued = true;
1170 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
1172 /* if we need to force an update to the hscroller stuff,
1173 don't set no_zoom_repos_update.
1176 no_zoom_repos_update = (frame != leftmost_frame);
1178 set_frames_per_unit (nfpu);
1179 if (no_zoom_repos_update) {
1180 reposition_x_origin (frame);
1182 no_zoom_repos_update = false;
1183 repos_zoom_queued = false;
1189 Editor::on_realize ()
1191 /* Even though we're not using acceleration, we want the
1195 track_context_menu.accelerate (*this->get_toplevel());
1196 track_region_context_menu.accelerate (*this->get_toplevel());
1198 Window::on_realize ();
1200 GdkPixmap* empty_pixmap = gdk_pixmap_new (get_window()->gobj(), 1, 1, 1);
1201 GdkPixmap* empty_bitmap = gdk_pixmap_new (get_window()->gobj(), 1, 1, 1);
1202 GdkColor white = { 0, 0, 0 };
1204 null_cursor = gdk_cursor_new_from_pixmap (empty_pixmap, empty_bitmap, &white, &white, 0, 0);
1212 track_canvas_scroller.get_window()->set_cursor (current_canvas_cursor);
1213 time_canvas_scroller.get_window()->set_cursor (timebar_cursor);
1217 Editor::track_canvas_allocate (GtkAllocation *alloc)
1219 canvas_width = alloc->width;
1220 canvas_height = alloc->height;
1222 if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) {
1224 Pango::FontDescription font = get_font_for_style (N_("FirstActionMessage"));
1226 const char *txt1 = _("Start a new session\n");
1227 const char *txt2 = _("via Session menu");
1229 /* this mess of code is here to find out how wide this text is and
1230 position the message in the center of the editor window. there
1231 are two lines, so we use the longer of the the lines to
1232 compute width, and multiply the height by 2.
1238 /* this is a dummy widget that exists so that we can get the
1239 style from the RC file.
1242 Label foo (_(txt2));
1243 Glib::RefPtr<Pango::Layout> layout;
1244 foo.set_name ("NoSessionMessage");
1245 foo.ensure_style ();
1247 layout = foo.create_pango_layout (_(txt2));
1248 layout->set_font_description (font);
1249 layout->get_pixel_size (pixel_width, pixel_height);
1251 if (first_action_message == 0) {
1253 char txt[strlen(txt1)+strlen(txt2)+1];
1255 /* merge both lines */
1257 strcpy (txt, _(txt1));
1258 strcat (txt, _(txt2));
1260 first_action_message = gnome_canvas_item_new (gnome_canvas_root(GNOME_CANVAS(track_gnome_canvas)),
1261 gnome_canvas_text_get_type(),
1263 "fill_color_rgba", color_map[cFirstActionMessage],
1264 "x", (gdouble) (canvas_width - pixel_width) / 2.0,
1265 "y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)),
1266 "anchor", GTK_ANCHOR_NORTH_WEST,
1274 gnome_canvas_item_set (first_action_message,
1275 "x", (gdouble) (canvas_width - pixel_width) / 2.0,
1276 "y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)),
1281 zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit));
1282 edit_cursor->set_position (edit_cursor->current_frame);
1283 playhead_cursor->set_position (playhead_cursor->current_frame);
1284 reset_scrolling_region (alloc);
1286 Resized (); /* EMIT_SIGNAL */
1290 Editor::reset_scrolling_region (GtkAllocation *alloc)
1292 guint32 last_canvas_unit;
1294 guint32 canvas_alloc_height, canvas_alloc_width;
1295 TrackViewList::iterator i;
1296 static bool first_time = true;
1298 /* We need to make sure that the canvas always has its
1299 scrolling region set to larger of:
1301 - the size allocated for it (within the container its packed in)
1302 - the size required to see the entire session
1304 If we don't ensure at least the first of these, the canvas
1305 does some wierd and in my view unnecessary stuff to center
1306 itself within the allocated area, which causes bad, bad
1309 XXX GnomeCanvas has fixed this, and has an option to
1310 control the centering behaviour.
1313 last_canvas_unit = (guint32) ceil ((float) max_frames / frames_per_unit);
1318 for (i = track_views.begin(); i != track_views.end(); ++i) {
1319 if ((*i)->control_parent) {
1320 height += (*i)->effective_height;
1321 height += track_spacing;
1326 height -= track_spacing;
1330 canvas_height = (guint32) height;
1333 canvas_alloc_height = alloc->height;
1334 canvas_alloc_width = alloc->width;
1336 canvas_alloc_height = track_gnome_canvas->allocation.height;
1337 canvas_alloc_width = track_gnome_canvas->allocation.width;
1340 canvas_height = max (canvas_height, canvas_alloc_height);
1342 gnome_canvas_set_scroll_region (GNOME_CANVAS(track_gnome_canvas), 0.0, 0.0,
1343 max (last_canvas_unit, canvas_alloc_width),
1346 if (edit_cursor) edit_cursor->set_length (canvas_alloc_height);
1347 if (playhead_cursor) playhead_cursor->set_length (canvas_alloc_height);
1349 if (marker_drag_line) {
1350 marker_drag_line_points->coords[3] = canvas_height;
1351 // cerr << "set mlA points, nc = " << marker_drag_line_points->num_points << endl;
1352 gnome_canvas_item_set (marker_drag_line, "points", marker_drag_line_points, NULL);
1354 if (range_marker_drag_rect) {
1355 gnome_canvas_item_set (range_marker_drag_rect, "y1", 0.0, "y2", (double) canvas_height, NULL);
1357 if (transport_loop_range_rect) {
1358 gnome_canvas_item_set (transport_loop_range_rect, "y1", 0.0, "y2", (double) canvas_height, NULL);
1360 if (transport_punch_range_rect) {
1361 gnome_canvas_item_set (transport_punch_range_rect, "y1", 0.0, "y2", (double) canvas_height, NULL);
1363 if (transport_punchin_line) {
1364 gnome_canvas_item_set (transport_punchin_line, "y1", 0.0, "y2", (double) canvas_height, NULL);
1366 if (transport_punchout_line) {
1367 gnome_canvas_item_set (transport_punchout_line, "y1", 0.0, "y2", (double) canvas_height, NULL);
1371 update_fixed_rulers ();
1373 if (is_visible() && first_time) {
1374 tempo_map_changed (Change (0));
1382 Editor::queue_session_control_changed (Session::ControlType t)
1384 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1388 Editor::session_control_changed (Session::ControlType t)
1390 // right now we're only tracking the loop and punch state
1393 case Session::AutoLoop:
1394 update_loop_range_view (true);
1396 case Session::PunchIn:
1397 case Session::PunchOut:
1398 update_punch_range_view (true);
1407 Editor::fake_add_edit_group (RouteGroup *group)
1409 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1413 Editor::fake_handle_new_audio_region (AudioRegion *region)
1415 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1419 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1421 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1425 Editor::fake_handle_new_duration ()
1427 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1431 Editor::start_scrolling ()
1433 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1434 (mem_fun(*this, &Editor::update_current_screen));
1436 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1437 (mem_fun(*this, &Editor::update_slower));
1441 Editor::stop_scrolling ()
1443 scroll_connection.disconnect ();
1444 slower_update_connection.disconnect ();
1448 Editor::map_position_change (jack_nframes_t frame)
1450 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1452 if (session == 0 || !_follow_playhead) {
1456 center_screen (frame);
1457 playhead_cursor->set_position (frame);
1461 Editor::center_screen (jack_nframes_t frame)
1463 float page = canvas_width * frames_per_unit;
1465 /* if we're off the page, then scroll.
1468 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1469 center_screen_internal (frame,page);
1474 Editor::center_screen_internal (jack_nframes_t frame, float page)
1479 frame -= (jack_nframes_t) page;
1484 reposition_x_origin (frame);
1488 Editor::handle_new_duration ()
1490 reset_scrolling_region ();
1493 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1494 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1497 update_hscroller ();
1501 Editor::update_title_s (string snap_name)
1503 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1509 Editor::update_title ()
1511 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1514 bool dirty = session->dirty();
1516 string wintitle = _("ardour: editor: ");
1522 wintitle += session->name();
1524 if (session->snap_name() != session->name()) {
1526 wintitle += session->snap_name();
1533 set_title (wintitle);
1538 Editor::connect_to_session (Session *t)
1542 if (first_action_message) {
1543 gnome_canvas_item_hide (first_action_message);
1546 flush_track_canvas();
1550 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1552 /* These signals can all be emitted by a non-GUI thread. Therefore the
1553 handlers for them must not attempt to directly interact with the GUI,
1554 but use Gtkmm2ext::UI::instance()->call_slot();
1557 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1558 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1559 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1560 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1561 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1562 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1563 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1564 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1565 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1566 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1567 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1568 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1569 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1571 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1572 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1574 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1576 session->foreach_edit_group(this, &Editor::add_edit_group);
1578 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1579 editor_mixer_button.set_name (X_("EditorMixerButton"));
1581 edit_cursor_clock.set_session (session);
1582 selection_start_clock.set_session (session);
1583 selection_end_clock.set_session (session);
1584 zoom_range_clock.set_session (session);
1585 _playlist_selector->set_session (session);
1586 nudge_clock.set_session (session);
1588 switch (session->get_edit_mode()) {
1590 edit_mode_selector.get_entry()->set_text (edit_mode_strings[splice_index]);
1594 edit_mode_selector.get_entry()->set_text (edit_mode_strings[slide_index]);
1598 Location* loc = session->locations()->auto_loop_location();
1600 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1601 if (loc->start() == loc->end()) {
1602 loc->set_end (loc->start() + 1);
1604 session->locations()->add (loc, false);
1605 session->set_auto_loop_location (loc);
1609 loc->set_name (_("Loop"));
1612 loc = session->locations()->auto_punch_location();
1614 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1615 if (loc->start() == loc->end()) {
1616 loc->set_end (loc->start() + 1);
1618 session->locations()->add (loc, false);
1619 session->set_auto_punch_location (loc);
1623 loc->set_name (_("Punch"));
1626 update_loop_range_view (true);
1627 update_punch_range_view (true);
1629 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1632 refresh_location_display ();
1633 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1634 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1635 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1636 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1637 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1639 reset_scrolling_region ();
1641 redisplay_regions ();
1642 redisplay_named_selections ();
1644 route_list.freeze ();
1645 route_list.clear ();
1646 session->foreach_route (this, &Editor::handle_new_route);
1647 // route_list.select_all ();
1649 route_list_reordered ();
1652 if (embed_audio_item) {
1653 embed_audio_item->set_sensitive (true);
1655 if (import_audio_item) {
1656 import_audio_item->set_sensitive (true);
1659 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1660 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1663 /* ::reposition_x_origin() doesn't work right here, since the old
1664 position may be zero already, and it does nothing in such
1670 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1671 track_canvas_scroller.get_hadjustment()->set_value (0);
1673 update_hscroller ();
1674 restore_ruler_visibility ();
1675 tempo_map_changed (Change (0));
1677 edit_cursor->set_position (0);
1678 playhead_cursor->set_position (0);
1682 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1685 /* don't show master bus in a new session */
1687 if (ARDOUR_UI::instance()->session_is_new ()) {
1689 Gtk::CList_Helpers::RowList::iterator i;
1690 Gtk::CList_Helpers::RowList& rowlist = route_list.rows();
1692 route_list.freeze ();
1694 for (i = rowlist.begin(); i != rowlist.end(); ++i) {
1695 TimeAxisView *tv = (TimeAxisView *) i->get_data ();
1696 AudioTimeAxisView *atv;
1698 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1699 if (atv->route().master()) {
1710 Editor::build_cursors ()
1712 GdkPixmap *source, *mask;
1713 GdkColor fg = { 0, 65535, 0, 0 }; /* Red. */
1714 GdkColor bg = { 0, 0, 0, 65535 }; /* Blue. */
1716 source = gdk_bitmap_create_from_data (NULL, hand_bits,
1717 hand_width, hand_height);
1718 mask = gdk_bitmap_create_from_data (NULL, handmask_bits,
1719 handmask_width, handmask_height);
1720 grabber_cursor = gdk_cursor_new_from_pixmap (source, mask, &fg, &bg, hand_x_hot, hand_y_hot);
1721 gdk_pixmap_unref (source);
1722 gdk_pixmap_unref (mask);
1725 GdkColor mbg = { 0, 0, 0, 0 }; /* Black */
1726 GdkColor mfg = { 0, 0, 0, 65535 }; /* Blue. */
1728 source = gdk_bitmap_create_from_data (NULL, mag_bits,
1729 mag_width, mag_height);
1730 mask = gdk_bitmap_create_from_data (NULL, magmask_bits,
1731 mag_width, mag_height);
1732 zoom_cursor = gdk_cursor_new_from_pixmap (source, mask, &mfg, &mbg, mag_x_hot, mag_y_hot);
1733 gdk_pixmap_unref (source);
1734 gdk_pixmap_unref (mask);
1736 GdkColor fbg = { 0, 65535, 65535, 65535 };
1737 GdkColor ffg = { 0, 0, 0, 0 };
1739 source = gdk_bitmap_create_from_data (NULL, fader_cursor_bits,
1740 fader_cursor_width, fader_cursor_height);
1741 mask = gdk_bitmap_create_from_data (NULL, fader_cursor_mask_bits,
1742 fader_cursor_width, fader_cursor_height);
1743 fader_cursor = gdk_cursor_new_from_pixmap (source, mask, &ffg, &fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1744 gdk_pixmap_unref (source);
1745 gdk_pixmap_unref (mask);
1747 source = gdk_bitmap_create_from_data (NULL, speaker_cursor_bits,
1748 speaker_cursor_width, speaker_cursor_height);
1749 mask = gdk_bitmap_create_from_data (NULL, speaker_cursor_mask_bits,
1750 speaker_cursor_width, speaker_cursor_height);
1751 speaker_cursor = gdk_cursor_new_from_pixmap (source, mask, &ffg, &fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1752 gdk_pixmap_unref (source);
1753 gdk_pixmap_unref (mask);
1755 cross_hair_cursor = gdk_cursor_new (GDK_CROSSHAIR);
1756 trimmer_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
1757 selector_cursor = gdk_cursor_new (GDK_XTERM);
1758 time_fx_cursor = gdk_cursor_new (GDK_SIZING);
1759 wait_cursor = gdk_cursor_new (GDK_WATCH);
1760 timebar_cursor = gdk_cursor_new (GDK_LEFT_PTR);
1764 Editor::popup_fade_context_menu (int button, int32_t time, GnomeCanvasItem* item, ItemType item_type)
1766 using namespace Menu_Helpers;
1767 AudioRegionView* arv = static_cast<AudioRegionView*> (gtk_object_get_data (GTK_OBJECT(item), "regionview"));
1770 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1774 MenuList& items (fade_context_menu.items());
1778 switch (item_type) {
1780 case FadeInHandleItem:
1781 if (arv->region.fade_in_active()) {
1782 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1784 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1787 items.push_back (SeparatorElem());
1789 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1790 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1791 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1792 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1793 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1797 case FadeOutHandleItem:
1798 if (arv->region.fade_out_active()) {
1799 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1801 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1804 items.push_back (SeparatorElem());
1806 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1807 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1808 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1809 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1810 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1814 fatal << _("programming error: ")
1815 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1820 fade_context_menu.popup (button, time);
1824 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1826 using namespace Menu_Helpers;
1827 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1830 switch (item_type) {
1832 case AudioRegionViewName:
1833 case AudioRegionViewNameHighlight:
1834 if (with_selection) {
1835 build_menu_function = &Editor::build_track_selection_context_menu;
1837 build_menu_function = &Editor::build_track_region_context_menu;
1842 if (with_selection) {
1843 build_menu_function = &Editor::build_track_selection_context_menu;
1845 build_menu_function = &Editor::build_track_context_menu;
1849 case CrossfadeViewItem:
1850 build_menu_function = &Editor::build_track_crossfade_context_menu;
1854 if (clicked_audio_trackview->get_diskstream()) {
1855 build_menu_function = &Editor::build_track_context_menu;
1857 build_menu_function = &Editor::build_track_bus_context_menu;
1862 /* probably shouldn't happen but if it does, we don't care */
1866 menu = (this->*build_menu_function)(frame);
1867 menu->set_name ("ArdourContextMenu");
1869 /* now handle specific situations */
1871 switch (item_type) {
1873 case AudioRegionViewName:
1874 case AudioRegionViewNameHighlight:
1875 if (!with_selection) {
1876 if (region_edit_menu_split_item) {
1877 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1878 region_edit_menu_split_item->set_sensitive (true);
1880 region_edit_menu_split_item->set_sensitive (false);
1883 if (region_edit_menu_split_multichannel_item) {
1884 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1885 region_edit_menu_split_multichannel_item->set_sensitive (true);
1887 region_edit_menu_split_multichannel_item->set_sensitive (false);
1896 case CrossfadeViewItem:
1903 /* probably shouldn't happen but if it does, we don't care */
1907 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1909 /* Bounce to disk */
1911 using namespace Menu_Helpers;
1912 MenuList& edit_items = menu->items();
1914 edit_items.push_back (SeparatorElem());
1916 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1917 case AudioTrack::NoFreeze:
1918 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1921 case AudioTrack::Frozen:
1922 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1925 case AudioTrack::UnFrozen:
1926 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1932 menu->popup (button, time);
1936 Editor::build_track_context_menu (jack_nframes_t ignored)
1938 using namespace Menu_Helpers;
1940 MenuList& edit_items = track_context_menu.items();
1943 add_dstream_context_items (edit_items);
1944 return &track_context_menu;
1948 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1950 using namespace Menu_Helpers;
1952 MenuList& edit_items = track_context_menu.items();
1955 add_bus_context_items (edit_items);
1956 return &track_context_menu;
1960 Editor::build_track_region_context_menu (jack_nframes_t frame)
1962 using namespace Menu_Helpers;
1963 MenuList& edit_items = track_region_context_menu.items();
1966 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1972 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1973 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1974 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1975 add_region_context_items (atv->view, (*i), edit_items);
1981 add_dstream_context_items (edit_items);
1983 return &track_region_context_menu;
1987 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1989 using namespace Menu_Helpers;
1990 MenuList& edit_items = track_crossfade_context_menu.items();
1991 edit_items.clear ();
1993 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
2000 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
2002 Playlist::RegionList* regions = pl->regions_at (frame);
2003 AudioPlaylist::Crossfades xfades;
2005 apl->crossfades_at (frame, xfades);
2007 bool many = xfades.size() > 1;
2009 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
2010 add_crossfade_context_items (atv->view, (*i), edit_items, many);
2013 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
2014 add_region_context_items (atv->view, (*i), edit_items);
2021 add_dstream_context_items (edit_items);
2023 return &track_crossfade_context_menu;
2027 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
2029 using namespace Menu_Helpers;
2030 MenuList& edit_items = track_selection_context_menu.items();
2031 edit_items.clear ();
2033 add_selection_context_items (edit_items);
2034 add_dstream_context_items (edit_items);
2036 return &track_selection_context_menu;
2040 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
2042 using namespace Menu_Helpers;
2043 Menu *xfade_menu = manage (new Menu);
2044 MenuList& items = xfade_menu->items();
2045 xfade_menu->set_name ("ArdourContextMenu");
2048 if (xfade->active()) {
2054 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
2055 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
2057 if (xfade->can_follow_overlap()) {
2059 if (xfade->following_overlap()) {
2060 str = _("Convert to short");
2062 str = _("Convert to full");
2065 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
2069 str = xfade->out().name();
2071 str += xfade->in().name();
2073 str = _("Crossfade");
2076 edit_items.push_back (MenuElem (str, *xfade_menu));
2077 edit_items.push_back (SeparatorElem());
2081 Editor::xfade_edit_left_region ()
2083 if (clicked_crossfadeview) {
2084 clicked_crossfadeview->left_view.show_region_editor ();
2089 Editor::xfade_edit_right_region ()
2091 if (clicked_crossfadeview) {
2092 clicked_crossfadeview->right_view.show_region_editor ();
2097 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
2099 using namespace Menu_Helpers;
2100 Menu *region_menu = manage (new Menu);
2101 MenuList& items = region_menu->items();
2102 region_menu->set_name ("ArdourContextMenu");
2104 AudioRegion* ar = 0;
2107 ar = dynamic_cast<AudioRegion*> (region);
2110 /* when this particular menu pops up, make the relevant region
2114 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
2116 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
2117 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
2118 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
2119 items.push_back (SeparatorElem());
2120 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
2121 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
2122 items.push_back (SeparatorElem());
2124 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
2125 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
2126 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
2127 items.push_back (SeparatorElem());
2129 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
2130 might be able to figure out which overloaded member function to use in
2134 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
2136 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
2137 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
2138 items.push_back (SeparatorElem());
2140 if (region->muted()) {
2141 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
2143 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
2145 items.push_back (SeparatorElem());
2147 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
2148 items.push_back (SeparatorElem());
2153 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
2154 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
2155 items.push_back (SeparatorElem());
2157 if (ar->scale_amplitude() != 1.0f) {
2158 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
2160 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
2163 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
2164 items.push_back (SeparatorElem());
2168 Menu *nudge_menu = manage (new Menu());
2169 MenuList& nudge_items = nudge_menu->items();
2170 nudge_menu->set_name ("ArdourContextMenu");
2172 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
2173 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
2174 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
2175 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
2177 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2178 items.push_back (SeparatorElem());
2180 Menu *trim_menu = manage (new Menu);
2181 MenuList& trim_items = trim_menu->items();
2182 trim_menu->set_name ("ArdourContextMenu");
2184 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
2185 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
2187 items.push_back (MenuElem (_("Trim"), *trim_menu));
2188 items.push_back (SeparatorElem());
2190 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
2191 region_edit_menu_split_item = &items.back();
2193 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
2194 region_edit_menu_split_multichannel_item = &items.back();
2196 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
2197 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
2198 items.push_back (SeparatorElem());
2199 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
2200 items.push_back (SeparatorElem());
2201 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
2203 /* OK, stick the region submenu at the top of the list, and then add
2207 /* we have to hack up the region name because "_" has a special
2208 meaning for menu titles.
2211 string::size_type pos = 0;
2212 string menu_item_name = region->name();
2214 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
2215 menu_item_name.replace (pos, 1, "__");
2219 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
2220 edit_items.push_back (SeparatorElem());
2224 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
2226 using namespace Menu_Helpers;
2227 Menu *selection_menu = manage (new Menu);
2228 MenuList& items = selection_menu->items();
2229 selection_menu->set_name ("ArdourContextMenu");
2231 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
2232 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
2233 items.push_back (SeparatorElem());
2234 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
2235 items.push_back (SeparatorElem());
2236 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
2237 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
2238 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
2239 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
2240 items.push_back (SeparatorElem());
2241 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
2242 items.push_back (SeparatorElem());
2243 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
2244 items.push_back (SeparatorElem());
2245 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
2247 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
2248 edit_items.push_back (SeparatorElem());
2252 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
2254 using namespace Menu_Helpers;
2258 Menu *play_menu = manage (new Menu);
2259 MenuList& play_items = play_menu->items();
2260 play_menu->set_name ("ArdourContextMenu");
2262 play_items.push_back (MenuElem (_("Play from edit cursor")));
2263 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2264 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
2265 play_items.push_back (SeparatorElem());
2266 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
2268 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2272 Menu *select_menu = manage (new Menu);
2273 MenuList& select_items = select_menu->items();
2274 select_menu->set_name ("ArdourContextMenu");
2276 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2277 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2278 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2279 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2280 select_items.push_back (SeparatorElem());
2281 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2282 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2283 select_items.push_back (SeparatorElem());
2285 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2289 Menu *cutnpaste_menu = manage (new Menu);
2290 MenuList& cutnpaste_items = cutnpaste_menu->items();
2291 cutnpaste_menu->set_name ("ArdourContextMenu");
2293 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2294 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2295 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2296 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
2298 cutnpaste_items.push_back (SeparatorElem());
2300 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
2301 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
2303 cutnpaste_items.push_back (SeparatorElem());
2305 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
2307 cutnpaste_items.push_back (SeparatorElem());
2309 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
2310 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
2312 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2314 /* Adding new material */
2316 Menu *import_menu = manage (new Menu());
2317 MenuList& import_items = import_menu->items();
2318 import_menu->set_name ("ArdourContextMenu");
2320 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2321 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
2323 edit_items.push_back (MenuElem (_("Import"), *import_menu));
2327 Menu *nudge_menu = manage (new Menu());
2328 MenuList& nudge_items = nudge_menu->items();
2329 nudge_menu->set_name ("ArdourContextMenu");
2331 edit_items.push_back (SeparatorElem());
2332 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2333 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2334 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2335 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2337 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2341 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2343 using namespace Menu_Helpers;
2347 Menu *play_menu = manage (new Menu);
2348 MenuList& play_items = play_menu->items();
2349 play_menu->set_name ("ArdourContextMenu");
2351 play_items.push_back (MenuElem (_("Play from edit cursor")));
2352 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2353 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2357 Menu *select_menu = manage (new Menu);
2358 MenuList& select_items = select_menu->items();
2359 select_menu->set_name ("ArdourContextMenu");
2361 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2362 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2363 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2364 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2365 select_items.push_back (SeparatorElem());
2366 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2367 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2368 select_items.push_back (SeparatorElem());
2370 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2374 Menu *cutnpaste_menu = manage (new Menu);
2375 MenuList& cutnpaste_items = cutnpaste_menu->items();
2376 cutnpaste_menu->set_name ("ArdourContextMenu");
2378 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2379 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2380 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2382 Menu *nudge_menu = manage (new Menu());
2383 MenuList& nudge_items = nudge_menu->items();
2384 nudge_menu->set_name ("ArdourContextMenu");
2386 edit_items.push_back (SeparatorElem());
2387 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2388 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2389 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2390 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2392 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2395 /* CURSOR SETTING AND MARKS AND STUFF */
2398 Editor::set_snap_to (SnapType st)
2401 vector<string> txt = internationalize (snap_type_strings);
2402 snap_type_selector.get_entry()->set_text (txt[(int)st]);
2406 switch (snap_type) {
2407 case SnapToAThirtysecondBeat:
2408 case SnapToASixteenthBeat:
2409 case SnapToAEighthBeat:
2410 case SnapToAQuarterBeat:
2411 case SnapToAThirdBeat:
2412 update_tempo_based_rulers ();
2420 Editor::set_snap_mode (SnapMode mode)
2423 vector<string> txt = internationalize (snap_mode_strings);
2424 snap_mode_selector.get_entry()->set_text (txt[(int)mode]);
2430 Editor::add_location_from_selection ()
2432 if (selection->time.empty()) {
2436 if (session == 0 || clicked_trackview == 0) {
2440 jack_nframes_t start = selection->time[clicked_selection].start;
2441 jack_nframes_t end = selection->time[clicked_selection].end;
2443 Location *location = new Location (start, end, "selection");
2445 session->begin_reversible_command (_("add marker"));
2446 session->add_undo (session->locations()->get_memento());
2447 session->locations()->add (location, true);
2448 session->add_redo_no_execute (session->locations()->get_memento());
2449 session->commit_reversible_command ();
2453 Editor::add_location_from_playhead_cursor ()
2455 jack_nframes_t where = session->audible_frame();
2457 Location *location = new Location (where, where, "mark", Location::IsMark);
2458 session->begin_reversible_command (_("add marker"));
2459 session->add_undo (session->locations()->get_memento());
2460 session->locations()->add (location, true);
2461 session->add_redo_no_execute (session->locations()->get_memento());
2462 session->commit_reversible_command ();
2467 Editor::set_state (const XMLNode& node)
2469 const XMLProperty* prop;
2471 int x, y, width, height, xoff, yoff;
2473 if ((geometry = find_named_node (node, "geometry")) == 0) {
2475 width = default_width;
2476 height = default_height;
2484 width = atoi(geometry->property("x_size")->value());
2485 height = atoi(geometry->property("y_size")->value());
2486 x = atoi(geometry->property("x_pos")->value());
2487 y = atoi(geometry->property("y_pos")->value());
2488 xoff = atoi(geometry->property("x_off")->value());
2489 yoff = atoi(geometry->property("y_off")->value());
2492 set_default_size(width, height);
2493 set_uposition(x, y-yoff);
2495 if ((prop = node.property ("zoom-focus"))) {
2496 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2499 if ((prop = node.property ("zoom"))) {
2500 set_frames_per_unit (atof (prop->value()));
2503 if ((prop = node.property ("snap-to"))) {
2504 set_snap_to ((SnapType) atoi (prop->value()));
2507 if ((prop = node.property ("snap-mode"))) {
2508 set_snap_mode ((SnapMode) atoi (prop->value()));
2511 if ((prop = node.property ("show-waveforms"))) {
2512 bool yn = (prop->value() == "yes");
2513 _show_waveforms = !yn;
2514 set_show_waveforms (yn);
2517 if ((prop = node.property ("show-waveforms-recording"))) {
2518 bool yn = (prop->value() == "yes");
2519 _show_waveforms_recording = !yn;
2520 set_show_waveforms_recording (yn);
2523 if ((prop = node.property ("show-measures"))) {
2524 bool yn = (prop->value() == "yes");
2525 _show_measures = !yn;
2526 set_show_measures (yn);
2529 if ((prop = node.property ("follow-playhead"))) {
2530 bool yn = (prop->value() == "yes");
2531 _follow_playhead = !yn;
2532 set_follow_playhead (yn);
2535 if ((prop = node.property ("xfades-visible"))) {
2536 bool yn = (prop->value() == "yes");
2537 _xfade_visibility = !yn;
2538 set_xfade_visibility (yn);
2541 if ((prop = node.property ("region-list-sort-type"))) {
2542 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2543 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2546 if ((prop = node.property ("mouse-mode"))) {
2547 MouseMode m = str2mousemode(prop->value());
2548 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2549 set_mouse_mode (m, true);
2551 mouse_mode = MouseGain; /* lie, to force the mode switch */
2552 set_mouse_mode (MouseObject, true);
2555 if ((prop = node.property ("editor-mixer-button"))) {
2556 editor_mixer_button.set_active(prop->value() == "yes");
2563 Editor::get_state ()
2565 XMLNode* node = new XMLNode ("Editor");
2568 if (is_realized()) {
2569 Gdk_Window win = get_window();
2571 int x, y, xoff, yoff, width, height;
2572 win.get_root_origin(x, y);
2573 win.get_position(xoff, yoff);
2574 win.get_size(width, height);
2576 XMLNode* geometry = new XMLNode ("geometry");
2578 snprintf(buf, sizeof(buf), "%d", width);
2579 geometry->add_property("x_size", string(buf));
2580 snprintf(buf, sizeof(buf), "%d", height);
2581 geometry->add_property("y_size", string(buf));
2582 snprintf(buf, sizeof(buf), "%d", x);
2583 geometry->add_property("x_pos", string(buf));
2584 snprintf(buf, sizeof(buf), "%d", y);
2585 geometry->add_property("y_pos", string(buf));
2586 snprintf(buf, sizeof(buf), "%d", xoff);
2587 geometry->add_property("x_off", string(buf));
2588 snprintf(buf, sizeof(buf), "%d", yoff);
2589 geometry->add_property("y_off", string(buf));
2590 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gobj()));
2591 geometry->add_property("canvas_region_list_pane_pos", string(buf));
2592 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gobj()));
2593 geometry->add_property("track_list_canvas_pane_pos", string(buf));
2594 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(®ion_selection_vpane)->gobj()));
2595 geometry->add_property("region_selection_pane_pos", string(buf));
2596 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gobj()));
2597 geometry->add_property("route_group_pane_pos", string(buf));
2599 node->add_child_nocopy (*geometry);
2602 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2603 node->add_property ("zoom-focus", buf);
2604 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2605 node->add_property ("zoom", buf);
2606 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2607 node->add_property ("snap-to", buf);
2608 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2609 node->add_property ("snap-mode", buf);
2611 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2612 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2613 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2614 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2615 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2616 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2617 node->add_property ("mouse-mode", enum2str(mouse_mode));
2618 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2626 Editor::trackview_by_y_position (double y)
2628 TrackViewList::iterator iter;
2631 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2639 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2648 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2650 Location* before = 0;
2651 Location* after = 0;
2657 const jack_nframes_t one_second = session->frame_rate();
2658 const jack_nframes_t one_minute = session->frame_rate() * 60;
2660 jack_nframes_t presnap = start;
2662 switch (snap_type) {
2668 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2670 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2673 case SnapToSMPTEFrame:
2675 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2677 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2681 case SnapToSMPTESeconds:
2682 if (session->smpte_offset_negative())
2684 start += session->smpte_offset ();
2686 start -= session->smpte_offset ();
2688 if (direction > 0) {
2689 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2691 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2694 if (session->smpte_offset_negative())
2696 start -= session->smpte_offset ();
2698 start += session->smpte_offset ();
2702 case SnapToSMPTEMinutes:
2703 if (session->smpte_offset_negative())
2705 start += session->smpte_offset ();
2707 start -= session->smpte_offset ();
2710 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2712 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2714 if (session->smpte_offset_negative())
2716 start -= session->smpte_offset ();
2718 start += session->smpte_offset ();
2724 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2726 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2732 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2734 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2739 start = session->tempo_map().round_to_bar (start, direction);
2743 start = session->tempo_map().round_to_beat (start, direction);
2746 case SnapToAThirtysecondBeat:
2747 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2750 case SnapToASixteenthBeat:
2751 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2754 case SnapToAEighthBeat:
2755 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2758 case SnapToAQuarterBeat:
2759 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2762 case SnapToAThirdBeat:
2763 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2766 case SnapToEditCursor:
2767 start = edit_cursor->current_frame;
2775 before = session->locations()->first_location_before (start);
2776 after = session->locations()->first_location_after (start);
2778 if (direction < 0) {
2780 start = before->start();
2784 } else if (direction > 0) {
2786 start = after->start();
2788 start = session->current_end_frame();
2793 /* find nearest of the two */
2794 if ((start - before->start()) < (after->start() - start)) {
2795 start = before->start();
2797 start = after->start();
2800 start = before->start();
2803 start = after->start();
2810 case SnapToRegionStart:
2811 case SnapToRegionEnd:
2812 case SnapToRegionSync:
2813 case SnapToRegionBoundary:
2814 if (!region_boundary_cache.empty()) {
2815 vector<jack_nframes_t>::iterator i;
2817 if (direction > 0) {
2818 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2820 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2823 if (i != region_boundary_cache.end()) {
2826 start = region_boundary_cache.back();
2832 switch (snap_mode) {
2838 if (presnap > start) {
2839 if (presnap > (start + unit_to_frame(snap_threshold))) {
2843 } else if (presnap < start) {
2844 if (presnap < (start - unit_to_frame(snap_threshold))) {
2856 Editor::setup_toolbar ()
2858 nstring pixmap_path;
2859 vector<ToggleButton *> mouse_mode_buttons;
2861 mouse_mode_buttons.push_back (&mouse_move_button);
2862 mouse_mode_buttons.push_back (&mouse_select_button);
2863 mouse_mode_buttons.push_back (&mouse_gain_button);
2864 mouse_mode_buttons.push_back (&mouse_zoom_button);
2865 mouse_mode_buttons.push_back (&mouse_timefx_button);
2866 mouse_mode_buttons.push_back (&mouse_audition_button);
2867 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2869 mouse_mode_button_table.set_homogeneous (true);
2870 mouse_mode_button_table.set_col_spacings (2);
2871 mouse_mode_button_table.set_row_spacings (2);
2872 mouse_mode_button_table.set_border_width (5);
2874 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2875 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2876 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2878 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2879 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2880 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2882 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2883 mouse_mode_tearoff->set_name ("MouseModeBase");
2885 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2886 static_cast<Gtk::Widget*>(&mouse_mode_button_table)));
2887 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2888 static_cast<Gtk::Widget*> (&mouse_mode_button_table), 1));
2890 mouse_move_button.set_name ("MouseModeButton");
2891 mouse_select_button.set_name ("MouseModeButton");
2892 mouse_gain_button.set_name ("MouseModeButton");
2893 mouse_zoom_button.set_name ("MouseModeButton");
2894 mouse_timefx_button.set_name ("MouseModeButton");
2895 mouse_audition_button.set_name ("MouseModeButton");
2897 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2898 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2899 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2900 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2901 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2902 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2904 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2905 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2906 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2907 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2908 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2909 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2911 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2912 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2914 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2915 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2916 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2917 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2918 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2920 // mouse_move_button.set_active (true);
2922 /* automation control */
2924 global_automation_button.set_name ("MouseModeButton");
2925 automation_mode_button.set_name ("MouseModeButton");
2927 automation_box.set_spacing (2);
2928 automation_box.set_border_width (2);
2929 automation_box.pack_start (global_automation_button, false, false);
2930 automation_box.pack_start (automation_mode_button, false, false);
2934 edit_mode_label.set_name ("ToolBarLabel");
2936 edit_mode_selector.set_name ("EditModeSelector");
2937 edit_mode_selector.get_entry()->set_name ("EditModeSelector");
2938 edit_mode_selector.get_popwin()->set_name ("EditModeSelector");
2940 edit_mode_box.set_spacing (3);
2941 edit_mode_box.set_border_width (3);
2943 /* XXX another disgusting hack because of the way combo boxes size themselves */
2945 Gtkmm2ext::set_size_request_to_display_given_text (*edit_mode_selector.get_entry(), "EdgtMode", 2, 10);
2946 set_popdown_string (edit_mode_selector, internationalize (edit_mode_strings));
2948 edit_mode_box.pack_start (edit_mode_label, false, false);
2949 edit_mode_box.pack_start (edit_mode_selector, false, false);
2951 edit_mode_selector.get_popwin()->signal_unmap_event().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2955 snap_type_label.set_name ("ToolBarLabel");
2957 snap_type_selector.set_name ("SnapTypeSelector");
2958 snap_type_selector.get_entry()->set_name ("SnapTypeSelector");
2959 snap_type_selector.get_popwin()->set_name ("SnapTypeSelector");
2961 snap_type_box.set_spacing (3);
2962 snap_type_box.set_border_width (3);
2964 /* XXX another disgusting hack because of the way combo boxes size themselves */
2966 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2967 Gtkmm2ext::set_size_request_to_display_given_text (*snap_type_selector.get_entry(), "Region bounds", 2+FUDGE, 10);
2968 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2970 snap_type_box.pack_start (snap_type_label, false, false);
2971 snap_type_box.pack_start (snap_type_selector, false, false);
2973 snap_type_selector.get_popwin()->signal_unmap_event().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2975 /* Snap mode, not snap type */
2977 snap_mode_label.set_name ("ToolBarLabel");
2979 snap_mode_selector.set_name ("SnapModeSelector");
2980 snap_mode_selector.get_entry()->set_name ("SnapModeSelector");
2981 snap_mode_selector.get_popwin()->set_name ("SnapModeSelector");
2983 snap_mode_box.set_spacing (3);
2984 snap_mode_box.set_border_width (3);
2986 Gtkmm2ext::set_size_request_to_display_given_text (*snap_mode_selector.get_entry(), "SngpMode", 2, 10);
2987 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2989 snap_mode_box.pack_start (snap_mode_label, false, false);
2990 snap_mode_box.pack_start (snap_mode_selector, false, false);
2992 snap_mode_selector.get_popwin()->signal_unmap_event().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2994 /* Zoom focus mode */
2996 zoom_focus_label.set_name ("ToolBarLabel");
2998 zoom_focus_selector.set_name ("ZoomFocusSelector");
2999 zoom_focus_selector.get_entry()->set_name ("ZoomFocusSelector");
3000 zoom_focus_selector.get_popwin()->set_name ("ZoomFocusSelector");
3002 zoom_focus_box.set_spacing (3);
3003 zoom_focus_box.set_border_width (3);
3005 /* XXX another disgusting hack because of the way combo boxes size themselves */
3007 Gtkmm2ext::set_size_request_to_display_given_text (*zoom_focus_selector.get_entry(), "Edgt Cursor", 2, 10);
3008 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
3010 zoom_focus_box.pack_start (zoom_focus_label, false, false);
3011 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
3013 zoom_focus_selector.get_popwin()->signal_unmap_event().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
3015 /* selection/cursor clocks */
3017 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
3018 selection_start_clock_label.set_name ("ToolBarLabel");
3019 selection_end_clock_label.set_name ("ToolBarLabel");
3020 edit_cursor_clock_label.set_name ("ToolBarLabel");
3022 selection_start_clock_label.set_text (_("Start:"));
3023 selection_end_clock_label.set_text (_("End:"));
3024 edit_cursor_clock_label.set_text (_("Edit:"));
3026 toolbar_selection_clock_table.set_border_width (5);
3027 toolbar_selection_clock_table.set_col_spacings (2);
3028 toolbar_selection_clock_table.set_homogeneous (false);
3030 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
3031 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
3032 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
3034 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
3035 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
3036 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
3039 // toolbar_clock_vbox.set_spacing (2);
3040 // toolbar_clock_vbox.set_border_width (10);
3041 /* the editor/mixer button will be enabled at session connect */
3043 editor_mixer_button.set_active(false);
3044 editor_mixer_button.set_sensitive(false);
3046 HBox* hbox = new HBox;
3048 hbox->pack_start (editor_mixer_button, false, false);
3049 hbox->pack_start (toolbar_selection_clock_table, false, false);
3050 hbox->pack_start (zoom_indicator_vbox, false, false);
3051 hbox->pack_start (zoom_focus_box, false, false);
3052 hbox->pack_start (snap_type_box, false, false);
3053 hbox->pack_start (snap_mode_box, false, false);
3054 hbox->pack_start (edit_mode_box, false, false);
3056 VBox *vbox = manage (new VBox);
3058 vbox->set_spacing (3);
3059 vbox->set_border_width (3);
3061 HBox *nbox = manage (new HBox);
3063 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
3064 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
3066 nbox->pack_start (nudge_backward_button, false, false);
3067 nbox->pack_start (nudge_forward_button, false, false);
3068 nbox->pack_start (nudge_clock, false, false, 5);
3070 nudge_label.set_name ("ToolBarLabel");
3072 vbox->pack_start (nudge_label, false, false);
3073 vbox->pack_start (*nbox, false, false);
3075 hbox->pack_start (*vbox, false, false);
3079 tools_tearoff = new TearOff (*hbox);
3080 tools_tearoff->set_name ("MouseModeBase");
3082 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
3083 static_cast<Gtk::Widget*>(hbox)));
3084 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
3085 static_cast<Gtk::Widget*> (hbox), 0));
3087 toolbar_hbox.set_spacing (8);
3088 toolbar_hbox.set_border_width (2);
3090 toolbar_hbox.pack_start (*tools_tearoff, false, false);
3091 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
3093 toolbar_base.set_name ("ToolBarBase");
3094 toolbar_base.add (toolbar_hbox);
3096 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
3097 toolbar_frame.set_name ("BaseFrame");
3098 toolbar_frame.add (toolbar_base);
3102 Editor::_autoscroll_canvas (void *arg)
3104 return ((Editor *) arg)->autoscroll_canvas ();
3108 Editor::autoscroll_canvas ()
3110 jack_nframes_t new_frame;
3111 bool keep_calling = true;
3113 if (autoscroll_direction < 0) {
3114 if (leftmost_frame < autoscroll_distance) {
3117 new_frame = leftmost_frame - autoscroll_distance;
3120 if (leftmost_frame > max_frames - autoscroll_distance) {
3121 new_frame = max_frames;
3123 new_frame = leftmost_frame + autoscroll_distance;
3127 if (new_frame != leftmost_frame) {
3128 reposition_x_origin (new_frame);
3131 if (new_frame == 0 || new_frame == max_frames) {
3138 if (autoscroll_cnt == 1) {
3140 /* connect the timeout so that we get called repeatedly */
3142 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
3143 keep_calling = false;
3145 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
3147 /* after about a while, speed up a bit by changing the timeout interval */
3149 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
3150 keep_calling = false;
3152 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
3154 /* after about another while, speed up some more */
3156 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
3157 keep_calling = false;
3159 } else if (autoscroll_cnt >= 30) {
3161 /* we've been scrolling for a while ... crank it up */
3163 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
3166 return keep_calling;
3170 Editor::start_canvas_autoscroll (int dir)
3176 stop_canvas_autoscroll ();
3178 autoscroll_direction = dir;
3179 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
3182 /* do it right now, which will start the repeated callbacks */
3184 autoscroll_canvas ();
3188 Editor::stop_canvas_autoscroll ()
3190 if (autoscroll_timeout_tag >= 0) {
3191 gtk_timeout_remove (autoscroll_timeout_tag);
3192 autoscroll_timeout_tag = -1;
3197 Editor::convert_drop_to_paths (vector<string>& paths,
3198 GdkDragContext *context,
3201 GtkSelectionData *data,
3209 gchar *tname = gdk_atom_name (data->type);
3211 if (session == 0 || strcmp (tname, "text/plain") != 0) {
3215 /* Parse the "uri-list" format that Nautilus provides,
3216 where each pathname is delimited by \r\n
3219 path = (char *) data->data;
3222 for (int n = 0; n < data->length; ++n) {
3226 if (path[n] == '\r') {
3233 if (path[n] == '\n') {
3234 paths.push_back (spath);
3238 warning << _("incorrectly formatted URI list, ignored")
3246 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
3248 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3250 // cerr << "dropped text was " << *p << endl;
3254 // cerr << "decoded was " << *p << endl;
3256 if ((*p).substr (0,7) == "file://") {
3257 (*p) = (*p).substr (7);
3265 Editor::track_canvas_drag_data_received (GdkDragContext *context,
3268 GtkSelectionData *data,
3273 AudioTimeAxisView* tv;
3275 vector<string> paths;
3278 jack_nframes_t frame;
3280 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
3284 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
3290 gnome_canvas_window_to_world (GNOME_CANVAS(track_gnome_canvas), (double) x, (double) y, &wx, &wy);
3292 ev.type = GDK_BUTTON_RELEASE;
3296 frame = event_frame (&ev, 0, &cy);
3300 if ((tvp = trackview_by_y_position (cy)) == 0) {
3302 /* drop onto canvas background: create a new track */
3304 insert_paths_as_new_tracks (paths, false);
3307 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
3309 /* check that its an audio track, not a bus */
3311 if (tv->get_diskstream()) {
3313 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3314 insert_sndfile_into (*p, true, tv, frame);
3321 gtk_drag_finish (context, TRUE, FALSE, time);
3325 Editor::new_tempo_section ()
3331 Editor::map_transport_state ()
3333 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3335 if (session->transport_stopped()) {
3336 have_pending_keyboard_selection = false;
3342 Editor::State::State ()
3344 selection = new Selection;
3347 Editor::State::~State ()
3353 Editor::get_memento () const
3355 State *state = new State;
3357 store_state (*state);
3358 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3362 Editor::store_state (State& state) const
3364 *state.selection = *selection;
3368 Editor::restore_state (State *state)
3370 if (*selection == *state->selection) {
3374 *selection = *state->selection;
3375 time_selection_changed ();
3376 region_selection_changed ();
3378 /* XXX other selection change handlers? */
3382 Editor::begin_reversible_command (string name)
3385 UndoAction ua = get_memento();
3386 session->begin_reversible_command (name, &ua);
3391 Editor::commit_reversible_command ()
3394 UndoAction ua = get_memento();
3395 session->commit_reversible_command (&ua);
3400 Editor::flush_track_canvas ()
3402 /* I don't think this is necessary, and only causes more problems.
3403 I'm commenting it out
3404 and if the imageframe folks don't have any issues, we can take
3405 out this method entirely
3408 //gnome_canvas_update_now (GNOME_CANVAS(track_gnome_canvas));
3409 //gtk_main_iteration ();
3413 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3415 if (!clicked_trackview) {
3420 begin_reversible_command (_("set selected trackview"));
3425 if (selection->selected (clicked_trackview)) {
3427 selection->remove (clicked_trackview);
3430 selection->add (clicked_trackview);
3435 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3436 /* no commit necessary */
3440 selection->set (clicked_trackview);
3444 commit_reversible_command ();
3449 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3451 if (!clicked_control_point) {
3456 begin_reversible_command (_("set selected control point"));
3466 commit_reversible_command ();
3471 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3473 if (!clicked_regionview) {
3477 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3483 RouteGroup* group = atv->route().edit_group();
3484 vector<AudioRegionView*> all_equivalent_regions;
3486 if (group && group->is_active()) {
3488 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3490 AudioTimeAxisView* tatv;
3492 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3494 if (tatv->route().edit_group() != group) {
3499 vector<AudioRegion*> results;
3500 AudioRegionView* marv;
3503 if ((ds = tatv->get_diskstream()) == 0) {
3508 if ((pl = ds->playlist()) != 0) {
3509 pl->get_equivalent_regions (clicked_regionview->region,
3513 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3514 if ((marv = tatv->view->find_view (**ir)) != 0) {
3515 all_equivalent_regions.push_back (marv);
3524 all_equivalent_regions.push_back (clicked_regionview);
3528 begin_reversible_command (_("set selected regionview"));
3532 if (clicked_regionview->get_selected()) {
3533 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3534 /* reduce selection down to just the one clicked */
3535 selection->set (clicked_regionview);
3537 selection->remove (clicked_regionview);
3540 selection->add (all_equivalent_regions);
3543 set_selected_track_from_click (add, false, no_track_remove);
3547 // karsten wiese suggested these two lines to make
3548 // a selected region rise to the top. but this
3549 // leads to a mismatch between actual layering
3550 // and visual layering. resolution required ....
3552 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3553 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3555 if (clicked_regionview->get_selected()) {
3556 /* no commit necessary: we are the one selected. */
3561 selection->set (all_equivalent_regions);
3562 set_selected_track_from_click (add, false, false);
3566 commit_reversible_command () ;
3570 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3572 vector<AudioRegionView*> all_equivalent_regions;
3573 AudioRegion* region;
3575 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3579 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3581 AudioTimeAxisView* tatv;
3583 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3586 vector<AudioRegion*> results;
3587 AudioRegionView* marv;
3590 if ((ds = tatv->get_diskstream()) == 0) {
3595 if ((pl = ds->playlist()) != 0) {
3596 pl->get_region_list_equivalent_regions (*region, results);
3599 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3600 if ((marv = tatv->view->find_view (**ir)) != 0) {
3601 all_equivalent_regions.push_back (marv);
3608 begin_reversible_command (_("set selected regions"));
3612 selection->add (all_equivalent_regions);
3616 selection->set (all_equivalent_regions);
3619 commit_reversible_command () ;
3623 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3625 AudioRegionView* rv;
3628 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3632 if ((rv = sv->find_view (*ar)) == 0) {
3636 /* don't reset the selection if its something other than
3637 a single other region.
3640 if (selection->audio_regions.size() > 1) {
3644 begin_reversible_command (_("set selected regions"));
3646 selection->set (rv);
3648 commit_reversible_command () ;
3654 Editor::set_edit_group_solo (Route& route, bool yn)
3656 RouteGroup *edit_group;
3658 if ((edit_group = route.edit_group()) != 0) {
3659 edit_group->apply (&Route::set_solo, yn, this);
3661 route.set_solo (yn, this);
3666 Editor::set_edit_group_mute (Route& route, bool yn)
3668 RouteGroup *edit_group = 0;
3670 if ((edit_group == route.edit_group()) != 0) {
3671 edit_group->apply (&Route::set_mute, yn, this);
3673 route.set_mute (yn, this);
3678 Editor::set_edit_menu (Menu& menu)
3681 edit_menu->map_.connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3685 Editor::edit_menu_map_handler ()
3687 using namespace Menu_Helpers;
3688 MenuList& edit_items = edit_menu->items();
3691 /* Nuke all the old items */
3693 edit_items.clear ();
3699 if (session->undo_depth() == 0) {
3702 label = string_compose(_("Undo (%1)"), session->next_undo());
3705 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3707 if (session->undo_depth() == 0) {
3708 edit_items.back().set_sensitive (false);
3711 if (session->redo_depth() == 0) {
3714 label = string_compose(_("Redo (%1)"), session->next_redo());
3717 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3718 if (session->redo_depth() == 0) {
3719 edit_items.back().set_sensitive (false);
3722 vector<MenuItem*> mitems;
3724 edit_items.push_back (SeparatorElem());
3725 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3726 mitems.push_back (&edit_items.back());
3727 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3728 mitems.push_back (&edit_items.back());
3729 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3730 mitems.push_back (&edit_items.back());
3731 edit_items.push_back (SeparatorElem());
3732 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3733 mitems.push_back (&edit_items.back());
3734 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3735 mitems.push_back (&edit_items.back());
3736 edit_items.push_back (SeparatorElem());
3738 if (selection->empty()) {
3739 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3740 (*i)->set_sensitive (false);
3744 Menu* import_menu = manage (new Menu());
3745 import_menu->set_name ("ArdourContextMenu");
3746 MenuList& import_items = import_menu->items();
3748 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3749 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3751 Menu* embed_menu = manage (new Menu());
3752 embed_menu->set_name ("ArdourContextMenu");
3753 MenuList& embed_items = embed_menu->items();
3755 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3756 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3758 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3759 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3760 edit_items.push_back (SeparatorElem());
3762 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3763 if (!session->have_captured()) {
3764 edit_items.back().set_sensitive (false);
3769 Editor::duplicate_dialog (bool dup_region)
3772 if (clicked_regionview == 0) {
3776 if (selection->time.length() == 0) {
3781 ArdourDialog win ("duplicate dialog");
3783 Label label (_("Duplicate how many times?"));
3786 Button ok_button (_("OK"));
3787 Button cancel_button (_("Cancel"));
3790 button_box.set_spacing (7);
3791 set_size_request_to_display_given_text (ok_button, _("Cancel"), 20, 15); // this is cancel on purpose
3792 set_size_request_to_display_given_text (cancel_button, _("Cancel"), 20, 15);
3793 button_box.pack_end (ok_button, false, false);
3794 button_box.pack_end (cancel_button, false, false);
3796 hbox.set_spacing (5);
3797 hbox.pack_start (label);
3798 hbox.pack_start (entry, true, true);
3800 vbox.set_spacing (5);
3801 vbox.set_border_width (5);
3802 vbox.pack_start (hbox);
3803 vbox.pack_start (button_box);
3806 win.set_position (Gtk::WIN_POS_MOUSE);
3809 ok_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3810 entry.signal_activate().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3811 cancel_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 1));
3813 entry.signal_focus_in_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_in_event));
3814 entry.signal_focus_out_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_out_event));
3816 entry.set_text ("1");
3817 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3818 entry.select_region (0, entry.get_text_length());
3820 win.set_position (Gtk::WIN_POS_MOUSE);
3822 win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3824 entry.grab_focus ();
3828 if (win.run_status() != 0) {
3832 string text = entry.get_text();
3835 if (sscanf (text.c_str(), "%f", ×) == 1) {
3837 AudioRegionSelection regions;
3838 regions.add (clicked_regionview);
3839 duplicate_some_regions (regions, times);
3841 duplicate_selection (times);
3847 Editor::show_verbose_canvas_cursor ()
3849 gnome_canvas_item_raise_to_top (verbose_canvas_cursor);
3850 gnome_canvas_item_show (verbose_canvas_cursor);
3851 verbose_cursor_visible = true;
3855 Editor::hide_verbose_canvas_cursor ()
3857 gnome_canvas_item_hide (verbose_canvas_cursor);
3858 verbose_cursor_visible = false;
3862 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3864 /* XXX get origin of canvas relative to root window,
3865 add x and y and check compared to gdk_screen_{width,height}
3867 gnome_canvas_item_set (verbose_canvas_cursor, "text", txt.c_str(), "x", x, "y", y, NULL);
3871 Editor::set_verbose_canvas_cursor_text (string txt)
3873 gnome_canvas_item_set (verbose_canvas_cursor, "text", txt.c_str(), NULL);
3877 Editor::edit_mode_selection_done (GdkEventAny *ev)
3883 string choice = edit_mode_selector.get_entry()->get_text();
3884 EditMode mode = Slide;
3886 if (choice == _("Splice")) {
3888 } else if (choice == _("Slide")) {
3892 session->set_edit_mode (mode);
3898 Editor::snap_type_selection_done (GdkEventAny *ev)
3904 string choice = snap_type_selector.get_entry()->get_text();
3905 SnapType snaptype = SnapToFrame;
3907 if (choice == _("Beats/3")) {
3908 snaptype = SnapToAThirdBeat;
3909 } else if (choice == _("Beats/4")) {
3910 snaptype = SnapToAQuarterBeat;
3911 } else if (choice == _("Beats/8")) {
3912 snaptype = SnapToAEighthBeat;
3913 } else if (choice == _("Beats/16")) {
3914 snaptype = SnapToASixteenthBeat;
3915 } else if (choice == _("Beats/32")) {
3916 snaptype = SnapToAThirtysecondBeat;
3917 } else if (choice == _("Beats")) {
3918 snaptype = SnapToBeat;
3919 } else if (choice == _("Bars")) {
3920 snaptype = SnapToBar;
3921 } else if (choice == _("Marks")) {
3922 snaptype = SnapToMark;
3923 } else if (choice == _("Edit Cursor")) {
3924 snaptype = SnapToEditCursor;
3925 } else if (choice == _("Region starts")) {
3926 snaptype = SnapToRegionStart;
3927 } else if (choice == _("Region ends")) {
3928 snaptype = SnapToRegionEnd;
3929 } else if (choice == _("Region bounds")) {
3930 snaptype = SnapToRegionBoundary;
3931 } else if (choice == _("Region syncs")) {
3932 snaptype = SnapToRegionSync;
3933 } else if (choice == _("CD Frames")) {
3934 snaptype = SnapToCDFrame;
3935 } else if (choice == _("SMPTE Frames")) {
3936 snaptype = SnapToSMPTEFrame;
3937 } else if (choice == _("SMPTE Seconds")) {
3938 snaptype = SnapToSMPTESeconds;
3939 } else if (choice == _("SMPTE Minutes")) {
3940 snaptype = SnapToSMPTEMinutes;
3941 } else if (choice == _("Seconds")) {
3942 snaptype = SnapToSeconds;
3943 } else if (choice == _("Minutes")) {
3944 snaptype = SnapToMinutes;
3945 } else if (choice == _("None")) {
3946 snaptype = SnapToFrame;
3949 set_snap_to (snaptype);
3955 Editor::snap_mode_selection_done (GdkEventAny *ev)
3957 if(session == 0) return FALSE;
3959 string choice = snap_mode_selector.get_entry()->get_text();
3960 SnapMode mode = SnapNormal;
3962 if (choice == _("Normal")) {
3964 } else if (choice == _("Magnetic")) {
3965 mode = SnapMagnetic;
3968 set_snap_mode (mode);
3974 Editor::zoom_focus_selection_done (GdkEventAny *ev)
3980 string choice = zoom_focus_selector.get_entry()->get_text();
3981 ZoomFocus focus_type = ZoomFocusLeft;
3983 if (choice == _("Left")) {
3984 focus_type = ZoomFocusLeft;
3985 } else if (choice == _("Right")) {
3986 focus_type = ZoomFocusRight;
3987 } else if (choice == _("Center")) {
3988 focus_type = ZoomFocusCenter;
3989 } else if (choice == _("Playhead")) {
3990 focus_type = ZoomFocusPlayhead;
3991 } else if (choice == _("Edit Cursor")) {
3992 focus_type = ZoomFocusEdit;
3995 set_zoom_focus (focus_type);
4001 Editor::edit_controls_button_release (GdkEventButton* ev)
4003 if (Keyboard::is_context_menu_event (ev)) {
4004 ARDOUR_UI::instance()->add_route ();
4010 Editor::track_selection_changed ()
4012 switch (selection->tracks.size()){
4016 set_selected_mixer_strip (*(selection->tracks.front()));
4020 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4021 (*i)->set_selected (false);
4022 if (mouse_mode == MouseRange) {
4023 (*i)->hide_selection ();
4027 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4028 (*i)->set_selected (true);
4029 if (mouse_mode == MouseRange) {
4030 (*i)->show_selection (selection->time);
4036 Editor::time_selection_changed ()
4038 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4039 (*i)->hide_selection ();
4042 if (selection->tracks.empty()) {
4043 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4044 (*i)->show_selection (selection->time);
4047 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4048 (*i)->show_selection (selection->time);
4054 Editor::region_selection_changed ()
4056 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4057 (*i)->set_selected_regionviews (selection->audio_regions);
4062 Editor::point_selection_changed ()
4064 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4065 (*i)->set_selected_points (selection->points);
4070 Editor::run_sub_event_loop ()
4072 Keyboard::the_keyboard().allow_focus (true);
4073 sub_event_loop_status = 0;
4078 Editor::finish_sub_event_loop (int status)
4081 Keyboard::the_keyboard().allow_focus (false);
4082 sub_event_loop_status = status;
4086 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
4088 finish_sub_event_loop (status);
4093 Editor::mouse_select_button_release (GdkEventButton* ev)
4095 /* this handles just right-clicks */
4097 if (ev->button != 3) {
4104 Editor::TrackViewList *
4105 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
4108 TrackViewList::iterator i;
4110 v = new TrackViewList;
4112 if (track == 0 && group == 0) {
4116 for (i = track_views.begin(); i != track_views.end (); ++i) {
4120 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
4122 /* just the view for this track
4125 v->push_back (track);
4129 /* views for all tracks in the edit group */
4131 for (i = track_views.begin(); i != track_views.end (); ++i) {
4133 if (group == 0 || (*i)->edit_group() == group) {
4143 Editor::set_zoom_focus (ZoomFocus f)
4145 if (zoom_focus != f) {
4147 vector<string> txt = internationalize (zoom_focus_strings);
4148 zoom_focus_selector.get_entry()->set_text (txt[(int)f]);
4149 ZoomFocusChanged (); /* EMIT_SIGNAL */
4156 Editor::ensure_float (Window& win)
4158 win.set_transient_for (*this);
4162 Editor::pane_allocation_handler (GtkAllocation *alloc, Gtk::Paned* which)
4164 /* recover or initialize pane positions. do this here rather than earlier because
4165 we don't want the positions to change the child allocations, which they seem to do.
4171 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
4173 static int32_t done[4] = { 0, 0, 0, 0 };
4176 if ((geometry = find_named_node (*node, "geometry")) == 0) {
4177 width = default_width;
4178 height = default_height;
4180 width = atoi(geometry->property("x_size")->value());
4181 height = atoi(geometry->property("y_size")->value());
4184 if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
4190 if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
4192 snprintf (buf, sizeof(buf), "%d", pos);
4194 pos = atoi (prop->value());
4197 if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gobj())->allocation.width > pos)) {
4198 track_list_canvas_pane.set_position (pos);
4201 } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
4207 if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
4208 pos = width - (95 * 2);
4209 snprintf (buf, sizeof(buf), "%d", pos);
4211 pos = atoi (prop->value());
4214 if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gobj())->allocation.width > pos)) {
4215 canvas_region_list_pane.set_position (pos);
4218 } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
4224 if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
4225 pos = width - (95 * 2);
4226 snprintf (buf, sizeof(buf), "%d", pos);
4228 pos = atoi (prop->value());
4231 if ((done[2] = GTK_WIDGET(route_group_vpane.gobj())->allocation.height > pos)) {
4232 route_group_vpane.set_position (pos);
4235 } else if (which == static_cast<Gtk::Paned*> (®ion_selection_vpane)) {
4241 if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
4242 pos = width - (95 * 2);
4243 snprintf (buf, sizeof(buf), "%d", pos);
4245 pos = atoi (prop->value());
4248 if ((done[3] = GTK_WIDGET(region_selection_vpane.gobj())->allocation.height > pos)) {
4249 region_selection_vpane.set_position (pos);
4255 Editor::detach_tearoff (Gtk::Box* b, Gtk::Widget* w)
4257 if (tools_tearoff->torn_off() &&
4258 mouse_mode_tearoff->torn_off()) {
4259 top_hbox.remove (toolbar_frame);
4262 ensure_float (*w->get_toplevel());
4266 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Widget* w, int32_t n)
4268 if (toolbar_frame.get_parent() == 0) {
4269 top_hbox.pack_end (toolbar_frame);
4274 Editor::set_show_measures (bool yn)
4276 if (_show_measures != yn) {
4279 if ((_show_measures = yn) == true) {
4282 DisplayControlChanged (ShowMeasures);
4288 Editor::set_follow_playhead (bool yn)
4290 if (_follow_playhead != yn) {
4291 if ((_follow_playhead = yn) == true) {
4293 update_current_screen ();
4295 DisplayControlChanged (FollowPlayhead);
4301 Editor::toggle_xfade_active (Crossfade* xfade)
4303 xfade->set_active (!xfade->active());
4307 Editor::toggle_xfade_length (Crossfade* xfade)
4309 xfade->set_follow_overlap (!xfade->following_overlap());
4313 Editor::edit_xfade (Crossfade* xfade)
4315 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
4319 cew.ok_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 1));
4320 cew.cancel_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 0));
4321 cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
4325 if (cew.run_status() == 1) {
4327 xfade->StateChanged (Change (~0));
4332 Editor::playlist_selector () const
4334 return *_playlist_selector;
4338 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
4342 ret = nudge_clock.current_duration (pos);
4343 next = ret + 1; /* XXXX fix me */
4349 Editor::end_location_changed (Location* location)
4351 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
4352 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
4356 Editor::playlist_deletion_dialog (Playlist* pl)
4358 ArdourDialog dialog ("playlist deletion dialog");
4359 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4360 "If left alone, no audio files used by it will be cleaned.\n"
4361 "If deleted, audio files used by it alone by will cleaned."),
4364 Button del_button (_("Delete playlist"));
4365 Button keep_button (_("Keep playlist"));
4366 Button abort_button (_("Cancel cleanup"));
4369 button_box.set_spacing (7);
4370 button_box.set_homogeneous (true);
4371 button_box.pack_end (del_button, false, false);
4372 button_box.pack_end (keep_button, false, false);
4373 button_box.pack_end (abort_button, false, false);
4375 vbox.set_spacing (5);
4376 vbox.set_border_width (5);
4377 vbox.pack_start (label);
4378 vbox.pack_start (button_box);
4381 dialog.set_position (Gtk::WIN_POS_CENTER);
4384 del_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 0));
4385 keep_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 1));
4386 abort_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 2));
4389 dialog.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
4393 switch (dialog.run_status()) {
4395 /* keep the playlist */
4399 /* delete the playlist */
4407 /* keep the playlist */
4413 Editor::audio_region_selection_covers (jack_nframes_t where)
4415 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
4416 if ((*a)->region.covers (where)) {
4425 Editor::prepare_for_cleanup ()
4427 cut_buffer->clear_audio_regions ();
4428 cut_buffer->clear_playlists ();
4430 selection->clear_audio_regions ();
4431 selection->clear_playlists ();
4435 Editor::init_colormap ()
4437 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
4438 pair<ColorID,int> newpair;
4440 newpair.first = (ColorID) x;
4441 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
4442 color_map.insert (newpair);
4447 Editor::transport_loop_location()
4450 return session->locations()->auto_loop_location();
4457 Editor::transport_punch_location()
4460 return session->locations()->auto_punch_location();