2 Copyright (C) 2000 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include <sigc++/bind.h>
29 #include <libgnomecanvas/libgnomecanvas.h>
30 #include <pbd/error.h>
32 #include <gtkmm2ext/gtk_ui.h>
33 #include <gtkmm2ext/tearoff.h>
34 #include <gtkmm2ext/utils.h>
36 #include <ardour/audio_track.h>
37 #include <ardour/diskstream.h>
38 #include <ardour/plugin_manager.h>
39 #include <ardour/location.h>
40 #include <ardour/audioplaylist.h>
41 #include <ardour/audioregion.h>
42 #include <ardour/session.h>
43 #include <ardour/session_route.h>
44 #include <ardour/tempo.h>
45 #include <ardour/utils.h>
47 #include "ardour_ui.h"
48 #include "canvas-ruler.h"
49 #include "canvas-simpleline.h"
50 #include "canvas-simplerect.h"
51 #include "canvas-waveview.h"
52 #include "check_mark.h"
54 #include "grouped_buttons.h"
57 #include "playlist_selector.h"
58 #include "regionview.h"
59 #include "rgb_macros.h"
60 #include "selection.h"
61 #include "streamview.h"
62 #include "time_axis_view.h"
64 #include "crossfade_view.h"
66 #include "public_editor.h"
67 #include "crossfade_edit.h"
68 #include "audio_time_axis.h"
69 #include "gui_thread.h"
74 #include "imageframe_socket_handler.h"
75 /* </CMT Additions> */
79 using namespace ARDOUR;
81 using namespace Gtkmm2ext;
82 using namespace Editing;
84 /* XXX this is a hack. it ought to be the maximum value of an jack_nframes_t */
86 const double max_canvas_coordinate = 100000000.0;
87 const double Editor::timebar_height = 15.0;
89 #include "editor_xpms"
91 static const gchar *route_list_titles[] = {
96 static const gchar *edit_group_list_titles[] = {
100 static const gchar *named_selection_display_titles[] = {
105 static const int32_t slide_index = 0;
106 static const int32_t splice_index = 1;
108 static const gchar *edit_mode_strings[] = {
114 static const gchar *snap_type_strings[] = {
138 static const gchar *snap_mode_strings[] = {
144 static const gchar *zoom_focus_strings[] = {
153 /* Soundfile drag-n-drop */
161 static GtkTargetEntry target_table[] = {
162 { "STRING", 0, TARGET_STRING },
163 { "text/plain", 0, TARGET_STRING },
164 { "text/uri-list", 0, TARGET_URL },
165 { "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
168 static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
170 Gdk::Cursor* Editor::cross_hair_cursor = 0;
171 Gdk::Cursor* Editor::selector_cursor = 0;
172 Gdk::Cursor* Editor::trimmer_cursor = 0;
173 Gdk::Cursor* Editor::grabber_cursor = 0;
174 Gdk::Cursor* Editor::zoom_cursor = 0;
175 Gdk::Cursor* Editor::time_fx_cursor = 0;
176 Gdk::Cursor* Editor::fader_cursor = 0;
177 Gdk::Cursor* Editor::speaker_cursor = 0;
178 Gdk::Cursor* Editor::null_cursor = 0;
179 Gdk::Cursor* Editor::wait_cursor = 0;
180 Gdk::Cursor* Editor::timebar_cursor = 0;
182 GdkPixmap *Editor::check_pixmap = 0;
183 GdkBitmap *Editor::check_mask = 0;
184 GdkPixmap *Editor::empty_pixmap = 0;
185 GdkBitmap *Editor::empty_mask = 0;
187 Editor::Editor (AudioEngine& eng)
190 /* time display buttons */
192 minsec_label (_("Mins:Secs")),
193 bbt_label (_("Bars:Beats")),
194 smpte_label (_("SMPTE")),
195 frame_label (_("Frames")),
196 tempo_label (_("Tempo")),
197 meter_label (_("Meter")),
198 mark_label (_("Location Markers")),
199 range_mark_label (_("Range Markers")),
200 transport_mark_label (_("Loop/Punch Ranges")),
202 edit_packer (3, 3, false),
203 edit_hscroll_left_arrow (Gtk::ARROW_LEFT, Gtk::SHADOW_OUT),
204 edit_hscroll_right_arrow (Gtk::ARROW_RIGHT, Gtk::SHADOW_OUT),
206 named_selection_display (internationalize (named_selection_display_titles)),
208 /* tool bar related */
210 editor_mixer_button (_("editor\nmixer")),
212 selection_start_clock (X_("SelectionStartClock"), true),
213 selection_end_clock (X_("SelectionEndClock"), true),
214 edit_cursor_clock (X_("EditCursorClock"), true),
215 zoom_range_clock (X_("ZoomRangeClock"), true, true),
217 toolbar_selection_clock_table (2,3),
219 mouse_mode_button_table (2, 3),
221 mouse_select_button (_("range")),
222 mouse_move_button (_("object")),
223 mouse_gain_button (_("gain")),
224 mouse_zoom_button (_("zoom")),
225 mouse_timefx_button (_("timefx")),
226 mouse_audition_button (_("listen")),
228 automation_mode_button (_("mode")),
229 global_automation_button (_("automation")),
231 edit_mode_label (_("Edit Mode")),
232 snap_type_label (_("Snap To")),
233 snap_mode_label(_("Snap Mode")),
234 zoom_focus_label (_("Zoom Focus")),
236 /* <CMT Additions> */
237 image_socket_listener(0),
238 /* </CMT Additions> */
242 nudge_label (_("Nudge")),
243 nudge_clock (X_("NudgeClock"), true, true)
248 /* we are a singleton */
250 PublicEditor::_instance = this;
254 check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
255 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
256 &check_mask, NULL, (gchar **) check_xpm);
257 empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
258 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
259 &empty_mask, NULL, (gchar **) empty_xpm);
263 selection = new Selection;
264 cut_buffer = new Selection;
266 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
267 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
268 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
269 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
271 clicked_regionview = 0;
272 clicked_trackview = 0;
273 clicked_audio_trackview = 0;
274 clicked_crossfadeview = 0;
275 clicked_control_point = 0;
276 latest_regionview = 0;
277 last_update_frame = 0;
279 last_audition_region = 0;
280 current_mixer_strip = 0;
281 current_bbt_points = 0;
283 snap_type = SnapToFrame;
284 set_snap_to (snap_type);
285 snap_mode = SnapNormal;
286 set_snap_mode (snap_mode);
287 snap_threshold = 5.0;
288 bbt_beat_subdivision = 4;
291 autoscroll_timeout_tag = -1;
292 interthread_progress_window = 0;
293 current_interthread_info = 0;
294 _show_measures = true;
295 _show_waveforms = true;
296 _show_waveforms_recording = true;
297 first_action_message = 0;
299 show_gain_after_trim = false;
300 no_zoom_repos_update = false;
301 ignore_route_list_reorder = false;
302 verbose_cursor_on = true;
303 route_removal = false;
305 show_automatic_regions_in_region_list = true;
306 have_pending_keyboard_selection = false;
307 _follow_playhead = true;
308 _xfade_visibility = true;
309 editor_ruler_menu = 0;
310 no_ruler_shown_update = false;
311 edit_group_list_menu = 0;
313 region_list_menu = 0;
315 marker_menu_item = 0;
317 transport_marker_menu = 0;
318 new_transport_marker_menu = 0;
319 editor_mixer_strip_width = Wide;
320 repos_zoom_queued = false;
321 import_audio_item = 0;
322 embed_audio_item = 0;
323 region_edit_menu_split_item = 0;
325 region_edit_menu_split_multichannel_item = 0;
326 edit_hscroll_dragging = false;
328 ignore_mouse_mode_toggle = false;
329 current_stepping_trackview = 0;
331 entered_regionview = 0;
332 clear_entered_track = false;
333 _new_regionviews_show_envelope = false;
334 current_timestretch = 0;
339 location_marker_color = color_map[cLocationMarker];
340 location_range_color = color_map[cLocationRange];
341 location_cd_marker_color = color_map[cLocationCDMarker];
342 location_loop_color = color_map[cLocationLoop];
343 location_punch_color = color_map[cLocationPunch];
345 range_marker_drag_rect = 0;
346 marker_drag_line = 0;
348 mouse_mode = MouseZoom; /* force change in next call */
349 set_mouse_mode (MouseObject, true);
351 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
352 zoom_focus = ZoomFocusLeft;
353 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
355 initialize_rulers ();
356 initialize_canvas ();
358 track_canvas_scroller.add (track_canvas);
359 track_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
360 track_canvas_scroller.set_name ("TrackCanvasScroller");
362 track_canvas_scroller.get_vadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
363 track_canvas_scroller.get_vadjustment()->set_step_increment (10.0);
365 track_canvas_scroller.get_hadjustment()->set_lower (0.0);
366 track_canvas_scroller.get_hadjustment()->set_upper (1200.0);
367 track_canvas_scroller.get_hadjustment()->set_step_increment (20.0);
368 track_canvas_scroller.get_hadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
370 edit_vscrollbar.set_adjustment(*track_canvas_scroller.get_vadjustment());
371 edit_hscrollbar.set_adjustment(*track_canvas_scroller.get_hadjustment());
373 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_press));
374 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_release));
375 edit_hscrollbar.size_allocate.connect (mem_fun(*this, &Editor::hscroll_slider_allocate));
377 time_canvas_scroller.add (time_canvas);
378 time_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
379 time_canvas_scroller.set_hadjustment (*track_canvas_scroller.get_hadjustment());
380 time_canvas_scroller.set_name ("TimeCanvasScroller");
382 edit_controls_vbox.set_spacing (track_spacing);
383 edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
384 edit_controls_scroller.add (edit_controls_hbox);
385 edit_controls_scroller.set_name ("EditControlsBase");
386 edit_controls_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
388 Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
390 viewport->set_shadow_type (Gtk::SHADOW_NONE);
391 viewport->set_name ("EditControlsBase");
392 viewport->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
393 viewport->signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
398 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
401 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
403 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
404 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
405 time_canvas_vbox.pack_start (*frames_ruler, false, false);
406 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
407 time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
408 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
410 bbt_label.set_name ("EditorTimeButton");
411 bbt_label.set_size_request (-1, (int)timebar_height);
412 bbt_label.set_alignment (1.0, 0.5);
413 bbt_label.set_padding (5,0);
414 minsec_label.set_name ("EditorTimeButton");
415 minsec_label.set_size_request (-1, (int)timebar_height);
416 minsec_label.set_alignment (1.0, 0.5);
417 minsec_label.set_padding (5,0);
418 smpte_label.set_name ("EditorTimeButton");
419 smpte_label.set_size_request (-1, (int)timebar_height);
420 smpte_label.set_alignment (1.0, 0.5);
421 smpte_label.set_padding (5,0);
422 frame_label.set_name ("EditorTimeButton");
423 frame_label.set_size_request (-1, (int)timebar_height);
424 frame_label.set_alignment (1.0, 0.5);
425 frame_label.set_padding (5,0);
426 tempo_label.set_name ("EditorTimeButton");
427 tempo_label.set_size_request (-1, (int)timebar_height);
428 tempo_label.set_alignment (1.0, 0.5);
429 tempo_label.set_padding (5,0);
430 meter_label.set_name ("EditorTimeButton");
431 meter_label.set_size_request (-1, (int)timebar_height);
432 meter_label.set_alignment (1.0, 0.5);
433 meter_label.set_padding (5,0);
434 mark_label.set_name ("EditorTimeButton");
435 mark_label.set_size_request (-1, (int)timebar_height);
436 mark_label.set_alignment (1.0, 0.5);
437 mark_label.set_padding (5,0);
438 range_mark_label.set_name ("EditorTimeButton");
439 range_mark_label.set_size_request (-1, (int)timebar_height);
440 range_mark_label.set_alignment (1.0, 0.5);
441 range_mark_label.set_padding (5,0);
442 transport_mark_label.set_name ("EditorTimeButton");
443 transport_mark_label.set_size_request (-1, (int)timebar_height);
444 transport_mark_label.set_alignment (1.0, 0.5);
445 transport_mark_label.set_padding (5,0);
447 time_button_vbox.pack_start (minsec_label, false, false);
448 time_button_vbox.pack_start (smpte_label, false, false);
449 time_button_vbox.pack_start (frame_label, false, false);
450 time_button_vbox.pack_start (bbt_label, false, false);
451 time_button_vbox.pack_start (meter_label, false, false);
452 time_button_vbox.pack_start (tempo_label, false, false);
453 time_button_vbox.pack_start (mark_label, false, false);
455 time_button_event_box.add (time_button_vbox);
457 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
458 time_button_event_box.set_name ("TimebarLabelBase");
459 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
461 /* these enable us to have a dedicated window (for cursor setting, etc.)
462 for the canvas areas.
465 track_canvas_event_box.add (track_canvas_scroller);
467 time_canvas_event_box.add (time_canvas_vbox);
468 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
471 edit_packer.set_col_spacings (0);
472 edit_packer.set_row_spacings (0);
473 edit_packer.set_homogeneous (false);
474 edit_packer.set_name ("EditorWindow");
476 // edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, Gtk::FILL, 0, 0, 0);
477 // edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, 0, 0, 0);
478 // edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, Gtk::FILL, 0, 0, 0);
479 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
481 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
482 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
484 edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
485 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
486 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
488 edit_frame.set_name ("BaseFrame");
489 edit_frame.set_shadow_type (SHADOW_IN);
490 edit_frame.add (edit_packer);
492 zoom_in_button.set_name ("EditorTimeButton");
493 zoom_out_button.set_name ("EditorTimeButton");
494 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
495 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
497 // zoom_onetoone_button.set_name ("EditorTimeButton");
498 zoom_out_full_button.set_name ("EditorTimeButton");
499 // ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1"));
500 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
502 zoom_in_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_in_button_xpm)))));
503 zoom_out_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_button_xpm)))));
504 zoom_out_full_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_full_button_xpm)))));
505 // zoom_onetoone_button.add (*(manage (new Gtk::Image (zoom_onetoone_button_xpm))));
508 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
509 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
510 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
511 // zoom_onetoone_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom), 1.0));
513 zoom_indicator_box.pack_start (zoom_out_button, false, false);
514 zoom_indicator_box.pack_start (zoom_in_button, false, false);
515 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
516 // zoom_indicator_box.pack_start (zoom_onetoone_button, false, false);
517 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
519 zoom_indicator_label.set_text (_("Zoom Span"));
520 zoom_indicator_label.set_name ("ToolBarLabel");
523 zoom_indicator_vbox.set_spacing (3);
524 zoom_indicator_vbox.set_border_width (3);
525 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
526 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
529 bottom_hbox.set_border_width (3);
530 bottom_hbox.set_spacing (3);
532 route_display_model = ListStore::create(route_display_columns);
533 route_list.set_model (route_display_model);
534 route_list.append_column (_("Tracks"), route_display_columns.text);
535 route_list.set_name ("TrackListDisplay");
536 route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
537 route_list.set_reorderable (true);
539 route_list.set_size_request (75,-1);
540 route_list.set_headers_visible (true);
541 route_list.set_headers_clickable (true);
543 route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func));
545 //route_list.set_shadow_type (Gtk::SHADOW_IN);
547 route_list_scroller.add (route_list);
548 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
550 route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed));
551 route_list.rows_reordered.connect (mem_fun (*this, &Editor::queue_route_list_reordered));
552 route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click));
554 edit_group_list_button_label.set_text (_("Edit Groups"));
555 edit_group_list_button_label.set_name ("EditGroupTitleButton");
556 edit_group_list_button.add (edit_group_list_button_label);
557 edit_group_list_button.set_name ("EditGroupTitleButton");
559 group_model = ListStore::create(group_columns);
560 edit_group_list.set_model (group_model);
561 edit_group_list.append_column (_("active"), group_columns.is_active);
562 edit_group_list.append_column (_("groupname"), group_columns.text);
563 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
564 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
566 /* use checkbox for the active column */
568 CellRendererToggle *active_cell = dynamic_cast<CellRendererToggle*>(edit_group_list.get_column_cell_renderer (0));
569 active_cell->set_property ("activatable", true);
570 active_cell->set_property ("radio", false);
572 edit_group_list.set_name ("MixerGroupList");
573 //edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
574 route_list.set_headers_visible (false);
575 edit_group_list.set_reorderable (false);
576 edit_group_list.set_size_request (75, -1);
577 edit_group_list.columns_autosize ();
578 edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
580 edit_group_list_scroller.add (edit_group_list);
581 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
583 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
584 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
585 edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed));
587 TreeModel::Row row = *(group_model->append());
588 row[group_columns.is_active] = false;
589 row[group_columns.text] = (_("-all-"));
590 edit_group_list.get_selection()->select (row);
591 /* GTK2FIX is set_data(0) setting the is_active to false here?
592 list<string> stupid_list;
594 stupid_list.push_back ("*");
595 stupid_list.push_back (_("-all-"));
597 edit_group_list.rows().push_back (stupid_list);
598 edit_group_list.rows().back().set_data (0);
599 edit_group_list.rows().back().select();
602 edit_group_vbox.pack_start (edit_group_list_button, false, false);
603 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
605 route_list_frame.set_name ("BaseFrame");
606 route_list_frame.set_shadow_type (Gtk::SHADOW_IN);
607 route_list_frame.add (route_list_scroller);
609 edit_group_list_frame.set_name ("BaseFrame");
610 edit_group_list_frame.set_shadow_type (Gtk::SHADOW_IN);
611 edit_group_list_frame.add (edit_group_vbox);
613 route_group_vpane.add1 (route_list_frame);
614 route_group_vpane.add2 (edit_group_list_frame);
616 list_vpacker.pack_start (route_group_vpane, true, true);
618 region_list_model = TreeStore::create (region_list_columns);
619 region_list_sort_model = TreeModelSort::create (region_list_model);
620 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
622 region_list_display.set_model (region_list_sort_model);
623 region_list_display.append_column (_("Regions"), region_list_columns.name);
624 region_list_display.set_reorderable (true);
625 region_list_display.set_size_request (100, -1);
626 region_list_display.set_data ("editor", this);
627 region_list_display.set_flags (Gtk::CAN_FOCUS);
628 region_list_display.set_name ("RegionListDisplay");
630 region_list_scroller.add (region_list_display);
631 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
633 region_list_display.drag_dest_set (GTK_DEST_DEFAULT_ALL,
634 target_table, n_targets - 1,
635 GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
636 region_list_display.drag_data_received.connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
638 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
639 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
640 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
641 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
642 region_list_display.signal_motion_notify_event().connect (mem_fun(*this, &Editor::region_list_display_motion));
643 region_list_display.signal_enter_notify_event().connect (mem_fun(*this, &Editor::region_list_display_enter_notify));
644 region_list_display.signal_leave_notify_event().connect (mem_fun(*this, &Editor::region_list_display_leave_notify));
645 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
646 //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
647 region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click));
649 named_selection_scroller.add (named_selection_display);
650 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
652 named_selection_model = TreeStore::create (named_selection_columns);
653 named_selection_display.set_model (named_selection_model);
654 named_selection_display.set_name ("RegionListDisplay");
655 named_selection_display.set_size_request (100, -1);
656 named_selection_display.set_headers_visible (true);
657 named_selection_display.set_headers_clickable (true);
658 named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
659 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
660 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
662 region_selection_vpane.pack1 (region_list_scroller, true, true);
663 region_selection_vpane.pack2 (named_selection_scroller, true, true);
665 canvas_region_list_pane.pack1 (edit_frame, true, true);
666 canvas_region_list_pane.pack2 (region_selection_vpane, true, true);
668 track_list_canvas_pane.size_allocate.connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
669 static_cast<Gtk::Paned*> (&track_list_canvas_pane)));
670 canvas_region_list_pane.size_allocate.connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
671 static_cast<Gtk::Paned*> (&canvas_region_list_pane)));
672 route_group_vpane.size_allocate.connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
673 static_cast<Gtk::Paned*> (&route_group_vpane)));
674 region_selection_vpane.size_allocate.connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
675 static_cast<Gtk::Paned*> (®ion_selection_vpane)));
677 track_list_canvas_pane.pack1 (list_vpacker, true, true);
678 track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true);
680 /* provide special pane-handle event handling for easy "hide" action */
682 /* 0: collapse to show left/upper child
683 1: collapse to show right/lower child
686 route_group_vpane.set_data ("collapse-direction", (gpointer) 0);
687 region_selection_vpane.set_data ("collapse-direction", (gpointer) 0);
688 canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0);
689 track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1);
691 route_group_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&route_group_vpane)));
692 region_selection_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (®ion_selection_vpane)));
693 canvas_region_list_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&canvas_region_list_pane)));
694 track_list_canvas_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&track_list_canvas_pane)));
696 top_hbox.pack_start (toolbar_frame, true, true);
698 HBox *hbox = manage (new HBox);
699 hbox->pack_start (track_list_canvas_pane, true, true);
701 global_vpacker.pack_start (top_hbox, false, false);
702 global_vpacker.pack_start (*hbox, true, true);
704 global_hpacker.pack_start (global_vpacker, true, true);
706 set_name ("EditorWindow");
708 vpacker.pack_end (global_hpacker, true, true);
710 _playlist_selector = new PlaylistSelector();
711 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
713 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
717 nudge_forward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
718 nudge_backward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
720 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
721 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
723 nudge_forward_button.set_name ("TransportButton");
724 nudge_backward_button.set_name ("TransportButton");
726 fade_context_menu.set_name ("ArdourContextMenu");
728 install_keybindings ();
730 set_title (_("ardour: editor"));
731 set_wmclass (_("ardour_editor"), "Ardour");
734 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
736 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
737 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
745 /* <CMT Additions> */
746 if(image_socket_listener)
748 if(image_socket_listener->is_connected())
750 image_socket_listener->close_connection() ;
753 delete image_socket_listener ;
754 image_socket_listener = 0 ;
756 /* </CMT Additions> */
760 Editor::add_toplevel_controls (Container& cont)
762 vpacker.pack_start (cont, false, false);
767 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
769 /* note: the selection will take care of the vanishing
770 audioregionview by itself.
773 if (clicked_regionview == rv) {
774 clicked_regionview = 0;
777 if (entered_regionview == rv) {
778 set_entered_regionview (0);
783 Editor::set_entered_regionview (AudioRegionView* rv)
785 if (rv == entered_regionview) {
789 if (entered_regionview) {
790 entered_regionview->exited ();
793 if ((entered_regionview = rv) != 0) {
794 entered_regionview->entered ();
799 Editor::set_entered_track (TimeAxisView* tav)
802 entered_track->exited ();
805 if ((entered_track = tav) != 0) {
806 entered_track->entered ();
811 Editor::left_track_canvas (GdkEventCrossing *ev)
813 set_entered_track (0);
814 set_entered_regionview (0);
820 Editor::initialize_canvas ()
822 gnome_canvas_init ();
824 /* adjust sensitivity for "picking" items */
826 // GNOME_CANVAS(track_canvas)->close_enough = 2;
828 track_canvas.signal_event().connect (mem_fun (*this, &Editor::track_canvas_event));
829 track_canvas.set_name ("EditorMainCanvas");
830 track_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
831 track_canvas.signal_event().connect (mem_fun (*this, &Editor::track_canvas_event));
832 track_canvas.signal_leave_notify_event().connect (mem_fun(*this, &Editor::left_track_canvas));
834 /* set up drag-n-drop */
836 track_canvas.drag_dest_set (GTK_DEST_DEFAULT_ALL,
837 target_table, n_targets - 1,
838 GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
839 track_canvas.drag_data_received.connect (mem_fun(*this, &Editor::track_canvas_drag_data_received));
841 /* stuff for the verbose canvas cursor */
843 Pango::FontDescription font = get_font_for_style (N_("VerboseCanvasCursor"));
845 verbose_canvas_cursor = new Gnome::Canvas::Text (*track_canvas.root());
846 verbose_canvas_cursor->set_property ("font_desc", font);
847 verbose_canvas_cursor->set_property ("anchor", GTK_ANCHOR_NW);
848 verbose_canvas_cursor->set_property ("fill_color_rgba", color_map[cVerboseCanvasCursor]);
850 verbose_cursor_visible = false;
852 /* a group to hold time (measure) lines */
854 time_line_group = new Gnome::Canvas::Group (*track_canvas.root(), 0.0, 0.0);
855 cursor_group = new Gnome::Canvas::Group (*track_canvas.root(), 0.0, 0.0);
857 time_canvas.set_name ("EditorTimeCanvas");
858 time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
860 meter_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, 0.0);
861 tempo_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, 0.0);
862 marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 2.0);
863 range_marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 3.0);
864 transport_marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 4.0);
866 tempo_bar = new Gnome::Canvas::SimpleRect (*tempo_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
867 tempo_bar->set_property ("fill_color_rgba", color_map[cTempoBar]);
868 tempo_bar->set_property ("outline_pixels", 0);
870 meter_bar = new Gnome::Canvas::SimpleRect (*meter_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
871 meter_bar->set_property ("fill_color_rgba", color_map[cMeterBar]);
872 meter_bar->set_property ("outline_pixels",0);
874 marker_bar = new Gnome::Canvas::SimpleRect (*marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
875 marker_bar->set_property ("fill_color_rgba", color_map[cMarkerBar]);
876 marker_bar->set_property ("outline_pixels", 0);
878 range_marker_bar = new Gnome::Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
879 range_marker_bar->set_property ("fill_color_rgba", color_map[cRangeMarkerBar]);
880 range_marker_bar->set_property ("outline_pixels", 0);
882 transport_marker_bar = new Gnome::Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
883 transport_marker_bar->set_property ("fill_color_rgba", color_map[cTransportMarkerBar]);
884 transport_marker_bar->set_property ("outline_pixels", 0);
886 range_bar_drag_rect = new Gnome::Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
887 range_bar_drag_rect->set_property ("fill_color_rgba", color_map[cRangeBarDragRectFill]);
888 range_bar_drag_rect->set_property ("outline_color_rgba", color_map[cRangeBarDragRect]);
889 range_bar_drag_rect->set_property ("outline_pixels", 0);
890 range_bar_drag_rect->hide ();
892 transport_bar_drag_rect = new Gnome::Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
893 transport_bar_drag_rect ->set_property ("fill_color_rgba", color_map[cTransportBarDragRectFill]);
894 transport_bar_drag_rect->set_property ("outline_color_rgba", color_map[cTransportBarDragRect]);
895 transport_bar_drag_rect->set_property ("outline_pixels", 0);
896 transport_bar_drag_rect->hide ();
898 marker_drag_line_points = new Gnome::Canvas::Points (2);
899 marker_drag_line_points[0]->set_x (0.0);
900 marker_drag_line_points[0]->set_y (0.0);
901 marker_drag_line_points[1]->set_x (0.0);
902 marker_drag_line_points[1]->set_y (0.0);
904 marker_drag_line = new Gnome::Canvas::Line (*track_canvas.root());
905 marker_drag_line->set_property ("width_pixels", 1);
906 marker_drag_line->set_property("fill_color_rgba", color_map[cMarkerDragLine]);
907 marker_drag_line->set_property("points", marker_drag_line_points);
908 marker_drag_line->hide();
910 range_marker_drag_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
911 range_marker_drag_rect->set_property ("fill_color_rgba", color_map[cRangeDragRectFill]);
912 range_marker_drag_rect->set_property ("outline_color_rgba", color_map[cRangeDragRect]);
913 range_marker_drag_rect->hide ();
915 transport_loop_range_rect = new Gnome::Canvas::SimpleRect (group.root(), 0.0, 0.0, 0.0, 0.0);
916 transport_loop_range_rect->set_property ("fill_color_rgba", color_map[cTransportLoopRectFill]);
917 transport_loop_range_rect->set_property ("outline_color_rgba", color_map[cTransportLoopRect]);
918 transport_loop_range_rect->set_property ("outline_pixels", 1);
919 transport_loop_range_rect->hide();
921 transport_punch_range_rect = new Gnome::Canvas::SimpleRect (group.root(), 0.0, 0.0, 0.0, 0.0);
922 transport_punch_range_rect->set_property ("fill_color_rgba", color_map[cTransportPunchRectFill]);
923 transport_punch_range_rect->set_property ("outline_color_rgba", color_map[cTransportPunchRect]);
924 transport_punch_range_rect->set_property ("outline_pixels", 0);
925 transport_punch_range_rect->hide();
927 transport_loop_range_rect->lower_to_bottom (); // loop on the bottom
929 transport_punchin_line = new Gnome::Canvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
930 transport_punchin_line->set_property ("outline_color_rgba", color_map[cPunchInLine]);
931 transport_punchin_line->set_property ("outline_pixels", 1);
932 transport_punchin_line->hide ();
934 transport_punchout_line = new Gnome::Canvas::SimpleRect (group.root(), 0.0, 0.0, 0.0, 0.0);
935 transport_punchout_line->set_property ("outline_color_rgba", color_map[cPunchOutLine]);
936 transport_punchout_line->set_property ("outline_pixels", 1);
937 transport_punchout_line->hide();
939 // used to show zoom mode active zooming
940 zoom_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
941 zoom_rect->set_property ("fill_color_rgba", color_map[cZoomRectFill]);
942 zoom_rect->set_property ("outline_color_rgba", color_map[cZoomRect]);
943 zoom_rect->set_property ("outline_pixels", 1);
946 zoom_rect->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_zoom_rect_event));
948 // used as rubberband rect
949 rubberband_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
950 rubberband_rect->set_property ("outline_color_rgba", color_map[cRubberBandRect]);
951 rubberband_rect->set_property ("fill_color_rgba", (guint32) color_map[cRubberBandRectFill]);
952 rubberband_rect->set_property ("outline_pixels", 1);
953 rubberband_rect->hide();
955 tempo_bar->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_tempo_bar_event));
956 meter_bar->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_meter_bar_event));
957 marker_bar->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_marker_bar_event));
958 range_marker_bar->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_range_marker_bar_event));
959 transport_marker_bar->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_transport_marker_bar_event));
961 /* separator lines */
963 tempo_line_points = new Gnome::Canvas::Points (2);
964 tempo_line_points[0]->set_x (0.0);
965 tempo_line_points[0]->set_y (timebar_height);
966 tempo_line_points[1]->set_x (max_canvas_coordinate);
967 tempo_line_points[1]->set_y (timebar_height);
969 tempo_line = new Gnome::Canvas::Line (*tempo_group, *tempo_line_points);
970 tempo_line->set_property ("width_pixels", 0);
971 tempo_line->set_property ("fill_color", black);
973 meter_line_points = new Gnome::Canvas::Points (2);
974 meter_line_points[0]->set_x (0);
975 meter_line_points[0]->set_y (timebar_height);
976 meter_line_points[1]->set_x (max_canvas_coordinate);
977 meter_line_points[1]->set_y (timebar_height);
979 meter_line = new Gnome::Canvas::Line (*meter_group, *meter_line_points);
980 meter_line->set_property ("width_pixels", 0);
981 meter_line->set_property ("fill_color", black);
983 marker_line_points = new Gnome::Canvas::Points (2);
984 marker_line_points[0]->set_x (0);
985 marker_line_points[0]->set_y (timebar_height);
986 marker_line_points[1]->set_x (max_canvas_coordinate);
987 marker_line_points[1]->set_y (timebar_height);
989 marker_line = new Gnome::Canvas::Line (*marker_group, *marker_line_points);
990 marker_line->set_property ("width_pixels", 0);
991 marker_line->set_property ("fill_color", black);
993 range_marker_line = new Gnome::Canvas::Line (*range_marker_group, *marker_line_points);
994 range_marker_line->set_property ("width_pixels", 0);
995 range_marker_line->set_property ("fill_color", black);
997 transport_marker_line = new Gnome::Canvas::Line (*transport_marker_group, *marker_line_points);
998 transport_marker_line->set_property ("width_pixels", 0);
999 transport_marker_line->set_property ("fill_color", black);
1001 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_loop_range_view), false));
1002 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_punch_range_view), false));
1004 double time_height = timebar_height * 5;
1005 double time_width = FLT_MAX/frames_per_unit;
1006 time_canvas.set_scroll_region(0.0, 0.0, time_width, time_height);
1008 edit_cursor = new Cursor (*this, "blue", (GtkSignalFunc) _canvas_edit_cursor_event);
1009 playhead_cursor = new Cursor (*this, "red", (GtkSignalFunc) _canvas_playhead_cursor_event);
1011 track_canvas.size_allocate.connect (mem_fun(*this, &Editor::track_canvas_allocate));
1015 Editor::show_window ()
1019 /* now reset all audio_time_axis heights, because widgets might need
1025 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1026 tv = (static_cast<TimeAxisView*>(*i));
1027 tv->reset_height ();
1032 Editor::tie_vertical_scrolling ()
1034 edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
1036 float y1 = track_canvas_scroller.get_vadjustment()->get_value();
1037 playhead_cursor->set_y_axis(y1);
1038 edit_cursor->set_y_axis(y1);
1042 Editor::set_frames_per_unit (double fpu)
1044 jack_nframes_t frames;
1046 if (fpu == frames_per_unit) {
1054 // convert fpu to frame count
1056 frames = (jack_nframes_t) (fpu * canvas_width);
1058 /* don't allow zooms that fit more than the maximum number
1059 of frames into an 800 pixel wide space.
1062 if (max_frames / fpu < 800.0) {
1066 frames_per_unit = fpu;
1068 if (frames != zoom_range_clock.current_duration()) {
1069 zoom_range_clock.set (frames);
1072 /* only update these if we not about to call reposition_x_origin,
1073 which will do the same updates.
1077 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1080 if (!no_zoom_repos_update) {
1081 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1082 update_hscroller ();
1083 update_fixed_rulers ();
1084 tempo_map_changed (Change (0));
1087 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
1088 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1089 (*i)->reshow_selection (selection->time);
1093 ZoomChanged (); /* EMIT_SIGNAL */
1095 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
1096 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
1103 Editor::instant_save ()
1105 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
1110 session->add_instant_xml(get_state(), session->path());
1112 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
1117 Editor::reposition_x_origin (jack_nframes_t frame)
1119 if (frame != leftmost_frame) {
1120 leftmost_frame = frame;
1121 double pixel = frame_to_pixel (frame);
1122 if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
1123 track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
1125 track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
1126 XOriginChanged (); /* EMIT_SIGNAL */
1131 Editor::edit_cursor_clock_changed()
1133 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
1134 edit_cursor->set_position (edit_cursor_clock.current_time());
1140 Editor::zoom_adjustment_changed ()
1142 if (session == 0 || no_zoom_repos_update) {
1146 double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width;
1150 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1152 else if (fpu > session->current_end_frame() / (double) canvas_width) {
1153 fpu = session->current_end_frame() / (double) canvas_width;
1154 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1157 temporal_zoom (fpu);
1161 Editor::canvas_horizontally_scrolled ()
1163 /* XXX note the potential loss of accuracy here caused by
1164 adjustments being 32bit floats with only a 24 bit mantissa,
1165 whereas jack_nframes_t is at least a 32 bit uint32_teger.
1168 leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
1170 update_hscroller ();
1171 update_fixed_rulers ();
1173 if (!edit_hscroll_dragging) {
1174 tempo_map_changed (Change (0));
1176 update_tempo_based_rulers();
1181 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
1183 if (!repos_zoom_queued) {
1184 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
1185 repos_zoom_queued = true;
1190 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
1192 /* if we need to force an update to the hscroller stuff,
1193 don't set no_zoom_repos_update.
1196 no_zoom_repos_update = (frame != leftmost_frame);
1198 set_frames_per_unit (nfpu);
1199 if (no_zoom_repos_update) {
1200 reposition_x_origin (frame);
1202 no_zoom_repos_update = false;
1203 repos_zoom_queued = false;
1209 Editor::on_realize ()
1211 /* Even though we're not using acceleration, we want the
1214 Glib::RefPtr<Gdk::Pixmap> empty_pixmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1215 Glib::RefPtr<Gdk::Pixmap> empty_bitmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1218 track_context_menu.accelerate (*this->get_toplevel());
1219 track_region_context_menu.accelerate (*this->get_toplevel());
1221 Window::on_realize ();
1223 Gdk::Color white ("#ffffff" );
1224 null_cursor = new Gdk::Cursor(empty_pixmap, empty_bitmap, white, white, 0, 0);
1232 track_canvas_scroller.get_window()->set_cursor (*current_canvas_cursor);
1233 time_canvas_scroller.get_window()->set_cursor (*timebar_cursor);
1237 Editor::track_canvas_allocate (GtkAllocation *alloc)
1239 canvas_width = alloc->width;
1240 canvas_height = alloc->height;
1242 if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) {
1244 Pango::FontDescription font = get_font_for_style (N_("FirstActionMessage"));
1246 const char *txt1 = _("Start a new session\n");
1247 const char *txt2 = _("via Session menu");
1249 /* this mess of code is here to find out how wide this text is and
1250 position the message in the center of the editor window. there
1251 are two lines, so we use the longer of the the lines to
1252 compute width, and multiply the height by 2.
1258 /* this is a dummy widget that exists so that we can get the
1259 style from the RC file.
1262 Label foo (_(txt2));
1263 Glib::RefPtr<Pango::Layout> layout;
1264 foo.set_name ("NoSessionMessage");
1265 foo.ensure_style ();
1267 layout = foo.create_pango_layout (_(txt2));
1268 layout->set_font_description (font);
1269 layout->get_pixel_size (pixel_width, pixel_height);
1271 if (first_action_message == 0) {
1273 char txt[strlen(txt1)+strlen(txt2)+1];
1275 /* merge both lines */
1277 strcpy (txt, _(txt1));
1278 strcat (txt, _(txt2));
1280 first_action_message = gnome_canvas_item_new (gnome_canvas_root(GNOME_CANVAS(track_canvas)),
1281 gnome_canvas_text_get_type(),
1283 "fill_color_rgba", color_map[cFirstActionMessage],
1284 "x", (gdouble) (canvas_width - pixel_width) / 2.0,
1285 "y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)),
1286 "anchor", GTK_ANCHOR_NORTH_WEST,
1293 first_action_message->set_property ("x", (gdouble) (canvas_width - pixel_width) / 2.0),
1294 first_action_message->set_property ("y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)));
1298 zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit));
1299 edit_cursor->set_position (edit_cursor->current_frame);
1300 playhead_cursor->set_position (playhead_cursor->current_frame);
1301 reset_scrolling_region (alloc);
1303 Resized (); /* EMIT_SIGNAL */
1307 Editor::reset_scrolling_region (GtkAllocation *alloc)
1309 guint32 last_canvas_unit;
1311 guint32 canvas_alloc_height, canvas_alloc_width;
1312 TrackViewList::iterator i;
1313 static bool first_time = true;
1315 /* We need to make sure that the canvas always has its
1316 scrolling region set to larger of:
1318 - the size allocated for it (within the container its packed in)
1319 - the size required to see the entire session
1321 If we don't ensure at least the first of these, the canvas
1322 does some wierd and in my view unnecessary stuff to center
1323 itself within the allocated area, which causes bad, bad
1326 XXX GnomeCanvas has fixed this, and has an option to
1327 control the centering behaviour.
1330 last_canvas_unit = (guint32) ceil ((float) max_frames / frames_per_unit);
1335 for (i = track_views.begin(); i != track_views.end(); ++i) {
1336 if ((*i)->control_parent) {
1337 height += (*i)->effective_height;
1338 height += track_spacing;
1343 height -= track_spacing;
1347 canvas_height = (guint32) height;
1350 canvas_alloc_height = alloc->height;
1351 canvas_alloc_width = alloc->width;
1353 canvas_alloc_height = track_canvas.get_height();
1354 canvas_alloc_width = track_canvas.get_width();
1357 canvas_height = max (canvas_height, canvas_alloc_height);
1358 track_canvas.set_scroll_region ( 0.0, 0.0, max (last_canvas_unit, canvas_alloc_width), canvas_height);
1360 if (edit_cursor) edit_cursor->set_length (canvas_alloc_height);
1361 if (playhead_cursor) playhead_cursor->set_length (canvas_alloc_height);
1363 if (marker_drag_line) {
1364 marker_drag_line_points->coords[3] = canvas_height;
1365 // cerr << "set mlA points, nc = " << marker_drag_line_points->num_points << endl;
1366 marker_drag_line->set_property("points", marker_drag_line_points);
1368 if (range_marker_drag_rect) {
1369 range_marker_drag_rect->set_property("y1", 0.0);
1370 range_marker_drag_rect->set_property("y2", (double) canvas_height);
1372 if (transport_loop_range_rect) {
1373 transport_loop_range_rect->set_property("y1", 0.0);
1374 transport_loop_range_rect->set_property("y2", (double) canvas_height);
1376 if (transport_punch_range_rect) {
1377 transport_punch_range_rect->set_property("y1", 0.0);
1378 transport_punch_range_rect->set_property("y2", (double) canvas_height);
1380 if (transport_punchin_line) {
1381 transport_punchin_line->set_property("y1", 0.0);
1382 transport_punchin_line->set_property("y2", (double) canvas_height);
1384 if (transport_punchout_line) {
1385 transport_punchout_line->set_property("y1", 0.0);
1386 transport_punchout_line->set_property("y2", (double) canvas_height);
1389 update_fixed_rulers ();
1391 if (is_visible() && first_time) {
1392 tempo_map_changed (Change (0));
1400 Editor::queue_session_control_changed (Session::ControlType t)
1402 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1406 Editor::session_control_changed (Session::ControlType t)
1408 // right now we're only tracking the loop and punch state
1411 case Session::AutoLoop:
1412 update_loop_range_view (true);
1414 case Session::PunchIn:
1415 case Session::PunchOut:
1416 update_punch_range_view (true);
1425 Editor::fake_add_edit_group (RouteGroup *group)
1427 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1431 Editor::fake_handle_new_audio_region (AudioRegion *region)
1433 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1437 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1439 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1443 Editor::fake_handle_new_duration ()
1445 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1449 Editor::start_scrolling ()
1451 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1452 (mem_fun(*this, &Editor::update_current_screen));
1454 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1455 (mem_fun(*this, &Editor::update_slower));
1459 Editor::stop_scrolling ()
1461 scroll_connection.disconnect ();
1462 slower_update_connection.disconnect ();
1466 Editor::map_position_change (jack_nframes_t frame)
1468 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1470 if (session == 0 || !_follow_playhead) {
1474 center_screen (frame);
1475 playhead_cursor->set_position (frame);
1479 Editor::center_screen (jack_nframes_t frame)
1481 float page = canvas_width * frames_per_unit;
1483 /* if we're off the page, then scroll.
1486 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1487 center_screen_internal (frame,page);
1492 Editor::center_screen_internal (jack_nframes_t frame, float page)
1497 frame -= (jack_nframes_t) page;
1502 reposition_x_origin (frame);
1506 Editor::handle_new_duration ()
1508 reset_scrolling_region ();
1511 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1512 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1515 update_hscroller ();
1519 Editor::update_title_s (string snap_name)
1521 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1527 Editor::update_title ()
1529 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1532 bool dirty = session->dirty();
1534 string wintitle = _("ardour: editor: ");
1540 wintitle += session->name();
1542 if (session->snap_name() != session->name()) {
1544 wintitle += session->snap_name();
1551 set_title (wintitle);
1556 Editor::connect_to_session (Session *t)
1560 if (first_action_message) {
1561 first_action_message->hide();
1564 flush_track_canvas();
1568 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1570 /* These signals can all be emitted by a non-GUI thread. Therefore the
1571 handlers for them must not attempt to directly interact with the GUI,
1572 but use Gtkmm2ext::UI::instance()->call_slot();
1575 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1576 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1577 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1578 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1579 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1580 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1581 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1582 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1583 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1584 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1585 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1586 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1587 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1589 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1590 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1592 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1594 session->foreach_edit_group(this, &Editor::add_edit_group);
1596 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1597 editor_mixer_button.set_name (X_("EditorMixerButton"));
1599 edit_cursor_clock.set_session (session);
1600 selection_start_clock.set_session (session);
1601 selection_end_clock.set_session (session);
1602 zoom_range_clock.set_session (session);
1603 _playlist_selector->set_session (session);
1604 nudge_clock.set_session (session);
1606 switch (session->get_edit_mode()) {
1608 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1612 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1616 Location* loc = session->locations()->auto_loop_location();
1618 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1619 if (loc->start() == loc->end()) {
1620 loc->set_end (loc->start() + 1);
1622 session->locations()->add (loc, false);
1623 session->set_auto_loop_location (loc);
1627 loc->set_name (_("Loop"));
1630 loc = session->locations()->auto_punch_location();
1632 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1633 if (loc->start() == loc->end()) {
1634 loc->set_end (loc->start() + 1);
1636 session->locations()->add (loc, false);
1637 session->set_auto_punch_location (loc);
1641 loc->set_name (_("Punch"));
1644 update_loop_range_view (true);
1645 update_punch_range_view (true);
1647 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1650 refresh_location_display ();
1651 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1652 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1653 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1654 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1655 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1657 reset_scrolling_region ();
1659 redisplay_regions ();
1660 redisplay_named_selections ();
1662 //route_list.freeze (); GTK2FIX
1663 route_display_model.clear ();
1664 session->foreach_route (this, &Editor::handle_new_route);
1665 // route_list.select_all ();
1667 route_list_reordered ();
1668 //route_list.thaw ();
1670 if (embed_audio_item) {
1671 embed_audio_item->set_sensitive (true);
1673 if (import_audio_item) {
1674 import_audio_item->set_sensitive (true);
1677 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1678 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1681 /* ::reposition_x_origin() doesn't work right here, since the old
1682 position may be zero already, and it does nothing in such
1688 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1689 track_canvas_scroller.get_hadjustment()->set_value (0);
1691 update_hscroller ();
1692 restore_ruler_visibility ();
1693 tempo_map_changed (Change (0));
1695 edit_cursor->set_position (0);
1696 playhead_cursor->set_position (0);
1700 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1703 /* don't show master bus in a new session */
1705 if (ARDOUR_UI::instance()->session_is_new ()) {
1707 TreeModel::Children rows = route_display_model->children();
1708 TreeModel::Children::iterator i;
1710 //route_list.freeze ();
1712 for (i = rows.begin(); i != rows.end(); ++i) {
1713 TimeAxisView *tv = (*i)[route_display_columns.tv];
1714 AudioTimeAxisView *atv;
1716 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1717 if (atv->route().master()) {
1718 route_list.get_selection()->unselect (i);
1719 //(*i)->unselect ();
1724 //route_list.thaw ();
1729 Editor::build_cursors ()
1731 Glib::RefPtr <Gdk::Pixmap> source, mask;
1732 Gdk::Color fg ("#ff0000"); /* Red. */
1733 Gdk::Color bg ("#0000ff"); /* Blue. */
1735 Gdk::Pixmap::create_from_data (source, hand_bits,
1736 hand_width, hand_height, 1, fg, bg);
1737 Gdk::Pixmap::create_from_data(mask, handmask_bits,
1738 handmask_width, handmask_height, 1, fg, bg);
1739 grabber_cursor = new Gdk::Cursor (source, mask, fg, bg, hand_x_hot, hand_y_hot);
1740 source->unreference();
1741 mask->unreference();
1743 Gdk::Color mbg ("#000000" ); /* Black */
1744 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1746 Gdk::Pixmap::create_from_data (source, mag_bits,
1747 mag_width, mag_height, 1, fg, bg);
1748 Gdk::Pixmap::create_from_data (mask, magmask_bits,
1749 mag_width, mag_height, 1, fg, bg);
1750 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1751 source->unreference();
1752 mask->unreference();
1754 Gdk::Color fbg ("#ffffff" );
1755 Gdk::Color ffg ("#000000" );
1757 Gdk::Pixmap::create_from_data (source, fader_cursor_bits,
1758 fader_cursor_width, fader_cursor_height, 1, fg, bg);
1759 Gdk::Pixmap::create_from_data (mask, fader_cursor_mask_bits,
1760 fader_cursor_width, fader_cursor_height, 1, fg, bg);
1761 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1762 source->unreference();
1763 mask->unreference();
1765 Gdk::Pixmap::create_from_data (source,speaker_cursor_bits,
1766 speaker_cursor_width, speaker_cursor_height, 1, fg, bg);
1767 Gdk::Pixmap::create_from_data (mask, speaker_cursor_mask_bits,
1768 speaker_cursor_width, speaker_cursor_height, 1, fg, bg);
1769 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1770 source->unreference();
1771 mask->unreference();
1773 cross_hair_cursor = new Gdk::Cursor (Gdk::CROSSHAIR);
1774 trimmer_cursor = new Gdk::Cursor (Gdk::SB_H_DOUBLE_ARROW);
1775 selector_cursor = new Gdk::Cursor (Gdk::XTERM);
1776 time_fx_cursor = new Gdk::Cursor (Gdk::SIZING);
1777 wait_cursor = new Gdk::Cursor (Gdk::WATCH);
1778 timebar_cursor = new Gdk::Cursor(Gdk::LEFT_PTR);
1782 Editor::popup_fade_context_menu (int button, int32_t time, GnomeCanvasItem* item, ItemType item_type)
1784 using namespace Menu_Helpers;
1785 AudioRegionView* arv = static_cast<AudioRegionView*> (gtk_object_get_data (GTK_OBJECT(item), "regionview"));
1788 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1792 MenuList& items (fade_context_menu.items());
1796 switch (item_type) {
1798 case FadeInHandleItem:
1799 if (arv->region.fade_in_active()) {
1800 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1802 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1805 items.push_back (SeparatorElem());
1807 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1808 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1809 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1810 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1811 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1815 case FadeOutHandleItem:
1816 if (arv->region.fade_out_active()) {
1817 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1819 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1822 items.push_back (SeparatorElem());
1824 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1825 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1826 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1827 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1828 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1832 fatal << _("programming error: ")
1833 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1838 fade_context_menu.popup (button, time);
1842 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1844 using namespace Menu_Helpers;
1845 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1848 switch (item_type) {
1850 case AudioRegionViewName:
1851 case AudioRegionViewNameHighlight:
1852 if (with_selection) {
1853 build_menu_function = &Editor::build_track_selection_context_menu;
1855 build_menu_function = &Editor::build_track_region_context_menu;
1860 if (with_selection) {
1861 build_menu_function = &Editor::build_track_selection_context_menu;
1863 build_menu_function = &Editor::build_track_context_menu;
1867 case CrossfadeViewItem:
1868 build_menu_function = &Editor::build_track_crossfade_context_menu;
1872 if (clicked_audio_trackview->get_diskstream()) {
1873 build_menu_function = &Editor::build_track_context_menu;
1875 build_menu_function = &Editor::build_track_bus_context_menu;
1880 /* probably shouldn't happen but if it does, we don't care */
1884 menu = (this->*build_menu_function)(frame);
1885 menu->set_name ("ArdourContextMenu");
1887 /* now handle specific situations */
1889 switch (item_type) {
1891 case AudioRegionViewName:
1892 case AudioRegionViewNameHighlight:
1893 if (!with_selection) {
1894 if (region_edit_menu_split_item) {
1895 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1896 region_edit_menu_split_item->set_sensitive (true);
1898 region_edit_menu_split_item->set_sensitive (false);
1901 if (region_edit_menu_split_multichannel_item) {
1902 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1903 region_edit_menu_split_multichannel_item->set_sensitive (true);
1905 region_edit_menu_split_multichannel_item->set_sensitive (false);
1914 case CrossfadeViewItem:
1921 /* probably shouldn't happen but if it does, we don't care */
1925 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1927 /* Bounce to disk */
1929 using namespace Menu_Helpers;
1930 MenuList& edit_items = menu->items();
1932 edit_items.push_back (SeparatorElem());
1934 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1935 case AudioTrack::NoFreeze:
1936 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1939 case AudioTrack::Frozen:
1940 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1943 case AudioTrack::UnFrozen:
1944 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1950 menu->popup (button, time);
1954 Editor::build_track_context_menu (jack_nframes_t ignored)
1956 using namespace Menu_Helpers;
1958 MenuList& edit_items = track_context_menu.items();
1961 add_dstream_context_items (edit_items);
1962 return &track_context_menu;
1966 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1968 using namespace Menu_Helpers;
1970 MenuList& edit_items = track_context_menu.items();
1973 add_bus_context_items (edit_items);
1974 return &track_context_menu;
1978 Editor::build_track_region_context_menu (jack_nframes_t frame)
1980 using namespace Menu_Helpers;
1981 MenuList& edit_items = track_region_context_menu.items();
1984 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1990 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1991 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1992 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1993 add_region_context_items (atv->view, (*i), edit_items);
1999 add_dstream_context_items (edit_items);
2001 return &track_region_context_menu;
2005 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
2007 using namespace Menu_Helpers;
2008 MenuList& edit_items = track_crossfade_context_menu.items();
2009 edit_items.clear ();
2011 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
2018 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
2020 Playlist::RegionList* regions = pl->regions_at (frame);
2021 AudioPlaylist::Crossfades xfades;
2023 apl->crossfades_at (frame, xfades);
2025 bool many = xfades.size() > 1;
2027 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
2028 add_crossfade_context_items (atv->view, (*i), edit_items, many);
2031 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
2032 add_region_context_items (atv->view, (*i), edit_items);
2039 add_dstream_context_items (edit_items);
2041 return &track_crossfade_context_menu;
2045 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
2047 using namespace Menu_Helpers;
2048 MenuList& edit_items = track_selection_context_menu.items();
2049 edit_items.clear ();
2051 add_selection_context_items (edit_items);
2052 add_dstream_context_items (edit_items);
2054 return &track_selection_context_menu;
2058 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
2060 using namespace Menu_Helpers;
2061 Menu *xfade_menu = manage (new Menu);
2062 MenuList& items = xfade_menu->items();
2063 xfade_menu->set_name ("ArdourContextMenu");
2066 if (xfade->active()) {
2072 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
2073 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
2075 if (xfade->can_follow_overlap()) {
2077 if (xfade->following_overlap()) {
2078 str = _("Convert to short");
2080 str = _("Convert to full");
2083 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
2087 str = xfade->out().name();
2089 str += xfade->in().name();
2091 str = _("Crossfade");
2094 edit_items.push_back (MenuElem (str, *xfade_menu));
2095 edit_items.push_back (SeparatorElem());
2099 Editor::xfade_edit_left_region ()
2101 if (clicked_crossfadeview) {
2102 clicked_crossfadeview->left_view.show_region_editor ();
2107 Editor::xfade_edit_right_region ()
2109 if (clicked_crossfadeview) {
2110 clicked_crossfadeview->right_view.show_region_editor ();
2115 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
2117 using namespace Menu_Helpers;
2118 Menu *region_menu = manage (new Menu);
2119 MenuList& items = region_menu->items();
2120 region_menu->set_name ("ArdourContextMenu");
2122 AudioRegion* ar = 0;
2125 ar = dynamic_cast<AudioRegion*> (region);
2128 /* when this particular menu pops up, make the relevant region
2132 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
2134 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
2135 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
2136 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
2137 items.push_back (SeparatorElem());
2138 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
2139 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
2140 items.push_back (SeparatorElem());
2142 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
2143 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
2144 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
2145 items.push_back (SeparatorElem());
2147 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
2148 might be able to figure out which overloaded member function to use in
2152 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
2154 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
2155 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
2156 items.push_back (SeparatorElem());
2158 if (region->muted()) {
2159 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
2161 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
2163 items.push_back (SeparatorElem());
2165 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
2166 items.push_back (SeparatorElem());
2171 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
2172 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
2173 items.push_back (SeparatorElem());
2175 if (ar->scale_amplitude() != 1.0f) {
2176 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
2178 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
2181 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
2182 items.push_back (SeparatorElem());
2186 Menu *nudge_menu = manage (new Menu());
2187 MenuList& nudge_items = nudge_menu->items();
2188 nudge_menu->set_name ("ArdourContextMenu");
2190 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
2191 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
2192 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
2193 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
2195 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2196 items.push_back (SeparatorElem());
2198 Menu *trim_menu = manage (new Menu);
2199 MenuList& trim_items = trim_menu->items();
2200 trim_menu->set_name ("ArdourContextMenu");
2202 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
2203 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
2205 items.push_back (MenuElem (_("Trim"), *trim_menu));
2206 items.push_back (SeparatorElem());
2208 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
2209 region_edit_menu_split_item = &items.back();
2211 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
2212 region_edit_menu_split_multichannel_item = &items.back();
2214 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
2215 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
2216 items.push_back (SeparatorElem());
2217 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
2218 items.push_back (SeparatorElem());
2219 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
2221 /* OK, stick the region submenu at the top of the list, and then add
2225 /* we have to hack up the region name because "_" has a special
2226 meaning for menu titles.
2229 string::size_type pos = 0;
2230 string menu_item_name = region->name();
2232 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
2233 menu_item_name.replace (pos, 1, "__");
2237 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
2238 edit_items.push_back (SeparatorElem());
2242 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
2244 using namespace Menu_Helpers;
2245 Menu *selection_menu = manage (new Menu);
2246 MenuList& items = selection_menu->items();
2247 selection_menu->set_name ("ArdourContextMenu");
2249 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
2250 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
2251 items.push_back (SeparatorElem());
2252 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
2253 items.push_back (SeparatorElem());
2254 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
2255 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
2256 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
2257 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
2258 items.push_back (SeparatorElem());
2259 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
2260 items.push_back (SeparatorElem());
2261 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
2262 items.push_back (SeparatorElem());
2263 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
2265 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
2266 edit_items.push_back (SeparatorElem());
2270 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
2272 using namespace Menu_Helpers;
2276 Menu *play_menu = manage (new Menu);
2277 MenuList& play_items = play_menu->items();
2278 play_menu->set_name ("ArdourContextMenu");
2280 play_items.push_back (MenuElem (_("Play from edit cursor")));
2281 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2282 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
2283 play_items.push_back (SeparatorElem());
2284 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
2286 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2290 Menu *select_menu = manage (new Menu);
2291 MenuList& select_items = select_menu->items();
2292 select_menu->set_name ("ArdourContextMenu");
2294 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2295 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2296 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2297 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2298 select_items.push_back (SeparatorElem());
2299 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2300 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2301 select_items.push_back (SeparatorElem());
2303 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2307 Menu *cutnpaste_menu = manage (new Menu);
2308 MenuList& cutnpaste_items = cutnpaste_menu->items();
2309 cutnpaste_menu->set_name ("ArdourContextMenu");
2311 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2312 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2313 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2314 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
2316 cutnpaste_items.push_back (SeparatorElem());
2318 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
2319 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
2321 cutnpaste_items.push_back (SeparatorElem());
2323 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
2325 cutnpaste_items.push_back (SeparatorElem());
2327 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
2328 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
2330 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2332 /* Adding new material */
2334 Menu *import_menu = manage (new Menu());
2335 MenuList& import_items = import_menu->items();
2336 import_menu->set_name ("ArdourContextMenu");
2338 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2339 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
2341 edit_items.push_back (MenuElem (_("Import"), *import_menu));
2345 Menu *nudge_menu = manage (new Menu());
2346 MenuList& nudge_items = nudge_menu->items();
2347 nudge_menu->set_name ("ArdourContextMenu");
2349 edit_items.push_back (SeparatorElem());
2350 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2351 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2352 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2353 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2355 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2359 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2361 using namespace Menu_Helpers;
2365 Menu *play_menu = manage (new Menu);
2366 MenuList& play_items = play_menu->items();
2367 play_menu->set_name ("ArdourContextMenu");
2369 play_items.push_back (MenuElem (_("Play from edit cursor")));
2370 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2371 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2375 Menu *select_menu = manage (new Menu);
2376 MenuList& select_items = select_menu->items();
2377 select_menu->set_name ("ArdourContextMenu");
2379 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2380 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2381 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2382 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2383 select_items.push_back (SeparatorElem());
2384 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2385 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2386 select_items.push_back (SeparatorElem());
2388 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2392 Menu *cutnpaste_menu = manage (new Menu);
2393 MenuList& cutnpaste_items = cutnpaste_menu->items();
2394 cutnpaste_menu->set_name ("ArdourContextMenu");
2396 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2397 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2398 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2400 Menu *nudge_menu = manage (new Menu());
2401 MenuList& nudge_items = nudge_menu->items();
2402 nudge_menu->set_name ("ArdourContextMenu");
2404 edit_items.push_back (SeparatorElem());
2405 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2406 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2407 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2408 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2410 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2413 /* CURSOR SETTING AND MARKS AND STUFF */
2416 Editor::set_snap_to (SnapType st)
2419 vector<string> txt = internationalize (snap_type_strings);
2420 snap_type_selector.set_active_text (txt[(int)st]);
2424 switch (snap_type) {
2425 case SnapToAThirtysecondBeat:
2426 case SnapToASixteenthBeat:
2427 case SnapToAEighthBeat:
2428 case SnapToAQuarterBeat:
2429 case SnapToAThirdBeat:
2430 update_tempo_based_rulers ();
2438 Editor::set_snap_mode (SnapMode mode)
2441 vector<string> txt = internationalize (snap_mode_strings);
2442 snap_mode_selector.set_active_text (txt[(int)mode]);
2448 Editor::add_location_from_selection ()
2450 if (selection->time.empty()) {
2454 if (session == 0 || clicked_trackview == 0) {
2458 jack_nframes_t start = selection->time[clicked_selection].start;
2459 jack_nframes_t end = selection->time[clicked_selection].end;
2461 Location *location = new Location (start, end, "selection");
2463 session->begin_reversible_command (_("add marker"));
2464 session->add_undo (session->locations()->get_memento());
2465 session->locations()->add (location, true);
2466 session->add_redo_no_execute (session->locations()->get_memento());
2467 session->commit_reversible_command ();
2471 Editor::add_location_from_playhead_cursor ()
2473 jack_nframes_t where = session->audible_frame();
2475 Location *location = new Location (where, where, "mark", Location::IsMark);
2476 session->begin_reversible_command (_("add marker"));
2477 session->add_undo (session->locations()->get_memento());
2478 session->locations()->add (location, true);
2479 session->add_redo_no_execute (session->locations()->get_memento());
2480 session->commit_reversible_command ();
2485 Editor::set_state (const XMLNode& node)
2487 const XMLProperty* prop;
2489 int x, y, width, height, xoff, yoff;
2491 if ((geometry = find_named_node (node, "geometry")) == 0) {
2493 width = default_width;
2494 height = default_height;
2502 width = atoi(geometry->property("x_size")->value());
2503 height = atoi(geometry->property("y_size")->value());
2504 x = atoi(geometry->property("x_pos")->value());
2505 y = atoi(geometry->property("y_pos")->value());
2506 xoff = atoi(geometry->property("x_off")->value());
2507 yoff = atoi(geometry->property("y_off")->value());
2510 set_default_size(width, height);
2511 set_position(x, y-yoff);
2513 if ((prop = node.property ("zoom-focus"))) {
2514 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2517 if ((prop = node.property ("zoom"))) {
2518 set_frames_per_unit (atof (prop->value()));
2521 if ((prop = node.property ("snap-to"))) {
2522 set_snap_to ((SnapType) atoi (prop->value()));
2525 if ((prop = node.property ("snap-mode"))) {
2526 set_snap_mode ((SnapMode) atoi (prop->value()));
2529 if ((prop = node.property ("show-waveforms"))) {
2530 bool yn = (prop->value() == "yes");
2531 _show_waveforms = !yn;
2532 set_show_waveforms (yn);
2535 if ((prop = node.property ("show-waveforms-recording"))) {
2536 bool yn = (prop->value() == "yes");
2537 _show_waveforms_recording = !yn;
2538 set_show_waveforms_recording (yn);
2541 if ((prop = node.property ("show-measures"))) {
2542 bool yn = (prop->value() == "yes");
2543 _show_measures = !yn;
2544 set_show_measures (yn);
2547 if ((prop = node.property ("follow-playhead"))) {
2548 bool yn = (prop->value() == "yes");
2549 _follow_playhead = !yn;
2550 set_follow_playhead (yn);
2553 if ((prop = node.property ("xfades-visible"))) {
2554 bool yn = (prop->value() == "yes");
2555 _xfade_visibility = !yn;
2556 set_xfade_visibility (yn);
2559 if ((prop = node.property ("region-list-sort-type"))) {
2560 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2561 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2564 if ((prop = node.property ("mouse-mode"))) {
2565 MouseMode m = str2mousemode(prop->value());
2566 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2567 set_mouse_mode (m, true);
2569 mouse_mode = MouseGain; /* lie, to force the mode switch */
2570 set_mouse_mode (MouseObject, true);
2573 if ((prop = node.property ("editor-mixer-button"))) {
2574 editor_mixer_button.set_active(prop->value() == "yes");
2581 Editor::get_state ()
2583 XMLNode* node = new XMLNode ("Editor");
2586 if (is_realized()) {
2587 Glib::RefPtr<Gdk::Window> win = get_window();
2589 int x, y, xoff, yoff, width, height;
2590 win->get_root_origin(x, y);
2591 win->get_position(xoff, yoff);
2592 win->get_size(width, height);
2594 XMLNode* geometry = new XMLNode ("geometry");
2596 snprintf(buf, sizeof(buf), "%d", width);
2597 geometry->add_property("x_size", string(buf));
2598 snprintf(buf, sizeof(buf), "%d", height);
2599 geometry->add_property("y_size", string(buf));
2600 snprintf(buf, sizeof(buf), "%d", x);
2601 geometry->add_property("x_pos", string(buf));
2602 snprintf(buf, sizeof(buf), "%d", y);
2603 geometry->add_property("y_pos", string(buf));
2604 snprintf(buf, sizeof(buf), "%d", xoff);
2605 geometry->add_property("x_off", string(buf));
2606 snprintf(buf, sizeof(buf), "%d", yoff);
2607 geometry->add_property("y_off", string(buf));
2608 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gobj()));
2609 geometry->add_property("canvas_region_list_pane_pos", string(buf));
2610 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gobj()));
2611 geometry->add_property("track_list_canvas_pane_pos", string(buf));
2612 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(®ion_selection_vpane)->gobj()));
2613 geometry->add_property("region_selection_pane_pos", string(buf));
2614 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gobj()));
2615 geometry->add_property("route_group_pane_pos", string(buf));
2617 node->add_child_nocopy (*geometry);
2620 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2621 node->add_property ("zoom-focus", buf);
2622 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2623 node->add_property ("zoom", buf);
2624 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2625 node->add_property ("snap-to", buf);
2626 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2627 node->add_property ("snap-mode", buf);
2629 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2630 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2631 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2632 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2633 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2634 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2635 node->add_property ("mouse-mode", enum2str(mouse_mode));
2636 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2644 Editor::trackview_by_y_position (double y)
2646 TrackViewList::iterator iter;
2649 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2657 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2666 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2668 Location* before = 0;
2669 Location* after = 0;
2675 const jack_nframes_t one_second = session->frame_rate();
2676 const jack_nframes_t one_minute = session->frame_rate() * 60;
2678 jack_nframes_t presnap = start;
2680 switch (snap_type) {
2686 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2688 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2691 case SnapToSMPTEFrame:
2693 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2695 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2699 case SnapToSMPTESeconds:
2700 if (session->smpte_offset_negative())
2702 start += session->smpte_offset ();
2704 start -= session->smpte_offset ();
2706 if (direction > 0) {
2707 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2709 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2712 if (session->smpte_offset_negative())
2714 start -= session->smpte_offset ();
2716 start += session->smpte_offset ();
2720 case SnapToSMPTEMinutes:
2721 if (session->smpte_offset_negative())
2723 start += session->smpte_offset ();
2725 start -= session->smpte_offset ();
2728 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2730 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2732 if (session->smpte_offset_negative())
2734 start -= session->smpte_offset ();
2736 start += session->smpte_offset ();
2742 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2744 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2750 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2752 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2757 start = session->tempo_map().round_to_bar (start, direction);
2761 start = session->tempo_map().round_to_beat (start, direction);
2764 case SnapToAThirtysecondBeat:
2765 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2768 case SnapToASixteenthBeat:
2769 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2772 case SnapToAEighthBeat:
2773 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2776 case SnapToAQuarterBeat:
2777 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2780 case SnapToAThirdBeat:
2781 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2784 case SnapToEditCursor:
2785 start = edit_cursor->current_frame;
2793 before = session->locations()->first_location_before (start);
2794 after = session->locations()->first_location_after (start);
2796 if (direction < 0) {
2798 start = before->start();
2802 } else if (direction > 0) {
2804 start = after->start();
2806 start = session->current_end_frame();
2811 /* find nearest of the two */
2812 if ((start - before->start()) < (after->start() - start)) {
2813 start = before->start();
2815 start = after->start();
2818 start = before->start();
2821 start = after->start();
2828 case SnapToRegionStart:
2829 case SnapToRegionEnd:
2830 case SnapToRegionSync:
2831 case SnapToRegionBoundary:
2832 if (!region_boundary_cache.empty()) {
2833 vector<jack_nframes_t>::iterator i;
2835 if (direction > 0) {
2836 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2838 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2841 if (i != region_boundary_cache.end()) {
2844 start = region_boundary_cache.back();
2850 switch (snap_mode) {
2856 if (presnap > start) {
2857 if (presnap > (start + unit_to_frame(snap_threshold))) {
2861 } else if (presnap < start) {
2862 if (presnap < (start - unit_to_frame(snap_threshold))) {
2874 Editor::setup_toolbar ()
2877 vector<ToggleButton *> mouse_mode_buttons;
2879 mouse_mode_buttons.push_back (&mouse_move_button);
2880 mouse_mode_buttons.push_back (&mouse_select_button);
2881 mouse_mode_buttons.push_back (&mouse_gain_button);
2882 mouse_mode_buttons.push_back (&mouse_zoom_button);
2883 mouse_mode_buttons.push_back (&mouse_timefx_button);
2884 mouse_mode_buttons.push_back (&mouse_audition_button);
2885 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2887 mouse_mode_button_table.set_homogeneous (true);
2888 mouse_mode_button_table.set_col_spacings (2);
2889 mouse_mode_button_table.set_row_spacings (2);
2890 mouse_mode_button_table.set_border_width (5);
2892 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2893 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2894 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2896 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2897 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2898 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2900 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2901 mouse_mode_tearoff->set_name ("MouseModeBase");
2903 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2904 static_cast<Gtk::Widget*>(&mouse_mode_button_table)));
2905 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2906 static_cast<Gtk::Widget*> (&mouse_mode_button_table), 1));
2908 mouse_move_button.set_name ("MouseModeButton");
2909 mouse_select_button.set_name ("MouseModeButton");
2910 mouse_gain_button.set_name ("MouseModeButton");
2911 mouse_zoom_button.set_name ("MouseModeButton");
2912 mouse_timefx_button.set_name ("MouseModeButton");
2913 mouse_audition_button.set_name ("MouseModeButton");
2915 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2916 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2917 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2918 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2919 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2920 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2922 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2923 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2924 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2925 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2926 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2927 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2929 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2930 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2932 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2933 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2934 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2935 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2936 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2938 // mouse_move_button.set_active (true);
2940 /* automation control */
2942 global_automation_button.set_name ("MouseModeButton");
2943 automation_mode_button.set_name ("MouseModeButton");
2945 automation_box.set_spacing (2);
2946 automation_box.set_border_width (2);
2947 automation_box.pack_start (global_automation_button, false, false);
2948 automation_box.pack_start (automation_mode_button, false, false);
2952 edit_mode_label.set_name ("ToolBarLabel");
2954 edit_mode_selector.set_name ("EditModeSelector");
2956 edit_mode_box.set_spacing (3);
2957 edit_mode_box.set_border_width (3);
2959 /* XXX another disgusting hack because of the way combo boxes size themselves */
2961 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2, 10);
2962 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2963 edit_mode_box.pack_start (edit_mode_label, false, false);
2964 edit_mode_box.pack_start (edit_mode_selector, false, false);
2966 edit_mode_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2970 snap_type_label.set_name ("ToolBarLabel");
2972 snap_type_selector.set_name ("SnapTypeSelector");
2974 snap_type_box.set_spacing (3);
2975 snap_type_box.set_border_width (3);
2977 /* XXX another disgusting hack because of the way combo boxes size themselves */
2979 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2980 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "Region bounds", 2+FUDGE, 10);
2981 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2983 snap_type_box.pack_start (snap_type_label, false, false);
2984 snap_type_box.pack_start (snap_type_selector, false, false);
2986 snap_type_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2988 /* Snap mode, not snap type */
2990 snap_mode_label.set_name ("ToolBarLabel");
2992 snap_mode_selector.set_name ("SnapModeSelector");
2994 snap_mode_box.set_spacing (3);
2995 snap_mode_box.set_border_width (3);
2997 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2, 10);
2998 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
3000 snap_mode_box.pack_start (snap_mode_label, false, false);
3001 snap_mode_box.pack_start (snap_mode_selector, false, false);
3003 snap_mode_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
3005 /* Zoom focus mode */
3007 zoom_focus_label.set_name ("ToolBarLabel");
3009 zoom_focus_selector.set_name ("ZoomFocusSelector");
3011 zoom_focus_box.set_spacing (3);
3012 zoom_focus_box.set_border_width (3);
3014 /* XXX another disgusting hack because of the way combo boxes size themselves */
3016 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2, 10);
3017 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
3019 zoom_focus_box.pack_start (zoom_focus_label, false, false);
3020 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
3022 zoom_focus_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
3024 /* selection/cursor clocks */
3026 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
3027 selection_start_clock_label.set_name ("ToolBarLabel");
3028 selection_end_clock_label.set_name ("ToolBarLabel");
3029 edit_cursor_clock_label.set_name ("ToolBarLabel");
3031 selection_start_clock_label.set_text (_("Start:"));
3032 selection_end_clock_label.set_text (_("End:"));
3033 edit_cursor_clock_label.set_text (_("Edit:"));
3035 toolbar_selection_clock_table.set_border_width (5);
3036 toolbar_selection_clock_table.set_col_spacings (2);
3037 toolbar_selection_clock_table.set_homogeneous (false);
3039 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
3040 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
3041 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
3043 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
3044 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
3045 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
3048 // toolbar_clock_vbox.set_spacing (2);
3049 // toolbar_clock_vbox.set_border_width (10);
3050 /* the editor/mixer button will be enabled at session connect */
3052 editor_mixer_button.set_active(false);
3053 editor_mixer_button.set_sensitive(false);
3055 HBox* hbox = new HBox;
3057 hbox->pack_start (editor_mixer_button, false, false);
3058 hbox->pack_start (toolbar_selection_clock_table, false, false);
3059 hbox->pack_start (zoom_indicator_vbox, false, false);
3060 hbox->pack_start (zoom_focus_box, false, false);
3061 hbox->pack_start (snap_type_box, false, false);
3062 hbox->pack_start (snap_mode_box, false, false);
3063 hbox->pack_start (edit_mode_box, false, false);
3065 VBox *vbox = manage (new VBox);
3067 vbox->set_spacing (3);
3068 vbox->set_border_width (3);
3070 HBox *nbox = manage (new HBox);
3072 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
3073 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
3075 nbox->pack_start (nudge_backward_button, false, false);
3076 nbox->pack_start (nudge_forward_button, false, false);
3077 nbox->pack_start (nudge_clock, false, false, 5);
3079 nudge_label.set_name ("ToolBarLabel");
3081 vbox->pack_start (nudge_label, false, false);
3082 vbox->pack_start (*nbox, false, false);
3084 hbox->pack_start (*vbox, false, false);
3088 tools_tearoff = new TearOff (*hbox);
3089 tools_tearoff->set_name ("MouseModeBase");
3091 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
3092 static_cast<Gtk::Widget*>(hbox)));
3093 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
3094 static_cast<Gtk::Widget*> (hbox), 0));
3096 toolbar_hbox.set_spacing (8);
3097 toolbar_hbox.set_border_width (2);
3099 toolbar_hbox.pack_start (*tools_tearoff, false, false);
3100 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
3102 toolbar_base.set_name ("ToolBarBase");
3103 toolbar_base.add (toolbar_hbox);
3105 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
3106 toolbar_frame.set_name ("BaseFrame");
3107 toolbar_frame.add (toolbar_base);
3111 Editor::_autoscroll_canvas (void *arg)
3113 return ((Editor *) arg)->autoscroll_canvas ();
3117 Editor::autoscroll_canvas ()
3119 jack_nframes_t new_frame;
3120 bool keep_calling = true;
3122 if (autoscroll_direction < 0) {
3123 if (leftmost_frame < autoscroll_distance) {
3126 new_frame = leftmost_frame - autoscroll_distance;
3129 if (leftmost_frame > max_frames - autoscroll_distance) {
3130 new_frame = max_frames;
3132 new_frame = leftmost_frame + autoscroll_distance;
3136 if (new_frame != leftmost_frame) {
3137 reposition_x_origin (new_frame);
3140 if (new_frame == 0 || new_frame == max_frames) {
3147 if (autoscroll_cnt == 1) {
3149 /* connect the timeout so that we get called repeatedly */
3151 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
3152 keep_calling = false;
3154 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
3156 /* after about a while, speed up a bit by changing the timeout interval */
3158 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
3159 keep_calling = false;
3161 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
3163 /* after about another while, speed up some more */
3165 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
3166 keep_calling = false;
3168 } else if (autoscroll_cnt >= 30) {
3170 /* we've been scrolling for a while ... crank it up */
3172 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
3175 return keep_calling;
3179 Editor::start_canvas_autoscroll (int dir)
3185 stop_canvas_autoscroll ();
3187 autoscroll_direction = dir;
3188 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
3191 /* do it right now, which will start the repeated callbacks */
3193 autoscroll_canvas ();
3197 Editor::stop_canvas_autoscroll ()
3199 if (autoscroll_timeout_tag >= 0) {
3200 gtk_timeout_remove (autoscroll_timeout_tag);
3201 autoscroll_timeout_tag = -1;
3206 Editor::convert_drop_to_paths (vector<string>& paths,
3207 GdkDragContext *context,
3210 GtkSelectionData *data,
3218 gchar *tname = gdk_atom_name (data->type);
3220 if (session == 0 || strcmp (tname, "text/plain") != 0) {
3224 /* Parse the "uri-list" format that Nautilus provides,
3225 where each pathname is delimited by \r\n
3228 path = (char *) data->data;
3231 for (int n = 0; n < data->length; ++n) {
3235 if (path[n] == '\r') {
3242 if (path[n] == '\n') {
3243 paths.push_back (spath);
3247 warning << _("incorrectly formatted URI list, ignored")
3255 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
3257 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3259 // cerr << "dropped text was " << *p << endl;
3263 // cerr << "decoded was " << *p << endl;
3265 if ((*p).substr (0,7) == "file://") {
3266 (*p) = (*p).substr (7);
3274 Editor::track_canvas_drag_data_received (GdkDragContext *context,
3277 GtkSelectionData *data,
3282 AudioTimeAxisView* tv;
3284 vector<string> paths;
3287 jack_nframes_t frame;
3289 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
3293 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
3299 track_canvas.c2w( x, y, wx, wy);
3301 ev.type = GDK_BUTTON_RELEASE;
3305 frame = event_frame (&ev, 0, &cy);
3309 if ((tvp = trackview_by_y_position (cy)) == 0) {
3311 /* drop onto canvas background: create a new track */
3313 insert_paths_as_new_tracks (paths, false);
3316 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
3318 /* check that its an audio track, not a bus */
3320 if (tv->get_diskstream()) {
3322 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3323 insert_sndfile_into (*p, true, tv, frame);
3330 gtk_drag_finish (context, TRUE, FALSE, time);
3334 Editor::new_tempo_section ()
3340 Editor::map_transport_state ()
3342 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3344 if (session->transport_stopped()) {
3345 have_pending_keyboard_selection = false;
3351 Editor::State::State ()
3353 selection = new Selection;
3356 Editor::State::~State ()
3362 Editor::get_memento () const
3364 State *state = new State;
3366 store_state (*state);
3367 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3371 Editor::store_state (State& state) const
3373 *state.selection = *selection;
3377 Editor::restore_state (State *state)
3379 if (*selection == *state->selection) {
3383 *selection = *state->selection;
3384 time_selection_changed ();
3385 region_selection_changed ();
3387 /* XXX other selection change handlers? */
3391 Editor::begin_reversible_command (string name)
3394 UndoAction ua = get_memento();
3395 session->begin_reversible_command (name, &ua);
3400 Editor::commit_reversible_command ()
3403 UndoAction ua = get_memento();
3404 session->commit_reversible_command (&ua);
3409 Editor::flush_track_canvas ()
3411 /* I don't think this is necessary, and only causes more problems.
3412 I'm commenting it out
3413 and if the imageframe folks don't have any issues, we can take
3414 out this method entirely
3417 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
3418 //gtk_main_iteration ();
3422 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3424 if (!clicked_trackview) {
3429 begin_reversible_command (_("set selected trackview"));
3434 if (selection->selected (clicked_trackview)) {
3436 selection->remove (clicked_trackview);
3439 selection->add (clicked_trackview);
3444 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3445 /* no commit necessary */
3449 selection->set (clicked_trackview);
3453 commit_reversible_command ();
3458 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3460 if (!clicked_control_point) {
3465 begin_reversible_command (_("set selected control point"));
3475 commit_reversible_command ();
3480 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3482 if (!clicked_regionview) {
3486 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3492 RouteGroup* group = atv->route().edit_group();
3493 vector<AudioRegionView*> all_equivalent_regions;
3495 if (group && group->is_active()) {
3497 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3499 AudioTimeAxisView* tatv;
3501 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3503 if (tatv->route().edit_group() != group) {
3508 vector<AudioRegion*> results;
3509 AudioRegionView* marv;
3512 if ((ds = tatv->get_diskstream()) == 0) {
3517 if ((pl = ds->playlist()) != 0) {
3518 pl->get_equivalent_regions (clicked_regionview->region,
3522 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3523 if ((marv = tatv->view->find_view (**ir)) != 0) {
3524 all_equivalent_regions.push_back (marv);
3533 all_equivalent_regions.push_back (clicked_regionview);
3537 begin_reversible_command (_("set selected regionview"));
3541 if (clicked_regionview->get_selected()) {
3542 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3543 /* reduce selection down to just the one clicked */
3544 selection->set (clicked_regionview);
3546 selection->remove (clicked_regionview);
3549 selection->add (all_equivalent_regions);
3552 set_selected_track_from_click (add, false, no_track_remove);
3556 // karsten wiese suggested these two lines to make
3557 // a selected region rise to the top. but this
3558 // leads to a mismatch between actual layering
3559 // and visual layering. resolution required ....
3561 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3562 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3564 if (clicked_regionview->get_selected()) {
3565 /* no commit necessary: we are the one selected. */
3570 selection->set (all_equivalent_regions);
3571 set_selected_track_from_click (add, false, false);
3575 commit_reversible_command () ;
3579 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3581 vector<AudioRegionView*> all_equivalent_regions;
3582 AudioRegion* region;
3584 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3588 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3590 AudioTimeAxisView* tatv;
3592 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3595 vector<AudioRegion*> results;
3596 AudioRegionView* marv;
3599 if ((ds = tatv->get_diskstream()) == 0) {
3604 if ((pl = ds->playlist()) != 0) {
3605 pl->get_region_list_equivalent_regions (*region, results);
3608 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3609 if ((marv = tatv->view->find_view (**ir)) != 0) {
3610 all_equivalent_regions.push_back (marv);
3617 begin_reversible_command (_("set selected regions"));
3621 selection->add (all_equivalent_regions);
3625 selection->set (all_equivalent_regions);
3628 commit_reversible_command () ;
3632 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3634 AudioRegionView* rv;
3637 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3641 if ((rv = sv->find_view (*ar)) == 0) {
3645 /* don't reset the selection if its something other than
3646 a single other region.
3649 if (selection->audio_regions.size() > 1) {
3653 begin_reversible_command (_("set selected regions"));
3655 selection->set (rv);
3657 commit_reversible_command () ;
3663 Editor::set_edit_group_solo (Route& route, bool yn)
3665 RouteGroup *edit_group;
3667 if ((edit_group = route.edit_group()) != 0) {
3668 edit_group->apply (&Route::set_solo, yn, this);
3670 route.set_solo (yn, this);
3675 Editor::set_edit_group_mute (Route& route, bool yn)
3677 RouteGroup *edit_group = 0;
3679 if ((edit_group == route.edit_group()) != 0) {
3680 edit_group->apply (&Route::set_mute, yn, this);
3682 route.set_mute (yn, this);
3687 Editor::set_edit_menu (Menu& menu)
3690 edit_menu->map_.connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3694 Editor::edit_menu_map_handler ()
3696 using namespace Menu_Helpers;
3697 MenuList& edit_items = edit_menu->items();
3700 /* Nuke all the old items */
3702 edit_items.clear ();
3708 if (session->undo_depth() == 0) {
3711 label = string_compose(_("Undo (%1)"), session->next_undo());
3714 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3716 if (session->undo_depth() == 0) {
3717 edit_items.back().set_sensitive (false);
3720 if (session->redo_depth() == 0) {
3723 label = string_compose(_("Redo (%1)"), session->next_redo());
3726 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3727 if (session->redo_depth() == 0) {
3728 edit_items.back().set_sensitive (false);
3731 vector<MenuItem*> mitems;
3733 edit_items.push_back (SeparatorElem());
3734 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3735 mitems.push_back (&edit_items.back());
3736 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3737 mitems.push_back (&edit_items.back());
3738 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3739 mitems.push_back (&edit_items.back());
3740 edit_items.push_back (SeparatorElem());
3741 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3742 mitems.push_back (&edit_items.back());
3743 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3744 mitems.push_back (&edit_items.back());
3745 edit_items.push_back (SeparatorElem());
3747 if (selection->empty()) {
3748 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3749 (*i)->set_sensitive (false);
3753 Menu* import_menu = manage (new Menu());
3754 import_menu->set_name ("ArdourContextMenu");
3755 MenuList& import_items = import_menu->items();
3757 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3758 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3760 Menu* embed_menu = manage (new Menu());
3761 embed_menu->set_name ("ArdourContextMenu");
3762 MenuList& embed_items = embed_menu->items();
3764 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3765 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3767 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3768 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3769 edit_items.push_back (SeparatorElem());
3771 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3772 if (!session->have_captured()) {
3773 edit_items.back().set_sensitive (false);
3778 Editor::duplicate_dialog (bool dup_region)
3781 if (clicked_regionview == 0) {
3785 if (selection->time.length() == 0) {
3790 ArdourDialog win ("duplicate dialog");
3792 Label label (_("Duplicate how many times?"));
3795 Button ok_button (_("OK"));
3796 Button cancel_button (_("Cancel"));
3799 button_box.set_spacing (7);
3800 set_size_request_to_display_given_text (ok_button, _("Cancel"), 20, 15); // this is cancel on purpose
3801 set_size_request_to_display_given_text (cancel_button, _("Cancel"), 20, 15);
3802 button_box.pack_end (ok_button, false, false);
3803 button_box.pack_end (cancel_button, false, false);
3805 hbox.set_spacing (5);
3806 hbox.pack_start (label);
3807 hbox.pack_start (entry, true, true);
3809 vbox.set_spacing (5);
3810 vbox.set_border_width (5);
3811 vbox.pack_start (hbox);
3812 vbox.pack_start (button_box);
3815 win.set_position (Gtk::WIN_POS_MOUSE);
3818 ok_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3819 entry.signal_activate().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3820 cancel_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 1));
3822 entry.signal_focus_in_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_in_event));
3823 entry.signal_focus_out_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_out_event));
3825 entry.set_text ("1");
3826 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3827 entry.select_region (0, entry.get_text_length());
3829 win.set_position (Gtk::WIN_POS_MOUSE);
3831 win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3833 entry.grab_focus ();
3837 if (win.run_status() != 0) {
3841 string text = entry.get_text();
3844 if (sscanf (text.c_str(), "%f", ×) == 1) {
3846 AudioRegionSelection regions;
3847 regions.add (clicked_regionview);
3848 duplicate_some_regions (regions, times);
3850 duplicate_selection (times);
3856 Editor::show_verbose_canvas_cursor ()
3858 verbose_canvas_cursor->raise_to_top();
3859 verbose_canvas_cursor->show();
3860 verbose_cursor_visible = true;
3864 Editor::hide_verbose_canvas_cursor ()
3866 verbose_canvas_cursor->hide();
3867 verbose_cursor_visible = false;
3871 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3873 /* XXX get origin of canvas relative to root window,
3874 add x and y and check compared to gdk_screen_{width,height}
3876 verbose_canvas_cursor->set_property("text", txt.c_str());
3877 verbose_canvas_cursor->set_property("x", x);
3878 verbose_canvas_cursor->set_property("y", y);
3882 Editor::set_verbose_canvas_cursor_text (string txt)
3884 verbose_canvas_cursor->set_property("text", txt.c_str());
3888 Editor::edit_mode_selection_done (GdkEventAny *ev)
3894 string choice = edit_mode_selector.get_active_text();
3895 EditMode mode = Slide;
3897 if (choice == _("Splice")) {
3899 } else if (choice == _("Slide")) {
3903 session->set_edit_mode (mode);
3909 Editor::snap_type_selection_done (GdkEventAny *ev)
3915 string choice = snap_type_selector.get_active_text();
3916 SnapType snaptype = SnapToFrame;
3918 if (choice == _("Beats/3")) {
3919 snaptype = SnapToAThirdBeat;
3920 } else if (choice == _("Beats/4")) {
3921 snaptype = SnapToAQuarterBeat;
3922 } else if (choice == _("Beats/8")) {
3923 snaptype = SnapToAEighthBeat;
3924 } else if (choice == _("Beats/16")) {
3925 snaptype = SnapToASixteenthBeat;
3926 } else if (choice == _("Beats/32")) {
3927 snaptype = SnapToAThirtysecondBeat;
3928 } else if (choice == _("Beats")) {
3929 snaptype = SnapToBeat;
3930 } else if (choice == _("Bars")) {
3931 snaptype = SnapToBar;
3932 } else if (choice == _("Marks")) {
3933 snaptype = SnapToMark;
3934 } else if (choice == _("Edit Cursor")) {
3935 snaptype = SnapToEditCursor;
3936 } else if (choice == _("Region starts")) {
3937 snaptype = SnapToRegionStart;
3938 } else if (choice == _("Region ends")) {
3939 snaptype = SnapToRegionEnd;
3940 } else if (choice == _("Region bounds")) {
3941 snaptype = SnapToRegionBoundary;
3942 } else if (choice == _("Region syncs")) {
3943 snaptype = SnapToRegionSync;
3944 } else if (choice == _("CD Frames")) {
3945 snaptype = SnapToCDFrame;
3946 } else if (choice == _("SMPTE Frames")) {
3947 snaptype = SnapToSMPTEFrame;
3948 } else if (choice == _("SMPTE Seconds")) {
3949 snaptype = SnapToSMPTESeconds;
3950 } else if (choice == _("SMPTE Minutes")) {
3951 snaptype = SnapToSMPTEMinutes;
3952 } else if (choice == _("Seconds")) {
3953 snaptype = SnapToSeconds;
3954 } else if (choice == _("Minutes")) {
3955 snaptype = SnapToMinutes;
3956 } else if (choice == _("None")) {
3957 snaptype = SnapToFrame;
3960 set_snap_to (snaptype);
3966 Editor::snap_mode_selection_done (GdkEventAny *ev)
3968 if(session == 0) return FALSE;
3970 string choice = snap_mode_selector.get_active_text();
3971 SnapMode mode = SnapNormal;
3973 if (choice == _("Normal")) {
3975 } else if (choice == _("Magnetic")) {
3976 mode = SnapMagnetic;
3979 set_snap_mode (mode);
3985 Editor::zoom_focus_selection_done (GdkEventAny *ev)
3991 string choice = zoom_focus_selector.get_active_text();
3992 ZoomFocus focus_type = ZoomFocusLeft;
3994 if (choice == _("Left")) {
3995 focus_type = ZoomFocusLeft;
3996 } else if (choice == _("Right")) {
3997 focus_type = ZoomFocusRight;
3998 } else if (choice == _("Center")) {
3999 focus_type = ZoomFocusCenter;
4000 } else if (choice == _("Playhead")) {
4001 focus_type = ZoomFocusPlayhead;
4002 } else if (choice == _("Edit Cursor")) {
4003 focus_type = ZoomFocusEdit;
4006 set_zoom_focus (focus_type);
4012 Editor::edit_controls_button_release (GdkEventButton* ev)
4014 if (Keyboard::is_context_menu_event (ev)) {
4015 ARDOUR_UI::instance()->add_route ();
4021 Editor::track_selection_changed ()
4023 switch (selection->tracks.size()){
4027 set_selected_mixer_strip (*(selection->tracks.front()));
4031 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4032 (*i)->set_selected (false);
4033 if (mouse_mode == MouseRange) {
4034 (*i)->hide_selection ();
4038 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4039 (*i)->set_selected (true);
4040 if (mouse_mode == MouseRange) {
4041 (*i)->show_selection (selection->time);
4047 Editor::time_selection_changed ()
4049 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4050 (*i)->hide_selection ();
4053 if (selection->tracks.empty()) {
4054 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4055 (*i)->show_selection (selection->time);
4058 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4059 (*i)->show_selection (selection->time);
4065 Editor::region_selection_changed ()
4067 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4068 (*i)->set_selected_regionviews (selection->audio_regions);
4073 Editor::point_selection_changed ()
4075 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4076 (*i)->set_selected_points (selection->points);
4081 Editor::run_sub_event_loop ()
4083 Keyboard::the_keyboard().allow_focus (true);
4084 sub_event_loop_status = 0;
4089 Editor::finish_sub_event_loop (int status)
4092 Keyboard::the_keyboard().allow_focus (false);
4093 sub_event_loop_status = status;
4097 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
4099 finish_sub_event_loop (status);
4104 Editor::mouse_select_button_release (GdkEventButton* ev)
4106 /* this handles just right-clicks */
4108 if (ev->button != 3) {
4115 Editor::TrackViewList *
4116 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
4119 TrackViewList::iterator i;
4121 v = new TrackViewList;
4123 if (track == 0 && group == 0) {
4127 for (i = track_views.begin(); i != track_views.end (); ++i) {
4131 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
4133 /* just the view for this track
4136 v->push_back (track);
4140 /* views for all tracks in the edit group */
4142 for (i = track_views.begin(); i != track_views.end (); ++i) {
4144 if (group == 0 || (*i)->edit_group() == group) {
4154 Editor::set_zoom_focus (ZoomFocus f)
4156 if (zoom_focus != f) {
4158 vector<string> txt = internationalize (zoom_focus_strings);
4159 zoom_focus_selector.set_active_text (txt[(int)f]);
4160 ZoomFocusChanged (); /* EMIT_SIGNAL */
4167 Editor::ensure_float (Window& win)
4169 win.set_transient_for (*this);
4173 Editor::pane_allocation_handler (GtkAllocation *alloc, Gtk::Paned* which)
4175 /* recover or initialize pane positions. do this here rather than earlier because
4176 we don't want the positions to change the child allocations, which they seem to do.
4182 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
4184 static int32_t done[4] = { 0, 0, 0, 0 };
4187 if ((geometry = find_named_node (*node, "geometry")) == 0) {
4188 width = default_width;
4189 height = default_height;
4191 width = atoi(geometry->property("x_size")->value());
4192 height = atoi(geometry->property("y_size")->value());
4195 if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
4201 if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
4203 snprintf (buf, sizeof(buf), "%d", pos);
4205 pos = atoi (prop->value());
4208 if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gobj())->allocation.width > pos)) {
4209 track_list_canvas_pane.set_position (pos);
4212 } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
4218 if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
4219 pos = width - (95 * 2);
4220 snprintf (buf, sizeof(buf), "%d", pos);
4222 pos = atoi (prop->value());
4225 if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gobj())->allocation.width > pos)) {
4226 canvas_region_list_pane.set_position (pos);
4229 } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
4235 if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
4236 pos = width - (95 * 2);
4237 snprintf (buf, sizeof(buf), "%d", pos);
4239 pos = atoi (prop->value());
4242 if ((done[2] = GTK_WIDGET(route_group_vpane.gobj())->allocation.height > pos)) {
4243 route_group_vpane.set_position (pos);
4246 } else if (which == static_cast<Gtk::Paned*> (®ion_selection_vpane)) {
4252 if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
4253 pos = width - (95 * 2);
4254 snprintf (buf, sizeof(buf), "%d", pos);
4256 pos = atoi (prop->value());
4259 if ((done[3] = GTK_WIDGET(region_selection_vpane.gobj())->allocation.height > pos)) {
4260 region_selection_vpane.set_position (pos);
4266 Editor::detach_tearoff (Gtk::Box* b, Gtk::Widget* w)
4268 if (tools_tearoff->torn_off() &&
4269 mouse_mode_tearoff->torn_off()) {
4270 top_hbox.remove (toolbar_frame);
4273 ensure_float (*w->get_toplevel());
4277 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Widget* w, int32_t n)
4279 if (toolbar_frame.get_parent() == 0) {
4280 top_hbox.pack_end (toolbar_frame);
4285 Editor::set_show_measures (bool yn)
4287 if (_show_measures != yn) {
4290 if ((_show_measures = yn) == true) {
4293 DisplayControlChanged (ShowMeasures);
4299 Editor::set_follow_playhead (bool yn)
4301 if (_follow_playhead != yn) {
4302 if ((_follow_playhead = yn) == true) {
4304 update_current_screen ();
4306 DisplayControlChanged (FollowPlayhead);
4312 Editor::toggle_xfade_active (Crossfade* xfade)
4314 xfade->set_active (!xfade->active());
4318 Editor::toggle_xfade_length (Crossfade* xfade)
4320 xfade->set_follow_overlap (!xfade->following_overlap());
4324 Editor::edit_xfade (Crossfade* xfade)
4326 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
4330 cew.ok_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 1));
4331 cew.cancel_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 0));
4332 cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
4336 if (cew.run_status() == 1) {
4338 xfade->StateChanged (Change (~0));
4343 Editor::playlist_selector () const
4345 return *_playlist_selector;
4349 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
4353 ret = nudge_clock.current_duration (pos);
4354 next = ret + 1; /* XXXX fix me */
4360 Editor::end_location_changed (Location* location)
4362 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
4363 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
4367 Editor::playlist_deletion_dialog (Playlist* pl)
4369 ArdourDialog dialog ("playlist deletion dialog");
4370 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4371 "If left alone, no audio files used by it will be cleaned.\n"
4372 "If deleted, audio files used by it alone by will cleaned."),
4375 Button del_button (_("Delete playlist"));
4376 Button keep_button (_("Keep playlist"));
4377 Button abort_button (_("Cancel cleanup"));
4380 button_box.set_spacing (7);
4381 button_box.set_homogeneous (true);
4382 button_box.pack_end (del_button, false, false);
4383 button_box.pack_end (keep_button, false, false);
4384 button_box.pack_end (abort_button, false, false);
4386 vbox.set_spacing (5);
4387 vbox.set_border_width (5);
4388 vbox.pack_start (label);
4389 vbox.pack_start (button_box);
4392 dialog.set_position (Gtk::WIN_POS_CENTER);
4395 del_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 0));
4396 keep_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 1));
4397 abort_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 2));
4400 dialog.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
4404 switch (dialog.run_status()) {
4406 /* keep the playlist */
4410 /* delete the playlist */
4418 /* keep the playlist */
4424 Editor::audio_region_selection_covers (jack_nframes_t where)
4426 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
4427 if ((*a)->region.covers (where)) {
4436 Editor::prepare_for_cleanup ()
4438 cut_buffer->clear_audio_regions ();
4439 cut_buffer->clear_playlists ();
4441 selection->clear_audio_regions ();
4442 selection->clear_playlists ();
4446 Editor::init_colormap ()
4448 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
4449 pair<ColorID,int> newpair;
4451 newpair.first = (ColorID) x;
4452 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
4453 color_map.insert (newpair);
4458 Editor::transport_loop_location()
4461 return session->locations()->auto_loop_location();
4468 Editor::transport_punch_location()
4471 return session->locations()->auto_punch_location();