2 Copyright (C) 2000 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include <sigc++/bind.h>
29 #include <libgnomecanvasmm/init.h>
31 #include <pbd/error.h>
33 #include <gtkmm2ext/gtk_ui.h>
34 #include <gtkmm2ext/tearoff.h>
35 #include <gtkmm2ext/utils.h>
37 #include <ardour/audio_track.h>
38 #include <ardour/diskstream.h>
39 #include <ardour/plugin_manager.h>
40 #include <ardour/location.h>
41 #include <ardour/audioplaylist.h>
42 #include <ardour/audioregion.h>
43 #include <ardour/session.h>
44 #include <ardour/session_route.h>
45 #include <ardour/tempo.h>
46 #include <ardour/utils.h>
48 #include "ardour_ui.h"
49 #include "canvas-ruler.h"
50 #include "canvas-simpleline.h"
51 #include "canvas-simplerect.h"
52 #include "canvas-waveview.h"
53 #include "check_mark.h"
55 #include "grouped_buttons.h"
58 #include "playlist_selector.h"
59 #include "regionview.h"
60 #include "rgb_macros.h"
61 #include "selection.h"
62 #include "streamview.h"
63 #include "time_axis_view.h"
65 #include "crossfade_view.h"
67 #include "public_editor.h"
68 #include "crossfade_edit.h"
69 #include "audio_time_axis.h"
70 #include "gui_thread.h"
75 #include "imageframe_socket_handler.h"
76 /* </CMT Additions> */
80 using namespace ARDOUR;
83 using namespace Gtkmm2ext;
84 using namespace Editing;
86 /* XXX this is a hack. it ought to be the maximum value of an jack_nframes_t */
88 const double max_canvas_coordinate = 100000000.0;
89 const double Editor::timebar_height = 15.0;
91 #include "editor_xpms"
93 static const gchar *route_list_titles[] = {
98 static const gchar *edit_group_list_titles[] = {
102 static const gchar *named_selection_display_titles[] = {
107 static const int32_t slide_index = 0;
108 static const int32_t splice_index = 1;
110 static const gchar *edit_mode_strings[] = {
116 static const gchar *snap_type_strings[] = {
140 static const gchar *snap_mode_strings[] = {
146 static const gchar *zoom_focus_strings[] = {
155 /* Soundfile drag-n-drop */
157 Gdk::Cursor* Editor::cross_hair_cursor = 0;
158 Gdk::Cursor* Editor::selector_cursor = 0;
159 Gdk::Cursor* Editor::trimmer_cursor = 0;
160 Gdk::Cursor* Editor::grabber_cursor = 0;
161 Gdk::Cursor* Editor::zoom_cursor = 0;
162 Gdk::Cursor* Editor::time_fx_cursor = 0;
163 Gdk::Cursor* Editor::fader_cursor = 0;
164 Gdk::Cursor* Editor::speaker_cursor = 0;
165 Gdk::Cursor* Editor::null_cursor = 0;
166 Gdk::Cursor* Editor::wait_cursor = 0;
167 Gdk::Cursor* Editor::timebar_cursor = 0;
169 GdkPixmap *Editor::check_pixmap = 0;
170 GdkBitmap *Editor::check_mask = 0;
171 GdkPixmap *Editor::empty_pixmap = 0;
172 GdkBitmap *Editor::empty_mask = 0;
174 Editor::Editor (AudioEngine& eng)
177 /* time display buttons */
179 minsec_label (_("Mins:Secs")),
180 bbt_label (_("Bars:Beats")),
181 smpte_label (_("SMPTE")),
182 frame_label (_("Frames")),
183 tempo_label (_("Tempo")),
184 meter_label (_("Meter")),
185 mark_label (_("Location Markers")),
186 range_mark_label (_("Range Markers")),
187 transport_mark_label (_("Loop/Punch Ranges")),
189 edit_packer (3, 3, false),
190 edit_hscroll_left_arrow (Gtk::ARROW_LEFT, Gtk::SHADOW_OUT),
191 edit_hscroll_right_arrow (Gtk::ARROW_RIGHT, Gtk::SHADOW_OUT),
193 /* tool bar related */
195 editor_mixer_button (_("editor\nmixer")),
197 selection_start_clock (X_("SelectionStartClock"), true),
198 selection_end_clock (X_("SelectionEndClock"), true),
199 edit_cursor_clock (X_("EditCursorClock"), true),
200 zoom_range_clock (X_("ZoomRangeClock"), true, true),
202 toolbar_selection_clock_table (2,3),
204 mouse_mode_button_table (2, 3),
206 mouse_select_button (_("range")),
207 mouse_move_button (_("object")),
208 mouse_gain_button (_("gain")),
209 mouse_zoom_button (_("zoom")),
210 mouse_timefx_button (_("timefx")),
211 mouse_audition_button (_("listen")),
213 automation_mode_button (_("mode")),
214 global_automation_button (_("automation")),
216 edit_mode_label (_("Edit Mode")),
217 snap_type_label (_("Snap To")),
218 snap_mode_label(_("Snap Mode")),
219 zoom_focus_label (_("Zoom Focus")),
221 /* <CMT Additions> */
222 image_socket_listener(0),
223 /* </CMT Additions> */
227 nudge_label (_("Nudge")),
228 nudge_clock (X_("NudgeClock"), true, true)
233 /* we are a singleton */
235 PublicEditor::_instance = this;
239 check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
240 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
241 &check_mask, NULL, (gchar **) check_xpm);
242 empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
243 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
244 &empty_mask, NULL, (gchar **) empty_xpm);
248 selection = new Selection;
249 cut_buffer = new Selection;
251 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
252 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
253 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
254 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
256 clicked_regionview = 0;
257 clicked_trackview = 0;
258 clicked_audio_trackview = 0;
259 clicked_crossfadeview = 0;
260 clicked_control_point = 0;
261 latest_regionview = 0;
262 last_update_frame = 0;
264 last_audition_region = 0;
265 current_mixer_strip = 0;
266 current_bbt_points = 0;
268 snap_type = SnapToFrame;
269 set_snap_to (snap_type);
270 snap_mode = SnapNormal;
271 set_snap_mode (snap_mode);
272 snap_threshold = 5.0;
273 bbt_beat_subdivision = 4;
276 autoscroll_timeout_tag = -1;
277 interthread_progress_window = 0;
278 current_interthread_info = 0;
279 _show_measures = true;
280 _show_waveforms = true;
281 _show_waveforms_recording = true;
282 first_action_message = 0;
284 show_gain_after_trim = false;
285 no_zoom_repos_update = false;
286 ignore_route_list_reorder = false;
287 verbose_cursor_on = true;
288 route_removal = false;
290 show_automatic_regions_in_region_list = true;
291 have_pending_keyboard_selection = false;
292 _follow_playhead = true;
293 _xfade_visibility = true;
294 editor_ruler_menu = 0;
295 no_ruler_shown_update = false;
296 edit_group_list_menu = 0;
298 region_list_menu = 0;
300 marker_menu_item = 0;
302 transport_marker_menu = 0;
303 new_transport_marker_menu = 0;
304 editor_mixer_strip_width = Wide;
305 repos_zoom_queued = false;
306 import_audio_item = 0;
307 embed_audio_item = 0;
308 region_edit_menu_split_item = 0;
310 region_edit_menu_split_multichannel_item = 0;
311 edit_hscroll_dragging = false;
313 ignore_mouse_mode_toggle = false;
314 current_stepping_trackview = 0;
316 entered_regionview = 0;
317 clear_entered_track = false;
318 _new_regionviews_show_envelope = false;
319 current_timestretch = 0;
324 location_marker_color = color_map[cLocationMarker];
325 location_range_color = color_map[cLocationRange];
326 location_cd_marker_color = color_map[cLocationCDMarker];
327 location_loop_color = color_map[cLocationLoop];
328 location_punch_color = color_map[cLocationPunch];
330 range_marker_drag_rect = 0;
331 marker_drag_line = 0;
333 mouse_mode = MouseZoom; /* force change in next call */
334 set_mouse_mode (MouseObject, true);
336 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
337 zoom_focus = ZoomFocusLeft;
338 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
340 initialize_rulers ();
341 initialize_canvas ();
343 track_canvas_scroller.add (track_canvas);
344 track_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
345 track_canvas_scroller.set_name ("TrackCanvasScroller");
347 track_canvas_scroller.get_vadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
348 track_canvas_scroller.get_vadjustment()->set_step_increment (10.0);
350 track_canvas_scroller.get_hadjustment()->set_lower (0.0);
351 track_canvas_scroller.get_hadjustment()->set_upper (1200.0);
352 track_canvas_scroller.get_hadjustment()->set_step_increment (20.0);
353 track_canvas_scroller.get_hadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
355 edit_vscrollbar.set_adjustment(*track_canvas_scroller.get_vadjustment());
356 edit_hscrollbar.set_adjustment(*track_canvas_scroller.get_hadjustment());
358 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_press));
359 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_release));
360 edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscroll_slider_allocate));
362 time_canvas_scroller.add (time_canvas);
363 time_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
364 time_canvas_scroller.set_hadjustment (*track_canvas_scroller.get_hadjustment());
365 time_canvas_scroller.set_name ("TimeCanvasScroller");
367 edit_controls_vbox.set_spacing (track_spacing);
368 edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
369 edit_controls_scroller.add (edit_controls_hbox);
370 edit_controls_scroller.set_name ("EditControlsBase");
371 edit_controls_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
373 Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
375 viewport->set_shadow_type (Gtk::SHADOW_NONE);
376 viewport->set_name ("EditControlsBase");
377 viewport->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
378 viewport->signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
383 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
386 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
388 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
389 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
390 time_canvas_vbox.pack_start (*frames_ruler, false, false);
391 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
392 time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
393 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
395 bbt_label.set_name ("EditorTimeButton");
396 bbt_label.set_size_request (-1, (int)timebar_height);
397 bbt_label.set_alignment (1.0, 0.5);
398 bbt_label.set_padding (5,0);
399 minsec_label.set_name ("EditorTimeButton");
400 minsec_label.set_size_request (-1, (int)timebar_height);
401 minsec_label.set_alignment (1.0, 0.5);
402 minsec_label.set_padding (5,0);
403 smpte_label.set_name ("EditorTimeButton");
404 smpte_label.set_size_request (-1, (int)timebar_height);
405 smpte_label.set_alignment (1.0, 0.5);
406 smpte_label.set_padding (5,0);
407 frame_label.set_name ("EditorTimeButton");
408 frame_label.set_size_request (-1, (int)timebar_height);
409 frame_label.set_alignment (1.0, 0.5);
410 frame_label.set_padding (5,0);
411 tempo_label.set_name ("EditorTimeButton");
412 tempo_label.set_size_request (-1, (int)timebar_height);
413 tempo_label.set_alignment (1.0, 0.5);
414 tempo_label.set_padding (5,0);
415 meter_label.set_name ("EditorTimeButton");
416 meter_label.set_size_request (-1, (int)timebar_height);
417 meter_label.set_alignment (1.0, 0.5);
418 meter_label.set_padding (5,0);
419 mark_label.set_name ("EditorTimeButton");
420 mark_label.set_size_request (-1, (int)timebar_height);
421 mark_label.set_alignment (1.0, 0.5);
422 mark_label.set_padding (5,0);
423 range_mark_label.set_name ("EditorTimeButton");
424 range_mark_label.set_size_request (-1, (int)timebar_height);
425 range_mark_label.set_alignment (1.0, 0.5);
426 range_mark_label.set_padding (5,0);
427 transport_mark_label.set_name ("EditorTimeButton");
428 transport_mark_label.set_size_request (-1, (int)timebar_height);
429 transport_mark_label.set_alignment (1.0, 0.5);
430 transport_mark_label.set_padding (5,0);
432 time_button_vbox.pack_start (minsec_label, false, false);
433 time_button_vbox.pack_start (smpte_label, false, false);
434 time_button_vbox.pack_start (frame_label, false, false);
435 time_button_vbox.pack_start (bbt_label, false, false);
436 time_button_vbox.pack_start (meter_label, false, false);
437 time_button_vbox.pack_start (tempo_label, false, false);
438 time_button_vbox.pack_start (mark_label, false, false);
440 time_button_event_box.add (time_button_vbox);
442 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
443 time_button_event_box.set_name ("TimebarLabelBase");
444 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
446 /* these enable us to have a dedicated window (for cursor setting, etc.)
447 for the canvas areas.
450 track_canvas_event_box.add (track_canvas_scroller);
452 time_canvas_event_box.add (time_canvas_vbox);
453 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
456 edit_packer.set_col_spacings (0);
457 edit_packer.set_row_spacings (0);
458 edit_packer.set_homogeneous (false);
459 edit_packer.set_name ("EditorWindow");
461 // edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, Gtk::FILL, 0, 0, 0);
462 // edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, 0, 0, 0);
463 // edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, Gtk::FILL, 0, 0, 0);
464 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
466 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
467 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
469 edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
470 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
471 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
473 edit_frame.set_name ("BaseFrame");
474 edit_frame.set_shadow_type (SHADOW_IN);
475 edit_frame.add (edit_packer);
477 zoom_in_button.set_name ("EditorTimeButton");
478 zoom_out_button.set_name ("EditorTimeButton");
479 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
480 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
482 // zoom_onetoone_button.set_name ("EditorTimeButton");
483 zoom_out_full_button.set_name ("EditorTimeButton");
484 // ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1"));
485 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
487 zoom_in_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_in_button_xpm)))));
488 zoom_out_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_button_xpm)))));
489 zoom_out_full_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_full_button_xpm)))));
490 // zoom_onetoone_button.add (*(manage (new Gtk::Image (zoom_onetoone_button_xpm))));
493 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
494 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
495 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
496 // zoom_onetoone_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom), 1.0));
498 zoom_indicator_box.pack_start (zoom_out_button, false, false);
499 zoom_indicator_box.pack_start (zoom_in_button, false, false);
500 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
501 // zoom_indicator_box.pack_start (zoom_onetoone_button, false, false);
502 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
504 zoom_indicator_label.set_text (_("Zoom Span"));
505 zoom_indicator_label.set_name ("ToolBarLabel");
508 zoom_indicator_vbox.set_spacing (3);
509 zoom_indicator_vbox.set_border_width (3);
510 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
511 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
514 bottom_hbox.set_border_width (3);
515 bottom_hbox.set_spacing (3);
517 route_display_model = ListStore::create(route_display_columns);
518 route_list.set_model (route_display_model);
519 route_list.append_column (_("Tracks"), route_display_columns.text);
520 route_list.set_name ("TrackListDisplay");
521 route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
522 route_list.set_reorderable (true);
524 route_list.set_size_request (75,-1);
525 route_list.set_headers_visible (true);
526 route_list.set_headers_clickable (true);
528 route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func));
529 route_display_model->signal_rows_reordered().connect (mem_fun (*this, &Editor::queue_route_list_reordered));
532 //route_list.set_shadow_type (Gtk::SHADOW_IN);
534 route_list_scroller.add (route_list);
535 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
537 route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed));
538 route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click));
540 edit_group_list_button_label.set_text (_("Edit Groups"));
541 edit_group_list_button_label.set_name ("EditGroupTitleButton");
542 edit_group_list_button.add (edit_group_list_button_label);
543 edit_group_list_button.set_name ("EditGroupTitleButton");
545 group_model = ListStore::create(group_columns);
546 edit_group_list.set_model (group_model);
547 edit_group_list.append_column (_("active"), group_columns.is_active);
548 edit_group_list.append_column (_("groupname"), group_columns.text);
549 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
550 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
552 /* use checkbox for the active column */
554 CellRendererToggle *active_cell = dynamic_cast<CellRendererToggle*>(edit_group_list.get_column_cell_renderer (0));
555 active_cell->set_property ("activatable", true);
556 active_cell->set_property ("radio", false);
558 edit_group_list.set_name ("MixerGroupList");
559 //edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
560 route_list.set_headers_visible (false);
561 edit_group_list.set_reorderable (false);
562 edit_group_list.set_size_request (75, -1);
563 edit_group_list.columns_autosize ();
564 edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
566 edit_group_list_scroller.add (edit_group_list);
567 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
569 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
570 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
571 edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed));
573 TreeModel::Row row = *(group_model->append());
574 row[group_columns.is_active] = false;
575 row[group_columns.text] = (_("-all-"));
576 edit_group_list.get_selection()->select (row);
577 /* GTK2FIX is set_data(0) setting the is_active to false here?
578 list<string> stupid_list;
580 stupid_list.push_back ("*");
581 stupid_list.push_back (_("-all-"));
583 edit_group_list.rows().push_back (stupid_list);
584 edit_group_list.rows().back().set_data (0);
585 edit_group_list.rows().back().select();
588 edit_group_vbox.pack_start (edit_group_list_button, false, false);
589 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
591 route_list_frame.set_name ("BaseFrame");
592 route_list_frame.set_shadow_type (Gtk::SHADOW_IN);
593 route_list_frame.add (route_list_scroller);
595 edit_group_list_frame.set_name ("BaseFrame");
596 edit_group_list_frame.set_shadow_type (Gtk::SHADOW_IN);
597 edit_group_list_frame.add (edit_group_vbox);
599 route_group_vpane.add1 (route_list_frame);
600 route_group_vpane.add2 (edit_group_list_frame);
602 list_vpacker.pack_start (route_group_vpane, true, true);
604 region_list_model = TreeStore::create (region_list_columns);
605 region_list_sort_model = TreeModelSort::create (region_list_model);
606 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
608 region_list_display.set_model (region_list_sort_model);
609 region_list_display.append_column (_("Regions"), region_list_columns.name);
610 region_list_display.set_reorderable (true);
611 region_list_display.set_size_request (100, -1);
612 region_list_display.set_data ("editor", this);
613 region_list_display.set_flags (Gtk::CAN_FOCUS);
614 region_list_display.set_name ("RegionListDisplay");
616 region_list_scroller.add (region_list_display);
617 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
619 vector<Gtk::TargetEntry> region_list_target_table;
621 region_list_target_table.push_back (TargetEntry ("STRING"));
622 region_list_target_table.push_back (TargetEntry ("text/plain"));
623 region_list_target_table.push_back (TargetEntry ("text/uri-list"));
624 region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
626 region_list_display.drag_dest_set (region_list_target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
627 region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
629 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
630 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
631 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
632 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
633 region_list_display.signal_enter_notify_event().connect (mem_fun(*this, &Editor::region_list_display_enter_notify));
634 region_list_display.signal_leave_notify_event().connect (mem_fun(*this, &Editor::region_list_display_leave_notify));
635 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
637 //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
638 //region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click));
640 named_selection_scroller.add (named_selection_display);
641 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
643 named_selection_model = TreeStore::create (named_selection_columns);
644 named_selection_display.set_model (named_selection_model);
645 named_selection_display.set_name ("RegionListDisplay");
646 named_selection_display.set_size_request (100, -1);
647 named_selection_display.set_headers_visible (true);
648 named_selection_display.set_headers_clickable (true);
649 named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
650 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
651 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
653 region_selection_vpane.pack1 (region_list_scroller, true, true);
654 region_selection_vpane.pack2 (named_selection_scroller, true, true);
656 canvas_region_list_pane.pack1 (edit_frame, true, true);
657 canvas_region_list_pane.pack2 (region_selection_vpane, true, true);
659 track_list_canvas_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
660 static_cast<Gtk::Paned*> (&track_list_canvas_pane)));
661 canvas_region_list_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
662 static_cast<Gtk::Paned*> (&canvas_region_list_pane)));
663 route_group_vpane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
664 static_cast<Gtk::Paned*> (&route_group_vpane)));
665 region_selection_vpane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
666 static_cast<Gtk::Paned*> (®ion_selection_vpane)));
668 track_list_canvas_pane.pack1 (list_vpacker, true, true);
669 track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true);
671 /* provide special pane-handle event handling for easy "hide" action */
673 /* 0: collapse to show left/upper child
674 1: collapse to show right/lower child
677 route_group_vpane.set_data ("collapse-direction", (gpointer) 0);
678 region_selection_vpane.set_data ("collapse-direction", (gpointer) 0);
679 canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0);
680 track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1);
682 route_group_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&route_group_vpane)));
683 region_selection_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (®ion_selection_vpane)));
684 canvas_region_list_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&canvas_region_list_pane)));
685 track_list_canvas_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&track_list_canvas_pane)));
687 top_hbox.pack_start (toolbar_frame, true, true);
689 HBox *hbox = manage (new HBox);
690 hbox->pack_start (track_list_canvas_pane, true, true);
692 global_vpacker.pack_start (top_hbox, false, false);
693 global_vpacker.pack_start (*hbox, true, true);
695 global_hpacker.pack_start (global_vpacker, true, true);
697 set_name ("EditorWindow");
699 vpacker.pack_end (global_hpacker, true, true);
701 _playlist_selector = new PlaylistSelector();
702 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
704 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
708 nudge_forward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
709 nudge_backward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
711 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
712 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
714 nudge_forward_button.set_name ("TransportButton");
715 nudge_backward_button.set_name ("TransportButton");
717 fade_context_menu.set_name ("ArdourContextMenu");
719 install_keybindings ();
721 set_title (_("ardour: editor"));
722 set_wmclass (_("ardour_editor"), "Ardour");
725 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
727 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
728 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
736 /* <CMT Additions> */
737 if(image_socket_listener)
739 if(image_socket_listener->is_connected())
741 image_socket_listener->close_connection() ;
744 delete image_socket_listener ;
745 image_socket_listener = 0 ;
747 /* </CMT Additions> */
751 Editor::add_toplevel_controls (Container& cont)
753 vpacker.pack_start (cont, false, false);
758 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
760 /* note: the selection will take care of the vanishing
761 audioregionview by itself.
764 if (clicked_regionview == rv) {
765 clicked_regionview = 0;
768 if (entered_regionview == rv) {
769 set_entered_regionview (0);
774 Editor::set_entered_regionview (AudioRegionView* rv)
776 if (rv == entered_regionview) {
780 if (entered_regionview) {
781 entered_regionview->exited ();
784 if ((entered_regionview = rv) != 0) {
785 entered_regionview->entered ();
790 Editor::set_entered_track (TimeAxisView* tav)
793 entered_track->exited ();
796 if ((entered_track = tav) != 0) {
797 entered_track->entered ();
802 Editor::left_track_canvas (GdkEventCrossing *ev)
804 set_entered_track (0);
805 set_entered_regionview (0);
811 Editor::initialize_canvas ()
813 Gnome::Canvas::init ();
815 /* adjust sensitivity for "picking" items */
817 // GNOME_CANVAS(track_canvas)->close_enough = 2;
819 track_canvas.signal_event().connect (mem_fun (*this, &Editor::track_canvas_event));
820 track_canvas.set_name ("EditorMainCanvas");
821 track_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
822 track_canvas.signal_event().connect (mem_fun (*this, &Editor::track_canvas_event));
823 track_canvas.signal_leave_notify_event().connect (mem_fun(*this, &Editor::left_track_canvas));
825 /* set up drag-n-drop */
826 vector<Gtk::TargetEntry> target_table;
828 target_table.push_back (TargetEntry ("STRING"));
829 target_table.push_back (TargetEntry ("text/plain"));
830 target_table.push_back (TargetEntry ("text/uri-list"));
831 target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
833 track_canvas.drag_dest_set (target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
834 track_canvas.signal_drag_data_received().connect (mem_fun(*this, &Editor::track_canvas_drag_data_received));
836 /* stuff for the verbose canvas cursor */
838 Pango::FontDescription font = get_font_for_style (N_("VerboseCanvasCursor"));
840 verbose_canvas_cursor = new Gnome::Canvas::Text (*track_canvas.root());
841 verbose_canvas_cursor->set_property ("font_desc", font);
842 verbose_canvas_cursor->set_property ("anchor", GTK_ANCHOR_NW);
843 verbose_canvas_cursor->set_property ("fill_color_rgba", color_map[cVerboseCanvasCursor]);
845 verbose_cursor_visible = false;
847 /* a group to hold time (measure) lines */
849 time_line_group = new Gnome::Canvas::Group (*track_canvas.root(), 0.0, 0.0);
850 cursor_group = new Gnome::Canvas::Group (*track_canvas.root(), 0.0, 0.0);
852 time_canvas.set_name ("EditorTimeCanvas");
853 time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
855 meter_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, 0.0);
856 tempo_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, 0.0);
857 marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 2.0);
858 range_marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 3.0);
859 transport_marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 4.0);
861 tempo_bar = new Gnome::Canvas::SimpleRect (*tempo_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
862 tempo_bar->set_property ("fill_color_rgba", color_map[cTempoBar]);
863 tempo_bar->set_property ("outline_pixels", 0);
865 meter_bar = new Gnome::Canvas::SimpleRect (*meter_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
866 meter_bar->set_property ("fill_color_rgba", color_map[cMeterBar]);
867 meter_bar->set_property ("outline_pixels",0);
869 marker_bar = new Gnome::Canvas::SimpleRect (*marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
870 marker_bar->set_property ("fill_color_rgba", color_map[cMarkerBar]);
871 marker_bar->set_property ("outline_pixels", 0);
873 range_marker_bar = new Gnome::Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
874 range_marker_bar->set_property ("fill_color_rgba", color_map[cRangeMarkerBar]);
875 range_marker_bar->set_property ("outline_pixels", 0);
877 transport_marker_bar = new Gnome::Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
878 transport_marker_bar->set_property ("fill_color_rgba", color_map[cTransportMarkerBar]);
879 transport_marker_bar->set_property ("outline_pixels", 0);
881 range_bar_drag_rect = new Gnome::Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
882 range_bar_drag_rect->set_property ("fill_color_rgba", color_map[cRangeDragBarRectFill]);
883 range_bar_drag_rect->set_property ("outline_color_rgba", color_map[cRangeDragBarRect]);
884 range_bar_drag_rect->set_property ("outline_pixels", 0);
885 range_bar_drag_rect->hide ();
887 transport_bar_drag_rect = new Gnome::Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
888 transport_bar_drag_rect ->set_property ("fill_color_rgba", color_map[cTransportDragRectFill]);
889 transport_bar_drag_rect->set_property ("outline_color_rgba", color_map[cTransportDragRect]);
890 transport_bar_drag_rect->set_property ("outline_pixels", 0);
891 transport_bar_drag_rect->hide ();
893 marker_drag_line_points.push_back(Gnome::Art::Point(0.0, 0.0));
894 marker_drag_line_points.push_back(Gnome::Art::Point(0.0, 0.0));
896 marker_drag_line = new Gnome::Canvas::Line (*track_canvas.root());
897 marker_drag_line->set_property ("width_pixels", 1);
898 marker_drag_line->set_property("fill_color_rgba", color_map[cMarkerDragLine]);
899 marker_drag_line->set_property("points", marker_drag_line_points.gobj());
900 marker_drag_line->hide();
902 range_marker_drag_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
903 range_marker_drag_rect->set_property ("fill_color_rgba", color_map[cRangeDragRectFill]);
904 range_marker_drag_rect->set_property ("outline_color_rgba", color_map[cRangeDragRect]);
905 range_marker_drag_rect->hide ();
907 transport_loop_range_rect = new Gnome::Canvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
908 transport_loop_range_rect->set_property ("fill_color_rgba", color_map[cTransportLoopRectFill]);
909 transport_loop_range_rect->set_property ("outline_color_rgba", color_map[cTransportLoopRect]);
910 transport_loop_range_rect->set_property ("outline_pixels", 1);
911 transport_loop_range_rect->hide();
913 transport_punch_range_rect = new Gnome::Canvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
914 transport_punch_range_rect->set_property ("fill_color_rgba", color_map[cTransportPunchRectFill]);
915 transport_punch_range_rect->set_property ("outline_color_rgba", color_map[cTransportPunchRect]);
916 transport_punch_range_rect->set_property ("outline_pixels", 0);
917 transport_punch_range_rect->hide();
919 transport_loop_range_rect->lower_to_bottom (); // loop on the bottom
921 transport_punchin_line = new Gnome::Canvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
922 transport_punchin_line->set_property ("outline_color_rgba", color_map[cPunchInLine]);
923 transport_punchin_line->set_property ("outline_pixels", 1);
924 transport_punchin_line->hide ();
926 transport_punchout_line = new Gnome::Canvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
927 transport_punchout_line->set_property ("outline_color_rgba", color_map[cPunchOutLine]);
928 transport_punchout_line->set_property ("outline_pixels", 1);
929 transport_punchout_line->hide();
931 // used to show zoom mode active zooming
932 zoom_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
933 zoom_rect->set_property ("fill_color_rgba", color_map[cZoomRectFill]);
934 zoom_rect->set_property ("outline_color_rgba", color_map[cZoomRect]);
935 zoom_rect->set_property ("outline_pixels", 1);
938 zoom_rect->signal_event().connect (mem_fun (*this, &Editor::canvas_zoom_rect_event));
940 // used as rubberband rect
941 rubberband_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
942 rubberband_rect->set_property ("outline_color_rgba", color_map[cRubberBandRect]);
943 rubberband_rect->set_property ("fill_color_rgba", (guint32) color_map[cRubberBandRectFill]);
944 rubberband_rect->set_property ("outline_pixels", 1);
945 rubberband_rect->hide();
947 tempo_bar->signal_event().connect (mem_fun (*this, &Editor::canvas_tempo_bar_event));
948 meter_bar->signal_event().connect (mem_fun (*this, &Editor::canvas_meter_bar_event));
949 marker_bar->signal_event().connect (mem_fun (*this, &Editor::canvas_marker_bar_event));
950 range_marker_bar->signal_event().connect (mem_fun (*this, &Editor::canvas_range_marker_bar_event));
951 transport_marker_bar->signal_event().connect (mem_fun (*this, &Editor::canvas_transport_marker_bar_event));
953 /* separator lines */
955 tempo_line_points.push_back(Gnome::Art::Point(0, timebar_height));
956 tempo_line_points.push_back(Gnome::Art::Point(max_canvas_coordinate, timebar_height));
958 tempo_line = new Gnome::Canvas::Line (*tempo_group, *tempo_line_points);
959 tempo_line->set_property ("width_pixels", 0);
960 tempo_line->set_property ("fill_color", "#000000");
962 meter_line_points.push_back(Gnome::Art::Point (0, timebar_height));
963 meter_line_points.push_back(Gnome::Art::Point(max_canvas_coordinate, timebar_height));
965 meter_line = new Gnome::Canvas::Line (*meter_group, *meter_line_points);
966 meter_line->set_property ("width_pixels", 0);
967 meter_line->set_property ("fill_color", "#000000");
969 marker_line_points.push_back(Gnome::Art::Point (0, timebar_height));
970 marker_line_points.push_back(Gnome::Art::Point(max_canvas_coordinate, timebar_height));
972 marker_line = new Gnome::Canvas::Line (*marker_group, *marker_line_points);
973 marker_line->set_property ("width_pixels", 0);
974 marker_line->set_property ("fill_color", "#000000");
976 range_marker_line = new Gnome::Canvas::Line (*range_marker_group, *marker_line_points);
977 range_marker_line->set_property ("width_pixels", 0);
978 range_marker_line->set_property ("fill_color", "#000000");
980 transport_marker_line = new Gnome::Canvas::Line (*transport_marker_group, *marker_line_points);
981 transport_marker_line->set_property ("width_pixels", 0);
982 transport_marker_line->set_property ("fill_color", "#000000");
984 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_loop_range_view), false));
985 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_punch_range_view), false));
987 double time_height = timebar_height * 5;
988 double time_width = FLT_MAX/frames_per_unit;
989 time_canvas.set_scroll_region(0.0, 0.0, time_width, time_height);
991 edit_cursor = new Cursor (*this, "blue", canvas_edit_cursor_event);
992 playhead_cursor = new Cursor (*this, "red", canvas_playhead_cursor_event);
994 track_canvas.signal_size_allocate().connect (mem_fun(*this, &Editor::track_canvas_allocate));
998 Editor::show_window ()
1002 /* now reset all audio_time_axis heights, because widgets might need
1008 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1009 tv = (static_cast<TimeAxisView*>(*i));
1010 tv->reset_height ();
1015 Editor::tie_vertical_scrolling ()
1017 edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
1019 float y1 = track_canvas_scroller.get_vadjustment()->get_value();
1020 playhead_cursor->set_y_axis(y1);
1021 edit_cursor->set_y_axis(y1);
1025 Editor::set_frames_per_unit (double fpu)
1027 jack_nframes_t frames;
1029 if (fpu == frames_per_unit) {
1037 // convert fpu to frame count
1039 frames = (jack_nframes_t) (fpu * canvas_width);
1041 /* don't allow zooms that fit more than the maximum number
1042 of frames into an 800 pixel wide space.
1045 if (max_frames / fpu < 800.0) {
1049 frames_per_unit = fpu;
1051 if (frames != zoom_range_clock.current_duration()) {
1052 zoom_range_clock.set (frames);
1055 /* only update these if we not about to call reposition_x_origin,
1056 which will do the same updates.
1060 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1063 if (!no_zoom_repos_update) {
1064 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1065 update_hscroller ();
1066 update_fixed_rulers ();
1067 tempo_map_changed (Change (0));
1070 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
1071 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1072 (*i)->reshow_selection (selection->time);
1076 ZoomChanged (); /* EMIT_SIGNAL */
1078 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
1079 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
1086 Editor::instant_save ()
1088 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
1093 session->add_instant_xml(get_state(), session->path());
1095 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
1100 Editor::reposition_x_origin (jack_nframes_t frame)
1102 if (frame != leftmost_frame) {
1103 leftmost_frame = frame;
1104 double pixel = frame_to_pixel (frame);
1105 if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
1106 track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
1108 track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
1109 XOriginChanged (); /* EMIT_SIGNAL */
1114 Editor::edit_cursor_clock_changed()
1116 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
1117 edit_cursor->set_position (edit_cursor_clock.current_time());
1123 Editor::zoom_adjustment_changed ()
1125 if (session == 0 || no_zoom_repos_update) {
1129 double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width;
1133 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1135 else if (fpu > session->current_end_frame() / (double) canvas_width) {
1136 fpu = session->current_end_frame() / (double) canvas_width;
1137 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1140 temporal_zoom (fpu);
1144 Editor::canvas_horizontally_scrolled ()
1146 /* XXX note the potential loss of accuracy here caused by
1147 adjustments being 32bit floats with only a 24 bit mantissa,
1148 whereas jack_nframes_t is at least a 32 bit uint32_teger.
1151 leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
1153 update_hscroller ();
1154 update_fixed_rulers ();
1156 if (!edit_hscroll_dragging) {
1157 tempo_map_changed (Change (0));
1159 update_tempo_based_rulers();
1164 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
1166 if (!repos_zoom_queued) {
1167 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
1168 repos_zoom_queued = true;
1173 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
1175 /* if we need to force an update to the hscroller stuff,
1176 don't set no_zoom_repos_update.
1179 no_zoom_repos_update = (frame != leftmost_frame);
1181 set_frames_per_unit (nfpu);
1182 if (no_zoom_repos_update) {
1183 reposition_x_origin (frame);
1185 no_zoom_repos_update = false;
1186 repos_zoom_queued = false;
1192 Editor::on_realize ()
1194 /* Even though we're not using acceleration, we want the
1197 Glib::RefPtr<Gdk::Pixmap> empty_pixmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1198 Glib::RefPtr<Gdk::Pixmap> empty_bitmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1201 track_context_menu.accelerate (*this->get_toplevel());
1202 track_region_context_menu.accelerate (*this->get_toplevel());
1204 Window::on_realize ();
1206 Gdk::Color white ("#ffffff" );
1207 null_cursor = new Gdk::Cursor(empty_pixmap, empty_bitmap, white, white, 0, 0);
1215 track_canvas_scroller.get_window()->set_cursor (*current_canvas_cursor);
1216 time_canvas_scroller.get_window()->set_cursor (*timebar_cursor);
1220 Editor::track_canvas_allocate (GtkAllocation *alloc)
1222 canvas_width = alloc->width;
1223 canvas_height = alloc->height;
1225 if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) {
1227 Pango::FontDescription font = get_font_for_style (N_("FirstActionMessage"));
1229 const char *txt1 = _("Start a new session\n");
1230 const char *txt2 = _("via Session menu");
1232 /* this mess of code is here to find out how wide this text is and
1233 position the message in the center of the editor window. there
1234 are two lines, so we use the longer of the the lines to
1235 compute width, and multiply the height by 2.
1241 /* this is a dummy widget that exists so that we can get the
1242 style from the RC file.
1245 Label foo (_(txt2));
1246 Glib::RefPtr<Pango::Layout> layout;
1247 foo.set_name ("NoSessionMessage");
1248 foo.ensure_style ();
1250 layout = foo.create_pango_layout (_(txt2));
1251 layout->set_font_description (font);
1252 layout->get_pixel_size (pixel_width, pixel_height);
1254 if (first_action_message == 0) {
1256 char txt[strlen(txt1)+strlen(txt2)+1];
1258 /* merge both lines */
1260 strcpy (txt, _(txt1));
1261 strcat (txt, _(txt2));
1263 first_action_message = new Gnome::Canvas::Text (*track_canvas.root());
1264 first_action_message->set_property ("font_desc", font);
1265 first_action_message->set_property ("fill_color_rgba", color_map[cFirstActionMessage]);
1266 first_action_message->set_property ("x", (gdouble) (canvas_width - pixel_width) / 2.0);
1267 first_action_message->set_property ("y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)));
1268 first_action_message->set_property ("anchor", GTK_ANCHOR_NORTH_WEST);
1269 first_action_message->set_property ("text", ustring (txt));
1274 first_action_message->set_property ("x", (gdouble) (canvas_width - pixel_width) / 2.0),
1275 first_action_message->set_property ("y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)));
1279 zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit));
1280 edit_cursor->set_position (edit_cursor->current_frame);
1281 playhead_cursor->set_position (playhead_cursor->current_frame);
1282 reset_scrolling_region (alloc);
1284 Resized (); /* EMIT_SIGNAL */
1288 Editor::reset_scrolling_region (GtkAllocation *alloc)
1290 guint32 last_canvas_unit;
1292 guint32 canvas_alloc_height, canvas_alloc_width;
1293 TrackViewList::iterator i;
1294 static bool first_time = true;
1296 /* We need to make sure that the canvas always has its
1297 scrolling region set to larger of:
1299 - the size allocated for it (within the container its packed in)
1300 - the size required to see the entire session
1302 If we don't ensure at least the first of these, the canvas
1303 does some wierd and in my view unnecessary stuff to center
1304 itself within the allocated area, which causes bad, bad
1307 XXX GnomeCanvas has fixed this, and has an option to
1308 control the centering behaviour.
1311 last_canvas_unit = (guint32) ceil ((float) max_frames / frames_per_unit);
1316 for (i = track_views.begin(); i != track_views.end(); ++i) {
1317 if ((*i)->control_parent) {
1318 height += (*i)->effective_height;
1319 height += track_spacing;
1324 height -= track_spacing;
1328 canvas_height = (guint32) height;
1331 canvas_alloc_height = alloc->height;
1332 canvas_alloc_width = alloc->width;
1334 canvas_alloc_height = track_canvas.get_height();
1335 canvas_alloc_width = track_canvas.get_width();
1338 canvas_height = max (canvas_height, canvas_alloc_height);
1339 track_canvas.set_scroll_region ( 0.0, 0.0, max (last_canvas_unit, canvas_alloc_width), canvas_height);
1341 if (edit_cursor) edit_cursor->set_length (canvas_alloc_height);
1342 if (playhead_cursor) playhead_cursor->set_length (canvas_alloc_height);
1344 if (marker_drag_line) {
1345 marker_drag_line_points[1].set_y (canvas_height);
1346 marker_drag_line->set_property("points", marker_drag_line_points.gobj());
1348 if (range_marker_drag_rect) {
1349 range_marker_drag_rect->set_property("y1", 0.0);
1350 range_marker_drag_rect->set_property("y2", (double) canvas_height);
1353 if (transport_loop_range_rect) {
1354 transport_loop_range_rect->set_property("y1", 0.0);
1355 transport_loop_range_rect->set_property("y2", (double) canvas_height);
1358 if (transport_punch_range_rect) {
1359 transport_punch_range_rect->set_property("y1", 0.0);
1360 transport_punch_range_rect->set_property("y2", (double) canvas_height);
1363 if (transport_punchin_line) {
1364 transport_punchin_line->set_property("y1", 0.0);
1365 transport_punchin_line->set_property("y2", (double) canvas_height);
1368 if (transport_punchout_line) {
1369 transport_punchout_line->set_property("y1", 0.0);
1370 transport_punchout_line->set_property("y2", (double) canvas_height);
1373 update_fixed_rulers ();
1375 if (is_visible() && first_time) {
1376 tempo_map_changed (Change (0));
1384 Editor::queue_session_control_changed (Session::ControlType t)
1386 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1390 Editor::session_control_changed (Session::ControlType t)
1392 // right now we're only tracking the loop and punch state
1395 case Session::AutoLoop:
1396 update_loop_range_view (true);
1398 case Session::PunchIn:
1399 case Session::PunchOut:
1400 update_punch_range_view (true);
1409 Editor::fake_add_edit_group (RouteGroup *group)
1411 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1415 Editor::fake_handle_new_audio_region (AudioRegion *region)
1417 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1421 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1423 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1427 Editor::fake_handle_new_duration ()
1429 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1433 Editor::start_scrolling ()
1435 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1436 (mem_fun(*this, &Editor::update_current_screen));
1438 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1439 (mem_fun(*this, &Editor::update_slower));
1443 Editor::stop_scrolling ()
1445 scroll_connection.disconnect ();
1446 slower_update_connection.disconnect ();
1450 Editor::map_position_change (jack_nframes_t frame)
1452 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1454 if (session == 0 || !_follow_playhead) {
1458 center_screen (frame);
1459 playhead_cursor->set_position (frame);
1463 Editor::center_screen (jack_nframes_t frame)
1465 float page = canvas_width * frames_per_unit;
1467 /* if we're off the page, then scroll.
1470 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1471 center_screen_internal (frame,page);
1476 Editor::center_screen_internal (jack_nframes_t frame, float page)
1481 frame -= (jack_nframes_t) page;
1486 reposition_x_origin (frame);
1490 Editor::handle_new_duration ()
1492 reset_scrolling_region ();
1495 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1496 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1499 update_hscroller ();
1503 Editor::update_title_s (string snap_name)
1505 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1511 Editor::update_title ()
1513 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1516 bool dirty = session->dirty();
1518 string wintitle = _("ardour: editor: ");
1524 wintitle += session->name();
1526 if (session->snap_name() != session->name()) {
1528 wintitle += session->snap_name();
1535 set_title (wintitle);
1540 Editor::connect_to_session (Session *t)
1544 if (first_action_message) {
1545 first_action_message->hide();
1548 flush_track_canvas();
1552 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1554 /* These signals can all be emitted by a non-GUI thread. Therefore the
1555 handlers for them must not attempt to directly interact with the GUI,
1556 but use Gtkmm2ext::UI::instance()->call_slot();
1559 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1560 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1561 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1562 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1563 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1564 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1565 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1566 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1567 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1568 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1569 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1570 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1571 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1573 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1574 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1576 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1578 session->foreach_edit_group(this, &Editor::add_edit_group);
1580 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1581 editor_mixer_button.set_name (X_("EditorMixerButton"));
1583 edit_cursor_clock.set_session (session);
1584 selection_start_clock.set_session (session);
1585 selection_end_clock.set_session (session);
1586 zoom_range_clock.set_session (session);
1587 _playlist_selector->set_session (session);
1588 nudge_clock.set_session (session);
1590 switch (session->get_edit_mode()) {
1592 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1596 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1600 Location* loc = session->locations()->auto_loop_location();
1602 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1603 if (loc->start() == loc->end()) {
1604 loc->set_end (loc->start() + 1);
1606 session->locations()->add (loc, false);
1607 session->set_auto_loop_location (loc);
1611 loc->set_name (_("Loop"));
1614 loc = session->locations()->auto_punch_location();
1616 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1617 if (loc->start() == loc->end()) {
1618 loc->set_end (loc->start() + 1);
1620 session->locations()->add (loc, false);
1621 session->set_auto_punch_location (loc);
1625 loc->set_name (_("Punch"));
1628 update_loop_range_view (true);
1629 update_punch_range_view (true);
1631 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1634 refresh_location_display ();
1635 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1636 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1637 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1638 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1639 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1641 reset_scrolling_region ();
1643 redisplay_regions ();
1644 redisplay_named_selections ();
1646 //route_list.freeze (); GTK2FIX
1647 route_display_model.clear ();
1648 session->foreach_route (this, &Editor::handle_new_route);
1649 // route_list.select_all ();
1651 //route_list.sort ();
1652 route_list_reordered ();
1653 //route_list.thaw ();
1655 if (embed_audio_item) {
1656 embed_audio_item->set_sensitive (true);
1658 if (import_audio_item) {
1659 import_audio_item->set_sensitive (true);
1662 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1663 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1666 /* ::reposition_x_origin() doesn't work right here, since the old
1667 position may be zero already, and it does nothing in such
1673 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1674 track_canvas_scroller.get_hadjustment()->set_value (0);
1676 update_hscroller ();
1677 restore_ruler_visibility ();
1678 tempo_map_changed (Change (0));
1680 edit_cursor->set_position (0);
1681 playhead_cursor->set_position (0);
1685 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1688 /* don't show master bus in a new session */
1690 if (ARDOUR_UI::instance()->session_is_new ()) {
1692 TreeModel::Children rows = route_display_model->children();
1693 TreeModel::Children::iterator i;
1695 //route_list.freeze ();
1697 for (i = rows.begin(); i != rows.end(); ++i) {
1698 TimeAxisView *tv = (*i)[route_display_columns.tv];
1699 AudioTimeAxisView *atv;
1701 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1702 if (atv->route().master()) {
1703 route_list.get_selection()->unselect (i);
1704 //(*i)->unselect ();
1709 //route_list.thaw ();
1714 Editor::build_cursors ()
1716 Gdk::Color fg ("#ff0000"); /* Red. */
1717 Gdk::Color bg ("#0000ff"); /* Blue. */
1720 Glib::RefPtr <Gdk::Pixmap> source, mask;
1721 source = Gdk::Pixmap::create_from_data (source, hand_bits,
1722 hand_width, hand_height, 1, fg, bg);
1723 Gdk::Pixmap::create_from_data(mask, handmask_bits,
1724 handmask_width, handmask_height, 1, fg, bg);
1725 grabber_cursor = new Gdk::Cursor (source, mask, fg, bg, hand_x_hot, hand_y_hot);
1728 Gdk::Color mbg ("#000000" ); /* Black */
1729 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1732 Glib::RefPtr <Gdk::Pixmap> source, mask;
1734 Gdk::Pixmap::create_from_data (source, mag_bits,
1735 mag_width, mag_height, 1, fg, bg);
1736 Gdk::Pixmap::create_from_data (mask, magmask_bits,
1737 mag_width, mag_height, 1, fg, bg);
1738 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1741 Gdk::Color fbg ("#ffffff" );
1742 Gdk::Color ffg ("#000000" );
1745 Glib::RefPtr <Gdk::Pixmap> source, mask;
1747 Gdk::Pixmap::create_from_data (source, fader_cursor_bits,
1748 fader_cursor_width, fader_cursor_height, 1, fg, bg);
1749 Gdk::Pixmap::create_from_data (mask, fader_cursor_mask_bits,
1750 fader_cursor_width, fader_cursor_height, 1, fg, bg);
1751 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1755 Glib::RefPtr <Gdk::Pixmap> source, mask;
1756 Gdk::Pixmap::create_from_data (source,speaker_cursor_bits,
1757 speaker_cursor_width, speaker_cursor_height, 1, fg, bg);
1758 Gdk::Pixmap::create_from_data (mask, speaker_cursor_mask_bits,
1759 speaker_cursor_width, speaker_cursor_height, 1, fg, bg);
1760 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1763 cross_hair_cursor = new Gdk::Cursor (Gdk::CROSSHAIR);
1764 trimmer_cursor = new Gdk::Cursor (Gdk::SB_H_DOUBLE_ARROW);
1765 selector_cursor = new Gdk::Cursor (Gdk::XTERM);
1766 time_fx_cursor = new Gdk::Cursor (Gdk::SIZING);
1767 wait_cursor = new Gdk::Cursor (Gdk::WATCH);
1768 timebar_cursor = new Gdk::Cursor(Gdk::LEFT_PTR);
1772 Editor::popup_fade_context_menu (int button, int32_t time, GnomeCanvasItem* item, ItemType item_type)
1774 using namespace Menu_Helpers;
1775 AudioRegionView* arv = static_cast<AudioRegionView*> (gtk_object_get_data (GTK_OBJECT(item), "regionview"));
1778 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1782 MenuList& items (fade_context_menu.items());
1786 switch (item_type) {
1788 case FadeInHandleItem:
1789 if (arv->region.fade_in_active()) {
1790 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1792 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1795 items.push_back (SeparatorElem());
1797 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1798 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1799 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1800 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1801 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1805 case FadeOutHandleItem:
1806 if (arv->region.fade_out_active()) {
1807 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1809 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1812 items.push_back (SeparatorElem());
1814 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1815 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1816 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1817 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1818 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1822 fatal << _("programming error: ")
1823 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1828 fade_context_menu.popup (button, time);
1832 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1834 using namespace Menu_Helpers;
1835 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1838 switch (item_type) {
1840 case AudioRegionViewName:
1841 case AudioRegionViewNameHighlight:
1842 if (with_selection) {
1843 build_menu_function = &Editor::build_track_selection_context_menu;
1845 build_menu_function = &Editor::build_track_region_context_menu;
1850 if (with_selection) {
1851 build_menu_function = &Editor::build_track_selection_context_menu;
1853 build_menu_function = &Editor::build_track_context_menu;
1857 case CrossfadeViewItem:
1858 build_menu_function = &Editor::build_track_crossfade_context_menu;
1862 if (clicked_audio_trackview->get_diskstream()) {
1863 build_menu_function = &Editor::build_track_context_menu;
1865 build_menu_function = &Editor::build_track_bus_context_menu;
1870 /* probably shouldn't happen but if it does, we don't care */
1874 menu = (this->*build_menu_function)(frame);
1875 menu->set_name ("ArdourContextMenu");
1877 /* now handle specific situations */
1879 switch (item_type) {
1881 case AudioRegionViewName:
1882 case AudioRegionViewNameHighlight:
1883 if (!with_selection) {
1884 if (region_edit_menu_split_item) {
1885 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1886 region_edit_menu_split_item->set_sensitive (true);
1888 region_edit_menu_split_item->set_sensitive (false);
1891 if (region_edit_menu_split_multichannel_item) {
1892 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1893 region_edit_menu_split_multichannel_item->set_sensitive (true);
1895 region_edit_menu_split_multichannel_item->set_sensitive (false);
1904 case CrossfadeViewItem:
1911 /* probably shouldn't happen but if it does, we don't care */
1915 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1917 /* Bounce to disk */
1919 using namespace Menu_Helpers;
1920 MenuList& edit_items = menu->items();
1922 edit_items.push_back (SeparatorElem());
1924 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1925 case AudioTrack::NoFreeze:
1926 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1929 case AudioTrack::Frozen:
1930 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1933 case AudioTrack::UnFrozen:
1934 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1940 menu->popup (button, time);
1944 Editor::build_track_context_menu (jack_nframes_t ignored)
1946 using namespace Menu_Helpers;
1948 MenuList& edit_items = track_context_menu.items();
1951 add_dstream_context_items (edit_items);
1952 return &track_context_menu;
1956 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1958 using namespace Menu_Helpers;
1960 MenuList& edit_items = track_context_menu.items();
1963 add_bus_context_items (edit_items);
1964 return &track_context_menu;
1968 Editor::build_track_region_context_menu (jack_nframes_t frame)
1970 using namespace Menu_Helpers;
1971 MenuList& edit_items = track_region_context_menu.items();
1974 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1980 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1981 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1982 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1983 add_region_context_items (atv->view, (*i), edit_items);
1989 add_dstream_context_items (edit_items);
1991 return &track_region_context_menu;
1995 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1997 using namespace Menu_Helpers;
1998 MenuList& edit_items = track_crossfade_context_menu.items();
1999 edit_items.clear ();
2001 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
2008 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
2010 Playlist::RegionList* regions = pl->regions_at (frame);
2011 AudioPlaylist::Crossfades xfades;
2013 apl->crossfades_at (frame, xfades);
2015 bool many = xfades.size() > 1;
2017 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
2018 add_crossfade_context_items (atv->view, (*i), edit_items, many);
2021 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
2022 add_region_context_items (atv->view, (*i), edit_items);
2029 add_dstream_context_items (edit_items);
2031 return &track_crossfade_context_menu;
2035 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
2037 using namespace Menu_Helpers;
2038 MenuList& edit_items = track_selection_context_menu.items();
2039 edit_items.clear ();
2041 add_selection_context_items (edit_items);
2042 add_dstream_context_items (edit_items);
2044 return &track_selection_context_menu;
2048 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
2050 using namespace Menu_Helpers;
2051 Menu *xfade_menu = manage (new Menu);
2052 MenuList& items = xfade_menu->items();
2053 xfade_menu->set_name ("ArdourContextMenu");
2056 if (xfade->active()) {
2062 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
2063 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
2065 if (xfade->can_follow_overlap()) {
2067 if (xfade->following_overlap()) {
2068 str = _("Convert to short");
2070 str = _("Convert to full");
2073 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
2077 str = xfade->out().name();
2079 str += xfade->in().name();
2081 str = _("Crossfade");
2084 edit_items.push_back (MenuElem (str, *xfade_menu));
2085 edit_items.push_back (SeparatorElem());
2089 Editor::xfade_edit_left_region ()
2091 if (clicked_crossfadeview) {
2092 clicked_crossfadeview->left_view.show_region_editor ();
2097 Editor::xfade_edit_right_region ()
2099 if (clicked_crossfadeview) {
2100 clicked_crossfadeview->right_view.show_region_editor ();
2105 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
2107 using namespace Menu_Helpers;
2108 Menu *region_menu = manage (new Menu);
2109 MenuList& items = region_menu->items();
2110 region_menu->set_name ("ArdourContextMenu");
2112 AudioRegion* ar = 0;
2115 ar = dynamic_cast<AudioRegion*> (region);
2118 /* when this particular menu pops up, make the relevant region
2122 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
2124 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
2125 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
2126 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
2127 items.push_back (SeparatorElem());
2128 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
2129 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
2130 items.push_back (SeparatorElem());
2132 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
2133 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
2134 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
2135 items.push_back (SeparatorElem());
2137 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
2138 might be able to figure out which overloaded member function to use in
2142 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
2144 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
2145 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
2146 items.push_back (SeparatorElem());
2148 if (region->muted()) {
2149 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
2151 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
2153 items.push_back (SeparatorElem());
2155 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
2156 items.push_back (SeparatorElem());
2161 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
2162 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
2163 items.push_back (SeparatorElem());
2165 if (ar->scale_amplitude() != 1.0f) {
2166 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
2168 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
2171 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
2172 items.push_back (SeparatorElem());
2176 Menu *nudge_menu = manage (new Menu());
2177 MenuList& nudge_items = nudge_menu->items();
2178 nudge_menu->set_name ("ArdourContextMenu");
2180 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
2181 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
2182 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
2183 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
2185 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2186 items.push_back (SeparatorElem());
2188 Menu *trim_menu = manage (new Menu);
2189 MenuList& trim_items = trim_menu->items();
2190 trim_menu->set_name ("ArdourContextMenu");
2192 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
2193 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
2195 items.push_back (MenuElem (_("Trim"), *trim_menu));
2196 items.push_back (SeparatorElem());
2198 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
2199 region_edit_menu_split_item = &items.back();
2201 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
2202 region_edit_menu_split_multichannel_item = &items.back();
2204 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
2205 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
2206 items.push_back (SeparatorElem());
2207 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
2208 items.push_back (SeparatorElem());
2209 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
2211 /* OK, stick the region submenu at the top of the list, and then add
2215 /* we have to hack up the region name because "_" has a special
2216 meaning for menu titles.
2219 string::size_type pos = 0;
2220 string menu_item_name = region->name();
2222 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
2223 menu_item_name.replace (pos, 1, "__");
2227 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
2228 edit_items.push_back (SeparatorElem());
2232 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
2234 using namespace Menu_Helpers;
2235 Menu *selection_menu = manage (new Menu);
2236 MenuList& items = selection_menu->items();
2237 selection_menu->set_name ("ArdourContextMenu");
2239 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
2240 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
2241 items.push_back (SeparatorElem());
2242 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
2243 items.push_back (SeparatorElem());
2244 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
2245 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
2246 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
2247 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
2248 items.push_back (SeparatorElem());
2249 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
2250 items.push_back (SeparatorElem());
2251 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
2252 items.push_back (SeparatorElem());
2253 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
2255 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
2256 edit_items.push_back (SeparatorElem());
2260 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
2262 using namespace Menu_Helpers;
2266 Menu *play_menu = manage (new Menu);
2267 MenuList& play_items = play_menu->items();
2268 play_menu->set_name ("ArdourContextMenu");
2270 play_items.push_back (MenuElem (_("Play from edit cursor")));
2271 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2272 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
2273 play_items.push_back (SeparatorElem());
2274 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
2276 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2280 Menu *select_menu = manage (new Menu);
2281 MenuList& select_items = select_menu->items();
2282 select_menu->set_name ("ArdourContextMenu");
2284 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2285 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2286 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2287 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2288 select_items.push_back (SeparatorElem());
2289 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2290 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2291 select_items.push_back (SeparatorElem());
2293 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2297 Menu *cutnpaste_menu = manage (new Menu);
2298 MenuList& cutnpaste_items = cutnpaste_menu->items();
2299 cutnpaste_menu->set_name ("ArdourContextMenu");
2301 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2302 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2303 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2304 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
2306 cutnpaste_items.push_back (SeparatorElem());
2308 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
2309 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
2311 cutnpaste_items.push_back (SeparatorElem());
2313 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
2315 cutnpaste_items.push_back (SeparatorElem());
2317 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
2318 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
2320 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2322 /* Adding new material */
2324 Menu *import_menu = manage (new Menu());
2325 MenuList& import_items = import_menu->items();
2326 import_menu->set_name ("ArdourContextMenu");
2328 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2329 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
2331 edit_items.push_back (MenuElem (_("Import"), *import_menu));
2335 Menu *nudge_menu = manage (new Menu());
2336 MenuList& nudge_items = nudge_menu->items();
2337 nudge_menu->set_name ("ArdourContextMenu");
2339 edit_items.push_back (SeparatorElem());
2340 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2341 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2342 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2343 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2345 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2349 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2351 using namespace Menu_Helpers;
2355 Menu *play_menu = manage (new Menu);
2356 MenuList& play_items = play_menu->items();
2357 play_menu->set_name ("ArdourContextMenu");
2359 play_items.push_back (MenuElem (_("Play from edit cursor")));
2360 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2361 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2365 Menu *select_menu = manage (new Menu);
2366 MenuList& select_items = select_menu->items();
2367 select_menu->set_name ("ArdourContextMenu");
2369 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2370 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2371 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2372 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2373 select_items.push_back (SeparatorElem());
2374 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2375 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2376 select_items.push_back (SeparatorElem());
2378 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2382 Menu *cutnpaste_menu = manage (new Menu);
2383 MenuList& cutnpaste_items = cutnpaste_menu->items();
2384 cutnpaste_menu->set_name ("ArdourContextMenu");
2386 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2387 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2388 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2390 Menu *nudge_menu = manage (new Menu());
2391 MenuList& nudge_items = nudge_menu->items();
2392 nudge_menu->set_name ("ArdourContextMenu");
2394 edit_items.push_back (SeparatorElem());
2395 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2396 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2397 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2398 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2400 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2403 /* CURSOR SETTING AND MARKS AND STUFF */
2406 Editor::set_snap_to (SnapType st)
2409 vector<string> txt = internationalize (snap_type_strings);
2410 snap_type_selector.set_active_text (txt[(int)st]);
2414 switch (snap_type) {
2415 case SnapToAThirtysecondBeat:
2416 case SnapToASixteenthBeat:
2417 case SnapToAEighthBeat:
2418 case SnapToAQuarterBeat:
2419 case SnapToAThirdBeat:
2420 update_tempo_based_rulers ();
2428 Editor::set_snap_mode (SnapMode mode)
2431 vector<string> txt = internationalize (snap_mode_strings);
2432 snap_mode_selector.set_active_text (txt[(int)mode]);
2438 Editor::add_location_from_selection ()
2440 if (selection->time.empty()) {
2444 if (session == 0 || clicked_trackview == 0) {
2448 jack_nframes_t start = selection->time[clicked_selection].start;
2449 jack_nframes_t end = selection->time[clicked_selection].end;
2451 Location *location = new Location (start, end, "selection");
2453 session->begin_reversible_command (_("add marker"));
2454 session->add_undo (session->locations()->get_memento());
2455 session->locations()->add (location, true);
2456 session->add_redo_no_execute (session->locations()->get_memento());
2457 session->commit_reversible_command ();
2461 Editor::add_location_from_playhead_cursor ()
2463 jack_nframes_t where = session->audible_frame();
2465 Location *location = new Location (where, where, "mark", Location::IsMark);
2466 session->begin_reversible_command (_("add marker"));
2467 session->add_undo (session->locations()->get_memento());
2468 session->locations()->add (location, true);
2469 session->add_redo_no_execute (session->locations()->get_memento());
2470 session->commit_reversible_command ();
2475 Editor::set_state (const XMLNode& node)
2477 const XMLProperty* prop;
2479 int x, y, width, height, xoff, yoff;
2481 if ((geometry = find_named_node (node, "geometry")) == 0) {
2483 width = default_width;
2484 height = default_height;
2492 width = atoi(geometry->property("x_size")->value());
2493 height = atoi(geometry->property("y_size")->value());
2494 x = atoi(geometry->property("x_pos")->value());
2495 y = atoi(geometry->property("y_pos")->value());
2496 xoff = atoi(geometry->property("x_off")->value());
2497 yoff = atoi(geometry->property("y_off")->value());
2500 set_default_size(width, height);
2502 // set_position(x, y-yoff);
2504 if ((prop = node.property ("zoom-focus"))) {
2505 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2508 if ((prop = node.property ("zoom"))) {
2509 set_frames_per_unit (atof (prop->value()));
2512 if ((prop = node.property ("snap-to"))) {
2513 set_snap_to ((SnapType) atoi (prop->value()));
2516 if ((prop = node.property ("snap-mode"))) {
2517 set_snap_mode ((SnapMode) atoi (prop->value()));
2520 if ((prop = node.property ("show-waveforms"))) {
2521 bool yn = (prop->value() == "yes");
2522 _show_waveforms = !yn;
2523 set_show_waveforms (yn);
2526 if ((prop = node.property ("show-waveforms-recording"))) {
2527 bool yn = (prop->value() == "yes");
2528 _show_waveforms_recording = !yn;
2529 set_show_waveforms_recording (yn);
2532 if ((prop = node.property ("show-measures"))) {
2533 bool yn = (prop->value() == "yes");
2534 _show_measures = !yn;
2535 set_show_measures (yn);
2538 if ((prop = node.property ("follow-playhead"))) {
2539 bool yn = (prop->value() == "yes");
2540 _follow_playhead = !yn;
2541 set_follow_playhead (yn);
2544 if ((prop = node.property ("xfades-visible"))) {
2545 bool yn = (prop->value() == "yes");
2546 _xfade_visibility = !yn;
2547 set_xfade_visibility (yn);
2550 if ((prop = node.property ("region-list-sort-type"))) {
2551 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2552 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2555 if ((prop = node.property ("mouse-mode"))) {
2556 MouseMode m = str2mousemode(prop->value());
2557 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2558 set_mouse_mode (m, true);
2560 mouse_mode = MouseGain; /* lie, to force the mode switch */
2561 set_mouse_mode (MouseObject, true);
2564 if ((prop = node.property ("editor-mixer-button"))) {
2565 editor_mixer_button.set_active(prop->value() == "yes");
2572 Editor::get_state ()
2574 XMLNode* node = new XMLNode ("Editor");
2577 if (is_realized()) {
2578 Glib::RefPtr<Gdk::Window> win = get_window();
2580 int x, y, xoff, yoff, width, height;
2581 win->get_root_origin(x, y);
2582 win->get_position(xoff, yoff);
2583 win->get_size(width, height);
2585 XMLNode* geometry = new XMLNode ("geometry");
2587 snprintf(buf, sizeof(buf), "%d", width);
2588 geometry->add_property("x_size", string(buf));
2589 snprintf(buf, sizeof(buf), "%d", height);
2590 geometry->add_property("y_size", string(buf));
2591 snprintf(buf, sizeof(buf), "%d", x);
2592 geometry->add_property("x_pos", string(buf));
2593 snprintf(buf, sizeof(buf), "%d", y);
2594 geometry->add_property("y_pos", string(buf));
2595 snprintf(buf, sizeof(buf), "%d", xoff);
2596 geometry->add_property("x_off", string(buf));
2597 snprintf(buf, sizeof(buf), "%d", yoff);
2598 geometry->add_property("y_off", string(buf));
2599 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gobj()));
2600 geometry->add_property("canvas_region_list_pane_pos", string(buf));
2601 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gobj()));
2602 geometry->add_property("track_list_canvas_pane_pos", string(buf));
2603 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(®ion_selection_vpane)->gobj()));
2604 geometry->add_property("region_selection_pane_pos", string(buf));
2605 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gobj()));
2606 geometry->add_property("route_group_pane_pos", string(buf));
2608 node->add_child_nocopy (*geometry);
2611 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2612 node->add_property ("zoom-focus", buf);
2613 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2614 node->add_property ("zoom", buf);
2615 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2616 node->add_property ("snap-to", buf);
2617 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2618 node->add_property ("snap-mode", buf);
2620 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2621 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2622 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2623 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2624 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2625 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2626 node->add_property ("mouse-mode", enum2str(mouse_mode));
2627 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2635 Editor::trackview_by_y_position (double y)
2637 TrackViewList::iterator iter;
2640 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2648 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2657 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2659 Location* before = 0;
2660 Location* after = 0;
2666 const jack_nframes_t one_second = session->frame_rate();
2667 const jack_nframes_t one_minute = session->frame_rate() * 60;
2669 jack_nframes_t presnap = start;
2671 switch (snap_type) {
2677 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2679 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2682 case SnapToSMPTEFrame:
2684 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2686 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2690 case SnapToSMPTESeconds:
2691 if (session->smpte_offset_negative())
2693 start += session->smpte_offset ();
2695 start -= session->smpte_offset ();
2697 if (direction > 0) {
2698 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2700 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2703 if (session->smpte_offset_negative())
2705 start -= session->smpte_offset ();
2707 start += session->smpte_offset ();
2711 case SnapToSMPTEMinutes:
2712 if (session->smpte_offset_negative())
2714 start += session->smpte_offset ();
2716 start -= session->smpte_offset ();
2719 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2721 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2723 if (session->smpte_offset_negative())
2725 start -= session->smpte_offset ();
2727 start += session->smpte_offset ();
2733 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2735 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2741 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2743 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2748 start = session->tempo_map().round_to_bar (start, direction);
2752 start = session->tempo_map().round_to_beat (start, direction);
2755 case SnapToAThirtysecondBeat:
2756 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2759 case SnapToASixteenthBeat:
2760 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2763 case SnapToAEighthBeat:
2764 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2767 case SnapToAQuarterBeat:
2768 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2771 case SnapToAThirdBeat:
2772 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2775 case SnapToEditCursor:
2776 start = edit_cursor->current_frame;
2784 before = session->locations()->first_location_before (start);
2785 after = session->locations()->first_location_after (start);
2787 if (direction < 0) {
2789 start = before->start();
2793 } else if (direction > 0) {
2795 start = after->start();
2797 start = session->current_end_frame();
2802 /* find nearest of the two */
2803 if ((start - before->start()) < (after->start() - start)) {
2804 start = before->start();
2806 start = after->start();
2809 start = before->start();
2812 start = after->start();
2819 case SnapToRegionStart:
2820 case SnapToRegionEnd:
2821 case SnapToRegionSync:
2822 case SnapToRegionBoundary:
2823 if (!region_boundary_cache.empty()) {
2824 vector<jack_nframes_t>::iterator i;
2826 if (direction > 0) {
2827 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2829 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2832 if (i != region_boundary_cache.end()) {
2835 start = region_boundary_cache.back();
2841 switch (snap_mode) {
2847 if (presnap > start) {
2848 if (presnap > (start + unit_to_frame(snap_threshold))) {
2852 } else if (presnap < start) {
2853 if (presnap < (start - unit_to_frame(snap_threshold))) {
2865 Editor::setup_toolbar ()
2868 vector<ToggleButton *> mouse_mode_buttons;
2870 mouse_mode_buttons.push_back (&mouse_move_button);
2871 mouse_mode_buttons.push_back (&mouse_select_button);
2872 mouse_mode_buttons.push_back (&mouse_gain_button);
2873 mouse_mode_buttons.push_back (&mouse_zoom_button);
2874 mouse_mode_buttons.push_back (&mouse_timefx_button);
2875 mouse_mode_buttons.push_back (&mouse_audition_button);
2876 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2878 mouse_mode_button_table.set_homogeneous (true);
2879 mouse_mode_button_table.set_col_spacings (2);
2880 mouse_mode_button_table.set_row_spacings (2);
2881 mouse_mode_button_table.set_border_width (5);
2883 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2884 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2885 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2887 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2888 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2889 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2891 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2892 mouse_mode_tearoff->set_name ("MouseModeBase");
2894 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2895 mouse_mode_tearoff->tearoff_window()));
2896 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2897 mmouse_mode_tearoff->tearoff_window(), 1));
2899 mouse_move_button.set_name ("MouseModeButton");
2900 mouse_select_button.set_name ("MouseModeButton");
2901 mouse_gain_button.set_name ("MouseModeButton");
2902 mouse_zoom_button.set_name ("MouseModeButton");
2903 mouse_timefx_button.set_name ("MouseModeButton");
2904 mouse_audition_button.set_name ("MouseModeButton");
2906 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2907 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2908 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2909 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2910 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2911 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2913 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2914 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2915 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2916 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2917 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2918 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2920 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2921 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2923 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2924 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2925 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2926 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2927 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2929 // mouse_move_button.set_active (true);
2931 /* automation control */
2933 global_automation_button.set_name ("MouseModeButton");
2934 automation_mode_button.set_name ("MouseModeButton");
2936 automation_box.set_spacing (2);
2937 automation_box.set_border_width (2);
2938 automation_box.pack_start (global_automation_button, false, false);
2939 automation_box.pack_start (automation_mode_button, false, false);
2943 edit_mode_label.set_name ("ToolBarLabel");
2945 edit_mode_selector.set_name ("EditModeSelector");
2947 edit_mode_box.set_spacing (3);
2948 edit_mode_box.set_border_width (3);
2950 /* XXX another disgusting hack because of the way combo boxes size themselves */
2952 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2, 10);
2953 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2954 edit_mode_box.pack_start (edit_mode_label, false, false);
2955 edit_mode_box.pack_start (edit_mode_selector, false, false);
2957 edit_mode_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2961 snap_type_label.set_name ("ToolBarLabel");
2963 snap_type_selector.set_name ("SnapTypeSelector");
2965 snap_type_box.set_spacing (3);
2966 snap_type_box.set_border_width (3);
2968 /* XXX another disgusting hack because of the way combo boxes size themselves */
2970 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2971 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "Region bounds", 2+FUDGE, 10);
2972 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2974 snap_type_box.pack_start (snap_type_label, false, false);
2975 snap_type_box.pack_start (snap_type_selector, false, false);
2977 snap_type_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2979 /* Snap mode, not snap type */
2981 snap_mode_label.set_name ("ToolBarLabel");
2983 snap_mode_selector.set_name ("SnapModeSelector");
2985 snap_mode_box.set_spacing (3);
2986 snap_mode_box.set_border_width (3);
2988 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2, 10);
2989 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2991 snap_mode_box.pack_start (snap_mode_label, false, false);
2992 snap_mode_box.pack_start (snap_mode_selector, false, false);
2994 snap_mode_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2996 /* Zoom focus mode */
2998 zoom_focus_label.set_name ("ToolBarLabel");
3000 zoom_focus_selector.set_name ("ZoomFocusSelector");
3002 zoom_focus_box.set_spacing (3);
3003 zoom_focus_box.set_border_width (3);
3005 /* XXX another disgusting hack because of the way combo boxes size themselves */
3007 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2, 10);
3008 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
3010 zoom_focus_box.pack_start (zoom_focus_label, false, false);
3011 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
3013 zoom_focus_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
3015 /* selection/cursor clocks */
3017 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
3018 selection_start_clock_label.set_name ("ToolBarLabel");
3019 selection_end_clock_label.set_name ("ToolBarLabel");
3020 edit_cursor_clock_label.set_name ("ToolBarLabel");
3022 selection_start_clock_label.set_text (_("Start:"));
3023 selection_end_clock_label.set_text (_("End:"));
3024 edit_cursor_clock_label.set_text (_("Edit:"));
3026 toolbar_selection_clock_table.set_border_width (5);
3027 toolbar_selection_clock_table.set_col_spacings (2);
3028 toolbar_selection_clock_table.set_homogeneous (false);
3030 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
3031 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
3032 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
3034 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
3035 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
3036 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
3039 // toolbar_clock_vbox.set_spacing (2);
3040 // toolbar_clock_vbox.set_border_width (10);
3041 /* the editor/mixer button will be enabled at session connect */
3043 editor_mixer_button.set_active(false);
3044 editor_mixer_button.set_sensitive(false);
3046 HBox* hbox = new HBox;
3048 hbox->pack_start (editor_mixer_button, false, false);
3049 hbox->pack_start (toolbar_selection_clock_table, false, false);
3050 hbox->pack_start (zoom_indicator_vbox, false, false);
3051 hbox->pack_start (zoom_focus_box, false, false);
3052 hbox->pack_start (snap_type_box, false, false);
3053 hbox->pack_start (snap_mode_box, false, false);
3054 hbox->pack_start (edit_mode_box, false, false);
3056 VBox *vbox = manage (new VBox);
3058 vbox->set_spacing (3);
3059 vbox->set_border_width (3);
3061 HBox *nbox = manage (new HBox);
3063 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
3064 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
3066 nbox->pack_start (nudge_backward_button, false, false);
3067 nbox->pack_start (nudge_forward_button, false, false);
3068 nbox->pack_start (nudge_clock, false, false, 5);
3070 nudge_label.set_name ("ToolBarLabel");
3072 vbox->pack_start (nudge_label, false, false);
3073 vbox->pack_start (*nbox, false, false);
3075 hbox->pack_start (*vbox, false, false);
3079 tools_tearoff = new TearOff (*hbox);
3080 tools_tearoff->set_name ("MouseModeBase");
3082 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
3083 tools_tearoff->tearoff_window());
3084 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
3085 tools_tearoff->tearoff_window(), 0));
3088 toolbar_hbox.set_spacing (8);
3089 toolbar_hbox.set_border_width (2);
3091 toolbar_hbox.pack_start (*tools_tearoff, false, false);
3092 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
3094 toolbar_base.set_name ("ToolBarBase");
3095 toolbar_base.add (toolbar_hbox);
3097 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
3098 toolbar_frame.set_name ("BaseFrame");
3099 toolbar_frame.add (toolbar_base);
3103 Editor::_autoscroll_canvas (void *arg)
3105 return ((Editor *) arg)->autoscroll_canvas ();
3109 Editor::autoscroll_canvas ()
3111 jack_nframes_t new_frame;
3112 bool keep_calling = true;
3114 if (autoscroll_direction < 0) {
3115 if (leftmost_frame < autoscroll_distance) {
3118 new_frame = leftmost_frame - autoscroll_distance;
3121 if (leftmost_frame > max_frames - autoscroll_distance) {
3122 new_frame = max_frames;
3124 new_frame = leftmost_frame + autoscroll_distance;
3128 if (new_frame != leftmost_frame) {
3129 reposition_x_origin (new_frame);
3132 if (new_frame == 0 || new_frame == max_frames) {
3139 if (autoscroll_cnt == 1) {
3141 /* connect the timeout so that we get called repeatedly */
3143 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
3144 keep_calling = false;
3146 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
3148 /* after about a while, speed up a bit by changing the timeout interval */
3150 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
3151 keep_calling = false;
3153 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
3155 /* after about another while, speed up some more */
3157 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
3158 keep_calling = false;
3160 } else if (autoscroll_cnt >= 30) {
3162 /* we've been scrolling for a while ... crank it up */
3164 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
3167 return keep_calling;
3171 Editor::start_canvas_autoscroll (int dir)
3177 stop_canvas_autoscroll ();
3179 autoscroll_direction = dir;
3180 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
3183 /* do it right now, which will start the repeated callbacks */
3185 autoscroll_canvas ();
3189 Editor::stop_canvas_autoscroll ()
3191 if (autoscroll_timeout_tag >= 0) {
3192 gtk_timeout_remove (autoscroll_timeout_tag);
3193 autoscroll_timeout_tag = -1;
3198 Editor::convert_drop_to_paths (vector<string>& paths,
3199 GdkDragContext *context,
3202 GtkSelectionData *data,
3210 gchar *tname = gdk_atom_name (data->type);
3212 if (session == 0 || strcmp (tname, "text/plain") != 0) {
3216 /* Parse the "uri-list" format that Nautilus provides,
3217 where each pathname is delimited by \r\n
3220 path = (char *) data->data;
3223 for (int n = 0; n < data->length; ++n) {
3227 if (path[n] == '\r') {
3234 if (path[n] == '\n') {
3235 paths.push_back (spath);
3239 warning << _("incorrectly formatted URI list, ignored")
3247 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
3249 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3251 // cerr << "dropped text was " << *p << endl;
3255 // cerr << "decoded was " << *p << endl;
3257 if ((*p).substr (0,7) == "file://") {
3258 (*p) = (*p).substr (7);
3266 Editor::track_canvas_drag_data_received (GdkDragContext *context,
3269 GtkSelectionData *data,
3274 AudioTimeAxisView* tv;
3276 vector<string> paths;
3279 jack_nframes_t frame;
3281 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
3285 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
3291 track_canvas.c2w( x, y, wx, wy);
3293 ev.type = GDK_BUTTON_RELEASE;
3297 frame = event_frame (&ev, 0, &cy);
3301 if ((tvp = trackview_by_y_position (cy)) == 0) {
3303 /* drop onto canvas background: create a new track */
3305 insert_paths_as_new_tracks (paths, false);
3308 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
3310 /* check that its an audio track, not a bus */
3312 if (tv->get_diskstream()) {
3314 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3315 insert_sndfile_into (*p, true, tv, frame);
3322 gtk_drag_finish (context, TRUE, FALSE, time);
3326 Editor::new_tempo_section ()
3332 Editor::map_transport_state ()
3334 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3336 if (session->transport_stopped()) {
3337 have_pending_keyboard_selection = false;
3343 Editor::State::State ()
3345 selection = new Selection;
3348 Editor::State::~State ()
3354 Editor::get_memento () const
3356 State *state = new State;
3358 store_state (*state);
3359 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3363 Editor::store_state (State& state) const
3365 *state.selection = *selection;
3369 Editor::restore_state (State *state)
3371 if (*selection == *state->selection) {
3375 *selection = *state->selection;
3376 time_selection_changed ();
3377 region_selection_changed ();
3379 /* XXX other selection change handlers? */
3383 Editor::begin_reversible_command (string name)
3386 UndoAction ua = get_memento();
3387 session->begin_reversible_command (name, &ua);
3392 Editor::commit_reversible_command ()
3395 UndoAction ua = get_memento();
3396 session->commit_reversible_command (&ua);
3401 Editor::flush_track_canvas ()
3403 /* I don't think this is necessary, and only causes more problems.
3404 I'm commenting it out
3405 and if the imageframe folks don't have any issues, we can take
3406 out this method entirely
3409 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
3410 //gtk_main_iteration ();
3414 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3416 if (!clicked_trackview) {
3421 begin_reversible_command (_("set selected trackview"));
3426 if (selection->selected (clicked_trackview)) {
3428 selection->remove (clicked_trackview);
3431 selection->add (clicked_trackview);
3436 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3437 /* no commit necessary */
3441 selection->set (clicked_trackview);
3445 commit_reversible_command ();
3450 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3452 if (!clicked_control_point) {
3457 begin_reversible_command (_("set selected control point"));
3467 commit_reversible_command ();
3472 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3474 if (!clicked_regionview) {
3478 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3484 RouteGroup* group = atv->route().edit_group();
3485 vector<AudioRegionView*> all_equivalent_regions;
3487 if (group && group->is_active()) {
3489 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3491 AudioTimeAxisView* tatv;
3493 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3495 if (tatv->route().edit_group() != group) {
3500 vector<AudioRegion*> results;
3501 AudioRegionView* marv;
3504 if ((ds = tatv->get_diskstream()) == 0) {
3509 if ((pl = ds->playlist()) != 0) {
3510 pl->get_equivalent_regions (clicked_regionview->region,
3514 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3515 if ((marv = tatv->view->find_view (**ir)) != 0) {
3516 all_equivalent_regions.push_back (marv);
3525 all_equivalent_regions.push_back (clicked_regionview);
3529 begin_reversible_command (_("set selected regionview"));
3533 if (clicked_regionview->get_selected()) {
3534 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3535 /* reduce selection down to just the one clicked */
3536 selection->set (clicked_regionview);
3538 selection->remove (clicked_regionview);
3541 selection->add (all_equivalent_regions);
3544 set_selected_track_from_click (add, false, no_track_remove);
3548 // karsten wiese suggested these two lines to make
3549 // a selected region rise to the top. but this
3550 // leads to a mismatch between actual layering
3551 // and visual layering. resolution required ....
3553 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3554 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3556 if (clicked_regionview->get_selected()) {
3557 /* no commit necessary: we are the one selected. */
3562 selection->set (all_equivalent_regions);
3563 set_selected_track_from_click (add, false, false);
3567 commit_reversible_command () ;
3571 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3573 vector<AudioRegionView*> all_equivalent_regions;
3574 AudioRegion* region;
3576 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3580 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3582 AudioTimeAxisView* tatv;
3584 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3587 vector<AudioRegion*> results;
3588 AudioRegionView* marv;
3591 if ((ds = tatv->get_diskstream()) == 0) {
3596 if ((pl = ds->playlist()) != 0) {
3597 pl->get_region_list_equivalent_regions (*region, results);
3600 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3601 if ((marv = tatv->view->find_view (**ir)) != 0) {
3602 all_equivalent_regions.push_back (marv);
3609 begin_reversible_command (_("set selected regions"));
3613 selection->add (all_equivalent_regions);
3617 selection->set (all_equivalent_regions);
3620 commit_reversible_command () ;
3624 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3626 AudioRegionView* rv;
3629 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3633 if ((rv = sv->find_view (*ar)) == 0) {
3637 /* don't reset the selection if its something other than
3638 a single other region.
3641 if (selection->audio_regions.size() > 1) {
3645 begin_reversible_command (_("set selected regions"));
3647 selection->set (rv);
3649 commit_reversible_command () ;
3655 Editor::set_edit_group_solo (Route& route, bool yn)
3657 RouteGroup *edit_group;
3659 if ((edit_group = route.edit_group()) != 0) {
3660 edit_group->apply (&Route::set_solo, yn, this);
3662 route.set_solo (yn, this);
3667 Editor::set_edit_group_mute (Route& route, bool yn)
3669 RouteGroup *edit_group = 0;
3671 if ((edit_group == route.edit_group()) != 0) {
3672 edit_group->apply (&Route::set_mute, yn, this);
3674 route.set_mute (yn, this);
3679 Editor::set_edit_menu (Menu& menu)
3682 edit_menu->signal_map.connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3686 Editor::edit_menu_map_handler ()
3688 using namespace Menu_Helpers;
3689 MenuList& edit_items = edit_menu->items();
3692 /* Nuke all the old items */
3694 edit_items.clear ();
3700 if (session->undo_depth() == 0) {
3703 label = string_compose(_("Undo (%1)"), session->next_undo());
3706 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3708 if (session->undo_depth() == 0) {
3709 edit_items.back().set_sensitive (false);
3712 if (session->redo_depth() == 0) {
3715 label = string_compose(_("Redo (%1)"), session->next_redo());
3718 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3719 if (session->redo_depth() == 0) {
3720 edit_items.back().set_sensitive (false);
3723 vector<MenuItem*> mitems;
3725 edit_items.push_back (SeparatorElem());
3726 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3727 mitems.push_back (&edit_items.back());
3728 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3729 mitems.push_back (&edit_items.back());
3730 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3731 mitems.push_back (&edit_items.back());
3732 edit_items.push_back (SeparatorElem());
3733 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3734 mitems.push_back (&edit_items.back());
3735 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3736 mitems.push_back (&edit_items.back());
3737 edit_items.push_back (SeparatorElem());
3739 if (selection->empty()) {
3740 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3741 (*i)->set_sensitive (false);
3745 Menu* import_menu = manage (new Menu());
3746 import_menu->set_name ("ArdourContextMenu");
3747 MenuList& import_items = import_menu->items();
3749 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3750 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3752 Menu* embed_menu = manage (new Menu());
3753 embed_menu->set_name ("ArdourContextMenu");
3754 MenuList& embed_items = embed_menu->items();
3756 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3757 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3759 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3760 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3761 edit_items.push_back (SeparatorElem());
3763 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3764 if (!session->have_captured()) {
3765 edit_items.back().set_sensitive (false);
3770 Editor::duplicate_dialog (bool dup_region)
3773 if (clicked_regionview == 0) {
3777 if (selection->time.length() == 0) {
3782 ArdourDialog win ("duplicate dialog");
3784 Label label (_("Duplicate how many times?"));
3787 Button ok_button (_("OK"));
3788 Button cancel_button (_("Cancel"));
3791 button_box.set_spacing (7);
3792 set_size_request_to_display_given_text (ok_button, _("Cancel"), 20, 15); // this is cancel on purpose
3793 set_size_request_to_display_given_text (cancel_button, _("Cancel"), 20, 15);
3794 button_box.pack_end (ok_button, false, false);
3795 button_box.pack_end (cancel_button, false, false);
3797 hbox.set_spacing (5);
3798 hbox.pack_start (label);
3799 hbox.pack_start (entry, true, true);
3801 vbox.set_spacing (5);
3802 vbox.set_border_width (5);
3803 vbox.pack_start (hbox);
3804 vbox.pack_start (button_box);
3807 win.set_position (Gtk::WIN_POS_MOUSE);
3810 ok_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3811 entry.signal_activate().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3812 cancel_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 1));
3814 entry.signal_focus_in_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_in_event));
3815 entry.signal_focus_out_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_out_event));
3817 entry.set_text ("1");
3818 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3819 entry.select_region (0, entry.get_text_length());
3821 win.set_position (Gtk::WIN_POS_MOUSE);
3824 // win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3826 entry.grab_focus ();
3830 if (win.run_status() != 0) {
3834 string text = entry.get_text();
3837 if (sscanf (text.c_str(), "%f", ×) == 1) {
3839 AudioRegionSelection regions;
3840 regions.add (clicked_regionview);
3841 duplicate_some_regions (regions, times);
3843 duplicate_selection (times);
3849 Editor::show_verbose_canvas_cursor ()
3851 verbose_canvas_cursor->raise_to_top();
3852 verbose_canvas_cursor->show();
3853 verbose_cursor_visible = true;
3857 Editor::hide_verbose_canvas_cursor ()
3859 verbose_canvas_cursor->hide();
3860 verbose_cursor_visible = false;
3864 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3866 /* XXX get origin of canvas relative to root window,
3867 add x and y and check compared to gdk_screen_{width,height}
3869 verbose_canvas_cursor->set_property("text", txt.c_str());
3870 verbose_canvas_cursor->set_property("x", x);
3871 verbose_canvas_cursor->set_property("y", y);
3875 Editor::set_verbose_canvas_cursor_text (string txt)
3877 verbose_canvas_cursor->set_property("text", txt.c_str());
3881 Editor::edit_mode_selection_done (GdkEventAny *ev)
3887 string choice = edit_mode_selector.get_active_text();
3888 EditMode mode = Slide;
3890 if (choice == _("Splice")) {
3892 } else if (choice == _("Slide")) {
3896 session->set_edit_mode (mode);
3902 Editor::snap_type_selection_done (GdkEventAny *ev)
3908 string choice = snap_type_selector.get_active_text();
3909 SnapType snaptype = SnapToFrame;
3911 if (choice == _("Beats/3")) {
3912 snaptype = SnapToAThirdBeat;
3913 } else if (choice == _("Beats/4")) {
3914 snaptype = SnapToAQuarterBeat;
3915 } else if (choice == _("Beats/8")) {
3916 snaptype = SnapToAEighthBeat;
3917 } else if (choice == _("Beats/16")) {
3918 snaptype = SnapToASixteenthBeat;
3919 } else if (choice == _("Beats/32")) {
3920 snaptype = SnapToAThirtysecondBeat;
3921 } else if (choice == _("Beats")) {
3922 snaptype = SnapToBeat;
3923 } else if (choice == _("Bars")) {
3924 snaptype = SnapToBar;
3925 } else if (choice == _("Marks")) {
3926 snaptype = SnapToMark;
3927 } else if (choice == _("Edit Cursor")) {
3928 snaptype = SnapToEditCursor;
3929 } else if (choice == _("Region starts")) {
3930 snaptype = SnapToRegionStart;
3931 } else if (choice == _("Region ends")) {
3932 snaptype = SnapToRegionEnd;
3933 } else if (choice == _("Region bounds")) {
3934 snaptype = SnapToRegionBoundary;
3935 } else if (choice == _("Region syncs")) {
3936 snaptype = SnapToRegionSync;
3937 } else if (choice == _("CD Frames")) {
3938 snaptype = SnapToCDFrame;
3939 } else if (choice == _("SMPTE Frames")) {
3940 snaptype = SnapToSMPTEFrame;
3941 } else if (choice == _("SMPTE Seconds")) {
3942 snaptype = SnapToSMPTESeconds;
3943 } else if (choice == _("SMPTE Minutes")) {
3944 snaptype = SnapToSMPTEMinutes;
3945 } else if (choice == _("Seconds")) {
3946 snaptype = SnapToSeconds;
3947 } else if (choice == _("Minutes")) {
3948 snaptype = SnapToMinutes;
3949 } else if (choice == _("None")) {
3950 snaptype = SnapToFrame;
3953 set_snap_to (snaptype);
3959 Editor::snap_mode_selection_done (GdkEventAny *ev)
3961 if(session == 0) return FALSE;
3963 string choice = snap_mode_selector.get_active_text();
3964 SnapMode mode = SnapNormal;
3966 if (choice == _("Normal")) {
3968 } else if (choice == _("Magnetic")) {
3969 mode = SnapMagnetic;
3972 set_snap_mode (mode);
3978 Editor::zoom_focus_selection_done (GdkEventAny *ev)
3984 string choice = zoom_focus_selector.get_active_text();
3985 ZoomFocus focus_type = ZoomFocusLeft;
3987 if (choice == _("Left")) {
3988 focus_type = ZoomFocusLeft;
3989 } else if (choice == _("Right")) {
3990 focus_type = ZoomFocusRight;
3991 } else if (choice == _("Center")) {
3992 focus_type = ZoomFocusCenter;
3993 } else if (choice == _("Playhead")) {
3994 focus_type = ZoomFocusPlayhead;
3995 } else if (choice == _("Edit Cursor")) {
3996 focus_type = ZoomFocusEdit;
3999 set_zoom_focus (focus_type);
4005 Editor::edit_controls_button_release (GdkEventButton* ev)
4007 if (Keyboard::is_context_menu_event (ev)) {
4008 ARDOUR_UI::instance()->add_route ();
4014 Editor::track_selection_changed ()
4016 switch (selection->tracks.size()){
4020 set_selected_mixer_strip (*(selection->tracks.front()));
4024 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4025 (*i)->set_selected (false);
4026 if (mouse_mode == MouseRange) {
4027 (*i)->hide_selection ();
4031 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4032 (*i)->set_selected (true);
4033 if (mouse_mode == MouseRange) {
4034 (*i)->show_selection (selection->time);
4040 Editor::time_selection_changed ()
4042 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4043 (*i)->hide_selection ();
4046 if (selection->tracks.empty()) {
4047 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4048 (*i)->show_selection (selection->time);
4051 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4052 (*i)->show_selection (selection->time);
4058 Editor::region_selection_changed ()
4060 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4061 (*i)->set_selected_regionviews (selection->audio_regions);
4066 Editor::point_selection_changed ()
4068 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4069 (*i)->set_selected_points (selection->points);
4074 Editor::run_sub_event_loop ()
4076 Keyboard::the_keyboard().allow_focus (true);
4077 sub_event_loop_status = 0;
4082 Editor::finish_sub_event_loop (int status)
4085 Keyboard::the_keyboard().allow_focus (false);
4086 sub_event_loop_status = status;
4090 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
4092 finish_sub_event_loop (status);
4097 Editor::mouse_select_button_release (GdkEventButton* ev)
4099 /* this handles just right-clicks */
4101 if (ev->button != 3) {
4108 Editor::TrackViewList *
4109 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
4112 TrackViewList::iterator i;
4114 v = new TrackViewList;
4116 if (track == 0 && group == 0) {
4120 for (i = track_views.begin(); i != track_views.end (); ++i) {
4124 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
4126 /* just the view for this track
4129 v->push_back (track);
4133 /* views for all tracks in the edit group */
4135 for (i = track_views.begin(); i != track_views.end (); ++i) {
4137 if (group == 0 || (*i)->edit_group() == group) {
4147 Editor::set_zoom_focus (ZoomFocus f)
4149 if (zoom_focus != f) {
4151 vector<string> txt = internationalize (zoom_focus_strings);
4152 zoom_focus_selector.set_active_text (txt[(int)f]);
4153 ZoomFocusChanged (); /* EMIT_SIGNAL */
4160 Editor::ensure_float (Window& win)
4162 win.set_transient_for (*this);
4166 Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which)
4168 /* recover or initialize pane positions. do this here rather than earlier because
4169 we don't want the positions to change the child allocations, which they seem to do.
4175 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
4177 static int32_t done[4] = { 0, 0, 0, 0 };
4180 if ((geometry = find_named_node (*node, "geometry")) == 0) {
4181 width = default_width;
4182 height = default_height;
4184 width = atoi(geometry->property("x_size")->value());
4185 height = atoi(geometry->property("y_size")->value());
4188 if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
4194 if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
4196 snprintf (buf, sizeof(buf), "%d", pos);
4198 pos = atoi (prop->value());
4201 if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gobj())->allocation.width > pos)) {
4202 track_list_canvas_pane.set_position (pos);
4205 } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
4211 if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
4212 pos = width - (95 * 2);
4213 snprintf (buf, sizeof(buf), "%d", pos);
4215 pos = atoi (prop->value());
4218 if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gobj())->allocation.width > pos)) {
4219 canvas_region_list_pane.set_position (pos);
4222 } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
4228 if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
4229 pos = width - (95 * 2);
4230 snprintf (buf, sizeof(buf), "%d", pos);
4232 pos = atoi (prop->value());
4235 if ((done[2] = GTK_WIDGET(route_group_vpane.gobj())->allocation.height > pos)) {
4236 route_group_vpane.set_position (pos);
4239 } else if (which == static_cast<Gtk::Paned*> (®ion_selection_vpane)) {
4245 if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
4246 pos = width - (95 * 2);
4247 snprintf (buf, sizeof(buf), "%d", pos);
4249 pos = atoi (prop->value());
4252 if ((done[3] = GTK_WIDGET(region_selection_vpane.gobj())->allocation.height > pos)) {
4253 region_selection_vpane.set_position (pos);
4259 Editor::detach_tearoff (Gtk::Box* b, Gtk::Window* w)
4261 if (tools_tearoff->torn_off() &&
4262 mouse_mode_tearoff->torn_off()) {
4263 top_hbox.remove (toolbar_frame);
4270 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Window* w, int32_t n)
4272 if (toolbar_frame.get_parent() == 0) {
4273 top_hbox.pack_end (toolbar_frame);
4278 Editor::set_show_measures (bool yn)
4280 if (_show_measures != yn) {
4283 if ((_show_measures = yn) == true) {
4286 DisplayControlChanged (ShowMeasures);
4292 Editor::set_follow_playhead (bool yn)
4294 if (_follow_playhead != yn) {
4295 if ((_follow_playhead = yn) == true) {
4297 update_current_screen ();
4299 DisplayControlChanged (FollowPlayhead);
4305 Editor::toggle_xfade_active (Crossfade* xfade)
4307 xfade->set_active (!xfade->active());
4311 Editor::toggle_xfade_length (Crossfade* xfade)
4313 xfade->set_follow_overlap (!xfade->following_overlap());
4317 Editor::edit_xfade (Crossfade* xfade)
4319 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
4323 cew.ok_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 1));
4324 cew.cancel_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 0));
4326 // cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
4330 if (cew.run_status() == 1) {
4332 xfade->StateChanged (Change (~0));
4337 Editor::playlist_selector () const
4339 return *_playlist_selector;
4343 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
4347 ret = nudge_clock.current_duration (pos);
4348 next = ret + 1; /* XXXX fix me */
4354 Editor::end_location_changed (Location* location)
4356 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
4357 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
4361 Editor::playlist_deletion_dialog (Playlist* pl)
4363 ArdourDialog dialog ("playlist deletion dialog");
4364 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4365 "If left alone, no audio files used by it will be cleaned.\n"
4366 "If deleted, audio files used by it alone by will cleaned."),
4369 Button del_button (_("Delete playlist"));
4370 Button keep_button (_("Keep playlist"));
4371 Button abort_button (_("Cancel cleanup"));
4374 button_box.set_spacing (7);
4375 button_box.set_homogeneous (true);
4376 button_box.pack_end (del_button, false, false);
4377 button_box.pack_end (keep_button, false, false);
4378 button_box.pack_end (abort_button, false, false);
4380 vbox.set_spacing (5);
4381 vbox.set_border_width (5);
4382 vbox.pack_start (label);
4383 vbox.pack_start (button_box);
4386 dialog.set_position (Gtk::WIN_POS_CENTER);
4389 del_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 0));
4390 keep_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 1));
4391 abort_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 2));
4394 // dialog.realize ();
4395 // dialog.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
4399 switch (dialog.run_status()) {
4401 /* keep the playlist */
4405 /* delete the playlist */
4413 /* keep the playlist */
4419 Editor::audio_region_selection_covers (jack_nframes_t where)
4421 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
4422 if ((*a)->region.covers (where)) {
4431 Editor::prepare_for_cleanup ()
4433 cut_buffer->clear_audio_regions ();
4434 cut_buffer->clear_playlists ();
4436 selection->clear_audio_regions ();
4437 selection->clear_playlists ();
4441 Editor::init_colormap ()
4443 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
4444 pair<ColorID,int> newpair;
4446 newpair.first = (ColorID) x;
4447 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
4448 color_map.insert (newpair);
4453 Editor::transport_loop_location()
4456 return session->locations()->auto_loop_location();
4463 Editor::transport_punch_location()
4466 return session->locations()->auto_punch_location();