2 Copyright (C) 2000 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include <sigc++/bind.h>
29 #include <libgnomecanvasmm/init.h>
31 #include <pbd/error.h>
33 #include <gtkmm2ext/gtk_ui.h>
34 #include <gtkmm2ext/tearoff.h>
35 #include <gtkmm2ext/utils.h>
37 #include <ardour/audio_track.h>
38 #include <ardour/diskstream.h>
39 #include <ardour/plugin_manager.h>
40 #include <ardour/location.h>
41 #include <ardour/audioplaylist.h>
42 #include <ardour/audioregion.h>
43 #include <ardour/session.h>
44 #include <ardour/session_route.h>
45 #include <ardour/tempo.h>
46 #include <ardour/utils.h>
48 #include "ardour_ui.h"
49 #include "canvas-ruler.h"
50 #include "canvas-simpleline.h"
51 #include "canvas-simplerect.h"
52 #include "canvas-waveview.h"
53 #include "check_mark.h"
55 #include "grouped_buttons.h"
58 #include "playlist_selector.h"
59 #include "regionview.h"
60 #include "rgb_macros.h"
61 #include "selection.h"
62 #include "streamview.h"
63 #include "time_axis_view.h"
65 #include "crossfade_view.h"
67 #include "public_editor.h"
68 #include "crossfade_edit.h"
69 #include "audio_time_axis.h"
70 #include "gui_thread.h"
75 #include "imageframe_socket_handler.h"
76 /* </CMT Additions> */
80 using namespace ARDOUR;
83 using namespace Gtkmm2ext;
84 using namespace Editing;
86 /* XXX this is a hack. it ought to be the maximum value of an jack_nframes_t */
88 const double max_canvas_coordinate = 100000000.0;
89 const double Editor::timebar_height = 15.0;
91 #include "editor_xpms"
93 static const gchar *route_list_titles[] = {
98 static const gchar *edit_group_list_titles[] = {
102 static const gchar *named_selection_display_titles[] = {
107 static const int32_t slide_index = 0;
108 static const int32_t splice_index = 1;
110 static const gchar *edit_mode_strings[] = {
116 static const gchar *snap_type_strings[] = {
140 static const gchar *snap_mode_strings[] = {
146 static const gchar *zoom_focus_strings[] = {
155 /* Soundfile drag-n-drop */
157 Gdk::Cursor* Editor::cross_hair_cursor = 0;
158 Gdk::Cursor* Editor::selector_cursor = 0;
159 Gdk::Cursor* Editor::trimmer_cursor = 0;
160 Gdk::Cursor* Editor::grabber_cursor = 0;
161 Gdk::Cursor* Editor::zoom_cursor = 0;
162 Gdk::Cursor* Editor::time_fx_cursor = 0;
163 Gdk::Cursor* Editor::fader_cursor = 0;
164 Gdk::Cursor* Editor::speaker_cursor = 0;
165 Gdk::Cursor* Editor::null_cursor = 0;
166 Gdk::Cursor* Editor::wait_cursor = 0;
167 Gdk::Cursor* Editor::timebar_cursor = 0;
169 GdkPixmap *Editor::check_pixmap = 0;
170 GdkBitmap *Editor::check_mask = 0;
171 GdkPixmap *Editor::empty_pixmap = 0;
172 GdkBitmap *Editor::empty_mask = 0;
174 Editor::Editor (AudioEngine& eng)
177 /* time display buttons */
179 minsec_label (_("Mins:Secs")),
180 bbt_label (_("Bars:Beats")),
181 smpte_label (_("SMPTE")),
182 frame_label (_("Frames")),
183 tempo_label (_("Tempo")),
184 meter_label (_("Meter")),
185 mark_label (_("Location Markers")),
186 range_mark_label (_("Range Markers")),
187 transport_mark_label (_("Loop/Punch Ranges")),
189 edit_packer (3, 3, false),
190 edit_hscroll_left_arrow (Gtk::ARROW_LEFT, Gtk::SHADOW_OUT),
191 edit_hscroll_right_arrow (Gtk::ARROW_RIGHT, Gtk::SHADOW_OUT),
193 /* tool bar related */
195 editor_mixer_button (_("editor\nmixer")),
197 selection_start_clock (X_("SelectionStartClock"), true),
198 selection_end_clock (X_("SelectionEndClock"), true),
199 edit_cursor_clock (X_("EditCursorClock"), true),
200 zoom_range_clock (X_("ZoomRangeClock"), true, true),
202 toolbar_selection_clock_table (2,3),
204 mouse_mode_button_table (2, 3),
206 mouse_select_button (_("range")),
207 mouse_move_button (_("object")),
208 mouse_gain_button (_("gain")),
209 mouse_zoom_button (_("zoom")),
210 mouse_timefx_button (_("timefx")),
211 mouse_audition_button (_("listen")),
213 automation_mode_button (_("mode")),
214 global_automation_button (_("automation")),
216 edit_mode_label (_("Edit Mode")),
217 snap_type_label (_("Snap To")),
218 snap_mode_label(_("Snap Mode")),
219 zoom_focus_label (_("Zoom Focus")),
221 /* <CMT Additions> */
222 image_socket_listener(0),
223 /* </CMT Additions> */
227 nudge_label (_("Nudge")),
228 nudge_clock (X_("NudgeClock"), true, true)
233 /* we are a singleton */
235 PublicEditor::_instance = this;
239 check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
240 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
241 &check_mask, NULL, (gchar **) check_xpm);
242 empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
243 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
244 &empty_mask, NULL, (gchar **) empty_xpm);
248 selection = new Selection;
249 cut_buffer = new Selection;
251 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
252 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
253 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
254 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
256 clicked_regionview = 0;
257 clicked_trackview = 0;
258 clicked_audio_trackview = 0;
259 clicked_crossfadeview = 0;
260 clicked_control_point = 0;
261 latest_regionview = 0;
262 last_update_frame = 0;
264 last_audition_region = 0;
265 current_mixer_strip = 0;
266 current_bbt_points = 0;
268 snap_type = SnapToFrame;
269 set_snap_to (snap_type);
270 snap_mode = SnapNormal;
271 set_snap_mode (snap_mode);
272 snap_threshold = 5.0;
273 bbt_beat_subdivision = 4;
276 autoscroll_timeout_tag = -1;
277 interthread_progress_window = 0;
278 current_interthread_info = 0;
279 _show_measures = true;
280 _show_waveforms = true;
281 _show_waveforms_recording = true;
282 first_action_message = 0;
284 show_gain_after_trim = false;
285 no_zoom_repos_update = false;
286 ignore_route_list_reorder = false;
287 verbose_cursor_on = true;
288 route_removal = false;
290 show_automatic_regions_in_region_list = true;
291 have_pending_keyboard_selection = false;
292 _follow_playhead = true;
293 _xfade_visibility = true;
294 editor_ruler_menu = 0;
295 no_ruler_shown_update = false;
296 edit_group_list_menu = 0;
298 region_list_menu = 0;
300 marker_menu_item = 0;
302 transport_marker_menu = 0;
303 new_transport_marker_menu = 0;
304 editor_mixer_strip_width = Wide;
305 repos_zoom_queued = false;
306 import_audio_item = 0;
307 embed_audio_item = 0;
308 region_edit_menu_split_item = 0;
310 region_edit_menu_split_multichannel_item = 0;
311 edit_hscroll_dragging = false;
313 ignore_mouse_mode_toggle = false;
314 current_stepping_trackview = 0;
316 entered_regionview = 0;
317 clear_entered_track = false;
318 _new_regionviews_show_envelope = false;
319 current_timestretch = 0;
324 location_marker_color = color_map[cLocationMarker];
325 location_range_color = color_map[cLocationRange];
326 location_cd_marker_color = color_map[cLocationCDMarker];
327 location_loop_color = color_map[cLocationLoop];
328 location_punch_color = color_map[cLocationPunch];
330 range_marker_drag_rect = 0;
331 marker_drag_line = 0;
333 mouse_mode = MouseZoom; /* force change in next call */
334 set_mouse_mode (MouseObject, true);
336 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
337 zoom_focus = ZoomFocusLeft;
338 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
340 initialize_rulers ();
341 initialize_canvas ();
343 track_canvas_scroller.add (track_canvas);
344 track_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
345 track_canvas_scroller.set_name ("TrackCanvasScroller");
347 track_canvas_scroller.get_vadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
348 track_canvas_scroller.get_vadjustment()->set_step_increment (10.0);
350 track_canvas_scroller.get_hadjustment()->set_lower (0.0);
351 track_canvas_scroller.get_hadjustment()->set_upper (1200.0);
352 track_canvas_scroller.get_hadjustment()->set_step_increment (20.0);
353 track_canvas_scroller.get_hadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
355 edit_vscrollbar.set_adjustment(*track_canvas_scroller.get_vadjustment());
356 edit_hscrollbar.set_adjustment(*track_canvas_scroller.get_hadjustment());
358 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_press));
359 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_release));
360 edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscroll_slider_allocate));
362 time_canvas_scroller.add (time_canvas);
363 time_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
364 time_canvas_scroller.set_hadjustment (*track_canvas_scroller.get_hadjustment());
365 time_canvas_scroller.set_name ("TimeCanvasScroller");
367 edit_controls_vbox.set_spacing (track_spacing);
368 edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
369 edit_controls_scroller.add (edit_controls_hbox);
370 edit_controls_scroller.set_name ("EditControlsBase");
371 edit_controls_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
373 Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
375 viewport->set_shadow_type (Gtk::SHADOW_NONE);
376 viewport->set_name ("EditControlsBase");
377 viewport->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
378 viewport->signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
383 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
386 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
388 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
389 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
390 time_canvas_vbox.pack_start (*frames_ruler, false, false);
391 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
392 time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
393 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
395 bbt_label.set_name ("EditorTimeButton");
396 bbt_label.set_size_request (-1, (int)timebar_height);
397 bbt_label.set_alignment (1.0, 0.5);
398 bbt_label.set_padding (5,0);
399 minsec_label.set_name ("EditorTimeButton");
400 minsec_label.set_size_request (-1, (int)timebar_height);
401 minsec_label.set_alignment (1.0, 0.5);
402 minsec_label.set_padding (5,0);
403 smpte_label.set_name ("EditorTimeButton");
404 smpte_label.set_size_request (-1, (int)timebar_height);
405 smpte_label.set_alignment (1.0, 0.5);
406 smpte_label.set_padding (5,0);
407 frame_label.set_name ("EditorTimeButton");
408 frame_label.set_size_request (-1, (int)timebar_height);
409 frame_label.set_alignment (1.0, 0.5);
410 frame_label.set_padding (5,0);
411 tempo_label.set_name ("EditorTimeButton");
412 tempo_label.set_size_request (-1, (int)timebar_height);
413 tempo_label.set_alignment (1.0, 0.5);
414 tempo_label.set_padding (5,0);
415 meter_label.set_name ("EditorTimeButton");
416 meter_label.set_size_request (-1, (int)timebar_height);
417 meter_label.set_alignment (1.0, 0.5);
418 meter_label.set_padding (5,0);
419 mark_label.set_name ("EditorTimeButton");
420 mark_label.set_size_request (-1, (int)timebar_height);
421 mark_label.set_alignment (1.0, 0.5);
422 mark_label.set_padding (5,0);
423 range_mark_label.set_name ("EditorTimeButton");
424 range_mark_label.set_size_request (-1, (int)timebar_height);
425 range_mark_label.set_alignment (1.0, 0.5);
426 range_mark_label.set_padding (5,0);
427 transport_mark_label.set_name ("EditorTimeButton");
428 transport_mark_label.set_size_request (-1, (int)timebar_height);
429 transport_mark_label.set_alignment (1.0, 0.5);
430 transport_mark_label.set_padding (5,0);
432 time_button_vbox.pack_start (minsec_label, false, false);
433 time_button_vbox.pack_start (smpte_label, false, false);
434 time_button_vbox.pack_start (frame_label, false, false);
435 time_button_vbox.pack_start (bbt_label, false, false);
436 time_button_vbox.pack_start (meter_label, false, false);
437 time_button_vbox.pack_start (tempo_label, false, false);
438 time_button_vbox.pack_start (mark_label, false, false);
440 time_button_event_box.add (time_button_vbox);
442 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
443 time_button_event_box.set_name ("TimebarLabelBase");
444 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
446 /* these enable us to have a dedicated window (for cursor setting, etc.)
447 for the canvas areas.
450 track_canvas_event_box.add (track_canvas_scroller);
452 time_canvas_event_box.add (time_canvas_vbox);
453 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
456 edit_packer.set_col_spacings (0);
457 edit_packer.set_row_spacings (0);
458 edit_packer.set_homogeneous (false);
459 edit_packer.set_name ("EditorWindow");
461 // edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, Gtk::FILL, 0, 0, 0);
462 // edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, 0, 0, 0);
463 // edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, Gtk::FILL, 0, 0, 0);
464 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
466 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
467 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
469 edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
470 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
471 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
473 edit_frame.set_name ("BaseFrame");
474 edit_frame.set_shadow_type (SHADOW_IN);
475 edit_frame.add (edit_packer);
477 zoom_in_button.set_name ("EditorTimeButton");
478 zoom_out_button.set_name ("EditorTimeButton");
479 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
480 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
482 // zoom_onetoone_button.set_name ("EditorTimeButton");
483 zoom_out_full_button.set_name ("EditorTimeButton");
484 // ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1"));
485 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
487 zoom_in_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_in_button_xpm)))));
488 zoom_out_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_button_xpm)))));
489 zoom_out_full_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_full_button_xpm)))));
490 // zoom_onetoone_button.add (*(manage (new Gtk::Image (zoom_onetoone_button_xpm))));
493 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
494 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
495 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
496 // zoom_onetoone_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom), 1.0));
498 zoom_indicator_box.pack_start (zoom_out_button, false, false);
499 zoom_indicator_box.pack_start (zoom_in_button, false, false);
500 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
501 // zoom_indicator_box.pack_start (zoom_onetoone_button, false, false);
502 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
504 zoom_indicator_label.set_text (_("Zoom Span"));
505 zoom_indicator_label.set_name ("ToolBarLabel");
508 zoom_indicator_vbox.set_spacing (3);
509 zoom_indicator_vbox.set_border_width (3);
510 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
511 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
514 bottom_hbox.set_border_width (3);
515 bottom_hbox.set_spacing (3);
517 route_display_model = ListStore::create(route_display_columns);
518 route_list.set_model (route_display_model);
519 route_list.append_column (_("Tracks"), route_display_columns.text);
520 route_list.set_name ("TrackListDisplay");
521 route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
522 route_list.set_reorderable (true);
524 route_list.set_size_request (75,-1);
525 route_list.set_headers_visible (true);
526 route_list.set_headers_clickable (true);
528 route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func));
529 route_display_model->signal_rows_reordered().connect (mem_fun (*this, &Editor::queue_route_list_reordered));
532 //route_list.set_shadow_type (Gtk::SHADOW_IN);
534 route_list_scroller.add (route_list);
535 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
537 route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed));
538 route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click));
540 edit_group_list_button_label.set_text (_("Edit Groups"));
541 edit_group_list_button_label.set_name ("EditGroupTitleButton");
542 edit_group_list_button.add (edit_group_list_button_label);
543 edit_group_list_button.set_name ("EditGroupTitleButton");
545 group_model = ListStore::create(group_columns);
546 edit_group_list.set_model (group_model);
547 edit_group_list.append_column (_("active"), group_columns.is_active);
548 edit_group_list.append_column (_("groupname"), group_columns.text);
549 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
550 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
552 /* use checkbox for the active column */
554 CellRendererToggle *active_cell = dynamic_cast<CellRendererToggle*>(edit_group_list.get_column_cell_renderer (0));
555 active_cell->set_property ("activatable", true);
556 active_cell->set_property ("radio", false);
558 edit_group_list.set_name ("MixerGroupList");
559 //edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
560 route_list.set_headers_visible (false);
561 edit_group_list.set_reorderable (false);
562 edit_group_list.set_size_request (75, -1);
563 edit_group_list.columns_autosize ();
564 edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
566 edit_group_list_scroller.add (edit_group_list);
567 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
569 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
570 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
571 edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed));
573 TreeModel::Row row = *(group_model->append());
574 row[group_columns.is_active] = false;
575 row[group_columns.text] = (_("-all-"));
576 edit_group_list.get_selection()->select (row);
577 /* GTK2FIX is set_data(0) setting the is_active to false here?
578 list<string> stupid_list;
580 stupid_list.push_back ("*");
581 stupid_list.push_back (_("-all-"));
583 edit_group_list.rows().push_back (stupid_list);
584 edit_group_list.rows().back().set_data (0);
585 edit_group_list.rows().back().select();
588 edit_group_vbox.pack_start (edit_group_list_button, false, false);
589 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
591 route_list_frame.set_name ("BaseFrame");
592 route_list_frame.set_shadow_type (Gtk::SHADOW_IN);
593 route_list_frame.add (route_list_scroller);
595 edit_group_list_frame.set_name ("BaseFrame");
596 edit_group_list_frame.set_shadow_type (Gtk::SHADOW_IN);
597 edit_group_list_frame.add (edit_group_vbox);
599 route_group_vpane.add1 (route_list_frame);
600 route_group_vpane.add2 (edit_group_list_frame);
602 list_vpacker.pack_start (route_group_vpane, true, true);
604 region_list_model = TreeStore::create (region_list_columns);
605 region_list_sort_model = TreeModelSort::create (region_list_model);
606 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
608 region_list_display.set_model (region_list_sort_model);
609 region_list_display.append_column (_("Regions"), region_list_columns.name);
610 region_list_display.set_reorderable (true);
611 region_list_display.set_size_request (100, -1);
612 region_list_display.set_data ("editor", this);
613 region_list_display.set_flags (Gtk::CAN_FOCUS);
614 region_list_display.set_name ("RegionListDisplay");
616 region_list_scroller.add (region_list_display);
617 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
619 vector<Gtk::TargetEntry> region_list_target_table;
621 region_list_target_table.push_back (TargetEntry ("STRING"));
622 region_list_target_table.push_back (TargetEntry ("text/plain"));
623 region_list_target_table.push_back (TargetEntry ("text/uri-list"));
624 region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
626 region_list_display.drag_dest_set (region_list_target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
627 region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
629 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
630 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
631 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
632 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
633 region_list_display.signal_enter_notify_event().connect (mem_fun(*this, &Editor::region_list_display_enter_notify));
634 region_list_display.signal_leave_notify_event().connect (mem_fun(*this, &Editor::region_list_display_leave_notify));
635 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
637 //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
638 //region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click));
640 named_selection_scroller.add (named_selection_display);
641 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
643 named_selection_model = TreeStore::create (named_selection_columns);
644 named_selection_display.set_model (named_selection_model);
645 named_selection_display.set_name ("RegionListDisplay");
646 named_selection_display.set_size_request (100, -1);
647 named_selection_display.set_headers_visible (true);
648 named_selection_display.set_headers_clickable (true);
649 named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
650 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
651 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
653 region_selection_vpane.pack1 (region_list_scroller, true, true);
654 region_selection_vpane.pack2 (named_selection_scroller, true, true);
656 canvas_region_list_pane.pack1 (edit_frame, true, true);
657 canvas_region_list_pane.pack2 (region_selection_vpane, true, true);
659 track_list_canvas_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
660 static_cast<Gtk::Paned*> (&track_list_canvas_pane)));
661 canvas_region_list_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
662 static_cast<Gtk::Paned*> (&canvas_region_list_pane)));
663 route_group_vpane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
664 static_cast<Gtk::Paned*> (&route_group_vpane)));
665 region_selection_vpane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
666 static_cast<Gtk::Paned*> (®ion_selection_vpane)));
668 track_list_canvas_pane.pack1 (list_vpacker, true, true);
669 track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true);
671 /* provide special pane-handle event handling for easy "hide" action */
673 /* 0: collapse to show left/upper child
674 1: collapse to show right/lower child
677 route_group_vpane.set_data ("collapse-direction", (gpointer) 0);
678 region_selection_vpane.set_data ("collapse-direction", (gpointer) 0);
679 canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0);
680 track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1);
682 route_group_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&route_group_vpane)));
683 region_selection_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (®ion_selection_vpane)));
684 canvas_region_list_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&canvas_region_list_pane)));
685 track_list_canvas_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&track_list_canvas_pane)));
687 top_hbox.pack_start (toolbar_frame, true, true);
689 HBox *hbox = manage (new HBox);
690 hbox->pack_start (track_list_canvas_pane, true, true);
692 global_vpacker.pack_start (top_hbox, false, false);
693 global_vpacker.pack_start (*hbox, true, true);
695 global_hpacker.pack_start (global_vpacker, true, true);
697 set_name ("EditorWindow");
699 vpacker.pack_end (global_hpacker, true, true);
701 _playlist_selector = new PlaylistSelector();
702 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
704 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
708 nudge_forward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
709 nudge_backward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
711 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
712 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
714 nudge_forward_button.set_name ("TransportButton");
715 nudge_backward_button.set_name ("TransportButton");
717 fade_context_menu.set_name ("ArdourContextMenu");
719 install_keybindings ();
721 set_title (_("ardour: editor"));
722 set_wmclass (_("ardour_editor"), "Ardour");
725 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
727 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
728 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
736 /* <CMT Additions> */
737 if(image_socket_listener)
739 if(image_socket_listener->is_connected())
741 image_socket_listener->close_connection() ;
744 delete image_socket_listener ;
745 image_socket_listener = 0 ;
747 /* </CMT Additions> */
751 Editor::add_toplevel_controls (Container& cont)
753 vpacker.pack_start (cont, false, false);
758 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
760 /* note: the selection will take care of the vanishing
761 audioregionview by itself.
764 if (clicked_regionview == rv) {
765 clicked_regionview = 0;
768 if (entered_regionview == rv) {
769 set_entered_regionview (0);
774 Editor::set_entered_regionview (AudioRegionView* rv)
776 if (rv == entered_regionview) {
780 if (entered_regionview) {
781 entered_regionview->exited ();
784 if ((entered_regionview = rv) != 0) {
785 entered_regionview->entered ();
790 Editor::set_entered_track (TimeAxisView* tav)
793 entered_track->exited ();
796 if ((entered_track = tav) != 0) {
797 entered_track->entered ();
802 Editor::left_track_canvas (GdkEventCrossing *ev)
804 set_entered_track (0);
805 set_entered_regionview (0);
811 Editor::initialize_canvas ()
813 Gnome::Canvas::init ();
815 /* adjust sensitivity for "picking" items */
817 // GNOME_CANVAS(track_canvas)->close_enough = 2;
819 track_canvas.signal_event().connect (mem_fun (*this, &Editor::track_canvas_event));
820 track_canvas.set_name ("EditorMainCanvas");
821 track_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
822 track_canvas.signal_event().connect (mem_fun (*this, &Editor::track_canvas_event));
823 track_canvas.signal_leave_notify_event().connect (mem_fun(*this, &Editor::left_track_canvas));
825 /* set up drag-n-drop */
826 vector<Gtk::TargetEntry> target_table;
828 target_table.push_back (TargetEntry ("STRING"));
829 target_table.push_back (TargetEntry ("text/plain"));
830 target_table.push_back (TargetEntry ("text/uri-list"));
831 target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
833 track_canvas.drag_dest_set (target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
834 track_canvas.signal_drag_data_received().connect (mem_fun(*this, &Editor::track_canvas_drag_data_received));
836 /* stuff for the verbose canvas cursor */
838 Pango::FontDescription font = get_font_for_style (N_("VerboseCanvasCursor"));
840 verbose_canvas_cursor = new Gnome::Canvas::Text (*track_canvas.root());
841 verbose_canvas_cursor->set_property ("font_desc", font);
842 verbose_canvas_cursor->set_property ("anchor", GTK_ANCHOR_NW);
843 verbose_canvas_cursor->set_property ("fill_color_rgba", color_map[cVerboseCanvasCursor]);
845 verbose_cursor_visible = false;
847 /* a group to hold time (measure) lines */
849 time_line_group = new Gnome::Canvas::Group (*track_canvas.root(), 0.0, 0.0);
850 cursor_group = new Gnome::Canvas::Group (*track_canvas.root(), 0.0, 0.0);
852 time_canvas.set_name ("EditorTimeCanvas");
853 time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
855 meter_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, 0.0);
856 tempo_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, 0.0);
857 marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 2.0);
858 range_marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 3.0);
859 transport_marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 4.0);
861 tempo_bar = new Gnome::Canvas::SimpleRect (*tempo_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
862 tempo_bar->set_property ("fill_color_rgba", color_map[cTempoBar]);
863 tempo_bar->set_property ("outline_pixels", 0);
865 meter_bar = new Gnome::Canvas::SimpleRect (*meter_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
866 meter_bar->set_property ("fill_color_rgba", color_map[cMeterBar]);
867 meter_bar->set_property ("outline_pixels",0);
869 marker_bar = new Gnome::Canvas::SimpleRect (*marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
870 marker_bar->set_property ("fill_color_rgba", color_map[cMarkerBar]);
871 marker_bar->set_property ("outline_pixels", 0);
873 range_marker_bar = new Gnome::Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
874 range_marker_bar->set_property ("fill_color_rgba", color_map[cRangeMarkerBar]);
875 range_marker_bar->set_property ("outline_pixels", 0);
877 transport_marker_bar = new Gnome::Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
878 transport_marker_bar->set_property ("fill_color_rgba", color_map[cTransportMarkerBar]);
879 transport_marker_bar->set_property ("outline_pixels", 0);
881 range_bar_drag_rect = new Gnome::Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
882 range_bar_drag_rect->set_property ("fill_color_rgba", color_map[cRangeDragBarRectFill]);
883 range_bar_drag_rect->set_property ("outline_color_rgba", color_map[cRangeDragBarRect]);
884 range_bar_drag_rect->set_property ("outline_pixels", 0);
885 range_bar_drag_rect->hide ();
887 transport_bar_drag_rect = new Gnome::Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
888 transport_bar_drag_rect ->set_property ("fill_color_rgba", color_map[cTransportDragRectFill]);
889 transport_bar_drag_rect->set_property ("outline_color_rgba", color_map[cTransportDragRect]);
890 transport_bar_drag_rect->set_property ("outline_pixels", 0);
891 transport_bar_drag_rect->hide ();
893 marker_drag_line_points->push_back(Gnome::Art::Point(0.0, 0.0));
894 marker_drag_line_points->push_back(Gnome::Art::Point(0.0, 0.0));
896 marker_drag_line = new Gnome::Canvas::Line (*track_canvas.root());
897 marker_drag_line->set_property ("width_pixels", 1);
898 marker_drag_line->set_property("fill_color_rgba", color_map[cMarkerDragLine]);
899 marker_drag_line->set_property("points", marker_drag_line_points->gobj());
900 marker_drag_line->hide();
902 range_marker_drag_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
903 range_marker_drag_rect->set_property ("fill_color_rgba", color_map[cRangeDragRectFill]);
904 range_marker_drag_rect->set_property ("outline_color_rgba", color_map[cRangeDragRect]);
905 range_marker_drag_rect->hide ();
907 transport_loop_range_rect = new Gnome::Canvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
908 transport_loop_range_rect->set_property ("fill_color_rgba", color_map[cTransportLoopRectFill]);
909 transport_loop_range_rect->set_property ("outline_color_rgba", color_map[cTransportLoopRect]);
910 transport_loop_range_rect->set_property ("outline_pixels", 1);
911 transport_loop_range_rect->hide();
913 transport_punch_range_rect = new Gnome::Canvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
914 transport_punch_range_rect->set_property ("fill_color_rgba", color_map[cTransportPunchRectFill]);
915 transport_punch_range_rect->set_property ("outline_color_rgba", color_map[cTransportPunchRect]);
916 transport_punch_range_rect->set_property ("outline_pixels", 0);
917 transport_punch_range_rect->hide();
919 transport_loop_range_rect->lower_to_bottom (); // loop on the bottom
921 transport_punchin_line = new Gnome::Canvas::Line (*time_line_group);
922 transport_punchin_line->set_property ("x1", 0.0);
923 transport_punchin_line->set_property ("y1", 0.0);
924 transport_punchin_line->set_property ("x2", 0.0);
925 transport_punchin_line->set_property ("y2", 0.0);
927 transport_punchin_line->set_property ("outline_color_rgba", color_map[cPunchInLine]);
928 transport_punchin_line->set_property ("outline_pixels", 1);
929 transport_punchin_line->hide ();
931 transport_punchout_line = new Gnome::Canvas::Line (*time_line_group);
932 transport_punchout_line->set_property ("x1", 0.0);
933 transport_punchout_line->set_property ("y1", 0.0);
934 transport_punchout_line->set_property ("x2", 0.0);
935 transport_punchout_line->set_property ("y2", 0.0);
936 transport_punchout_line->set_property ("outline_color_rgba", color_map[cPunchOutLine]);
937 transport_punchout_line->set_property ("outline_pixels", 1);
938 transport_punchout_line->hide();
940 // used to show zoom mode active zooming
941 zoom_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
942 zoom_rect->set_property ("fill_color_rgba", color_map[cZoomRectFill]);
943 zoom_rect->set_property ("outline_color_rgba", color_map[cZoomRect]);
944 zoom_rect->set_property ("outline_pixels", 1);
947 zoom_rect->signal_event().connect (mem_fun (*this, &Editor::canvas_zoom_rect_event));
949 // used as rubberband rect
950 rubberband_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
951 rubberband_rect->set_property ("outline_color_rgba", color_map[cRubberBandRect]);
952 rubberband_rect->set_property ("fill_color_rgba", (guint32) color_map[cRubberBandRectFill]);
953 rubberband_rect->set_property ("outline_pixels", 1);
954 rubberband_rect->hide();
956 tempo_bar->signal_event().connect (mem_fun (*this, &Editor::canvas_tempo_bar_event));
957 meter_bar->signal_event().connect (mem_fun (*this, &Editor::canvas_meter_bar_event));
958 marker_bar->signal_event().connect (mem_fun (*this, &Editor::canvas_marker_bar_event));
959 range_marker_bar->signal_event().connect (mem_fun (*this, &Editor::canvas_range_marker_bar_event));
960 transport_marker_bar->signal_event().connect (mem_fun (*this, &Editor::canvas_transport_marker_bar_event));
962 /* separator lines */
964 tempo_line_points.push_back(Gnome::Art::Point(0, timebar_height));
965 tempo_line_points.push_back(Gnome::Art::Point(max_canvas_coordinate, timebar_height));
967 tempo_line = new Gnome::Canvas::Line (*tempo_group, tempo_line_points);
968 tempo_line->set_property ("width_pixels", 0);
969 tempo_line->set_property ("fill_color", Gdk::Color ("#000000"));
971 meter_line_points.push_back(Gnome::Art::Point (0, timebar_height));
972 meter_line_points.push_back(Gnome::Art::Point(max_canvas_coordinate, timebar_height));
974 meter_line = new Gnome::Canvas::Line (*meter_group, meter_line_points);
975 meter_line->set_property ("width_pixels", 0);
976 meter_line->set_property ("fill_color", Gdk::Color ("#000000"));
978 marker_line_points.push_back(Gnome::Art::Point (0, timebar_height));
979 marker_line_points.push_back(Gnome::Art::Point(max_canvas_coordinate, timebar_height));
981 marker_line = new Gnome::Canvas::Line (*marker_group, marker_line_points);
982 marker_line->set_property ("width_pixels", 0);
983 marker_line->set_property ("fill_color", Gdk::Color ("#000000"));
985 range_marker_line = new Gnome::Canvas::Line (*range_marker_group, marker_line_points);
986 range_marker_line->set_property ("width_pixels", 0);
987 range_marker_line->set_property ("fill_color", Gdk::Color ("#000000"));
989 transport_marker_line = new Gnome::Canvas::Line (*transport_marker_group, marker_line_points);
990 transport_marker_line->set_property ("width_pixels", 0);
991 transport_marker_line->set_property ("fill_color", Gdk::Color ("#000000"));
993 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_loop_range_view), false));
994 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_punch_range_view), false));
996 double time_height = timebar_height * 5;
997 double time_width = FLT_MAX/frames_per_unit;
998 time_canvas.set_scroll_region(0.0, 0.0, time_width, time_height);
1000 edit_cursor = new Cursor (*this, "blue", canvas_edit_cursor_event);
1001 playhead_cursor = new Cursor (*this, "red", canvas_playhead_cursor_event);
1003 track_canvas.signal_size_allocate().connect (mem_fun(*this, &Editor::track_canvas_allocate));
1007 Editor::show_window ()
1011 /* now reset all audio_time_axis heights, because widgets might need
1017 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1018 tv = (static_cast<TimeAxisView*>(*i));
1019 tv->reset_height ();
1024 Editor::tie_vertical_scrolling ()
1026 edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
1028 float y1 = track_canvas_scroller.get_vadjustment()->get_value();
1029 playhead_cursor->set_y_axis(y1);
1030 edit_cursor->set_y_axis(y1);
1034 Editor::set_frames_per_unit (double fpu)
1036 jack_nframes_t frames;
1038 if (fpu == frames_per_unit) {
1046 // convert fpu to frame count
1048 frames = (jack_nframes_t) (fpu * canvas_width);
1050 /* don't allow zooms that fit more than the maximum number
1051 of frames into an 800 pixel wide space.
1054 if (max_frames / fpu < 800.0) {
1058 frames_per_unit = fpu;
1060 if (frames != zoom_range_clock.current_duration()) {
1061 zoom_range_clock.set (frames);
1064 /* only update these if we not about to call reposition_x_origin,
1065 which will do the same updates.
1069 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1072 if (!no_zoom_repos_update) {
1073 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1074 update_hscroller ();
1075 update_fixed_rulers ();
1076 tempo_map_changed (Change (0));
1079 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
1080 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1081 (*i)->reshow_selection (selection->time);
1085 ZoomChanged (); /* EMIT_SIGNAL */
1087 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
1088 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
1095 Editor::instant_save ()
1097 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
1102 session->add_instant_xml(get_state(), session->path());
1104 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
1109 Editor::reposition_x_origin (jack_nframes_t frame)
1111 if (frame != leftmost_frame) {
1112 leftmost_frame = frame;
1113 double pixel = frame_to_pixel (frame);
1114 if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
1115 track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
1117 track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
1118 XOriginChanged (); /* EMIT_SIGNAL */
1123 Editor::edit_cursor_clock_changed()
1125 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
1126 edit_cursor->set_position (edit_cursor_clock.current_time());
1132 Editor::zoom_adjustment_changed ()
1134 if (session == 0 || no_zoom_repos_update) {
1138 double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width;
1142 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1144 else if (fpu > session->current_end_frame() / (double) canvas_width) {
1145 fpu = session->current_end_frame() / (double) canvas_width;
1146 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1149 temporal_zoom (fpu);
1153 Editor::canvas_horizontally_scrolled ()
1155 /* XXX note the potential loss of accuracy here caused by
1156 adjustments being 32bit floats with only a 24 bit mantissa,
1157 whereas jack_nframes_t is at least a 32 bit uint32_teger.
1160 leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
1162 update_hscroller ();
1163 update_fixed_rulers ();
1165 if (!edit_hscroll_dragging) {
1166 tempo_map_changed (Change (0));
1168 update_tempo_based_rulers();
1173 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
1175 if (!repos_zoom_queued) {
1176 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
1177 repos_zoom_queued = true;
1182 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
1184 /* if we need to force an update to the hscroller stuff,
1185 don't set no_zoom_repos_update.
1188 no_zoom_repos_update = (frame != leftmost_frame);
1190 set_frames_per_unit (nfpu);
1191 if (no_zoom_repos_update) {
1192 reposition_x_origin (frame);
1194 no_zoom_repos_update = false;
1195 repos_zoom_queued = false;
1201 Editor::on_realize ()
1203 /* Even though we're not using acceleration, we want the
1206 Glib::RefPtr<Gdk::Pixmap> empty_pixmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1207 Glib::RefPtr<Gdk::Pixmap> empty_bitmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1210 track_context_menu.accelerate (*this->get_toplevel());
1211 track_region_context_menu.accelerate (*this->get_toplevel());
1213 Window::on_realize ();
1215 Gdk::Color white ("#ffffff" );
1216 null_cursor = new Gdk::Cursor(empty_pixmap, empty_bitmap, white, white, 0, 0);
1224 track_canvas_scroller.get_window()->set_cursor (*current_canvas_cursor);
1225 time_canvas_scroller.get_window()->set_cursor (*timebar_cursor);
1229 Editor::track_canvas_allocate (GtkAllocation *alloc)
1231 canvas_width = alloc->width;
1232 canvas_height = alloc->height;
1234 if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) {
1236 Pango::FontDescription font = get_font_for_style (N_("FirstActionMessage"));
1238 const char *txt1 = _("Start a new session\n");
1239 const char *txt2 = _("via Session menu");
1241 /* this mess of code is here to find out how wide this text is and
1242 position the message in the center of the editor window. there
1243 are two lines, so we use the longer of the the lines to
1244 compute width, and multiply the height by 2.
1250 /* this is a dummy widget that exists so that we can get the
1251 style from the RC file.
1254 Label foo (_(txt2));
1255 Glib::RefPtr<Pango::Layout> layout;
1256 foo.set_name ("NoSessionMessage");
1257 foo.ensure_style ();
1259 layout = foo.create_pango_layout (_(txt2));
1260 layout->set_font_description (font);
1261 layout->get_pixel_size (pixel_width, pixel_height);
1263 if (first_action_message == 0) {
1265 char txt[strlen(txt1)+strlen(txt2)+1];
1267 /* merge both lines */
1269 strcpy (txt, _(txt1));
1270 strcat (txt, _(txt2));
1272 first_action_message = new Gnome::Canvas::Text (*track_canvas.root());
1273 first_action_message->set_property ("font_desc", font);
1274 first_action_message->set_property ("fill_color_rgba", color_map[cFirstActionMessage]);
1275 first_action_message->set_property ("x", (gdouble) (canvas_width - pixel_width) / 2.0);
1276 first_action_message->set_property ("y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)));
1277 first_action_message->set_property ("anchor", GTK_ANCHOR_NORTH_WEST);
1278 first_action_message->set_property ("text", ustring (txt));
1283 first_action_message->set_property ("x", (gdouble) (canvas_width - pixel_width) / 2.0),
1284 first_action_message->set_property ("y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)));
1288 zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit));
1289 edit_cursor->set_position (edit_cursor->current_frame);
1290 playhead_cursor->set_position (playhead_cursor->current_frame);
1291 reset_scrolling_region (alloc);
1293 Resized (); /* EMIT_SIGNAL */
1297 Editor::reset_scrolling_region (GtkAllocation *alloc)
1299 guint32 last_canvas_unit;
1301 guint32 canvas_alloc_height, canvas_alloc_width;
1302 TrackViewList::iterator i;
1303 static bool first_time = true;
1305 /* We need to make sure that the canvas always has its
1306 scrolling region set to larger of:
1308 - the size allocated for it (within the container its packed in)
1309 - the size required to see the entire session
1311 If we don't ensure at least the first of these, the canvas
1312 does some wierd and in my view unnecessary stuff to center
1313 itself within the allocated area, which causes bad, bad
1316 XXX GnomeCanvas has fixed this, and has an option to
1317 control the centering behaviour.
1320 last_canvas_unit = (guint32) ceil ((float) max_frames / frames_per_unit);
1325 for (i = track_views.begin(); i != track_views.end(); ++i) {
1326 if ((*i)->control_parent) {
1327 height += (*i)->effective_height;
1328 height += track_spacing;
1333 height -= track_spacing;
1337 canvas_height = (guint32) height;
1340 canvas_alloc_height = alloc->height;
1341 canvas_alloc_width = alloc->width;
1343 canvas_alloc_height = track_canvas.get_height();
1344 canvas_alloc_width = track_canvas.get_width();
1347 canvas_height = max (canvas_height, canvas_alloc_height);
1348 track_canvas.set_scroll_region ( 0.0, 0.0, max (last_canvas_unit, canvas_alloc_width), canvas_height);
1350 if (edit_cursor) edit_cursor->set_length (canvas_alloc_height);
1351 if (playhead_cursor) playhead_cursor->set_length (canvas_alloc_height);
1353 if (marker_drag_line) {
1354 marker_drag_line_points->back().set_x(canvas_height);
1355 // cerr << "set mlA points, nc = " << marker_drag_line_points->num_points << endl;
1356 marker_drag_line->set_property("points", marker_drag_line_points);
1358 if (range_marker_drag_rect) {
1359 range_marker_drag_rect->set_property("y1", 0.0);
1360 range_marker_drag_rect->set_property("y2", (double) canvas_height);
1363 if (transport_loop_range_rect) {
1364 transport_loop_range_rect->set_property("y1", 0.0);
1365 transport_loop_range_rect->set_property("y2", (double) canvas_height);
1368 if (transport_punch_range_rect) {
1369 transport_punch_range_rect->set_property("y1", 0.0);
1370 transport_punch_range_rect->set_property("y2", (double) canvas_height);
1373 if (transport_punchin_line) {
1374 transport_punchin_line->set_property("y1", 0.0);
1375 transport_punchin_line->set_property("y2", (double) canvas_height);
1378 if (transport_punchout_line) {
1379 transport_punchout_line->set_property("y1", 0.0);
1380 transport_punchout_line->set_property("y2", (double) canvas_height);
1383 update_fixed_rulers ();
1385 if (is_visible() && first_time) {
1386 tempo_map_changed (Change (0));
1394 Editor::queue_session_control_changed (Session::ControlType t)
1396 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1400 Editor::session_control_changed (Session::ControlType t)
1402 // right now we're only tracking the loop and punch state
1405 case Session::AutoLoop:
1406 update_loop_range_view (true);
1408 case Session::PunchIn:
1409 case Session::PunchOut:
1410 update_punch_range_view (true);
1419 Editor::fake_add_edit_group (RouteGroup *group)
1421 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1425 Editor::fake_handle_new_audio_region (AudioRegion *region)
1427 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1431 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1433 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1437 Editor::fake_handle_new_duration ()
1439 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1443 Editor::start_scrolling ()
1445 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1446 (mem_fun(*this, &Editor::update_current_screen));
1448 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1449 (mem_fun(*this, &Editor::update_slower));
1453 Editor::stop_scrolling ()
1455 scroll_connection.disconnect ();
1456 slower_update_connection.disconnect ();
1460 Editor::map_position_change (jack_nframes_t frame)
1462 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1464 if (session == 0 || !_follow_playhead) {
1468 center_screen (frame);
1469 playhead_cursor->set_position (frame);
1473 Editor::center_screen (jack_nframes_t frame)
1475 float page = canvas_width * frames_per_unit;
1477 /* if we're off the page, then scroll.
1480 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1481 center_screen_internal (frame,page);
1486 Editor::center_screen_internal (jack_nframes_t frame, float page)
1491 frame -= (jack_nframes_t) page;
1496 reposition_x_origin (frame);
1500 Editor::handle_new_duration ()
1502 reset_scrolling_region ();
1505 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1506 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1509 update_hscroller ();
1513 Editor::update_title_s (string snap_name)
1515 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1521 Editor::update_title ()
1523 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1526 bool dirty = session->dirty();
1528 string wintitle = _("ardour: editor: ");
1534 wintitle += session->name();
1536 if (session->snap_name() != session->name()) {
1538 wintitle += session->snap_name();
1545 set_title (wintitle);
1550 Editor::connect_to_session (Session *t)
1554 if (first_action_message) {
1555 first_action_message->hide();
1558 flush_track_canvas();
1562 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1564 /* These signals can all be emitted by a non-GUI thread. Therefore the
1565 handlers for them must not attempt to directly interact with the GUI,
1566 but use Gtkmm2ext::UI::instance()->call_slot();
1569 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1570 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1571 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1572 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1573 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1574 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1575 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1576 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1577 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1578 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1579 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1580 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1581 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1583 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1584 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1586 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1588 session->foreach_edit_group(this, &Editor::add_edit_group);
1590 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1591 editor_mixer_button.set_name (X_("EditorMixerButton"));
1593 edit_cursor_clock.set_session (session);
1594 selection_start_clock.set_session (session);
1595 selection_end_clock.set_session (session);
1596 zoom_range_clock.set_session (session);
1597 _playlist_selector->set_session (session);
1598 nudge_clock.set_session (session);
1600 switch (session->get_edit_mode()) {
1602 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1606 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1610 Location* loc = session->locations()->auto_loop_location();
1612 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1613 if (loc->start() == loc->end()) {
1614 loc->set_end (loc->start() + 1);
1616 session->locations()->add (loc, false);
1617 session->set_auto_loop_location (loc);
1621 loc->set_name (_("Loop"));
1624 loc = session->locations()->auto_punch_location();
1626 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1627 if (loc->start() == loc->end()) {
1628 loc->set_end (loc->start() + 1);
1630 session->locations()->add (loc, false);
1631 session->set_auto_punch_location (loc);
1635 loc->set_name (_("Punch"));
1638 update_loop_range_view (true);
1639 update_punch_range_view (true);
1641 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1644 refresh_location_display ();
1645 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1646 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1647 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1648 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1649 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1651 reset_scrolling_region ();
1653 redisplay_regions ();
1654 redisplay_named_selections ();
1656 //route_list.freeze (); GTK2FIX
1657 route_display_model.clear ();
1658 session->foreach_route (this, &Editor::handle_new_route);
1659 // route_list.select_all ();
1661 //route_list.sort ();
1662 route_list_reordered ();
1663 //route_list.thaw ();
1665 if (embed_audio_item) {
1666 embed_audio_item->set_sensitive (true);
1668 if (import_audio_item) {
1669 import_audio_item->set_sensitive (true);
1672 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1673 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1676 /* ::reposition_x_origin() doesn't work right here, since the old
1677 position may be zero already, and it does nothing in such
1683 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1684 track_canvas_scroller.get_hadjustment()->set_value (0);
1686 update_hscroller ();
1687 restore_ruler_visibility ();
1688 tempo_map_changed (Change (0));
1690 edit_cursor->set_position (0);
1691 playhead_cursor->set_position (0);
1695 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1698 /* don't show master bus in a new session */
1700 if (ARDOUR_UI::instance()->session_is_new ()) {
1702 TreeModel::Children rows = route_display_model->children();
1703 TreeModel::Children::iterator i;
1705 //route_list.freeze ();
1707 for (i = rows.begin(); i != rows.end(); ++i) {
1708 TimeAxisView *tv = (*i)[route_display_columns.tv];
1709 AudioTimeAxisView *atv;
1711 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1712 if (atv->route().master()) {
1713 route_list.get_selection()->unselect (i);
1714 //(*i)->unselect ();
1719 //route_list.thaw ();
1724 Editor::build_cursors ()
1726 Gdk::Color fg ("#ff0000"); /* Red. */
1727 Gdk::Color bg ("#0000ff"); /* Blue. */
1730 Glib::RefPtr <Gdk::Pixmap> source, mask;
1731 source = Gdk::Pixmap::create_from_data (source, hand_bits,
1732 hand_width, hand_height, 1, fg, bg);
1733 Gdk::Pixmap::create_from_data(mask, handmask_bits,
1734 handmask_width, handmask_height, 1, fg, bg);
1735 grabber_cursor = new Gdk::Cursor (source, mask, fg, bg, hand_x_hot, hand_y_hot);
1738 Gdk::Color mbg ("#000000" ); /* Black */
1739 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1742 Glib::RefPtr <Gdk::Pixmap> source, mask;
1744 Gdk::Pixmap::create_from_data (source, mag_bits,
1745 mag_width, mag_height, 1, fg, bg);
1746 Gdk::Pixmap::create_from_data (mask, magmask_bits,
1747 mag_width, mag_height, 1, fg, bg);
1748 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1751 Gdk::Color fbg ("#ffffff" );
1752 Gdk::Color ffg ("#000000" );
1755 Glib::RefPtr <Gdk::Pixmap> source, mask;
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);
1765 Glib::RefPtr <Gdk::Pixmap> source, mask;
1766 Gdk::Pixmap::create_from_data (source,speaker_cursor_bits,
1767 speaker_cursor_width, speaker_cursor_height, 1, fg, bg);
1768 Gdk::Pixmap::create_from_data (mask, speaker_cursor_mask_bits,
1769 speaker_cursor_width, speaker_cursor_height, 1, fg, bg);
1770 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
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, Gnome::Canvas::Item* 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);
2512 // set_position(x, y-yoff);
2514 if ((prop = node.property ("zoom-focus"))) {
2515 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2518 if ((prop = node.property ("zoom"))) {
2519 set_frames_per_unit (atof (prop->value()));
2522 if ((prop = node.property ("snap-to"))) {
2523 set_snap_to ((SnapType) atoi (prop->value()));
2526 if ((prop = node.property ("snap-mode"))) {
2527 set_snap_mode ((SnapMode) atoi (prop->value()));
2530 if ((prop = node.property ("show-waveforms"))) {
2531 bool yn = (prop->value() == "yes");
2532 _show_waveforms = !yn;
2533 set_show_waveforms (yn);
2536 if ((prop = node.property ("show-waveforms-recording"))) {
2537 bool yn = (prop->value() == "yes");
2538 _show_waveforms_recording = !yn;
2539 set_show_waveforms_recording (yn);
2542 if ((prop = node.property ("show-measures"))) {
2543 bool yn = (prop->value() == "yes");
2544 _show_measures = !yn;
2545 set_show_measures (yn);
2548 if ((prop = node.property ("follow-playhead"))) {
2549 bool yn = (prop->value() == "yes");
2550 _follow_playhead = !yn;
2551 set_follow_playhead (yn);
2554 if ((prop = node.property ("xfades-visible"))) {
2555 bool yn = (prop->value() == "yes");
2556 _xfade_visibility = !yn;
2557 set_xfade_visibility (yn);
2560 if ((prop = node.property ("region-list-sort-type"))) {
2561 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2562 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2565 if ((prop = node.property ("mouse-mode"))) {
2566 MouseMode m = str2mousemode(prop->value());
2567 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2568 set_mouse_mode (m, true);
2570 mouse_mode = MouseGain; /* lie, to force the mode switch */
2571 set_mouse_mode (MouseObject, true);
2574 if ((prop = node.property ("editor-mixer-button"))) {
2575 editor_mixer_button.set_active(prop->value() == "yes");
2582 Editor::get_state ()
2584 XMLNode* node = new XMLNode ("Editor");
2587 if (is_realized()) {
2588 Glib::RefPtr<Gdk::Window> win = get_window();
2590 int x, y, xoff, yoff, width, height;
2591 win->get_root_origin(x, y);
2592 win->get_position(xoff, yoff);
2593 win->get_size(width, height);
2595 XMLNode* geometry = new XMLNode ("geometry");
2597 snprintf(buf, sizeof(buf), "%d", width);
2598 geometry->add_property("x_size", string(buf));
2599 snprintf(buf, sizeof(buf), "%d", height);
2600 geometry->add_property("y_size", string(buf));
2601 snprintf(buf, sizeof(buf), "%d", x);
2602 geometry->add_property("x_pos", string(buf));
2603 snprintf(buf, sizeof(buf), "%d", y);
2604 geometry->add_property("y_pos", string(buf));
2605 snprintf(buf, sizeof(buf), "%d", xoff);
2606 geometry->add_property("x_off", string(buf));
2607 snprintf(buf, sizeof(buf), "%d", yoff);
2608 geometry->add_property("y_off", string(buf));
2609 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gobj()));
2610 geometry->add_property("canvas_region_list_pane_pos", string(buf));
2611 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gobj()));
2612 geometry->add_property("track_list_canvas_pane_pos", string(buf));
2613 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(®ion_selection_vpane)->gobj()));
2614 geometry->add_property("region_selection_pane_pos", string(buf));
2615 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gobj()));
2616 geometry->add_property("route_group_pane_pos", string(buf));
2618 node->add_child_nocopy (*geometry);
2621 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2622 node->add_property ("zoom-focus", buf);
2623 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2624 node->add_property ("zoom", buf);
2625 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2626 node->add_property ("snap-to", buf);
2627 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2628 node->add_property ("snap-mode", buf);
2630 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2631 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2632 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2633 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2634 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2635 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2636 node->add_property ("mouse-mode", enum2str(mouse_mode));
2637 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2645 Editor::trackview_by_y_position (double y)
2647 TrackViewList::iterator iter;
2650 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2658 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2667 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2669 Location* before = 0;
2670 Location* after = 0;
2676 const jack_nframes_t one_second = session->frame_rate();
2677 const jack_nframes_t one_minute = session->frame_rate() * 60;
2679 jack_nframes_t presnap = start;
2681 switch (snap_type) {
2687 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2689 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2692 case SnapToSMPTEFrame:
2694 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2696 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2700 case SnapToSMPTESeconds:
2701 if (session->smpte_offset_negative())
2703 start += session->smpte_offset ();
2705 start -= session->smpte_offset ();
2707 if (direction > 0) {
2708 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2710 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2713 if (session->smpte_offset_negative())
2715 start -= session->smpte_offset ();
2717 start += session->smpte_offset ();
2721 case SnapToSMPTEMinutes:
2722 if (session->smpte_offset_negative())
2724 start += session->smpte_offset ();
2726 start -= session->smpte_offset ();
2729 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2731 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2733 if (session->smpte_offset_negative())
2735 start -= session->smpte_offset ();
2737 start += session->smpte_offset ();
2743 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2745 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2751 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2753 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2758 start = session->tempo_map().round_to_bar (start, direction);
2762 start = session->tempo_map().round_to_beat (start, direction);
2765 case SnapToAThirtysecondBeat:
2766 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2769 case SnapToASixteenthBeat:
2770 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2773 case SnapToAEighthBeat:
2774 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2777 case SnapToAQuarterBeat:
2778 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2781 case SnapToAThirdBeat:
2782 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2785 case SnapToEditCursor:
2786 start = edit_cursor->current_frame;
2794 before = session->locations()->first_location_before (start);
2795 after = session->locations()->first_location_after (start);
2797 if (direction < 0) {
2799 start = before->start();
2803 } else if (direction > 0) {
2805 start = after->start();
2807 start = session->current_end_frame();
2812 /* find nearest of the two */
2813 if ((start - before->start()) < (after->start() - start)) {
2814 start = before->start();
2816 start = after->start();
2819 start = before->start();
2822 start = after->start();
2829 case SnapToRegionStart:
2830 case SnapToRegionEnd:
2831 case SnapToRegionSync:
2832 case SnapToRegionBoundary:
2833 if (!region_boundary_cache.empty()) {
2834 vector<jack_nframes_t>::iterator i;
2836 if (direction > 0) {
2837 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2839 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2842 if (i != region_boundary_cache.end()) {
2845 start = region_boundary_cache.back();
2851 switch (snap_mode) {
2857 if (presnap > start) {
2858 if (presnap > (start + unit_to_frame(snap_threshold))) {
2862 } else if (presnap < start) {
2863 if (presnap < (start - unit_to_frame(snap_threshold))) {
2875 Editor::setup_toolbar ()
2878 vector<ToggleButton *> mouse_mode_buttons;
2880 mouse_mode_buttons.push_back (&mouse_move_button);
2881 mouse_mode_buttons.push_back (&mouse_select_button);
2882 mouse_mode_buttons.push_back (&mouse_gain_button);
2883 mouse_mode_buttons.push_back (&mouse_zoom_button);
2884 mouse_mode_buttons.push_back (&mouse_timefx_button);
2885 mouse_mode_buttons.push_back (&mouse_audition_button);
2886 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2888 mouse_mode_button_table.set_homogeneous (true);
2889 mouse_mode_button_table.set_col_spacings (2);
2890 mouse_mode_button_table.set_row_spacings (2);
2891 mouse_mode_button_table.set_border_width (5);
2893 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2894 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2895 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2897 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2898 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2899 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2901 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2902 mouse_mode_tearoff->set_name ("MouseModeBase");
2904 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2905 mouse_mode_tearoff->tearoff_window()));
2906 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2907 mouse_mode_tearoff->tearoff_window(), 1));
2909 mouse_move_button.set_name ("MouseModeButton");
2910 mouse_select_button.set_name ("MouseModeButton");
2911 mouse_gain_button.set_name ("MouseModeButton");
2912 mouse_zoom_button.set_name ("MouseModeButton");
2913 mouse_timefx_button.set_name ("MouseModeButton");
2914 mouse_audition_button.set_name ("MouseModeButton");
2916 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2917 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2918 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2919 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2920 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2921 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2923 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2924 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2925 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2926 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2927 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2928 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2930 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2931 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2933 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2934 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2935 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2936 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2937 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2939 // mouse_move_button.set_active (true);
2941 /* automation control */
2943 global_automation_button.set_name ("MouseModeButton");
2944 automation_mode_button.set_name ("MouseModeButton");
2946 automation_box.set_spacing (2);
2947 automation_box.set_border_width (2);
2948 automation_box.pack_start (global_automation_button, false, false);
2949 automation_box.pack_start (automation_mode_button, false, false);
2953 edit_mode_label.set_name ("ToolBarLabel");
2955 edit_mode_selector.set_name ("EditModeSelector");
2957 edit_mode_box.set_spacing (3);
2958 edit_mode_box.set_border_width (3);
2960 /* XXX another disgusting hack because of the way combo boxes size themselves */
2962 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2, 10);
2963 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2964 edit_mode_box.pack_start (edit_mode_label, false, false);
2965 edit_mode_box.pack_start (edit_mode_selector, false, false);
2967 edit_mode_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2971 snap_type_label.set_name ("ToolBarLabel");
2973 snap_type_selector.set_name ("SnapTypeSelector");
2975 snap_type_box.set_spacing (3);
2976 snap_type_box.set_border_width (3);
2978 /* XXX another disgusting hack because of the way combo boxes size themselves */
2980 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2981 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "Region bounds", 2+FUDGE, 10);
2982 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2984 snap_type_box.pack_start (snap_type_label, false, false);
2985 snap_type_box.pack_start (snap_type_selector, false, false);
2987 snap_type_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2989 /* Snap mode, not snap type */
2991 snap_mode_label.set_name ("ToolBarLabel");
2993 snap_mode_selector.set_name ("SnapModeSelector");
2995 snap_mode_box.set_spacing (3);
2996 snap_mode_box.set_border_width (3);
2998 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2, 10);
2999 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
3001 snap_mode_box.pack_start (snap_mode_label, false, false);
3002 snap_mode_box.pack_start (snap_mode_selector, false, false);
3004 snap_mode_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
3006 /* Zoom focus mode */
3008 zoom_focus_label.set_name ("ToolBarLabel");
3010 zoom_focus_selector.set_name ("ZoomFocusSelector");
3012 zoom_focus_box.set_spacing (3);
3013 zoom_focus_box.set_border_width (3);
3015 /* XXX another disgusting hack because of the way combo boxes size themselves */
3017 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2, 10);
3018 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
3020 zoom_focus_box.pack_start (zoom_focus_label, false, false);
3021 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
3023 zoom_focus_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
3025 /* selection/cursor clocks */
3027 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
3028 selection_start_clock_label.set_name ("ToolBarLabel");
3029 selection_end_clock_label.set_name ("ToolBarLabel");
3030 edit_cursor_clock_label.set_name ("ToolBarLabel");
3032 selection_start_clock_label.set_text (_("Start:"));
3033 selection_end_clock_label.set_text (_("End:"));
3034 edit_cursor_clock_label.set_text (_("Edit:"));
3036 toolbar_selection_clock_table.set_border_width (5);
3037 toolbar_selection_clock_table.set_col_spacings (2);
3038 toolbar_selection_clock_table.set_homogeneous (false);
3040 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
3041 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
3042 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
3044 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
3045 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
3046 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
3049 // toolbar_clock_vbox.set_spacing (2);
3050 // toolbar_clock_vbox.set_border_width (10);
3051 /* the editor/mixer button will be enabled at session connect */
3053 editor_mixer_button.set_active(false);
3054 editor_mixer_button.set_sensitive(false);
3056 HBox* hbox = new HBox;
3058 hbox->pack_start (editor_mixer_button, false, false);
3059 hbox->pack_start (toolbar_selection_clock_table, false, false);
3060 hbox->pack_start (zoom_indicator_vbox, false, false);
3061 hbox->pack_start (zoom_focus_box, false, false);
3062 hbox->pack_start (snap_type_box, false, false);
3063 hbox->pack_start (snap_mode_box, false, false);
3064 hbox->pack_start (edit_mode_box, false, false);
3066 VBox *vbox = manage (new VBox);
3068 vbox->set_spacing (3);
3069 vbox->set_border_width (3);
3071 HBox *nbox = manage (new HBox);
3073 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
3074 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
3076 nbox->pack_start (nudge_backward_button, false, false);
3077 nbox->pack_start (nudge_forward_button, false, false);
3078 nbox->pack_start (nudge_clock, false, false, 5);
3080 nudge_label.set_name ("ToolBarLabel");
3082 vbox->pack_start (nudge_label, false, false);
3083 vbox->pack_start (*nbox, false, false);
3085 hbox->pack_start (*vbox, false, false);
3089 tools_tearoff = new TearOff (*hbox);
3090 tools_tearoff->set_name ("MouseModeBase");
3092 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
3093 tools_tearoff->tearoff_window(), 0));
3094 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
3095 tools_tearoff->tearoff_window(), 0));
3098 toolbar_hbox.set_spacing (8);
3099 toolbar_hbox.set_border_width (2);
3101 toolbar_hbox.pack_start (*tools_tearoff, false, false);
3102 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
3104 toolbar_base.set_name ("ToolBarBase");
3105 toolbar_base.add (toolbar_hbox);
3107 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
3108 toolbar_frame.set_name ("BaseFrame");
3109 toolbar_frame.add (toolbar_base);
3113 Editor::_autoscroll_canvas (void *arg)
3115 return ((Editor *) arg)->autoscroll_canvas ();
3119 Editor::autoscroll_canvas ()
3121 jack_nframes_t new_frame;
3122 bool keep_calling = true;
3124 if (autoscroll_direction < 0) {
3125 if (leftmost_frame < autoscroll_distance) {
3128 new_frame = leftmost_frame - autoscroll_distance;
3131 if (leftmost_frame > max_frames - autoscroll_distance) {
3132 new_frame = max_frames;
3134 new_frame = leftmost_frame + autoscroll_distance;
3138 if (new_frame != leftmost_frame) {
3139 reposition_x_origin (new_frame);
3142 if (new_frame == 0 || new_frame == max_frames) {
3149 if (autoscroll_cnt == 1) {
3151 /* connect the timeout so that we get called repeatedly */
3153 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
3154 keep_calling = false;
3156 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
3158 /* after about a while, speed up a bit by changing the timeout interval */
3160 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
3161 keep_calling = false;
3163 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
3165 /* after about another while, speed up some more */
3167 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
3168 keep_calling = false;
3170 } else if (autoscroll_cnt >= 30) {
3172 /* we've been scrolling for a while ... crank it up */
3174 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
3177 return keep_calling;
3181 Editor::start_canvas_autoscroll (int dir)
3187 stop_canvas_autoscroll ();
3189 autoscroll_direction = dir;
3190 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
3193 /* do it right now, which will start the repeated callbacks */
3195 autoscroll_canvas ();
3199 Editor::stop_canvas_autoscroll ()
3201 if (autoscroll_timeout_tag >= 0) {
3202 gtk_timeout_remove (autoscroll_timeout_tag);
3203 autoscroll_timeout_tag = -1;
3208 Editor::convert_drop_to_paths (vector<string>& paths,
3209 GdkDragContext *context,
3212 GtkSelectionData *data,
3220 gchar *tname = gdk_atom_name (data->type);
3222 if (session == 0 || strcmp (tname, "text/plain") != 0) {
3226 /* Parse the "uri-list" format that Nautilus provides,
3227 where each pathname is delimited by \r\n
3230 path = (char *) data->data;
3233 for (int n = 0; n < data->length; ++n) {
3237 if (path[n] == '\r') {
3244 if (path[n] == '\n') {
3245 paths.push_back (spath);
3249 warning << _("incorrectly formatted URI list, ignored")
3257 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
3259 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3261 // cerr << "dropped text was " << *p << endl;
3265 // cerr << "decoded was " << *p << endl;
3267 if ((*p).substr (0,7) == "file://") {
3268 (*p) = (*p).substr (7);
3276 Editor::track_canvas_drag_data_received (GdkDragContext *context,
3279 GtkSelectionData *data,
3284 AudioTimeAxisView* tv;
3286 vector<string> paths;
3289 jack_nframes_t frame;
3291 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
3295 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
3301 track_canvas.c2w( x, y, wx, wy);
3303 ev.type = GDK_BUTTON_RELEASE;
3307 frame = event_frame (&ev, 0, &cy);
3311 if ((tvp = trackview_by_y_position (cy)) == 0) {
3313 /* drop onto canvas background: create a new track */
3315 insert_paths_as_new_tracks (paths, false);
3318 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
3320 /* check that its an audio track, not a bus */
3322 if (tv->get_diskstream()) {
3324 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3325 insert_sndfile_into (*p, true, tv, frame);
3332 gtk_drag_finish (context, TRUE, FALSE, time);
3336 Editor::new_tempo_section ()
3342 Editor::map_transport_state ()
3344 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3346 if (session->transport_stopped()) {
3347 have_pending_keyboard_selection = false;
3353 Editor::State::State ()
3355 selection = new Selection;
3358 Editor::State::~State ()
3364 Editor::get_memento () const
3366 State *state = new State;
3368 store_state (*state);
3369 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3373 Editor::store_state (State& state) const
3375 *state.selection = *selection;
3379 Editor::restore_state (State *state)
3381 if (*selection == *state->selection) {
3385 *selection = *state->selection;
3386 time_selection_changed ();
3387 region_selection_changed ();
3389 /* XXX other selection change handlers? */
3393 Editor::begin_reversible_command (string name)
3396 UndoAction ua = get_memento();
3397 session->begin_reversible_command (name, &ua);
3402 Editor::commit_reversible_command ()
3405 UndoAction ua = get_memento();
3406 session->commit_reversible_command (&ua);
3411 Editor::flush_track_canvas ()
3413 /* I don't think this is necessary, and only causes more problems.
3414 I'm commenting it out
3415 and if the imageframe folks don't have any issues, we can take
3416 out this method entirely
3419 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
3420 //gtk_main_iteration ();
3424 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3426 if (!clicked_trackview) {
3431 begin_reversible_command (_("set selected trackview"));
3436 if (selection->selected (clicked_trackview)) {
3438 selection->remove (clicked_trackview);
3441 selection->add (clicked_trackview);
3446 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3447 /* no commit necessary */
3451 selection->set (clicked_trackview);
3455 commit_reversible_command ();
3460 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3462 if (!clicked_control_point) {
3467 begin_reversible_command (_("set selected control point"));
3477 commit_reversible_command ();
3482 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3484 if (!clicked_regionview) {
3488 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3494 RouteGroup* group = atv->route().edit_group();
3495 vector<AudioRegionView*> all_equivalent_regions;
3497 if (group && group->is_active()) {
3499 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3501 AudioTimeAxisView* tatv;
3503 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3505 if (tatv->route().edit_group() != group) {
3510 vector<AudioRegion*> results;
3511 AudioRegionView* marv;
3514 if ((ds = tatv->get_diskstream()) == 0) {
3519 if ((pl = ds->playlist()) != 0) {
3520 pl->get_equivalent_regions (clicked_regionview->region,
3524 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3525 if ((marv = tatv->view->find_view (**ir)) != 0) {
3526 all_equivalent_regions.push_back (marv);
3535 all_equivalent_regions.push_back (clicked_regionview);
3539 begin_reversible_command (_("set selected regionview"));
3543 if (clicked_regionview->get_selected()) {
3544 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3545 /* reduce selection down to just the one clicked */
3546 selection->set (clicked_regionview);
3548 selection->remove (clicked_regionview);
3551 selection->add (all_equivalent_regions);
3554 set_selected_track_from_click (add, false, no_track_remove);
3558 // karsten wiese suggested these two lines to make
3559 // a selected region rise to the top. but this
3560 // leads to a mismatch between actual layering
3561 // and visual layering. resolution required ....
3563 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3564 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3566 if (clicked_regionview->get_selected()) {
3567 /* no commit necessary: we are the one selected. */
3572 selection->set (all_equivalent_regions);
3573 set_selected_track_from_click (add, false, false);
3577 commit_reversible_command () ;
3581 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3583 vector<AudioRegionView*> all_equivalent_regions;
3584 AudioRegion* region;
3586 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3590 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3592 AudioTimeAxisView* tatv;
3594 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3597 vector<AudioRegion*> results;
3598 AudioRegionView* marv;
3601 if ((ds = tatv->get_diskstream()) == 0) {
3606 if ((pl = ds->playlist()) != 0) {
3607 pl->get_region_list_equivalent_regions (*region, results);
3610 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3611 if ((marv = tatv->view->find_view (**ir)) != 0) {
3612 all_equivalent_regions.push_back (marv);
3619 begin_reversible_command (_("set selected regions"));
3623 selection->add (all_equivalent_regions);
3627 selection->set (all_equivalent_regions);
3630 commit_reversible_command () ;
3634 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3636 AudioRegionView* rv;
3639 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3643 if ((rv = sv->find_view (*ar)) == 0) {
3647 /* don't reset the selection if its something other than
3648 a single other region.
3651 if (selection->audio_regions.size() > 1) {
3655 begin_reversible_command (_("set selected regions"));
3657 selection->set (rv);
3659 commit_reversible_command () ;
3665 Editor::set_edit_group_solo (Route& route, bool yn)
3667 RouteGroup *edit_group;
3669 if ((edit_group = route.edit_group()) != 0) {
3670 edit_group->apply (&Route::set_solo, yn, this);
3672 route.set_solo (yn, this);
3677 Editor::set_edit_group_mute (Route& route, bool yn)
3679 RouteGroup *edit_group = 0;
3681 if ((edit_group == route.edit_group()) != 0) {
3682 edit_group->apply (&Route::set_mute, yn, this);
3684 route.set_mute (yn, this);
3689 Editor::set_edit_menu (Menu& menu)
3692 edit_menu->signal_map_event().connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3696 Editor::edit_menu_map_handler ()
3698 using namespace Menu_Helpers;
3699 MenuList& edit_items = edit_menu->items();
3702 /* Nuke all the old items */
3704 edit_items.clear ();
3710 if (session->undo_depth() == 0) {
3713 label = string_compose(_("Undo (%1)"), session->next_undo());
3716 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3718 if (session->undo_depth() == 0) {
3719 edit_items.back().set_sensitive (false);
3722 if (session->redo_depth() == 0) {
3725 label = string_compose(_("Redo (%1)"), session->next_redo());
3728 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3729 if (session->redo_depth() == 0) {
3730 edit_items.back().set_sensitive (false);
3733 vector<MenuItem*> mitems;
3735 edit_items.push_back (SeparatorElem());
3736 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3737 mitems.push_back (&edit_items.back());
3738 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3739 mitems.push_back (&edit_items.back());
3740 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3741 mitems.push_back (&edit_items.back());
3742 edit_items.push_back (SeparatorElem());
3743 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3744 mitems.push_back (&edit_items.back());
3745 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3746 mitems.push_back (&edit_items.back());
3747 edit_items.push_back (SeparatorElem());
3749 if (selection->empty()) {
3750 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3751 (*i)->set_sensitive (false);
3755 Menu* import_menu = manage (new Menu());
3756 import_menu->set_name ("ArdourContextMenu");
3757 MenuList& import_items = import_menu->items();
3759 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3760 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3762 Menu* embed_menu = manage (new Menu());
3763 embed_menu->set_name ("ArdourContextMenu");
3764 MenuList& embed_items = embed_menu->items();
3766 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3767 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3769 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3770 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3771 edit_items.push_back (SeparatorElem());
3773 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3774 if (!session->have_captured()) {
3775 edit_items.back().set_sensitive (false);
3780 Editor::duplicate_dialog (bool dup_region)
3783 if (clicked_regionview == 0) {
3787 if (selection->time.length() == 0) {
3792 ArdourDialog win ("duplicate dialog");
3794 Label label (_("Duplicate how many times?"));
3797 Button ok_button (_("OK"));
3798 Button cancel_button (_("Cancel"));
3801 button_box.set_spacing (7);
3802 set_size_request_to_display_given_text (ok_button, _("Cancel"), 20, 15); // this is cancel on purpose
3803 set_size_request_to_display_given_text (cancel_button, _("Cancel"), 20, 15);
3804 button_box.pack_end (ok_button, false, false);
3805 button_box.pack_end (cancel_button, false, false);
3807 hbox.set_spacing (5);
3808 hbox.pack_start (label);
3809 hbox.pack_start (entry, true, true);
3811 vbox.set_spacing (5);
3812 vbox.set_border_width (5);
3813 vbox.pack_start (hbox);
3814 vbox.pack_start (button_box);
3817 win.set_position (Gtk::WIN_POS_MOUSE);
3820 ok_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3821 entry.signal_activate().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3822 cancel_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 1));
3824 entry.signal_focus_in_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_in_event));
3825 entry.signal_focus_out_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_out_event));
3827 entry.set_text ("1");
3828 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3829 entry.select_region (0, entry.get_text_length());
3831 win.set_position (Gtk::WIN_POS_MOUSE);
3834 // win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3836 entry.grab_focus ();
3840 if (win.run_status() != 0) {
3844 string text = entry.get_text();
3847 if (sscanf (text.c_str(), "%f", ×) == 1) {
3849 AudioRegionSelection regions;
3850 regions.add (clicked_regionview);
3851 duplicate_some_regions (regions, times);
3853 duplicate_selection (times);
3859 Editor::show_verbose_canvas_cursor ()
3861 verbose_canvas_cursor->raise_to_top();
3862 verbose_canvas_cursor->show();
3863 verbose_cursor_visible = true;
3867 Editor::hide_verbose_canvas_cursor ()
3869 verbose_canvas_cursor->hide();
3870 verbose_cursor_visible = false;
3874 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3876 /* XXX get origin of canvas relative to root window,
3877 add x and y and check compared to gdk_screen_{width,height}
3879 verbose_canvas_cursor->set_property("text", txt.c_str());
3880 verbose_canvas_cursor->set_property("x", x);
3881 verbose_canvas_cursor->set_property("y", y);
3885 Editor::set_verbose_canvas_cursor_text (string txt)
3887 verbose_canvas_cursor->set_property("text", txt.c_str());
3891 Editor::edit_mode_selection_done (GdkEventAny *ev)
3897 string choice = edit_mode_selector.get_active_text();
3898 EditMode mode = Slide;
3900 if (choice == _("Splice")) {
3902 } else if (choice == _("Slide")) {
3906 session->set_edit_mode (mode);
3912 Editor::snap_type_selection_done (GdkEventAny *ev)
3918 string choice = snap_type_selector.get_active_text();
3919 SnapType snaptype = SnapToFrame;
3921 if (choice == _("Beats/3")) {
3922 snaptype = SnapToAThirdBeat;
3923 } else if (choice == _("Beats/4")) {
3924 snaptype = SnapToAQuarterBeat;
3925 } else if (choice == _("Beats/8")) {
3926 snaptype = SnapToAEighthBeat;
3927 } else if (choice == _("Beats/16")) {
3928 snaptype = SnapToASixteenthBeat;
3929 } else if (choice == _("Beats/32")) {
3930 snaptype = SnapToAThirtysecondBeat;
3931 } else if (choice == _("Beats")) {
3932 snaptype = SnapToBeat;
3933 } else if (choice == _("Bars")) {
3934 snaptype = SnapToBar;
3935 } else if (choice == _("Marks")) {
3936 snaptype = SnapToMark;
3937 } else if (choice == _("Edit Cursor")) {
3938 snaptype = SnapToEditCursor;
3939 } else if (choice == _("Region starts")) {
3940 snaptype = SnapToRegionStart;
3941 } else if (choice == _("Region ends")) {
3942 snaptype = SnapToRegionEnd;
3943 } else if (choice == _("Region bounds")) {
3944 snaptype = SnapToRegionBoundary;
3945 } else if (choice == _("Region syncs")) {
3946 snaptype = SnapToRegionSync;
3947 } else if (choice == _("CD Frames")) {
3948 snaptype = SnapToCDFrame;
3949 } else if (choice == _("SMPTE Frames")) {
3950 snaptype = SnapToSMPTEFrame;
3951 } else if (choice == _("SMPTE Seconds")) {
3952 snaptype = SnapToSMPTESeconds;
3953 } else if (choice == _("SMPTE Minutes")) {
3954 snaptype = SnapToSMPTEMinutes;
3955 } else if (choice == _("Seconds")) {
3956 snaptype = SnapToSeconds;
3957 } else if (choice == _("Minutes")) {
3958 snaptype = SnapToMinutes;
3959 } else if (choice == _("None")) {
3960 snaptype = SnapToFrame;
3963 set_snap_to (snaptype);
3969 Editor::snap_mode_selection_done (GdkEventAny *ev)
3971 if(session == 0) return FALSE;
3973 string choice = snap_mode_selector.get_active_text();
3974 SnapMode mode = SnapNormal;
3976 if (choice == _("Normal")) {
3978 } else if (choice == _("Magnetic")) {
3979 mode = SnapMagnetic;
3982 set_snap_mode (mode);
3988 Editor::zoom_focus_selection_done (GdkEventAny *ev)
3994 string choice = zoom_focus_selector.get_active_text();
3995 ZoomFocus focus_type = ZoomFocusLeft;
3997 if (choice == _("Left")) {
3998 focus_type = ZoomFocusLeft;
3999 } else if (choice == _("Right")) {
4000 focus_type = ZoomFocusRight;
4001 } else if (choice == _("Center")) {
4002 focus_type = ZoomFocusCenter;
4003 } else if (choice == _("Playhead")) {
4004 focus_type = ZoomFocusPlayhead;
4005 } else if (choice == _("Edit Cursor")) {
4006 focus_type = ZoomFocusEdit;
4009 set_zoom_focus (focus_type);
4015 Editor::edit_controls_button_release (GdkEventButton* ev)
4017 if (Keyboard::is_context_menu_event (ev)) {
4018 ARDOUR_UI::instance()->add_route ();
4024 Editor::track_selection_changed ()
4026 switch (selection->tracks.size()){
4030 set_selected_mixer_strip (*(selection->tracks.front()));
4034 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4035 (*i)->set_selected (false);
4036 if (mouse_mode == MouseRange) {
4037 (*i)->hide_selection ();
4041 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4042 (*i)->set_selected (true);
4043 if (mouse_mode == MouseRange) {
4044 (*i)->show_selection (selection->time);
4050 Editor::time_selection_changed ()
4052 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4053 (*i)->hide_selection ();
4056 if (selection->tracks.empty()) {
4057 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4058 (*i)->show_selection (selection->time);
4061 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4062 (*i)->show_selection (selection->time);
4068 Editor::region_selection_changed ()
4070 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4071 (*i)->set_selected_regionviews (selection->audio_regions);
4076 Editor::point_selection_changed ()
4078 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4079 (*i)->set_selected_points (selection->points);
4084 Editor::run_sub_event_loop ()
4086 Keyboard::the_keyboard().allow_focus (true);
4087 sub_event_loop_status = 0;
4092 Editor::finish_sub_event_loop (int status)
4095 Keyboard::the_keyboard().allow_focus (false);
4096 sub_event_loop_status = status;
4100 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
4102 finish_sub_event_loop (status);
4107 Editor::mouse_select_button_release (GdkEventButton* ev)
4109 /* this handles just right-clicks */
4111 if (ev->button != 3) {
4118 Editor::TrackViewList *
4119 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
4122 TrackViewList::iterator i;
4124 v = new TrackViewList;
4126 if (track == 0 && group == 0) {
4130 for (i = track_views.begin(); i != track_views.end (); ++i) {
4134 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
4136 /* just the view for this track
4139 v->push_back (track);
4143 /* views for all tracks in the edit group */
4145 for (i = track_views.begin(); i != track_views.end (); ++i) {
4147 if (group == 0 || (*i)->edit_group() == group) {
4157 Editor::set_zoom_focus (ZoomFocus f)
4159 if (zoom_focus != f) {
4161 vector<string> txt = internationalize (zoom_focus_strings);
4162 zoom_focus_selector.set_active_text (txt[(int)f]);
4163 ZoomFocusChanged (); /* EMIT_SIGNAL */
4170 Editor::ensure_float (Window& win)
4172 win.set_transient_for (*this);
4176 Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which)
4178 /* recover or initialize pane positions. do this here rather than earlier because
4179 we don't want the positions to change the child allocations, which they seem to do.
4185 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
4187 static int32_t done[4] = { 0, 0, 0, 0 };
4190 if ((geometry = find_named_node (*node, "geometry")) == 0) {
4191 width = default_width;
4192 height = default_height;
4194 width = atoi(geometry->property("x_size")->value());
4195 height = atoi(geometry->property("y_size")->value());
4198 if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
4204 if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
4206 snprintf (buf, sizeof(buf), "%d", pos);
4208 pos = atoi (prop->value());
4211 if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gobj())->allocation.width > pos)) {
4212 track_list_canvas_pane.set_position (pos);
4215 } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
4221 if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
4222 pos = width - (95 * 2);
4223 snprintf (buf, sizeof(buf), "%d", pos);
4225 pos = atoi (prop->value());
4228 if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gobj())->allocation.width > pos)) {
4229 canvas_region_list_pane.set_position (pos);
4232 } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
4238 if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
4239 pos = width - (95 * 2);
4240 snprintf (buf, sizeof(buf), "%d", pos);
4242 pos = atoi (prop->value());
4245 if ((done[2] = GTK_WIDGET(route_group_vpane.gobj())->allocation.height > pos)) {
4246 route_group_vpane.set_position (pos);
4249 } else if (which == static_cast<Gtk::Paned*> (®ion_selection_vpane)) {
4255 if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
4256 pos = width - (95 * 2);
4257 snprintf (buf, sizeof(buf), "%d", pos);
4259 pos = atoi (prop->value());
4262 if ((done[3] = GTK_WIDGET(region_selection_vpane.gobj())->allocation.height > pos)) {
4263 region_selection_vpane.set_position (pos);
4269 Editor::detach_tearoff (Gtk::Box* b, Gtk::Window* w)
4271 if (tools_tearoff->torn_off() &&
4272 mouse_mode_tearoff->torn_off()) {
4273 top_hbox.remove (toolbar_frame);
4280 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Window* w, int32_t n)
4282 if (toolbar_frame.get_parent() == 0) {
4283 top_hbox.pack_end (toolbar_frame);
4288 Editor::set_show_measures (bool yn)
4290 if (_show_measures != yn) {
4293 if ((_show_measures = yn) == true) {
4296 DisplayControlChanged (ShowMeasures);
4302 Editor::set_follow_playhead (bool yn)
4304 if (_follow_playhead != yn) {
4305 if ((_follow_playhead = yn) == true) {
4307 update_current_screen ();
4309 DisplayControlChanged (FollowPlayhead);
4315 Editor::toggle_xfade_active (Crossfade* xfade)
4317 xfade->set_active (!xfade->active());
4321 Editor::toggle_xfade_length (Crossfade* xfade)
4323 xfade->set_follow_overlap (!xfade->following_overlap());
4327 Editor::edit_xfade (Crossfade* xfade)
4329 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
4333 cew.ok_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 1));
4334 cew.cancel_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 0));
4336 // cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
4340 if (cew.run_status() == 1) {
4342 xfade->StateChanged (Change (~0));
4347 Editor::playlist_selector () const
4349 return *_playlist_selector;
4353 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
4357 ret = nudge_clock.current_duration (pos);
4358 next = ret + 1; /* XXXX fix me */
4364 Editor::end_location_changed (Location* location)
4366 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
4367 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
4371 Editor::playlist_deletion_dialog (Playlist* pl)
4373 ArdourDialog dialog ("playlist deletion dialog");
4374 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4375 "If left alone, no audio files used by it will be cleaned.\n"
4376 "If deleted, audio files used by it alone by will cleaned."),
4379 Button del_button (_("Delete playlist"));
4380 Button keep_button (_("Keep playlist"));
4381 Button abort_button (_("Cancel cleanup"));
4384 button_box.set_spacing (7);
4385 button_box.set_homogeneous (true);
4386 button_box.pack_end (del_button, false, false);
4387 button_box.pack_end (keep_button, false, false);
4388 button_box.pack_end (abort_button, false, false);
4390 vbox.set_spacing (5);
4391 vbox.set_border_width (5);
4392 vbox.pack_start (label);
4393 vbox.pack_start (button_box);
4396 dialog.set_position (Gtk::WIN_POS_CENTER);
4399 del_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 0));
4400 keep_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 1));
4401 abort_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 2));
4404 // dialog.realize ();
4405 // dialog.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
4409 switch (dialog.run_status()) {
4411 /* keep the playlist */
4415 /* delete the playlist */
4423 /* keep the playlist */
4429 Editor::audio_region_selection_covers (jack_nframes_t where)
4431 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
4432 if ((*a)->region.covers (where)) {
4441 Editor::prepare_for_cleanup ()
4443 cut_buffer->clear_audio_regions ();
4444 cut_buffer->clear_playlists ();
4446 selection->clear_audio_regions ();
4447 selection->clear_playlists ();
4451 Editor::init_colormap ()
4453 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
4454 pair<ColorID,int> newpair;
4456 newpair.first = (ColorID) x;
4457 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
4458 color_map.insert (newpair);
4463 Editor::transport_loop_location()
4466 return session->locations()->auto_loop_location();
4473 Editor::transport_punch_location()
4476 return session->locations()->auto_punch_location();