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"
57 #include "playlist_selector.h"
58 #include "regionview.h"
59 #include "rgb_macros.h"
60 #include "selection.h"
61 #include "streamview.h"
62 #include "time_axis_view.h"
64 #include "crossfade_view.h"
66 #include "public_editor.h"
67 #include "crossfade_edit.h"
68 #include "audio_time_axis.h"
69 #include "gui_thread.h"
74 #include "imageframe_socket_handler.h"
75 /* </CMT Additions> */
79 using namespace ARDOUR;
81 using namespace Gtkmm2ext;
82 using namespace Editing;
84 /* XXX this is a hack. it ought to be the maximum value of an jack_nframes_t */
86 const double max_canvas_coordinate = 100000000.0;
87 const double Editor::timebar_height = 15.0;
89 #include "editor_xpms"
91 static const gchar *route_list_titles[] = {
96 static const gchar *edit_group_list_titles[] = {
100 static const gchar *named_selection_display_titles[] = {
105 static const int32_t slide_index = 0;
106 static const int32_t splice_index = 1;
108 static const gchar *edit_mode_strings[] = {
114 static const gchar *snap_type_strings[] = {
138 static const gchar *snap_mode_strings[] = {
144 static const gchar *zoom_focus_strings[] = {
153 /* Soundfile drag-n-drop */
161 static GtkTargetEntry target_table[] = {
162 { "STRING", 0, TARGET_STRING },
163 { "text/plain", 0, TARGET_STRING },
164 { "text/uri-list", 0, TARGET_URL },
165 { "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
168 static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
170 GdkCursor* Editor::cross_hair_cursor = 0;
171 GdkCursor* Editor::selector_cursor = 0;
172 GdkCursor* Editor::trimmer_cursor = 0;
173 GdkCursor* Editor::grabber_cursor = 0;
174 GdkCursor* Editor::zoom_cursor = 0;
175 GdkCursor* Editor::time_fx_cursor = 0;
176 GdkCursor* Editor::fader_cursor = 0;
177 GdkCursor* Editor::speaker_cursor = 0;
178 GdkCursor* Editor::null_cursor = 0;
179 GdkCursor* Editor::wait_cursor = 0;
180 GdkCursor* Editor::timebar_cursor = 0;
182 GdkPixmap *Editor::check_pixmap = 0;
183 GdkBitmap *Editor::check_mask = 0;
184 GdkPixmap *Editor::empty_pixmap = 0;
185 GdkBitmap *Editor::empty_mask = 0;
187 extern gint route_list_compare_func (GtkCList*,gconstpointer,gconstpointer);
189 Editor::Editor (AudioEngine& eng)
192 /* time display buttons */
194 minsec_label (_("Mins:Secs")),
195 bbt_label (_("Bars:Beats")),
196 smpte_label (_("SMPTE")),
197 frame_label (_("Frames")),
198 tempo_label (_("Tempo")),
199 meter_label (_("Meter")),
200 mark_label (_("Location Markers")),
201 range_mark_label (_("Range Markers")),
202 transport_mark_label (_("Loop/Punch Ranges")),
204 edit_packer (3, 3, false),
205 edit_hscroll_left_arrow (Gtk::ARROW_LEFT, Gtk::SHADOW_OUT),
206 edit_hscroll_right_arrow (Gtk::ARROW_RIGHT, Gtk::SHADOW_OUT),
208 named_selection_display (internationalize (named_selection_display_titles)),
210 /* tool bar related */
212 editor_mixer_button (_("editor\nmixer")),
214 selection_start_clock (X_("SelectionStartClock"), true),
215 selection_end_clock (X_("SelectionEndClock"), true),
216 edit_cursor_clock (X_("EditCursorClock"), true),
217 zoom_range_clock (X_("ZoomRangeClock"), true, true),
219 toolbar_selection_clock_table (2,3),
221 mouse_mode_button_table (2, 3),
223 mouse_select_button (_("range")),
224 mouse_move_button (_("object")),
225 mouse_gain_button (_("gain")),
226 mouse_zoom_button (_("zoom")),
227 mouse_timefx_button (_("timefx")),
228 mouse_audition_button (_("listen")),
230 automation_mode_button (_("mode")),
231 global_automation_button (_("automation")),
233 edit_mode_label (_("Edit Mode")),
234 snap_type_label (_("Snap To")),
235 snap_mode_label(_("Snap Mode")),
236 zoom_focus_label (_("Zoom Focus")),
238 /* <CMT Additions> */
239 image_socket_listener(0),
240 /* </CMT Additions> */
244 nudge_label (_("Nudge")),
245 nudge_clock (X_("NudgeClock"), true, true)
250 /* we are a singleton */
252 PublicEditor::_instance = this;
256 check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
257 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
258 &check_mask, NULL, (gchar **) check_xpm);
259 empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
260 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
261 &empty_mask, NULL, (gchar **) empty_xpm);
265 selection = new Selection;
266 cut_buffer = new Selection;
268 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
269 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
270 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
271 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
273 clicked_regionview = 0;
274 clicked_trackview = 0;
275 clicked_audio_trackview = 0;
276 clicked_crossfadeview = 0;
277 clicked_control_point = 0;
278 latest_regionview = 0;
279 last_update_frame = 0;
281 last_audition_region = 0;
282 current_mixer_strip = 0;
283 current_bbt_points = 0;
285 snap_type = SnapToFrame;
286 set_snap_to (snap_type);
287 snap_mode = SnapNormal;
288 set_snap_mode (snap_mode);
289 snap_threshold = 5.0;
290 bbt_beat_subdivision = 4;
293 autoscroll_timeout_tag = -1;
294 interthread_progress_window = 0;
295 current_interthread_info = 0;
296 _show_measures = true;
297 _show_waveforms = true;
298 _show_waveforms_recording = true;
299 first_action_message = 0;
301 show_gain_after_trim = false;
302 no_zoom_repos_update = false;
303 ignore_route_list_reorder = false;
304 verbose_cursor_on = true;
305 route_removal = false;
307 show_automatic_regions_in_region_list = true;
308 have_pending_keyboard_selection = false;
309 _follow_playhead = true;
310 _xfade_visibility = true;
311 editor_ruler_menu = 0;
312 no_ruler_shown_update = false;
313 edit_group_list_menu = 0;
315 region_list_menu = 0;
317 marker_menu_item = 0;
319 transport_marker_menu = 0;
320 new_transport_marker_menu = 0;
321 editor_mixer_strip_width = Wide;
322 repos_zoom_queued = false;
323 import_audio_item = 0;
324 embed_audio_item = 0;
325 region_edit_menu_split_item = 0;
327 region_edit_menu_split_multichannel_item = 0;
328 edit_hscroll_dragging = false;
330 ignore_mouse_mode_toggle = false;
331 current_stepping_trackview = 0;
333 entered_regionview = 0;
334 clear_entered_track = false;
335 _new_regionviews_show_envelope = false;
336 current_timestretch = 0;
341 location_marker_color = color_map[cLocationMarker];
342 location_range_color = color_map[cLocationRange];
343 location_cd_marker_color = color_map[cLocationCDMarker];
344 location_loop_color = color_map[cLocationLoop];
345 location_punch_color = color_map[cLocationPunch];
347 range_marker_drag_rect = 0;
348 marker_drag_line = 0;
350 mouse_mode = MouseZoom; /* force change in next call */
351 set_mouse_mode (MouseObject, true);
353 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
354 zoom_focus = ZoomFocusLeft;
355 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
357 initialize_rulers ();
358 initialize_canvas ();
360 track_canvas_scroller.add (*track_canvas);
361 track_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
362 track_canvas_scroller.set_name ("TrackCanvasScroller");
364 track_canvas_scroller.get_vadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
365 track_canvas_scroller.get_vadjustment()->set_step_increment (10.0);
367 track_canvas_scroller.get_hadjustment()->set_lower (0.0);
368 track_canvas_scroller.get_hadjustment()->set_upper (1200.0);
369 track_canvas_scroller.get_hadjustment()->set_step_increment (20.0);
370 track_canvas_scroller.get_hadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
372 edit_vscrollbar.set_adjustment(*track_canvas_scroller.get_vadjustment());
373 edit_hscrollbar.set_adjustment(*track_canvas_scroller.get_hadjustment());
375 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_press));
376 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_release));
377 edit_hscrollbar.size_allocate.connect (mem_fun(*this, &Editor::hscroll_slider_allocate));
379 time_canvas_scroller.add (*time_canvas);
380 time_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
381 time_canvas_scroller.set_hadjustment (*track_canvas_scroller.get_hadjustment());
382 time_canvas_scroller.set_name ("TimeCanvasScroller");
384 edit_controls_vbox.set_spacing (track_spacing);
385 edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
386 edit_controls_scroller.add (edit_controls_hbox);
387 edit_controls_scroller.set_name ("EditControlsBase");
388 edit_controls_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
390 Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
392 viewport->set_shadow_type (Gtk::SHADOW_NONE);
393 viewport->set_name ("EditControlsBase");
394 viewport->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
395 viewport->signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
400 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
403 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
405 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
406 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
407 time_canvas_vbox.pack_start (*frames_ruler, false, false);
408 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
409 time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
410 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
412 bbt_label.set_name ("EditorTimeButton");
413 bbt_label.set_size_request (-1, (int)timebar_height);
414 bbt_label.set_alignment (1.0, 0.5);
415 bbt_label.set_padding (5,0);
416 minsec_label.set_name ("EditorTimeButton");
417 minsec_label.set_size_request (-1, (int)timebar_height);
418 minsec_label.set_alignment (1.0, 0.5);
419 minsec_label.set_padding (5,0);
420 smpte_label.set_name ("EditorTimeButton");
421 smpte_label.set_size_request (-1, (int)timebar_height);
422 smpte_label.set_alignment (1.0, 0.5);
423 smpte_label.set_padding (5,0);
424 frame_label.set_name ("EditorTimeButton");
425 frame_label.set_size_request (-1, (int)timebar_height);
426 frame_label.set_alignment (1.0, 0.5);
427 frame_label.set_padding (5,0);
428 tempo_label.set_name ("EditorTimeButton");
429 tempo_label.set_size_request (-1, (int)timebar_height);
430 tempo_label.set_alignment (1.0, 0.5);
431 tempo_label.set_padding (5,0);
432 meter_label.set_name ("EditorTimeButton");
433 meter_label.set_size_request (-1, (int)timebar_height);
434 meter_label.set_alignment (1.0, 0.5);
435 meter_label.set_padding (5,0);
436 mark_label.set_name ("EditorTimeButton");
437 mark_label.set_size_request (-1, (int)timebar_height);
438 mark_label.set_alignment (1.0, 0.5);
439 mark_label.set_padding (5,0);
440 range_mark_label.set_name ("EditorTimeButton");
441 range_mark_label.set_size_request (-1, (int)timebar_height);
442 range_mark_label.set_alignment (1.0, 0.5);
443 range_mark_label.set_padding (5,0);
444 transport_mark_label.set_name ("EditorTimeButton");
445 transport_mark_label.set_size_request (-1, (int)timebar_height);
446 transport_mark_label.set_alignment (1.0, 0.5);
447 transport_mark_label.set_padding (5,0);
449 time_button_vbox.pack_start (minsec_label, false, false);
450 time_button_vbox.pack_start (smpte_label, false, false);
451 time_button_vbox.pack_start (frame_label, false, false);
452 time_button_vbox.pack_start (bbt_label, false, false);
453 time_button_vbox.pack_start (meter_label, false, false);
454 time_button_vbox.pack_start (tempo_label, false, false);
455 time_button_vbox.pack_start (mark_label, false, false);
457 time_button_event_box.add (time_button_vbox);
459 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
460 time_button_event_box.set_name ("TimebarLabelBase");
461 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
463 /* these enable us to have a dedicated window (for cursor setting, etc.)
464 for the canvas areas.
467 track_canvas_event_box.add (track_canvas_scroller);
469 time_canvas_event_box.add (time_canvas_vbox);
470 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
473 edit_packer.set_col_spacings (0);
474 edit_packer.set_row_spacings (0);
475 edit_packer.set_homogeneous (false);
476 edit_packer.set_name ("EditorWindow");
478 // edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, Gtk::FILL, 0, 0, 0);
479 // edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, 0, 0, 0);
480 // edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, Gtk::FILL, 0, 0, 0);
481 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
483 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
484 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
486 edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
487 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
488 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
490 edit_frame.set_name ("BaseFrame");
491 edit_frame.set_shadow_type (SHADOW_IN);
492 edit_frame.add (edit_packer);
494 zoom_in_button.set_name ("EditorTimeButton");
495 zoom_out_button.set_name ("EditorTimeButton");
496 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
497 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
499 // zoom_onetoone_button.set_name ("EditorTimeButton");
500 zoom_out_full_button.set_name ("EditorTimeButton");
501 // ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1"));
502 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
504 zoom_in_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_in_button_xpm)))));
505 zoom_out_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_button_xpm)))));
506 zoom_out_full_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_full_button_xpm)))));
507 // zoom_onetoone_button.add (*(manage (new Gtk::Image (zoom_onetoone_button_xpm))));
510 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
511 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
512 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
513 // zoom_onetoone_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom), 1.0));
515 zoom_indicator_box.pack_start (zoom_out_button, false, false);
516 zoom_indicator_box.pack_start (zoom_in_button, false, false);
517 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
518 // zoom_indicator_box.pack_start (zoom_onetoone_button, false, false);
519 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
521 zoom_indicator_label.set_text (_("Zoom Span"));
522 zoom_indicator_label.set_name ("ToolBarLabel");
525 zoom_indicator_vbox.set_spacing (3);
526 zoom_indicator_vbox.set_border_width (3);
527 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
528 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
531 bottom_hbox.set_border_width (3);
532 bottom_hbox.set_spacing (3);
534 route_list.set_name ("TrackListDisplay");
535 route_list.set_size_request (75,-1);
536 route_list.column_titles_active();
537 route_list.set_compare_func (route_list_compare_func);
538 route_list.set_shadow_type (Gtk::SHADOW_IN);
539 route_list.set_selection_mode (Gtk::SELECTION_MULTIPLE);
540 route_list.set_reorderable (true);
541 edit_group_list.set_size_request (75, -1);
543 route_list_scroller.add (route_list);
544 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
546 route_list.select_row.connect (mem_fun(*this, &Editor::route_list_selected));
547 route_list.unselect_row.connect (mem_fun(*this, &Editor::route_list_unselected));
548 route_list.row_move.connect (mem_fun(*this, &Editor::queue_route_list_reordered));
549 route_list.click_column.connect (mem_fun(*this, &Editor::route_list_column_click));
551 edit_group_list_button_label.set_text (_("Edit Groups"));
552 edit_group_list_button_label.set_name ("EditGroupTitleButton");
553 edit_group_list_button.add (edit_group_list_button_label);
554 edit_group_list_button.set_name ("EditGroupTitleButton");
556 edit_group_list.column_titles_hide();
557 edit_group_list.set_name ("MixerGroupList");
558 edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
559 edit_group_list.set_selection_mode (Gtk::SELECTION_MULTIPLE);
560 edit_group_list.set_reorderable (false);
561 edit_group_list.set_size_request (75, -1);
562 edit_group_list.set_column_auto_resize (0, true);
563 edit_group_list.columns_autosize ();
565 edit_group_list_scroller.add (edit_group_list);
566 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
568 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
569 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
570 edit_group_list.select_row.connect (mem_fun(*this, &Editor::edit_group_selected));
571 edit_group_list.unselect_row.connect (mem_fun(*this, &Editor::edit_group_unselected));
573 list<string> stupid_list;
575 stupid_list.push_back ("*");
576 stupid_list.push_back (_("-all-"));
578 edit_group_list.rows().push_back (stupid_list);
579 edit_group_list.rows().back().set_data (0);
580 edit_group_list.rows().back().select();
582 edit_group_vbox.pack_start (edit_group_list_button, false, false);
583 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
585 route_list_frame.set_name ("BaseFrame");
586 route_list_frame.set_shadow_type (Gtk::SHADOW_IN);
587 route_list_frame.add (route_list_scroller);
589 edit_group_list_frame.set_name ("BaseFrame");
590 edit_group_list_frame.set_shadow_type (Gtk::SHADOW_IN);
591 edit_group_list_frame.add (edit_group_vbox);
593 route_group_vpane.add1 (route_list_frame);
594 route_group_vpane.add2 (edit_group_list_frame);
596 list_vpacker.pack_start (route_group_vpane, true, true);
598 region_list_model = TreeStore::create (region_list_columns));
599 region_list_sort_model = TreeModelSort::create (region_list_model);
600 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
602 region_list_display.set_model (region_list_sort_model);
603 region_list_display.append_column (_("Regions"), region_list_columns.name);
604 region_list_display.set_reorderable (true);
605 region_list_display.set_size_request (100, -1);
606 region_list_display.set_data ("editor", this);
607 region_list_display.set_flags (Gtk::CAN_FOCUS);
608 region_list_display.set_name ("RegionListDisplay");
610 region_list_scroller.add (region_list_display);
611 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
613 region_list_display.drag_dest_set (GTK_DEST_DEFAULT_ALL,
614 target_table, n_targets - 1,
615 GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
616 region_list_display.drag_data_received.connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
618 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
619 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
620 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
621 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
622 region_list_display.signal_motion_notify_event().connect (mem_fun(*this, &Editor::region_list_display_motion));
623 region_list_display.signal_enter_notify_event().connect (mem_fun(*this, &Editor::region_list_display_enter_notify));
624 region_list_display.signal_leave_notify_event().connect (mem_fun(*this, &Editor::region_list_display_leave_notify));
625 region_list_display.select_row.connect (mem_fun(*this, &Editor::region_list_display_selected));
626 region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
627 region_list_display.click_column.connect (mem_fun(*this, &Editor::region_list_column_click));
629 named_selection_scroller.add (named_selection_display);
630 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
632 named_selection_display.set_name ("RegionListDisplay");
633 named_selection_display.set_size_request (100, -1);
634 named_selection_display.column_titles_active ();
635 named_selection_display.set_selection_mode (Gtk::SELECTION_SINGLE);
637 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
638 named_selection_display.select_row.connect (mem_fun(*this, &Editor::named_selection_display_selected));
639 named_selection_display.unselect_row.connect (mem_fun(*this, &Editor::named_selection_display_unselected));
641 region_selection_vpane.pack1 (region_list_scroller, true, true);
642 region_selection_vpane.pack2 (named_selection_scroller, true, true);
644 canvas_region_list_pane.pack1 (edit_frame, true, true);
645 canvas_region_list_pane.pack2 (region_selection_vpane, true, true);
647 track_list_canvas_pane.signal_size_allocate().connect_after (bind (mem_fun(*this, &Editor::pane_allocation_handler),
648 static_cast<Gtk::Paned*> (&track_list_canvas_pane)));
649 canvas_region_list_pane.signal_size_allocate().connect_after (bind (mem_fun(*this, &Editor::pane_allocation_handler),
650 static_cast<Gtk::Paned*> (&canvas_region_list_pane)));
651 route_group_vpane.signal_size_allocate().connect_after (bind (mem_fun(*this, &Editor::pane_allocation_handler),
652 static_cast<Gtk::Paned*> (&route_group_vpane)));
653 region_selection_vpane.signal_size_allocate().connect_after (bind (mem_fun(*this, &Editor::pane_allocation_handler),
654 static_cast<Gtk::Paned*> (®ion_selection_vpane)));
656 track_list_canvas_pane.pack1 (list_vpacker, true, true);
657 track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true);
659 /* provide special pane-handle event handling for easy "hide" action */
661 /* 0: collapse to show left/upper child
662 1: collapse to show right/lower child
665 route_group_vpane.set_data ("collapse-direction", (gpointer) 0);
666 region_selection_vpane.set_data ("collapse-direction", (gpointer) 0);
667 canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0);
668 track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1);
670 route_group_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&route_group_vpane)));
671 region_selection_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (®ion_selection_vpane)));
672 canvas_region_list_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&canvas_region_list_pane)));
673 track_list_canvas_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&track_list_canvas_pane)));
675 top_hbox.pack_start (toolbar_frame, true, true);
677 HBox *hbox = manage (new HBox);
678 hbox->pack_start (track_list_canvas_pane, true, true);
680 global_vpacker.pack_start (top_hbox, false, false);
681 global_vpacker.pack_start (*hbox, true, true);
683 global_hpacker.pack_start (global_vpacker, true, true);
685 set_name ("EditorWindow");
687 vpacker.pack_end (global_hpacker, true, true);
689 _playlist_selector = new PlaylistSelector();
690 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
692 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
696 nudge_forward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
697 nudge_backward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
699 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
700 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
702 nudge_forward_button.set_name ("TransportButton");
703 nudge_backward_button.set_name ("TransportButton");
705 fade_context_menu.set_name ("ArdourContextMenu");
707 install_keybindings ();
709 set_title (_("ardour: editor"));
710 set_wmclass (_("ardour_editor"), "Ardour");
713 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
715 configure_event.connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
716 delete_event.connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
724 /* <CMT Additions> */
725 if(image_socket_listener)
727 if(image_socket_listener->is_connected())
729 image_socket_listener->close_connection() ;
732 delete image_socket_listener ;
733 image_socket_listener = 0 ;
735 /* </CMT Additions> */
739 Editor::add_toplevel_controls (Container& cont)
741 vpacker.pack_start (cont, false, false);
746 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
748 /* note: the selection will take care of the vanishing
749 audioregionview by itself.
752 if (clicked_regionview == rv) {
753 clicked_regionview = 0;
756 if (entered_regionview == rv) {
757 set_entered_regionview (0);
762 Editor::set_entered_regionview (AudioRegionView* rv)
764 if (rv == entered_regionview) {
768 if (entered_regionview) {
769 entered_regionview->exited ();
772 if ((entered_regionview = rv) != 0) {
773 entered_regionview->entered ();
778 Editor::set_entered_track (TimeAxisView* tav)
781 entered_track->exited ();
784 if ((entered_track = tav) != 0) {
785 entered_track->entered ();
790 Editor::left_track_canvas (GdkEventCrossing *ev)
792 set_entered_track (0);
793 set_entered_regionview (0);
799 Editor::initialize_canvas ()
801 gnome_canvas_init ();
803 /* adjust sensitivity for "picking" items */
805 // GNOME_CANVAS(track_canvas)->close_enough = 2;
807 track_canvas.signal_event().connect (slot (*this, &Editor::track_canvas_event));
808 track_canvas.set_name ("EditorMainCanvas");
809 track_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
810 track_canvas.signal_event().connect (slot (*this, &Editor::track_canvas_event));
811 track_canvas.signal_leave_notify_event().connect (mem_fun(*this, &Editor::left_track_canvas));
813 /* set up drag-n-drop */
815 track_canvas.drag_dest_set (GTK_DEST_DEFAULT_ALL,
816 target_table, n_targets - 1,
817 GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
818 track_canvas.drag_data_received.connect (mem_fun(*this, &Editor::track_canvas_drag_data_received));
820 /* stuff for the verbose canvas cursor */
822 Pango::FontDescription font = get_font_for_style (N_("VerboseCanvasCursor"));
824 verbose_canvas_cursor = new Canvas::Text (track_canvas.root());
825 verbose_canvas_cursor->property_font_descr() << font;
826 verbose_canvas_cursor->property_anchor() << GTK_ANCHOR_NW;
827 verbose_canvas_cursor->property_fill_color_rgba() << color_map[cVerboseCanvasCursor];
829 verbose_cursor_visible = false;
831 /* a group to hold time (measure) lines */
833 time_line_group = new Canvas::Group (track_canvas.root(), 0.0, 0.0);
834 cursor_group = new Canvas::Group (track_canvas.root(), 0.0, 0.0);
836 time_canvas.set_name ("EditorTimeCanvas");
837 time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
839 meter_group = new Canvas::Group (time_canvas.root(), 0.0, 0.0);
840 tempo_group = new Canvas::Group (time_canvas.root(), 0.0, 0.0);
841 marker_group = new Canvas::Group (time_canvas.root(), 0.0, timebar_height * 2.0);
842 range_marker_group = new Canvas::Group (time_canvas.root(), 0.0, timebar_height * 3.0);
843 transport_marker_group = new Canvas::Group (time_canvas.root(), 0.0, timebar_height * 4.0);
845 tempo_bar = Canvas::SimpleRect (*tempo_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
846 tempo_bar->property_fill_color_rgba() << color_map[cTempoBar];
847 tempo_bar->property_outline_pixels() << 0;
849 meter_bar = Canvas::SimpleRect (*meter_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
850 meter_bar->property_fill_color_rgba() << color_map[cMeterBar];
851 meter_bar->property_outline_pixels() << 0;
853 marker_bar = Canvas::SimpleRect (*marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
854 marker_bar->property_fill_color_rgba() << color_map[cMarkerBar];
855 marker_bar->property_outline_pixels() << 0;
857 range_marker_bar = Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
858 range_marker_bar->property_fill_color_rgba() << color_map[cRangeMarkerBar];
859 range_marker_bar->property_outline_pixels() << 0;
861 transport_marker_bar = Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
862 transport_marker_bar->property_fill_color_rgba() << color_map[cTransportMarkerBar];
863 transport_marker_bar->property_outline_pixels() << 0;
865 range_bar_drag_rect = Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
866 range_bar_drag_rect->property_fill_color_rgba() << color_map[cRangeBarDragRectFill];
867 range_bar_drag_rect->property_outline_color_rgba() << color_map[cRangeBarDragRect];
868 range_bar_drag_rect->property_outline_pixels() << 0;
869 range_bar_drag_rect->hide ();
871 transport_bar_drag_rect = Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
872 transport_bar_drag_rect ->property_fill_color_rgba() << color_map[cTransportBarDragRectFill];
873 transport_bar_drag_rect->property_outline_color_rgba() << color_map[cTransportBarDragRect];
874 transport_bar_drag_rect->property_outline_pixels() << 0;
875 transport_bar_drag_rect->hide ();
877 marker_drag_line_points = new Canvas::Points (2);
878 marker_drag_line_points[0]->set_x (0.0);
879 marker_drag_line_points[0]->set_y (0.0);
880 marker_drag_line_points[1]->set_x (0.0);
881 marker_drag_line_points[1]->set_y (0.0);
883 marker_drag_line = Canvas::Line (track_canvas.root());
884 marker_drag_line->property_width_pixels() << 1;
885 marker_drag_line->property_fill_color_rgba() << color_map[cMarkerDragLine];
886 marker_drag_line->property_points() << marker_drag_line_points;
887 marker_drag_line->hide();
889 range_marker_drag_rect = new Canvas::SimpleRect (track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
890 range_marker_drag_rect->property_fill_color_rgba() << color_map[cRangeDragRectFill];
891 range_marker_drag_rect->property_outline_color_rgba() << color_map[cRangeDragRect];
892 range_marker_drag_rect->hide ();
894 transport_loop_range_rect = new Canvas::Simplerect (group.root(), 0.0, 0.0, 0.0, 0.0);
895 transport_loop_range_rect->property_fill_color_rgba() << color_map[cTransportLoopRectFill];
896 transport_loop_range_rect->property_outline_color_rgba() << color_map[cTransportLoopRect];
897 transport_loop_range_rect->property_outline_pixels() << 1;
898 transport_loop_range_rect->hide();
900 transport_punch_range_rect = new Canvas::Simplerect (group.root(), 0.0, 0.0, 0.0, 0.0);
901 transport_punch_range_rect->property_fill_color_rgba() << color_map[cTransportPunchRectFill];
902 transport_punch_range_rect->property_outline_color_rgba() << color_map[cTransportPunchRect];
903 transport_punch_range_rect->property_outline_pixels() << 0;
904 transport_punch_range_rect->hide();
906 transport_loop_range_rect->lower_to_bottom (); // loop on the bottom
908 transport_punchin_line = new Canvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
909 transport_punchin_line->property_outline_color_rgba() << color_map[cPunchInLine];
910 transport_punchin_line->property_outline_pixels() << 1;
911 transport_punchin_line->hide ();
913 transport_punchout_line = new Canvas::Simplerect (group.root(), 0.0, 0.0, 0.0, 0.0);
914 transport_punchout_line->property_outline_color_rgba() << color_map[cPunchOutLine];
915 transport_punchout_line->property_outline_pixels() << 1;
916 transport_punchout_line->hide();
918 // used to show zoom mode active zooming
919 zoom_rect = new Canvas::Simplerect (track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
920 zoom_rect->property_fill_color_rgba() << color_map[cZoomRectFill];
921 zoom_rect->property_outline_color_rgba() << color_map[cZoomRect];
922 zoom_rect->property_outline_pixels() << 1;
925 zoom_rect.signal_event().connect (slot (*this, &PublicEditor::canvas_zoom_rect_event));
927 // used as rubberband rect
928 rubberband_rect = new Canvas::Simplerect (track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
929 rubberband_rect->property_outline_color_rgba() << color_map[cRubberBandRect];
930 rubberband_rect->property_fill_color_rgba() << (guint32) color_map[cRubberBandRectFill];
931 rubberband_rect->property_outline_pixels() << 1;
932 rubberband_rect->hide();
934 tempo_bar.signal_event().connect (slot (*this, &PublicEditor::canvas_tempo_bar_event));
935 meter_bar.signal_event().connect (slot (*this, &PublicEditor::canvas_meter_bar_event));
936 marker_bar.signal_event().connect (slot (*this, &PublicEditor::canvas_marker_bar_event));
937 range_marker_bar.signal_event().connect (slot (*this, &PublicEditor::canvas_range_marker_bar_event));
938 transport_marker_bar.signal_event().connect (slot (*this, &PublicEditor::canvas_transport_marker_bar_event));
940 /* separator lines */
942 tempo_line_points = new Canvas::Points (2);
943 tempo_line_points[0]->set_x (0.0);
944 tempo_line_points[0]->set_y (timebar_height);
945 tempo_line_points[1]->set_x (max_canvas_coordinate);
946 tempo_line_points[1]->set_y (timebar_height);
948 tempo_line = Canvas::Line (*tempo_group, *tempo_line_points);
949 tempo_line->property_width_pixels() << 0;
950 tempo_line->property_fill_color() << "black";
952 meter_line_points = new Canvas::Points (2);
953 meter_line_points[0]->set_x (0);
954 meter_line_points[0]->set_y (timebar_height);
955 meter_line_points[1]->set_x (max_canvas_coordinate);
956 meter_line_points[1]->set_y (timebar_height);
958 meter_line = Canvas::Line (*meter_group, *meter_line_points);
959 meter_line->property_width_pixels() << 0;
960 meter_line->property_fill_color() << "black";
962 marker_line_points = Canvas::Points (2);
963 marker_line_points[0]->set_x (0);
964 marker_line_points[0]->set_y (timebar_height);
965 marker_line_points[1]->set_x (max_canvas_coordinate);
966 marker_line_points[1]->set_y (timebar_height);
968 marker_line = new Canvas::Line (*marker_group, *marker_line_points);
969 marker_line->property_width_pixels() << 0;
970 marker_line->property_fill_color() << "black";
972 range_marker_line = new Canvas::Line (*range_marker_group, marker_line_points);
973 range_marker_line->property_width_pixels() << 0;
974 range_marker_line->property_fill_color() << "black";
976 transport_marker_line = new Canvas::Line (*transport_marker_group, marker_line_points);
977 transport_marker_line->property_width_pixels() << 0;
978 transport_marker_line->property_fill_color() << "black";
980 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_loop_range_view), false));
981 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_punch_range_view), false));
983 double time_height = timebar_height * 5;
984 double time_width = FLT_MAX/frames_per_unit;
985 gnome_canvas_set_scroll_region (GNOME_CANVAS(time_canvas), 0.0, 0.0, time_width, time_height);
987 edit_cursor = new Cursor (*this, "blue", (GtkSignalFunc) _canvas_edit_cursor_event);
988 playhead_cursor = new Cursor (*this, "red", (GtkSignalFunc) _canvas_playhead_cursor_event);
990 track_canvas.size_allocate.connect (mem_fun(*this, &Editor::track_canvas_allocate));
994 Editor::show_window ()
998 /* now reset all audio_time_axis heights, because widgets might need
1004 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1005 tv = (static_cast<TimeAxisView*>(*i));
1006 tv->reset_height ();
1011 Editor::tie_vertical_scrolling ()
1013 edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
1015 float y1 = track_canvas_scroller.get_vadjustment()->get_value();
1016 playhead_cursor->set_y_axis(y1);
1017 edit_cursor->set_y_axis(y1);
1021 Editor::set_frames_per_unit (double fpu)
1023 jack_nframes_t frames;
1025 if (fpu == frames_per_unit) {
1033 // convert fpu to frame count
1035 frames = (jack_nframes_t) (fpu * canvas_width);
1037 /* don't allow zooms that fit more than the maximum number
1038 of frames into an 800 pixel wide space.
1041 if (max_frames / fpu < 800.0) {
1045 frames_per_unit = fpu;
1047 if (frames != zoom_range_clock.current_duration()) {
1048 zoom_range_clock.set (frames);
1051 /* only update these if we not about to call reposition_x_origin,
1052 which will do the same updates.
1056 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1059 if (!no_zoom_repos_update) {
1060 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1061 update_hscroller ();
1062 update_fixed_rulers ();
1063 tempo_map_changed (Change (0));
1066 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
1067 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1068 (*i)->reshow_selection (selection->time);
1072 ZoomChanged (); /* EMIT_SIGNAL */
1074 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
1075 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
1082 Editor::instant_save ()
1084 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
1089 session->add_instant_xml(get_state(), session->path());
1091 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
1096 Editor::reposition_x_origin (jack_nframes_t frame)
1098 if (frame != leftmost_frame) {
1099 leftmost_frame = frame;
1100 double pixel = frame_to_pixel (frame);
1101 if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
1102 track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
1104 track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
1105 XOriginChanged (); /* EMIT_SIGNAL */
1110 Editor::edit_cursor_clock_changed()
1112 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
1113 edit_cursor->set_position (edit_cursor_clock.current_time());
1119 Editor::zoom_adjustment_changed ()
1121 if (session == 0 || no_zoom_repos_update) {
1125 double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width;
1129 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1131 else if (fpu > session->current_end_frame() / (double) canvas_width) {
1132 fpu = session->current_end_frame() / (double) canvas_width;
1133 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1136 temporal_zoom (fpu);
1140 Editor::canvas_horizontally_scrolled ()
1142 /* XXX note the potential loss of accuracy here caused by
1143 adjustments being 32bit floats with only a 24 bit mantissa,
1144 whereas jack_nframes_t is at least a 32 bit uint32_teger.
1147 leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
1149 update_hscroller ();
1150 update_fixed_rulers ();
1152 if (!edit_hscroll_dragging) {
1153 tempo_map_changed (Change (0));
1155 update_tempo_based_rulers();
1160 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
1162 if (!repos_zoom_queued) {
1163 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
1164 repos_zoom_queued = true;
1169 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
1171 /* if we need to force an update to the hscroller stuff,
1172 don't set no_zoom_repos_update.
1175 no_zoom_repos_update = (frame != leftmost_frame);
1177 set_frames_per_unit (nfpu);
1178 if (no_zoom_repos_update) {
1179 reposition_x_origin (frame);
1181 no_zoom_repos_update = false;
1182 repos_zoom_queued = false;
1188 Editor::on_realize ()
1190 /* Even though we're not using acceleration, we want the
1194 track_context_menu.accelerate (*this->get_toplevel());
1195 track_region_context_menu.accelerate (*this->get_toplevel());
1197 Window::on_realize ();
1199 GdkPixmap* empty_pixmap = gdk_pixmap_new (get_window()->gobj(), 1, 1, 1);
1200 GdkPixmap* empty_bitmap = gdk_pixmap_new (get_window()->gobj(), 1, 1, 1);
1201 GdkColor white = { 0, 0, 0 };
1203 null_cursor = gdk_cursor_new_from_pixmap (empty_pixmap, empty_bitmap, &white, &white, 0, 0);
1211 track_canvas_scroller.get_window()->set_cursor (current_canvas_cursor);
1212 time_canvas_scroller.get_window()->set_cursor (timebar_cursor);
1216 Editor::track_canvas_allocate (GtkAllocation *alloc)
1218 canvas_width = alloc->width;
1219 canvas_height = alloc->height;
1221 if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) {
1223 Pango::FontDescription font = get_font_for_style (N_("FirstActionMessage"));
1225 const char *txt1 = _("Start a new session\n");
1226 const char *txt2 = _("via Session menu");
1228 /* this mess of code is here to find out how wide this text is and
1229 position the message in the center of the editor window. there
1230 are two lines, so we use the longer of the the lines to
1231 compute width, and multiply the height by 2.
1237 /* this is a dummy widget that exists so that we can get the
1238 style from the RC file.
1241 Label foo (_(txt2));
1242 Glib::RefPtr<Pango::Layout> layout;
1243 foo.set_name ("NoSessionMessage");
1244 foo.ensure_style ();
1246 layout = foo.create_pango_layout (_(txt2));
1247 layout->set_font_description (font);
1248 layout->get_pixel_size (pixel_width, pixel_height);
1250 if (first_action_message == 0) {
1252 char txt[strlen(txt1)+strlen(txt2)+1];
1254 /* merge both lines */
1256 strcpy (txt, _(txt1));
1257 strcat (txt, _(txt2));
1259 first_action_message = gnome_canvas_item_new (gnome_canvas_root(GNOME_CANVAS(track_canvas)),
1260 gnome_canvas_text_get_type(),
1262 "fill_color_rgba", color_map[cFirstActionMessage],
1263 "x", (gdouble) (canvas_width - pixel_width) / 2.0,
1264 "y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)),
1265 "anchor", GTK_ANCHOR_NORTH_WEST,
1273 gnome_canvas_item_set (first_action_message,
1274 "x", (gdouble) (canvas_width - pixel_width) / 2.0,
1275 "y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)),
1280 zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit));
1281 edit_cursor->set_position (edit_cursor->current_frame);
1282 playhead_cursor->set_position (playhead_cursor->current_frame);
1283 reset_scrolling_region (alloc);
1285 Resized (); /* EMIT_SIGNAL */
1289 Editor::reset_scrolling_region (GtkAllocation *alloc)
1291 guint32 last_canvas_unit;
1293 guint32 canvas_alloc_height, canvas_alloc_width;
1294 TrackViewList::iterator i;
1295 static bool first_time = true;
1297 /* We need to make sure that the canvas always has its
1298 scrolling region set to larger of:
1300 - the size allocated for it (within the container its packed in)
1301 - the size required to see the entire session
1303 If we don't ensure at least the first of these, the canvas
1304 does some wierd and in my view unnecessary stuff to center
1305 itself within the allocated area, which causes bad, bad
1308 XXX GnomeCanvas has fixed this, and has an option to
1309 control the centering behaviour.
1312 last_canvas_unit = (guint32) ceil ((float) max_frames / frames_per_unit);
1317 for (i = track_views.begin(); i != track_views.end(); ++i) {
1318 if ((*i)->control_parent) {
1319 height += (*i)->effective_height;
1320 height += track_spacing;
1325 height -= track_spacing;
1329 canvas_height = (guint32) height;
1332 canvas_alloc_height = alloc->height;
1333 canvas_alloc_width = alloc->width;
1335 canvas_alloc_height = track_canvas->allocation.height;
1336 canvas_alloc_width = track_canvas->allocation.width;
1339 canvas_height = max (canvas_height, canvas_alloc_height);
1341 gnome_canvas_set_scroll_region (GNOME_CANVAS(track_canvas), 0.0, 0.0,
1342 max (last_canvas_unit, canvas_alloc_width),
1345 if (edit_cursor) edit_cursor->set_length (canvas_alloc_height);
1346 if (playhead_cursor) playhead_cursor->set_length (canvas_alloc_height);
1348 if (marker_drag_line) {
1349 marker_drag_line_points->coords[3] = canvas_height;
1350 // cerr << "set mlA points, nc = " << marker_drag_line_points->num_points << endl;
1351 gnome_canvas_item_set (marker_drag_line, "points", marker_drag_line_points, NULL);
1353 if (range_marker_drag_rect) {
1354 gnome_canvas_item_set (range_marker_drag_rect, "y1", 0.0, "y2", (double) canvas_height, NULL);
1356 if (transport_loop_range_rect) {
1357 gnome_canvas_item_set (transport_loop_range_rect, "y1", 0.0, "y2", (double) canvas_height, NULL);
1359 if (transport_punch_range_rect) {
1360 gnome_canvas_item_set (transport_punch_range_rect, "y1", 0.0, "y2", (double) canvas_height, NULL);
1362 if (transport_punchin_line) {
1363 gnome_canvas_item_set (transport_punchin_line, "y1", 0.0, "y2", (double) canvas_height, NULL);
1365 if (transport_punchout_line) {
1366 gnome_canvas_item_set (transport_punchout_line, "y1", 0.0, "y2", (double) canvas_height, NULL);
1370 update_fixed_rulers ();
1372 if (is_visible() && first_time) {
1373 tempo_map_changed (Change (0));
1381 Editor::queue_session_control_changed (Session::ControlType t)
1383 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1387 Editor::session_control_changed (Session::ControlType t)
1389 // right now we're only tracking the loop and punch state
1392 case Session::AutoLoop:
1393 update_loop_range_view (true);
1395 case Session::PunchIn:
1396 case Session::PunchOut:
1397 update_punch_range_view (true);
1406 Editor::fake_add_edit_group (RouteGroup *group)
1408 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1412 Editor::fake_handle_new_audio_region (AudioRegion *region)
1414 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1418 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1420 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1424 Editor::fake_handle_new_duration ()
1426 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1430 Editor::start_scrolling ()
1432 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1433 (mem_fun(*this, &Editor::update_current_screen));
1435 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1436 (mem_fun(*this, &Editor::update_slower));
1440 Editor::stop_scrolling ()
1442 scroll_connection.disconnect ();
1443 slower_update_connection.disconnect ();
1447 Editor::map_position_change (jack_nframes_t frame)
1449 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1451 if (session == 0 || !_follow_playhead) {
1455 center_screen (frame);
1456 playhead_cursor->set_position (frame);
1460 Editor::center_screen (jack_nframes_t frame)
1462 float page = canvas_width * frames_per_unit;
1464 /* if we're off the page, then scroll.
1467 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1468 center_screen_internal (frame,page);
1473 Editor::center_screen_internal (jack_nframes_t frame, float page)
1478 frame -= (jack_nframes_t) page;
1483 reposition_x_origin (frame);
1487 Editor::handle_new_duration ()
1489 reset_scrolling_region ();
1492 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1493 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1496 update_hscroller ();
1500 Editor::update_title_s (string snap_name)
1502 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1508 Editor::update_title ()
1510 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1513 bool dirty = session->dirty();
1515 string wintitle = _("ardour: editor: ");
1521 wintitle += session->name();
1523 if (session->snap_name() != session->name()) {
1525 wintitle += session->snap_name();
1532 set_title (wintitle);
1537 Editor::connect_to_session (Session *t)
1541 if (first_action_message) {
1542 gnome_canvas_item_hide (first_action_message);
1545 flush_track_canvas();
1549 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1551 /* These signals can all be emitted by a non-GUI thread. Therefore the
1552 handlers for them must not attempt to directly interact with the GUI,
1553 but use Gtkmm2ext::UI::instance()->call_slot();
1556 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1557 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1558 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1559 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1560 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1561 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1562 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1563 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1564 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1565 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1566 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1567 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1568 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1570 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1571 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1573 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1575 session->foreach_edit_group(this, &Editor::add_edit_group);
1577 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1578 editor_mixer_button.set_name (X_("EditorMixerButton"));
1580 edit_cursor_clock.set_session (session);
1581 selection_start_clock.set_session (session);
1582 selection_end_clock.set_session (session);
1583 zoom_range_clock.set_session (session);
1584 _playlist_selector->set_session (session);
1585 nudge_clock.set_session (session);
1587 switch (session->get_edit_mode()) {
1589 edit_mode_selector.get_entry()->set_text (edit_mode_strings[splice_index]);
1593 edit_mode_selector.get_entry()->set_text (edit_mode_strings[slide_index]);
1597 Location* loc = session->locations()->auto_loop_location();
1599 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1600 if (loc->start() == loc->end()) {
1601 loc->set_end (loc->start() + 1);
1603 session->locations()->add (loc, false);
1604 session->set_auto_loop_location (loc);
1608 loc->set_name (_("Loop"));
1611 loc = session->locations()->auto_punch_location();
1613 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1614 if (loc->start() == loc->end()) {
1615 loc->set_end (loc->start() + 1);
1617 session->locations()->add (loc, false);
1618 session->set_auto_punch_location (loc);
1622 loc->set_name (_("Punch"));
1625 update_loop_range_view (true);
1626 update_punch_range_view (true);
1628 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1631 refresh_location_display ();
1632 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1633 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1634 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1635 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1636 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1638 reset_scrolling_region ();
1640 redisplay_regions ();
1641 redisplay_named_selections ();
1643 route_list.freeze ();
1644 route_list.clear ();
1645 session->foreach_route (this, &Editor::handle_new_route);
1646 // route_list.select_all ();
1648 route_list_reordered ();
1651 if (embed_audio_item) {
1652 embed_audio_item->set_sensitive (true);
1654 if (import_audio_item) {
1655 import_audio_item->set_sensitive (true);
1658 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1659 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1662 /* ::reposition_x_origin() doesn't work right here, since the old
1663 position may be zero already, and it does nothing in such
1669 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1670 track_canvas_scroller.get_hadjustment()->set_value (0);
1672 update_hscroller ();
1673 restore_ruler_visibility ();
1674 tempo_map_changed (Change (0));
1676 edit_cursor->set_position (0);
1677 playhead_cursor->set_position (0);
1681 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1684 /* don't show master bus in a new session */
1686 if (ARDOUR_UI::instance()->session_is_new ()) {
1688 Gtk::CList_Helpers::RowList::iterator i;
1689 Gtk::CList_Helpers::RowList& rowlist = route_list.rows();
1691 route_list.freeze ();
1693 for (i = rowlist.begin(); i != rowlist.end(); ++i) {
1694 TimeAxisView *tv = (TimeAxisView *) i->get_data ();
1695 AudioTimeAxisView *atv;
1697 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1698 if (atv->route().master()) {
1709 Editor::build_cursors ()
1711 GdkPixmap *source, *mask;
1712 GdkColor fg = { 0, 65535, 0, 0 }; /* Red. */
1713 GdkColor bg = { 0, 0, 0, 65535 }; /* Blue. */
1715 source = gdk_bitmap_create_from_data (NULL, hand_bits,
1716 hand_width, hand_height);
1717 mask = gdk_bitmap_create_from_data (NULL, handmask_bits,
1718 handmask_width, handmask_height);
1719 grabber_cursor = gdk_cursor_new_from_pixmap (source, mask, &fg, &bg, hand_x_hot, hand_y_hot);
1720 gdk_pixmap_unref (source);
1721 gdk_pixmap_unref (mask);
1724 GdkColor mbg = { 0, 0, 0, 0 }; /* Black */
1725 GdkColor mfg = { 0, 0, 0, 65535 }; /* Blue. */
1727 source = gdk_bitmap_create_from_data (NULL, mag_bits,
1728 mag_width, mag_height);
1729 mask = gdk_bitmap_create_from_data (NULL, magmask_bits,
1730 mag_width, mag_height);
1731 zoom_cursor = gdk_cursor_new_from_pixmap (source, mask, &mfg, &mbg, mag_x_hot, mag_y_hot);
1732 gdk_pixmap_unref (source);
1733 gdk_pixmap_unref (mask);
1735 GdkColor fbg = { 0, 65535, 65535, 65535 };
1736 GdkColor ffg = { 0, 0, 0, 0 };
1738 source = gdk_bitmap_create_from_data (NULL, fader_cursor_bits,
1739 fader_cursor_width, fader_cursor_height);
1740 mask = gdk_bitmap_create_from_data (NULL, fader_cursor_mask_bits,
1741 fader_cursor_width, fader_cursor_height);
1742 fader_cursor = gdk_cursor_new_from_pixmap (source, mask, &ffg, &fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1743 gdk_pixmap_unref (source);
1744 gdk_pixmap_unref (mask);
1746 source = gdk_bitmap_create_from_data (NULL, speaker_cursor_bits,
1747 speaker_cursor_width, speaker_cursor_height);
1748 mask = gdk_bitmap_create_from_data (NULL, speaker_cursor_mask_bits,
1749 speaker_cursor_width, speaker_cursor_height);
1750 speaker_cursor = gdk_cursor_new_from_pixmap (source, mask, &ffg, &fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1751 gdk_pixmap_unref (source);
1752 gdk_pixmap_unref (mask);
1754 cross_hair_cursor = gdk_cursor_new (GDK_CROSSHAIR);
1755 trimmer_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
1756 selector_cursor = gdk_cursor_new (GDK_XTERM);
1757 time_fx_cursor = gdk_cursor_new (GDK_SIZING);
1758 wait_cursor = gdk_cursor_new (GDK_WATCH);
1759 timebar_cursor = gdk_cursor_new (GDK_LEFT_PTR);
1763 Editor::popup_fade_context_menu (int button, int32_t time, GnomeCanvasItem* item, ItemType item_type)
1765 using namespace Menu_Helpers;
1766 AudioRegionView* arv = static_cast<AudioRegionView*> (gtk_object_get_data (GTK_OBJECT(item), "regionview"));
1769 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1773 MenuList& items (fade_context_menu.items());
1777 switch (item_type) {
1779 case FadeInHandleItem:
1780 if (arv->region.fade_in_active()) {
1781 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1783 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1786 items.push_back (SeparatorElem());
1788 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1789 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1790 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1791 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1792 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1796 case FadeOutHandleItem:
1797 if (arv->region.fade_out_active()) {
1798 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1800 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1803 items.push_back (SeparatorElem());
1805 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1806 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1807 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1808 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1809 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1813 fatal << _("programming error: ")
1814 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1819 fade_context_menu.popup (button, time);
1823 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1825 using namespace Menu_Helpers;
1826 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1829 switch (item_type) {
1831 case AudioRegionViewName:
1832 case AudioRegionViewNameHighlight:
1833 if (with_selection) {
1834 build_menu_function = &Editor::build_track_selection_context_menu;
1836 build_menu_function = &Editor::build_track_region_context_menu;
1841 if (with_selection) {
1842 build_menu_function = &Editor::build_track_selection_context_menu;
1844 build_menu_function = &Editor::build_track_context_menu;
1848 case CrossfadeViewItem:
1849 build_menu_function = &Editor::build_track_crossfade_context_menu;
1853 if (clicked_audio_trackview->get_diskstream()) {
1854 build_menu_function = &Editor::build_track_context_menu;
1856 build_menu_function = &Editor::build_track_bus_context_menu;
1861 /* probably shouldn't happen but if it does, we don't care */
1865 menu = (this->*build_menu_function)(frame);
1866 menu->set_name ("ArdourContextMenu");
1868 /* now handle specific situations */
1870 switch (item_type) {
1872 case AudioRegionViewName:
1873 case AudioRegionViewNameHighlight:
1874 if (!with_selection) {
1875 if (region_edit_menu_split_item) {
1876 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1877 region_edit_menu_split_item->set_sensitive (true);
1879 region_edit_menu_split_item->set_sensitive (false);
1882 if (region_edit_menu_split_multichannel_item) {
1883 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1884 region_edit_menu_split_multichannel_item->set_sensitive (true);
1886 region_edit_menu_split_multichannel_item->set_sensitive (false);
1895 case CrossfadeViewItem:
1902 /* probably shouldn't happen but if it does, we don't care */
1906 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1908 /* Bounce to disk */
1910 using namespace Menu_Helpers;
1911 MenuList& edit_items = menu->items();
1913 edit_items.push_back (SeparatorElem());
1915 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1916 case AudioTrack::NoFreeze:
1917 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1920 case AudioTrack::Frozen:
1921 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1924 case AudioTrack::UnFrozen:
1925 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1931 menu->popup (button, time);
1935 Editor::build_track_context_menu (jack_nframes_t ignored)
1937 using namespace Menu_Helpers;
1939 MenuList& edit_items = track_context_menu.items();
1942 add_dstream_context_items (edit_items);
1943 return &track_context_menu;
1947 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1949 using namespace Menu_Helpers;
1951 MenuList& edit_items = track_context_menu.items();
1954 add_bus_context_items (edit_items);
1955 return &track_context_menu;
1959 Editor::build_track_region_context_menu (jack_nframes_t frame)
1961 using namespace Menu_Helpers;
1962 MenuList& edit_items = track_region_context_menu.items();
1965 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1971 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1972 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1973 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1974 add_region_context_items (atv->view, (*i), edit_items);
1980 add_dstream_context_items (edit_items);
1982 return &track_region_context_menu;
1986 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1988 using namespace Menu_Helpers;
1989 MenuList& edit_items = track_crossfade_context_menu.items();
1990 edit_items.clear ();
1992 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1999 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
2001 Playlist::RegionList* regions = pl->regions_at (frame);
2002 AudioPlaylist::Crossfades xfades;
2004 apl->crossfades_at (frame, xfades);
2006 bool many = xfades.size() > 1;
2008 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
2009 add_crossfade_context_items (atv->view, (*i), edit_items, many);
2012 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
2013 add_region_context_items (atv->view, (*i), edit_items);
2020 add_dstream_context_items (edit_items);
2022 return &track_crossfade_context_menu;
2026 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
2028 using namespace Menu_Helpers;
2029 MenuList& edit_items = track_selection_context_menu.items();
2030 edit_items.clear ();
2032 add_selection_context_items (edit_items);
2033 add_dstream_context_items (edit_items);
2035 return &track_selection_context_menu;
2039 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
2041 using namespace Menu_Helpers;
2042 Menu *xfade_menu = manage (new Menu);
2043 MenuList& items = xfade_menu->items();
2044 xfade_menu->set_name ("ArdourContextMenu");
2047 if (xfade->active()) {
2053 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
2054 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
2056 if (xfade->can_follow_overlap()) {
2058 if (xfade->following_overlap()) {
2059 str = _("Convert to short");
2061 str = _("Convert to full");
2064 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
2068 str = xfade->out().name();
2070 str += xfade->in().name();
2072 str = _("Crossfade");
2075 edit_items.push_back (MenuElem (str, *xfade_menu));
2076 edit_items.push_back (SeparatorElem());
2080 Editor::xfade_edit_left_region ()
2082 if (clicked_crossfadeview) {
2083 clicked_crossfadeview->left_view.show_region_editor ();
2088 Editor::xfade_edit_right_region ()
2090 if (clicked_crossfadeview) {
2091 clicked_crossfadeview->right_view.show_region_editor ();
2096 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
2098 using namespace Menu_Helpers;
2099 Menu *region_menu = manage (new Menu);
2100 MenuList& items = region_menu->items();
2101 region_menu->set_name ("ArdourContextMenu");
2103 AudioRegion* ar = 0;
2106 ar = dynamic_cast<AudioRegion*> (region);
2109 /* when this particular menu pops up, make the relevant region
2113 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
2115 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
2116 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
2117 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
2118 items.push_back (SeparatorElem());
2119 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
2120 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
2121 items.push_back (SeparatorElem());
2123 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
2124 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
2125 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
2126 items.push_back (SeparatorElem());
2128 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
2129 might be able to figure out which overloaded member function to use in
2133 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
2135 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
2136 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
2137 items.push_back (SeparatorElem());
2139 if (region->muted()) {
2140 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
2142 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
2144 items.push_back (SeparatorElem());
2146 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
2147 items.push_back (SeparatorElem());
2152 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
2153 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
2154 items.push_back (SeparatorElem());
2156 if (ar->scale_amplitude() != 1.0f) {
2157 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
2159 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
2162 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
2163 items.push_back (SeparatorElem());
2167 Menu *nudge_menu = manage (new Menu());
2168 MenuList& nudge_items = nudge_menu->items();
2169 nudge_menu->set_name ("ArdourContextMenu");
2171 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
2172 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
2173 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
2174 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
2176 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2177 items.push_back (SeparatorElem());
2179 Menu *trim_menu = manage (new Menu);
2180 MenuList& trim_items = trim_menu->items();
2181 trim_menu->set_name ("ArdourContextMenu");
2183 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
2184 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
2186 items.push_back (MenuElem (_("Trim"), *trim_menu));
2187 items.push_back (SeparatorElem());
2189 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
2190 region_edit_menu_split_item = &items.back();
2192 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
2193 region_edit_menu_split_multichannel_item = &items.back();
2195 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
2196 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
2197 items.push_back (SeparatorElem());
2198 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
2199 items.push_back (SeparatorElem());
2200 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
2202 /* OK, stick the region submenu at the top of the list, and then add
2206 /* we have to hack up the region name because "_" has a special
2207 meaning for menu titles.
2210 string::size_type pos = 0;
2211 string menu_item_name = region->name();
2213 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
2214 menu_item_name.replace (pos, 1, "__");
2218 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
2219 edit_items.push_back (SeparatorElem());
2223 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
2225 using namespace Menu_Helpers;
2226 Menu *selection_menu = manage (new Menu);
2227 MenuList& items = selection_menu->items();
2228 selection_menu->set_name ("ArdourContextMenu");
2230 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
2231 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
2232 items.push_back (SeparatorElem());
2233 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
2234 items.push_back (SeparatorElem());
2235 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
2236 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
2237 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
2238 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
2239 items.push_back (SeparatorElem());
2240 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
2241 items.push_back (SeparatorElem());
2242 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
2243 items.push_back (SeparatorElem());
2244 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
2246 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
2247 edit_items.push_back (SeparatorElem());
2251 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
2253 using namespace Menu_Helpers;
2257 Menu *play_menu = manage (new Menu);
2258 MenuList& play_items = play_menu->items();
2259 play_menu->set_name ("ArdourContextMenu");
2261 play_items.push_back (MenuElem (_("Play from edit cursor")));
2262 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2263 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
2264 play_items.push_back (SeparatorElem());
2265 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
2267 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2271 Menu *select_menu = manage (new Menu);
2272 MenuList& select_items = select_menu->items();
2273 select_menu->set_name ("ArdourContextMenu");
2275 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2276 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2277 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2278 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2279 select_items.push_back (SeparatorElem());
2280 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2281 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2282 select_items.push_back (SeparatorElem());
2284 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2288 Menu *cutnpaste_menu = manage (new Menu);
2289 MenuList& cutnpaste_items = cutnpaste_menu->items();
2290 cutnpaste_menu->set_name ("ArdourContextMenu");
2292 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2293 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2294 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2295 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
2297 cutnpaste_items.push_back (SeparatorElem());
2299 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
2300 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
2302 cutnpaste_items.push_back (SeparatorElem());
2304 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
2306 cutnpaste_items.push_back (SeparatorElem());
2308 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
2309 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
2311 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2313 /* Adding new material */
2315 Menu *import_menu = manage (new Menu());
2316 MenuList& import_items = import_menu->items();
2317 import_menu->set_name ("ArdourContextMenu");
2319 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2320 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
2322 edit_items.push_back (MenuElem (_("Import"), *import_menu));
2326 Menu *nudge_menu = manage (new Menu());
2327 MenuList& nudge_items = nudge_menu->items();
2328 nudge_menu->set_name ("ArdourContextMenu");
2330 edit_items.push_back (SeparatorElem());
2331 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2332 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2333 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2334 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2336 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2340 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2342 using namespace Menu_Helpers;
2346 Menu *play_menu = manage (new Menu);
2347 MenuList& play_items = play_menu->items();
2348 play_menu->set_name ("ArdourContextMenu");
2350 play_items.push_back (MenuElem (_("Play from edit cursor")));
2351 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2352 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2356 Menu *select_menu = manage (new Menu);
2357 MenuList& select_items = select_menu->items();
2358 select_menu->set_name ("ArdourContextMenu");
2360 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2361 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2362 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2363 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2364 select_items.push_back (SeparatorElem());
2365 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2366 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2367 select_items.push_back (SeparatorElem());
2369 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2373 Menu *cutnpaste_menu = manage (new Menu);
2374 MenuList& cutnpaste_items = cutnpaste_menu->items();
2375 cutnpaste_menu->set_name ("ArdourContextMenu");
2377 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2378 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2379 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2381 Menu *nudge_menu = manage (new Menu());
2382 MenuList& nudge_items = nudge_menu->items();
2383 nudge_menu->set_name ("ArdourContextMenu");
2385 edit_items.push_back (SeparatorElem());
2386 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2387 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2388 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2389 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2391 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2394 /* CURSOR SETTING AND MARKS AND STUFF */
2397 Editor::set_snap_to (SnapType st)
2400 vector<string> txt = internationalize (snap_type_strings);
2401 snap_type_selector.get_entry()->set_text (txt[(int)st]);
2405 switch (snap_type) {
2406 case SnapToAThirtysecondBeat:
2407 case SnapToASixteenthBeat:
2408 case SnapToAEighthBeat:
2409 case SnapToAQuarterBeat:
2410 case SnapToAThirdBeat:
2411 update_tempo_based_rulers ();
2419 Editor::set_snap_mode (SnapMode mode)
2422 vector<string> txt = internationalize (snap_mode_strings);
2423 snap_mode_selector.get_entry()->set_text (txt[(int)mode]);
2429 Editor::add_location_from_selection ()
2431 if (selection->time.empty()) {
2435 if (session == 0 || clicked_trackview == 0) {
2439 jack_nframes_t start = selection->time[clicked_selection].start;
2440 jack_nframes_t end = selection->time[clicked_selection].end;
2442 Location *location = new Location (start, end, "selection");
2444 session->begin_reversible_command (_("add marker"));
2445 session->add_undo (session->locations()->get_memento());
2446 session->locations()->add (location, true);
2447 session->add_redo_no_execute (session->locations()->get_memento());
2448 session->commit_reversible_command ();
2452 Editor::add_location_from_playhead_cursor ()
2454 jack_nframes_t where = session->audible_frame();
2456 Location *location = new Location (where, where, "mark", Location::IsMark);
2457 session->begin_reversible_command (_("add marker"));
2458 session->add_undo (session->locations()->get_memento());
2459 session->locations()->add (location, true);
2460 session->add_redo_no_execute (session->locations()->get_memento());
2461 session->commit_reversible_command ();
2466 Editor::set_state (const XMLNode& node)
2468 const XMLProperty* prop;
2470 int x, y, width, height, xoff, yoff;
2472 if ((geometry = find_named_node (node, "geometry")) == 0) {
2474 width = default_width;
2475 height = default_height;
2483 width = atoi(geometry->property("x_size")->value());
2484 height = atoi(geometry->property("y_size")->value());
2485 x = atoi(geometry->property("x_pos")->value());
2486 y = atoi(geometry->property("y_pos")->value());
2487 xoff = atoi(geometry->property("x_off")->value());
2488 yoff = atoi(geometry->property("y_off")->value());
2491 set_default_size(width, height);
2492 set_uposition(x, y-yoff);
2494 if ((prop = node.property ("zoom-focus"))) {
2495 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2498 if ((prop = node.property ("zoom"))) {
2499 set_frames_per_unit (atof (prop->value()));
2502 if ((prop = node.property ("snap-to"))) {
2503 set_snap_to ((SnapType) atoi (prop->value()));
2506 if ((prop = node.property ("snap-mode"))) {
2507 set_snap_mode ((SnapMode) atoi (prop->value()));
2510 if ((prop = node.property ("show-waveforms"))) {
2511 bool yn = (prop->value() == "yes");
2512 _show_waveforms = !yn;
2513 set_show_waveforms (yn);
2516 if ((prop = node.property ("show-waveforms-recording"))) {
2517 bool yn = (prop->value() == "yes");
2518 _show_waveforms_recording = !yn;
2519 set_show_waveforms_recording (yn);
2522 if ((prop = node.property ("show-measures"))) {
2523 bool yn = (prop->value() == "yes");
2524 _show_measures = !yn;
2525 set_show_measures (yn);
2528 if ((prop = node.property ("follow-playhead"))) {
2529 bool yn = (prop->value() == "yes");
2530 _follow_playhead = !yn;
2531 set_follow_playhead (yn);
2534 if ((prop = node.property ("xfades-visible"))) {
2535 bool yn = (prop->value() == "yes");
2536 _xfade_visibility = !yn;
2537 set_xfade_visibility (yn);
2540 if ((prop = node.property ("region-list-sort-type"))) {
2541 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2542 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2545 if ((prop = node.property ("mouse-mode"))) {
2546 MouseMode m = str2mousemode(prop->value());
2547 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2548 set_mouse_mode (m, true);
2550 mouse_mode = MouseGain; /* lie, to force the mode switch */
2551 set_mouse_mode (MouseObject, true);
2554 if ((prop = node.property ("editor-mixer-button"))) {
2555 editor_mixer_button.set_active(prop->value() == "yes");
2562 Editor::get_state ()
2564 XMLNode* node = new XMLNode ("Editor");
2567 if (is_realized()) {
2568 Gdk_Window win = get_window();
2570 int x, y, xoff, yoff, width, height;
2571 win.get_root_origin(x, y);
2572 win.get_position(xoff, yoff);
2573 win.get_size(width, height);
2575 XMLNode* geometry = new XMLNode ("geometry");
2577 snprintf(buf, sizeof(buf), "%d", width);
2578 geometry->add_property("x_size", string(buf));
2579 snprintf(buf, sizeof(buf), "%d", height);
2580 geometry->add_property("y_size", string(buf));
2581 snprintf(buf, sizeof(buf), "%d", x);
2582 geometry->add_property("x_pos", string(buf));
2583 snprintf(buf, sizeof(buf), "%d", y);
2584 geometry->add_property("y_pos", string(buf));
2585 snprintf(buf, sizeof(buf), "%d", xoff);
2586 geometry->add_property("x_off", string(buf));
2587 snprintf(buf, sizeof(buf), "%d", yoff);
2588 geometry->add_property("y_off", string(buf));
2589 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gobj()));
2590 geometry->add_property("canvas_region_list_pane_pos", string(buf));
2591 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gobj()));
2592 geometry->add_property("track_list_canvas_pane_pos", string(buf));
2593 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(®ion_selection_vpane)->gobj()));
2594 geometry->add_property("region_selection_pane_pos", string(buf));
2595 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gobj()));
2596 geometry->add_property("route_group_pane_pos", string(buf));
2598 node->add_child_nocopy (*geometry);
2601 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2602 node->add_property ("zoom-focus", buf);
2603 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2604 node->add_property ("zoom", buf);
2605 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2606 node->add_property ("snap-to", buf);
2607 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2608 node->add_property ("snap-mode", buf);
2610 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2611 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2612 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2613 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2614 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2615 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2616 node->add_property ("mouse-mode", enum2str(mouse_mode));
2617 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2625 Editor::trackview_by_y_position (double y)
2627 TrackViewList::iterator iter;
2630 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2638 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2647 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2649 Location* before = 0;
2650 Location* after = 0;
2656 const jack_nframes_t one_second = session->frame_rate();
2657 const jack_nframes_t one_minute = session->frame_rate() * 60;
2659 jack_nframes_t presnap = start;
2661 switch (snap_type) {
2667 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2669 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2672 case SnapToSMPTEFrame:
2674 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2676 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2680 case SnapToSMPTESeconds:
2681 if (session->smpte_offset_negative())
2683 start += session->smpte_offset ();
2685 start -= session->smpte_offset ();
2687 if (direction > 0) {
2688 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2690 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2693 if (session->smpte_offset_negative())
2695 start -= session->smpte_offset ();
2697 start += session->smpte_offset ();
2701 case SnapToSMPTEMinutes:
2702 if (session->smpte_offset_negative())
2704 start += session->smpte_offset ();
2706 start -= session->smpte_offset ();
2709 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2711 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2713 if (session->smpte_offset_negative())
2715 start -= session->smpte_offset ();
2717 start += session->smpte_offset ();
2723 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2725 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2731 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2733 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2738 start = session->tempo_map().round_to_bar (start, direction);
2742 start = session->tempo_map().round_to_beat (start, direction);
2745 case SnapToAThirtysecondBeat:
2746 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2749 case SnapToASixteenthBeat:
2750 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2753 case SnapToAEighthBeat:
2754 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2757 case SnapToAQuarterBeat:
2758 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2761 case SnapToAThirdBeat:
2762 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2765 case SnapToEditCursor:
2766 start = edit_cursor->current_frame;
2774 before = session->locations()->first_location_before (start);
2775 after = session->locations()->first_location_after (start);
2777 if (direction < 0) {
2779 start = before->start();
2783 } else if (direction > 0) {
2785 start = after->start();
2787 start = session->current_end_frame();
2792 /* find nearest of the two */
2793 if ((start - before->start()) < (after->start() - start)) {
2794 start = before->start();
2796 start = after->start();
2799 start = before->start();
2802 start = after->start();
2809 case SnapToRegionStart:
2810 case SnapToRegionEnd:
2811 case SnapToRegionSync:
2812 case SnapToRegionBoundary:
2813 if (!region_boundary_cache.empty()) {
2814 vector<jack_nframes_t>::iterator i;
2816 if (direction > 0) {
2817 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2819 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2822 if (i != region_boundary_cache.end()) {
2825 start = region_boundary_cache.back();
2831 switch (snap_mode) {
2837 if (presnap > start) {
2838 if (presnap > (start + unit_to_frame(snap_threshold))) {
2842 } else if (presnap < start) {
2843 if (presnap < (start - unit_to_frame(snap_threshold))) {
2855 Editor::setup_toolbar ()
2857 nstring pixmap_path;
2858 vector<ToggleButton *> mouse_mode_buttons;
2860 mouse_mode_buttons.push_back (&mouse_move_button);
2861 mouse_mode_buttons.push_back (&mouse_select_button);
2862 mouse_mode_buttons.push_back (&mouse_gain_button);
2863 mouse_mode_buttons.push_back (&mouse_zoom_button);
2864 mouse_mode_buttons.push_back (&mouse_timefx_button);
2865 mouse_mode_buttons.push_back (&mouse_audition_button);
2866 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2868 mouse_mode_button_table.set_homogeneous (true);
2869 mouse_mode_button_table.set_col_spacings (2);
2870 mouse_mode_button_table.set_row_spacings (2);
2871 mouse_mode_button_table.set_border_width (5);
2873 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2874 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2875 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2877 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2878 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2879 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2881 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2882 mouse_mode_tearoff->set_name ("MouseModeBase");
2884 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2885 static_cast<Gtk::Widget*>(&mouse_mode_button_table)));
2886 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2887 static_cast<Gtk::Widget*> (&mouse_mode_button_table), 1));
2889 mouse_move_button.set_name ("MouseModeButton");
2890 mouse_select_button.set_name ("MouseModeButton");
2891 mouse_gain_button.set_name ("MouseModeButton");
2892 mouse_zoom_button.set_name ("MouseModeButton");
2893 mouse_timefx_button.set_name ("MouseModeButton");
2894 mouse_audition_button.set_name ("MouseModeButton");
2896 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2897 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2898 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2899 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2900 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2901 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2903 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2904 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2905 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2906 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2907 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2908 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2910 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2911 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2913 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2914 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2915 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2916 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2917 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2919 // mouse_move_button.set_active (true);
2921 /* automation control */
2923 global_automation_button.set_name ("MouseModeButton");
2924 automation_mode_button.set_name ("MouseModeButton");
2926 automation_box.set_spacing (2);
2927 automation_box.set_border_width (2);
2928 automation_box.pack_start (global_automation_button, false, false);
2929 automation_box.pack_start (automation_mode_button, false, false);
2933 edit_mode_label.set_name ("ToolBarLabel");
2935 edit_mode_selector.set_name ("EditModeSelector");
2936 edit_mode_selector.get_entry()->set_name ("EditModeSelector");
2937 edit_mode_selector.get_popwin()->set_name ("EditModeSelector");
2939 edit_mode_box.set_spacing (3);
2940 edit_mode_box.set_border_width (3);
2942 /* XXX another disgusting hack because of the way combo boxes size themselves */
2944 Gtkmm2ext::set_size_request_to_display_given_text (*edit_mode_selector.get_entry(), "EdgtMode", 2, 10);
2945 set_popdown_string (edit_mode_selector, internationalize (edit_mode_strings));
2947 edit_mode_box.pack_start (edit_mode_label, false, false);
2948 edit_mode_box.pack_start (edit_mode_selector, false, false);
2950 edit_mode_selector.get_popwin()->signal_unmap_event().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2954 snap_type_label.set_name ("ToolBarLabel");
2956 snap_type_selector.set_name ("SnapTypeSelector");
2957 snap_type_selector.get_entry()->set_name ("SnapTypeSelector");
2958 snap_type_selector.get_popwin()->set_name ("SnapTypeSelector");
2960 snap_type_box.set_spacing (3);
2961 snap_type_box.set_border_width (3);
2963 /* XXX another disgusting hack because of the way combo boxes size themselves */
2965 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2966 Gtkmm2ext::set_size_request_to_display_given_text (*snap_type_selector.get_entry(), "Region bounds", 2+FUDGE, 10);
2967 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2969 snap_type_box.pack_start (snap_type_label, false, false);
2970 snap_type_box.pack_start (snap_type_selector, false, false);
2972 snap_type_selector.get_popwin()->signal_unmap_event().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2974 /* Snap mode, not snap type */
2976 snap_mode_label.set_name ("ToolBarLabel");
2978 snap_mode_selector.set_name ("SnapModeSelector");
2979 snap_mode_selector.get_entry()->set_name ("SnapModeSelector");
2980 snap_mode_selector.get_popwin()->set_name ("SnapModeSelector");
2982 snap_mode_box.set_spacing (3);
2983 snap_mode_box.set_border_width (3);
2985 Gtkmm2ext::set_size_request_to_display_given_text (*snap_mode_selector.get_entry(), "SngpMode", 2, 10);
2986 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2988 snap_mode_box.pack_start (snap_mode_label, false, false);
2989 snap_mode_box.pack_start (snap_mode_selector, false, false);
2991 snap_mode_selector.get_popwin()->signal_unmap_event().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2993 /* Zoom focus mode */
2995 zoom_focus_label.set_name ("ToolBarLabel");
2997 zoom_focus_selector.set_name ("ZoomFocusSelector");
2998 zoom_focus_selector.get_entry()->set_name ("ZoomFocusSelector");
2999 zoom_focus_selector.get_popwin()->set_name ("ZoomFocusSelector");
3001 zoom_focus_box.set_spacing (3);
3002 zoom_focus_box.set_border_width (3);
3004 /* XXX another disgusting hack because of the way combo boxes size themselves */
3006 Gtkmm2ext::set_size_request_to_display_given_text (*zoom_focus_selector.get_entry(), "Edgt Cursor", 2, 10);
3007 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
3009 zoom_focus_box.pack_start (zoom_focus_label, false, false);
3010 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
3012 zoom_focus_selector.get_popwin()->signal_unmap_event().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
3014 /* selection/cursor clocks */
3016 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
3017 selection_start_clock_label.set_name ("ToolBarLabel");
3018 selection_end_clock_label.set_name ("ToolBarLabel");
3019 edit_cursor_clock_label.set_name ("ToolBarLabel");
3021 selection_start_clock_label.set_text (_("Start:"));
3022 selection_end_clock_label.set_text (_("End:"));
3023 edit_cursor_clock_label.set_text (_("Edit:"));
3025 toolbar_selection_clock_table.set_border_width (5);
3026 toolbar_selection_clock_table.set_col_spacings (2);
3027 toolbar_selection_clock_table.set_homogeneous (false);
3029 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
3030 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
3031 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
3033 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
3034 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
3035 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
3038 // toolbar_clock_vbox.set_spacing (2);
3039 // toolbar_clock_vbox.set_border_width (10);
3040 /* the editor/mixer button will be enabled at session connect */
3042 editor_mixer_button.set_active(false);
3043 editor_mixer_button.set_sensitive(false);
3045 HBox* hbox = new HBox;
3047 hbox->pack_start (editor_mixer_button, false, false);
3048 hbox->pack_start (toolbar_selection_clock_table, false, false);
3049 hbox->pack_start (zoom_indicator_vbox, false, false);
3050 hbox->pack_start (zoom_focus_box, false, false);
3051 hbox->pack_start (snap_type_box, false, false);
3052 hbox->pack_start (snap_mode_box, false, false);
3053 hbox->pack_start (edit_mode_box, false, false);
3055 VBox *vbox = manage (new VBox);
3057 vbox->set_spacing (3);
3058 vbox->set_border_width (3);
3060 HBox *nbox = manage (new HBox);
3062 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
3063 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
3065 nbox->pack_start (nudge_backward_button, false, false);
3066 nbox->pack_start (nudge_forward_button, false, false);
3067 nbox->pack_start (nudge_clock, false, false, 5);
3069 nudge_label.set_name ("ToolBarLabel");
3071 vbox->pack_start (nudge_label, false, false);
3072 vbox->pack_start (*nbox, false, false);
3074 hbox->pack_start (*vbox, false, false);
3078 tools_tearoff = new TearOff (*hbox);
3079 tools_tearoff->set_name ("MouseModeBase");
3081 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
3082 static_cast<Gtk::Widget*>(hbox)));
3083 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
3084 static_cast<Gtk::Widget*> (hbox), 0));
3086 toolbar_hbox.set_spacing (8);
3087 toolbar_hbox.set_border_width (2);
3089 toolbar_hbox.pack_start (*tools_tearoff, false, false);
3090 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
3092 toolbar_base.set_name ("ToolBarBase");
3093 toolbar_base.add (toolbar_hbox);
3095 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
3096 toolbar_frame.set_name ("BaseFrame");
3097 toolbar_frame.add (toolbar_base);
3101 Editor::_autoscroll_canvas (void *arg)
3103 return ((Editor *) arg)->autoscroll_canvas ();
3107 Editor::autoscroll_canvas ()
3109 jack_nframes_t new_frame;
3110 bool keep_calling = true;
3112 if (autoscroll_direction < 0) {
3113 if (leftmost_frame < autoscroll_distance) {
3116 new_frame = leftmost_frame - autoscroll_distance;
3119 if (leftmost_frame > max_frames - autoscroll_distance) {
3120 new_frame = max_frames;
3122 new_frame = leftmost_frame + autoscroll_distance;
3126 if (new_frame != leftmost_frame) {
3127 reposition_x_origin (new_frame);
3130 if (new_frame == 0 || new_frame == max_frames) {
3137 if (autoscroll_cnt == 1) {
3139 /* connect the timeout so that we get called repeatedly */
3141 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
3142 keep_calling = false;
3144 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
3146 /* after about a while, speed up a bit by changing the timeout interval */
3148 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
3149 keep_calling = false;
3151 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
3153 /* after about another while, speed up some more */
3155 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
3156 keep_calling = false;
3158 } else if (autoscroll_cnt >= 30) {
3160 /* we've been scrolling for a while ... crank it up */
3162 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
3165 return keep_calling;
3169 Editor::start_canvas_autoscroll (int dir)
3175 stop_canvas_autoscroll ();
3177 autoscroll_direction = dir;
3178 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
3181 /* do it right now, which will start the repeated callbacks */
3183 autoscroll_canvas ();
3187 Editor::stop_canvas_autoscroll ()
3189 if (autoscroll_timeout_tag >= 0) {
3190 gtk_timeout_remove (autoscroll_timeout_tag);
3191 autoscroll_timeout_tag = -1;
3196 Editor::convert_drop_to_paths (vector<string>& paths,
3197 GdkDragContext *context,
3200 GtkSelectionData *data,
3208 gchar *tname = gdk_atom_name (data->type);
3210 if (session == 0 || strcmp (tname, "text/plain") != 0) {
3214 /* Parse the "uri-list" format that Nautilus provides,
3215 where each pathname is delimited by \r\n
3218 path = (char *) data->data;
3221 for (int n = 0; n < data->length; ++n) {
3225 if (path[n] == '\r') {
3232 if (path[n] == '\n') {
3233 paths.push_back (spath);
3237 warning << _("incorrectly formatted URI list, ignored")
3245 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
3247 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3249 // cerr << "dropped text was " << *p << endl;
3253 // cerr << "decoded was " << *p << endl;
3255 if ((*p).substr (0,7) == "file://") {
3256 (*p) = (*p).substr (7);
3264 Editor::track_canvas_drag_data_received (GdkDragContext *context,
3267 GtkSelectionData *data,
3272 AudioTimeAxisView* tv;
3274 vector<string> paths;
3277 jack_nframes_t frame;
3279 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
3283 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
3289 gnome_canvas_window_to_world (GNOME_CANVAS(track_canvas), (double) x, (double) y, &wx, &wy);
3291 ev.type = GDK_BUTTON_RELEASE;
3295 frame = event_frame (&ev, 0, &cy);
3299 if ((tvp = trackview_by_y_position (cy)) == 0) {
3301 /* drop onto canvas background: create a new track */
3303 insert_paths_as_new_tracks (paths, false);
3306 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
3308 /* check that its an audio track, not a bus */
3310 if (tv->get_diskstream()) {
3312 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3313 insert_sndfile_into (*p, true, tv, frame);
3320 gtk_drag_finish (context, TRUE, FALSE, time);
3324 Editor::new_tempo_section ()
3330 Editor::map_transport_state ()
3332 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3334 if (session->transport_stopped()) {
3335 have_pending_keyboard_selection = false;
3341 Editor::State::State ()
3343 selection = new Selection;
3346 Editor::State::~State ()
3352 Editor::get_memento () const
3354 State *state = new State;
3356 store_state (*state);
3357 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3361 Editor::store_state (State& state) const
3363 *state.selection = *selection;
3367 Editor::restore_state (State *state)
3369 if (*selection == *state->selection) {
3373 *selection = *state->selection;
3374 time_selection_changed ();
3375 region_selection_changed ();
3377 /* XXX other selection change handlers? */
3381 Editor::begin_reversible_command (string name)
3384 UndoAction ua = get_memento();
3385 session->begin_reversible_command (name, &ua);
3390 Editor::commit_reversible_command ()
3393 UndoAction ua = get_memento();
3394 session->commit_reversible_command (&ua);
3399 Editor::flush_track_canvas ()
3401 /* I don't think this is necessary, and only causes more problems.
3402 I'm commenting it out
3403 and if the imageframe folks don't have any issues, we can take
3404 out this method entirely
3407 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
3408 //gtk_main_iteration ();
3412 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3414 if (!clicked_trackview) {
3419 begin_reversible_command (_("set selected trackview"));
3424 if (selection->selected (clicked_trackview)) {
3426 selection->remove (clicked_trackview);
3429 selection->add (clicked_trackview);
3434 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3435 /* no commit necessary */
3439 selection->set (clicked_trackview);
3443 commit_reversible_command ();
3448 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3450 if (!clicked_control_point) {
3455 begin_reversible_command (_("set selected control point"));
3465 commit_reversible_command ();
3470 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3472 if (!clicked_regionview) {
3476 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3482 RouteGroup* group = atv->route().edit_group();
3483 vector<AudioRegionView*> all_equivalent_regions;
3485 if (group && group->is_active()) {
3487 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3489 AudioTimeAxisView* tatv;
3491 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3493 if (tatv->route().edit_group() != group) {
3498 vector<AudioRegion*> results;
3499 AudioRegionView* marv;
3502 if ((ds = tatv->get_diskstream()) == 0) {
3507 if ((pl = ds->playlist()) != 0) {
3508 pl->get_equivalent_regions (clicked_regionview->region,
3512 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3513 if ((marv = tatv->view->find_view (**ir)) != 0) {
3514 all_equivalent_regions.push_back (marv);
3523 all_equivalent_regions.push_back (clicked_regionview);
3527 begin_reversible_command (_("set selected regionview"));
3531 if (clicked_regionview->get_selected()) {
3532 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3533 /* reduce selection down to just the one clicked */
3534 selection->set (clicked_regionview);
3536 selection->remove (clicked_regionview);
3539 selection->add (all_equivalent_regions);
3542 set_selected_track_from_click (add, false, no_track_remove);
3546 // karsten wiese suggested these two lines to make
3547 // a selected region rise to the top. but this
3548 // leads to a mismatch between actual layering
3549 // and visual layering. resolution required ....
3551 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3552 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3554 if (clicked_regionview->get_selected()) {
3555 /* no commit necessary: we are the one selected. */
3560 selection->set (all_equivalent_regions);
3561 set_selected_track_from_click (add, false, false);
3565 commit_reversible_command () ;
3569 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3571 vector<AudioRegionView*> all_equivalent_regions;
3572 AudioRegion* region;
3574 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3578 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3580 AudioTimeAxisView* tatv;
3582 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3585 vector<AudioRegion*> results;
3586 AudioRegionView* marv;
3589 if ((ds = tatv->get_diskstream()) == 0) {
3594 if ((pl = ds->playlist()) != 0) {
3595 pl->get_region_list_equivalent_regions (*region, results);
3598 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3599 if ((marv = tatv->view->find_view (**ir)) != 0) {
3600 all_equivalent_regions.push_back (marv);
3607 begin_reversible_command (_("set selected regions"));
3611 selection->add (all_equivalent_regions);
3615 selection->set (all_equivalent_regions);
3618 commit_reversible_command () ;
3622 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3624 AudioRegionView* rv;
3627 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3631 if ((rv = sv->find_view (*ar)) == 0) {
3635 /* don't reset the selection if its something other than
3636 a single other region.
3639 if (selection->audio_regions.size() > 1) {
3643 begin_reversible_command (_("set selected regions"));
3645 selection->set (rv);
3647 commit_reversible_command () ;
3653 Editor::set_edit_group_solo (Route& route, bool yn)
3655 RouteGroup *edit_group;
3657 if ((edit_group = route.edit_group()) != 0) {
3658 edit_group->apply (&Route::set_solo, yn, this);
3660 route.set_solo (yn, this);
3665 Editor::set_edit_group_mute (Route& route, bool yn)
3667 RouteGroup *edit_group = 0;
3669 if ((edit_group == route.edit_group()) != 0) {
3670 edit_group->apply (&Route::set_mute, yn, this);
3672 route.set_mute (yn, this);
3677 Editor::set_edit_menu (Menu& menu)
3680 edit_menu->map_.connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3684 Editor::edit_menu_map_handler ()
3686 using namespace Menu_Helpers;
3687 MenuList& edit_items = edit_menu->items();
3690 /* Nuke all the old items */
3692 edit_items.clear ();
3698 if (session->undo_depth() == 0) {
3701 label = string_compose(_("Undo (%1)"), session->next_undo());
3704 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3706 if (session->undo_depth() == 0) {
3707 edit_items.back().set_sensitive (false);
3710 if (session->redo_depth() == 0) {
3713 label = string_compose(_("Redo (%1)"), session->next_redo());
3716 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3717 if (session->redo_depth() == 0) {
3718 edit_items.back().set_sensitive (false);
3721 vector<MenuItem*> mitems;
3723 edit_items.push_back (SeparatorElem());
3724 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3725 mitems.push_back (&edit_items.back());
3726 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3727 mitems.push_back (&edit_items.back());
3728 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3729 mitems.push_back (&edit_items.back());
3730 edit_items.push_back (SeparatorElem());
3731 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3732 mitems.push_back (&edit_items.back());
3733 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3734 mitems.push_back (&edit_items.back());
3735 edit_items.push_back (SeparatorElem());
3737 if (selection->empty()) {
3738 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3739 (*i)->set_sensitive (false);
3743 Menu* import_menu = manage (new Menu());
3744 import_menu->set_name ("ArdourContextMenu");
3745 MenuList& import_items = import_menu->items();
3747 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3748 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3750 Menu* embed_menu = manage (new Menu());
3751 embed_menu->set_name ("ArdourContextMenu");
3752 MenuList& embed_items = embed_menu->items();
3754 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3755 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3757 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3758 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3759 edit_items.push_back (SeparatorElem());
3761 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3762 if (!session->have_captured()) {
3763 edit_items.back().set_sensitive (false);
3768 Editor::duplicate_dialog (bool dup_region)
3771 if (clicked_regionview == 0) {
3775 if (selection->time.length() == 0) {
3780 ArdourDialog win ("duplicate dialog");
3782 Label label (_("Duplicate how many times?"));
3785 Button ok_button (_("OK"));
3786 Button cancel_button (_("Cancel"));
3789 button_box.set_spacing (7);
3790 set_size_request_to_display_given_text (ok_button, _("Cancel"), 20, 15); // this is cancel on purpose
3791 set_size_request_to_display_given_text (cancel_button, _("Cancel"), 20, 15);
3792 button_box.pack_end (ok_button, false, false);
3793 button_box.pack_end (cancel_button, false, false);
3795 hbox.set_spacing (5);
3796 hbox.pack_start (label);
3797 hbox.pack_start (entry, true, true);
3799 vbox.set_spacing (5);
3800 vbox.set_border_width (5);
3801 vbox.pack_start (hbox);
3802 vbox.pack_start (button_box);
3805 win.set_position (Gtk::WIN_POS_MOUSE);
3808 ok_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3809 entry.signal_activate().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3810 cancel_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 1));
3812 entry.signal_focus_in_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_in_event));
3813 entry.signal_focus_out_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_out_event));
3815 entry.set_text ("1");
3816 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3817 entry.select_region (0, entry.get_text_length());
3819 win.set_position (Gtk::WIN_POS_MOUSE);
3821 win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3823 entry.grab_focus ();
3827 if (win.run_status() != 0) {
3831 string text = entry.get_text();
3834 if (sscanf (text.c_str(), "%f", ×) == 1) {
3836 AudioRegionSelection regions;
3837 regions.add (clicked_regionview);
3838 duplicate_some_regions (regions, times);
3840 duplicate_selection (times);
3846 Editor::show_verbose_canvas_cursor ()
3848 gnome_canvas_item_raise_to_top (verbose_canvas_cursor);
3849 gnome_canvas_item_show (verbose_canvas_cursor);
3850 verbose_cursor_visible = true;
3854 Editor::hide_verbose_canvas_cursor ()
3856 gnome_canvas_item_hide (verbose_canvas_cursor);
3857 verbose_cursor_visible = false;
3861 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3863 /* XXX get origin of canvas relative to root window,
3864 add x and y and check compared to gdk_screen_{width,height}
3866 gnome_canvas_item_set (verbose_canvas_cursor, "text", txt.c_str(), "x", x, "y", y, NULL);
3870 Editor::set_verbose_canvas_cursor_text (string txt)
3872 gnome_canvas_item_set (verbose_canvas_cursor, "text", txt.c_str(), NULL);
3876 Editor::edit_mode_selection_done (GdkEventAny *ev)
3882 string choice = edit_mode_selector.get_entry()->get_text();
3883 EditMode mode = Slide;
3885 if (choice == _("Splice")) {
3887 } else if (choice == _("Slide")) {
3891 session->set_edit_mode (mode);
3897 Editor::snap_type_selection_done (GdkEventAny *ev)
3903 string choice = snap_type_selector.get_entry()->get_text();
3904 SnapType snaptype = SnapToFrame;
3906 if (choice == _("Beats/3")) {
3907 snaptype = SnapToAThirdBeat;
3908 } else if (choice == _("Beats/4")) {
3909 snaptype = SnapToAQuarterBeat;
3910 } else if (choice == _("Beats/8")) {
3911 snaptype = SnapToAEighthBeat;
3912 } else if (choice == _("Beats/16")) {
3913 snaptype = SnapToASixteenthBeat;
3914 } else if (choice == _("Beats/32")) {
3915 snaptype = SnapToAThirtysecondBeat;
3916 } else if (choice == _("Beats")) {
3917 snaptype = SnapToBeat;
3918 } else if (choice == _("Bars")) {
3919 snaptype = SnapToBar;
3920 } else if (choice == _("Marks")) {
3921 snaptype = SnapToMark;
3922 } else if (choice == _("Edit Cursor")) {
3923 snaptype = SnapToEditCursor;
3924 } else if (choice == _("Region starts")) {
3925 snaptype = SnapToRegionStart;
3926 } else if (choice == _("Region ends")) {
3927 snaptype = SnapToRegionEnd;
3928 } else if (choice == _("Region bounds")) {
3929 snaptype = SnapToRegionBoundary;
3930 } else if (choice == _("Region syncs")) {
3931 snaptype = SnapToRegionSync;
3932 } else if (choice == _("CD Frames")) {
3933 snaptype = SnapToCDFrame;
3934 } else if (choice == _("SMPTE Frames")) {
3935 snaptype = SnapToSMPTEFrame;
3936 } else if (choice == _("SMPTE Seconds")) {
3937 snaptype = SnapToSMPTESeconds;
3938 } else if (choice == _("SMPTE Minutes")) {
3939 snaptype = SnapToSMPTEMinutes;
3940 } else if (choice == _("Seconds")) {
3941 snaptype = SnapToSeconds;
3942 } else if (choice == _("Minutes")) {
3943 snaptype = SnapToMinutes;
3944 } else if (choice == _("None")) {
3945 snaptype = SnapToFrame;
3948 set_snap_to (snaptype);
3954 Editor::snap_mode_selection_done (GdkEventAny *ev)
3956 if(session == 0) return FALSE;
3958 string choice = snap_mode_selector.get_entry()->get_text();
3959 SnapMode mode = SnapNormal;
3961 if (choice == _("Normal")) {
3963 } else if (choice == _("Magnetic")) {
3964 mode = SnapMagnetic;
3967 set_snap_mode (mode);
3973 Editor::zoom_focus_selection_done (GdkEventAny *ev)
3979 string choice = zoom_focus_selector.get_entry()->get_text();
3980 ZoomFocus focus_type = ZoomFocusLeft;
3982 if (choice == _("Left")) {
3983 focus_type = ZoomFocusLeft;
3984 } else if (choice == _("Right")) {
3985 focus_type = ZoomFocusRight;
3986 } else if (choice == _("Center")) {
3987 focus_type = ZoomFocusCenter;
3988 } else if (choice == _("Playhead")) {
3989 focus_type = ZoomFocusPlayhead;
3990 } else if (choice == _("Edit Cursor")) {
3991 focus_type = ZoomFocusEdit;
3994 set_zoom_focus (focus_type);
4000 Editor::edit_controls_button_release (GdkEventButton* ev)
4002 if (Keyboard::is_context_menu_event (ev)) {
4003 ARDOUR_UI::instance()->add_route ();
4009 Editor::track_selection_changed ()
4011 switch (selection->tracks.size()){
4015 set_selected_mixer_strip (*(selection->tracks.front()));
4019 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4020 (*i)->set_selected (false);
4021 if (mouse_mode == MouseRange) {
4022 (*i)->hide_selection ();
4026 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4027 (*i)->set_selected (true);
4028 if (mouse_mode == MouseRange) {
4029 (*i)->show_selection (selection->time);
4035 Editor::time_selection_changed ()
4037 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4038 (*i)->hide_selection ();
4041 if (selection->tracks.empty()) {
4042 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4043 (*i)->show_selection (selection->time);
4046 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4047 (*i)->show_selection (selection->time);
4053 Editor::region_selection_changed ()
4055 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4056 (*i)->set_selected_regionviews (selection->audio_regions);
4061 Editor::point_selection_changed ()
4063 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4064 (*i)->set_selected_points (selection->points);
4069 Editor::run_sub_event_loop ()
4071 Keyboard::the_keyboard().allow_focus (true);
4072 sub_event_loop_status = 0;
4077 Editor::finish_sub_event_loop (int status)
4080 Keyboard::the_keyboard().allow_focus (false);
4081 sub_event_loop_status = status;
4085 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
4087 finish_sub_event_loop (status);
4092 Editor::mouse_select_button_release (GdkEventButton* ev)
4094 /* this handles just right-clicks */
4096 if (ev->button != 3) {
4103 Editor::TrackViewList *
4104 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
4107 TrackViewList::iterator i;
4109 v = new TrackViewList;
4111 if (track == 0 && group == 0) {
4115 for (i = track_views.begin(); i != track_views.end (); ++i) {
4119 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
4121 /* just the view for this track
4124 v->push_back (track);
4128 /* views for all tracks in the edit group */
4130 for (i = track_views.begin(); i != track_views.end (); ++i) {
4132 if (group == 0 || (*i)->edit_group() == group) {
4142 Editor::set_zoom_focus (ZoomFocus f)
4144 if (zoom_focus != f) {
4146 vector<string> txt = internationalize (zoom_focus_strings);
4147 zoom_focus_selector.get_entry()->set_text (txt[(int)f]);
4148 ZoomFocusChanged (); /* EMIT_SIGNAL */
4155 Editor::ensure_float (Window& win)
4157 win.set_transient_for (*this);
4161 Editor::pane_allocation_handler (GtkAllocation *alloc, Gtk::Paned* which)
4163 /* recover or initialize pane positions. do this here rather than earlier because
4164 we don't want the positions to change the child allocations, which they seem to do.
4170 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
4172 static int32_t done[4] = { 0, 0, 0, 0 };
4175 if ((geometry = find_named_node (*node, "geometry")) == 0) {
4176 width = default_width;
4177 height = default_height;
4179 width = atoi(geometry->property("x_size")->value());
4180 height = atoi(geometry->property("y_size")->value());
4183 if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
4189 if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
4191 snprintf (buf, sizeof(buf), "%d", pos);
4193 pos = atoi (prop->value());
4196 if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gobj())->allocation.width > pos)) {
4197 track_list_canvas_pane.set_position (pos);
4200 } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
4206 if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
4207 pos = width - (95 * 2);
4208 snprintf (buf, sizeof(buf), "%d", pos);
4210 pos = atoi (prop->value());
4213 if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gobj())->allocation.width > pos)) {
4214 canvas_region_list_pane.set_position (pos);
4217 } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
4223 if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
4224 pos = width - (95 * 2);
4225 snprintf (buf, sizeof(buf), "%d", pos);
4227 pos = atoi (prop->value());
4230 if ((done[2] = GTK_WIDGET(route_group_vpane.gobj())->allocation.height > pos)) {
4231 route_group_vpane.set_position (pos);
4234 } else if (which == static_cast<Gtk::Paned*> (®ion_selection_vpane)) {
4240 if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
4241 pos = width - (95 * 2);
4242 snprintf (buf, sizeof(buf), "%d", pos);
4244 pos = atoi (prop->value());
4247 if ((done[3] = GTK_WIDGET(region_selection_vpane.gobj())->allocation.height > pos)) {
4248 region_selection_vpane.set_position (pos);
4254 Editor::detach_tearoff (Gtk::Box* b, Gtk::Widget* w)
4256 if (tools_tearoff->torn_off() &&
4257 mouse_mode_tearoff->torn_off()) {
4258 top_hbox.remove (toolbar_frame);
4261 ensure_float (*w->get_toplevel());
4265 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Widget* w, int32_t n)
4267 if (toolbar_frame.get_parent() == 0) {
4268 top_hbox.pack_end (toolbar_frame);
4273 Editor::set_show_measures (bool yn)
4275 if (_show_measures != yn) {
4278 if ((_show_measures = yn) == true) {
4281 DisplayControlChanged (ShowMeasures);
4287 Editor::set_follow_playhead (bool yn)
4289 if (_follow_playhead != yn) {
4290 if ((_follow_playhead = yn) == true) {
4292 update_current_screen ();
4294 DisplayControlChanged (FollowPlayhead);
4300 Editor::toggle_xfade_active (Crossfade* xfade)
4302 xfade->set_active (!xfade->active());
4306 Editor::toggle_xfade_length (Crossfade* xfade)
4308 xfade->set_follow_overlap (!xfade->following_overlap());
4312 Editor::edit_xfade (Crossfade* xfade)
4314 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
4318 cew.ok_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 1));
4319 cew.cancel_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 0));
4320 cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
4324 if (cew.run_status() == 1) {
4326 xfade->StateChanged (Change (~0));
4331 Editor::playlist_selector () const
4333 return *_playlist_selector;
4337 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
4341 ret = nudge_clock.current_duration (pos);
4342 next = ret + 1; /* XXXX fix me */
4348 Editor::end_location_changed (Location* location)
4350 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
4351 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
4355 Editor::playlist_deletion_dialog (Playlist* pl)
4357 ArdourDialog dialog ("playlist deletion dialog");
4358 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4359 "If left alone, no audio files used by it will be cleaned.\n"
4360 "If deleted, audio files used by it alone by will cleaned."),
4363 Button del_button (_("Delete playlist"));
4364 Button keep_button (_("Keep playlist"));
4365 Button abort_button (_("Cancel cleanup"));
4368 button_box.set_spacing (7);
4369 button_box.set_homogeneous (true);
4370 button_box.pack_end (del_button, false, false);
4371 button_box.pack_end (keep_button, false, false);
4372 button_box.pack_end (abort_button, false, false);
4374 vbox.set_spacing (5);
4375 vbox.set_border_width (5);
4376 vbox.pack_start (label);
4377 vbox.pack_start (button_box);
4380 dialog.set_position (Gtk::WIN_POS_CENTER);
4383 del_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 0));
4384 keep_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 1));
4385 abort_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 2));
4388 dialog.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
4392 switch (dialog.run_status()) {
4394 /* keep the playlist */
4398 /* delete the playlist */
4406 /* keep the playlist */
4412 Editor::audio_region_selection_covers (jack_nframes_t where)
4414 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
4415 if ((*a)->region.covers (where)) {
4424 Editor::prepare_for_cleanup ()
4426 cut_buffer->clear_audio_regions ();
4427 cut_buffer->clear_playlists ();
4429 selection->clear_audio_regions ();
4430 selection->clear_playlists ();
4434 Editor::init_colormap ()
4436 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
4437 pair<ColorID,int> newpair;
4439 newpair.first = (ColorID) x;
4440 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
4441 color_map.insert (newpair);
4446 Editor::transport_loop_location()
4449 return session->locations()->auto_loop_location();
4456 Editor::transport_punch_location()
4459 return session->locations()->auto_punch_location();