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 <pbd/error.h>
31 #include <gtkmm/image.h>
32 #include <gdkmm/color.h>
33 #include <gdkmm/bitmap.h>
35 #include <gtkmm2ext/gtk_ui.h>
36 #include <gtkmm2ext/tearoff.h>
37 #include <gtkmm2ext/utils.h>
39 #include <ardour/audio_track.h>
40 #include <ardour/diskstream.h>
41 #include <ardour/plugin_manager.h>
42 #include <ardour/location.h>
43 #include <ardour/audioplaylist.h>
44 #include <ardour/audioregion.h>
45 #include <ardour/region.h>
46 #include <ardour/session_route.h>
47 #include <ardour/tempo.h>
48 #include <ardour/utils.h>
50 #include "ardour_ui.h"
51 #include "check_mark.h"
53 #include "grouped_buttons.h"
56 #include "playlist_selector.h"
57 #include "regionview.h"
58 #include "rgb_macros.h"
59 #include "selection.h"
60 #include "streamview.h"
61 #include "time_axis_view.h"
63 #include "crossfade_view.h"
65 #include "public_editor.h"
66 #include "crossfade_edit.h"
67 #include "audio_time_axis.h"
68 #include "canvas_impl.h"
69 #include "gui_thread.h"
74 #include "imageframe_socket_handler.h"
75 /* </CMT Additions> */
79 using namespace ARDOUR;
82 using namespace Gtkmm2ext;
83 using namespace Editing;
85 const double Editor::timebar_height = 15.0;
87 #include "editor_xpms"
89 static const int32_t slide_index = 0;
90 static const int32_t splice_index = 1;
92 static const gchar *edit_mode_strings[] = {
98 static const gchar *snap_type_strings[] = {
122 static const gchar *snap_mode_strings[] = {
128 static const gchar *zoom_focus_strings[] = {
137 /* Soundfile drag-n-drop */
139 Gdk::Cursor* Editor::cross_hair_cursor = 0;
140 Gdk::Cursor* Editor::selector_cursor = 0;
141 Gdk::Cursor* Editor::trimmer_cursor = 0;
142 Gdk::Cursor* Editor::grabber_cursor = 0;
143 Gdk::Cursor* Editor::zoom_cursor = 0;
144 Gdk::Cursor* Editor::time_fx_cursor = 0;
145 Gdk::Cursor* Editor::fader_cursor = 0;
146 Gdk::Cursor* Editor::speaker_cursor = 0;
147 Gdk::Cursor* Editor::null_cursor = 0;
148 Gdk::Cursor* Editor::wait_cursor = 0;
149 Gdk::Cursor* Editor::timebar_cursor = 0;
151 GdkPixmap *Editor::check_pixmap = 0;
152 GdkBitmap *Editor::check_mask = 0;
153 GdkPixmap *Editor::empty_pixmap = 0;
154 GdkBitmap *Editor::empty_mask = 0;
156 Editor::Editor (AudioEngine& eng)
159 /* time display buttons */
161 minsec_label (_("Mins:Secs")),
162 bbt_label (_("Bars:Beats")),
163 smpte_label (_("SMPTE")),
164 frame_label (_("Frames")),
165 tempo_label (_("Tempo")),
166 meter_label (_("Meter")),
167 mark_label (_("Location Markers")),
168 range_mark_label (_("Range Markers")),
169 transport_mark_label (_("Loop/Punch Ranges")),
171 edit_packer (3, 3, false),
172 edit_hscroll_left_arrow (Gtk::ARROW_LEFT, Gtk::SHADOW_OUT),
173 edit_hscroll_right_arrow (Gtk::ARROW_RIGHT, Gtk::SHADOW_OUT),
175 /* tool bar related */
177 editor_mixer_button (_("editor\nmixer")),
179 selection_start_clock (X_("SelectionStartClock"), true),
180 selection_end_clock (X_("SelectionEndClock"), true),
181 edit_cursor_clock (X_("EditCursorClock"), true),
182 zoom_range_clock (X_("ZoomRangeClock"), true, true),
184 toolbar_selection_clock_table (2,3),
186 mouse_mode_button_table (2, 3),
188 mouse_select_button (_("range")),
189 mouse_move_button (_("object")),
190 mouse_gain_button (_("gain")),
191 mouse_zoom_button (_("zoom")),
192 mouse_timefx_button (_("timefx")),
193 mouse_audition_button (_("listen")),
195 automation_mode_button (_("mode")),
196 global_automation_button (_("automation")),
198 edit_mode_label (_("Edit Mode")),
199 snap_type_label (_("Snap To")),
200 snap_mode_label(_("Snap Mode")),
201 zoom_focus_label (_("Zoom Focus")),
203 /* <CMT Additions> */
204 image_socket_listener(0),
205 /* </CMT Additions> */
209 nudge_label (_("Nudge")),
210 nudge_clock (X_("NudgeClock"), true, true)
215 /* we are a singleton */
217 PublicEditor::_instance = this;
221 check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
222 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
223 &check_mask, NULL, (gchar **) check_xpm);
224 empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
225 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
226 &empty_mask, NULL, (gchar **) empty_xpm);
230 selection = new Selection;
231 cut_buffer = new Selection;
233 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
234 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
235 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
236 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
238 clicked_regionview = 0;
239 clicked_trackview = 0;
240 clicked_audio_trackview = 0;
241 clicked_crossfadeview = 0;
242 clicked_control_point = 0;
243 latest_regionview = 0;
244 last_update_frame = 0;
246 last_audition_region = 0;
247 current_mixer_strip = 0;
248 current_bbt_points = 0;
250 snap_type = SnapToFrame;
251 set_snap_to (snap_type);
252 snap_mode = SnapNormal;
253 set_snap_mode (snap_mode);
254 snap_threshold = 5.0;
255 bbt_beat_subdivision = 4;
258 autoscroll_timeout_tag = -1;
259 interthread_progress_window = 0;
260 current_interthread_info = 0;
261 _show_measures = true;
262 _show_waveforms = true;
263 _show_waveforms_recording = true;
264 first_action_message = 0;
266 show_gain_after_trim = false;
267 no_zoom_repos_update = false;
268 ignore_route_list_reorder = false;
269 verbose_cursor_on = true;
270 route_removal = false;
272 show_automatic_regions_in_region_list = true;
273 have_pending_keyboard_selection = false;
274 _follow_playhead = true;
275 _xfade_visibility = true;
276 editor_ruler_menu = 0;
277 no_ruler_shown_update = false;
278 edit_group_list_menu = 0;
280 region_list_menu = 0;
282 marker_menu_item = 0;
284 transport_marker_menu = 0;
285 new_transport_marker_menu = 0;
286 editor_mixer_strip_width = Wide;
287 repos_zoom_queued = false;
288 import_audio_item = 0;
289 embed_audio_item = 0;
290 region_edit_menu_split_item = 0;
292 region_edit_menu_split_multichannel_item = 0;
293 edit_hscroll_dragging = false;
295 ignore_mouse_mode_toggle = false;
296 current_stepping_trackview = 0;
298 entered_regionview = 0;
299 clear_entered_track = false;
300 _new_regionviews_show_envelope = false;
301 current_timestretch = 0;
306 location_marker_color = color_map[cLocationMarker];
307 location_range_color = color_map[cLocationRange];
308 location_cd_marker_color = color_map[cLocationCDMarker];
309 location_loop_color = color_map[cLocationLoop];
310 location_punch_color = color_map[cLocationPunch];
312 range_marker_drag_rect = 0;
313 marker_drag_line = 0;
315 mouse_mode = MouseZoom; /* force change in next call */
316 set_mouse_mode (MouseObject, true);
318 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
319 zoom_focus = ZoomFocusLeft;
320 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
322 initialize_rulers ();
323 initialize_canvas ();
325 track_canvas_scroller.add (track_canvas);
326 track_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
327 track_canvas_scroller.set_name ("TrackCanvasScroller");
329 track_canvas_scroller.get_vadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
330 track_canvas_scroller.get_vadjustment()->set_step_increment (10.0);
332 track_canvas_scroller.get_hadjustment()->set_lower (0.0);
333 track_canvas_scroller.get_hadjustment()->set_upper (1200.0);
334 track_canvas_scroller.get_hadjustment()->set_step_increment (20.0);
335 track_canvas_scroller.get_hadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
337 edit_vscrollbar.set_adjustment(*track_canvas_scroller.get_vadjustment());
338 edit_hscrollbar.set_adjustment(*track_canvas_scroller.get_hadjustment());
340 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_press));
341 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_release));
342 edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscroll_slider_allocate));
344 time_canvas_scroller.add (time_canvas);
345 time_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
346 time_canvas_scroller.set_hadjustment (*track_canvas_scroller.get_hadjustment());
347 time_canvas_scroller.set_name ("TimeCanvasScroller");
349 edit_controls_vbox.set_spacing (track_spacing);
350 edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
351 edit_controls_scroller.add (edit_controls_hbox);
352 edit_controls_scroller.set_name ("EditControlsBase");
353 edit_controls_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
355 Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
357 viewport->set_shadow_type (Gtk::SHADOW_NONE);
358 viewport->set_name ("EditControlsBase");
359 viewport->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
360 viewport->signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
365 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
367 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
368 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
369 time_canvas_vbox.pack_start (*frames_ruler, false, false);
370 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
371 time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
372 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
374 bbt_label.set_name ("EditorTimeButton");
375 bbt_label.set_size_request (-1, (int)timebar_height);
376 bbt_label.set_alignment (1.0, 0.5);
377 bbt_label.set_padding (5,0);
378 minsec_label.set_name ("EditorTimeButton");
379 minsec_label.set_size_request (-1, (int)timebar_height);
380 minsec_label.set_alignment (1.0, 0.5);
381 minsec_label.set_padding (5,0);
382 smpte_label.set_name ("EditorTimeButton");
383 smpte_label.set_size_request (-1, (int)timebar_height);
384 smpte_label.set_alignment (1.0, 0.5);
385 smpte_label.set_padding (5,0);
386 frame_label.set_name ("EditorTimeButton");
387 frame_label.set_size_request (-1, (int)timebar_height);
388 frame_label.set_alignment (1.0, 0.5);
389 frame_label.set_padding (5,0);
390 tempo_label.set_name ("EditorTimeButton");
391 tempo_label.set_size_request (-1, (int)timebar_height);
392 tempo_label.set_alignment (1.0, 0.5);
393 tempo_label.set_padding (5,0);
394 meter_label.set_name ("EditorTimeButton");
395 meter_label.set_size_request (-1, (int)timebar_height);
396 meter_label.set_alignment (1.0, 0.5);
397 meter_label.set_padding (5,0);
398 mark_label.set_name ("EditorTimeButton");
399 mark_label.set_size_request (-1, (int)timebar_height);
400 mark_label.set_alignment (1.0, 0.5);
401 mark_label.set_padding (5,0);
402 range_mark_label.set_name ("EditorTimeButton");
403 range_mark_label.set_size_request (-1, (int)timebar_height);
404 range_mark_label.set_alignment (1.0, 0.5);
405 range_mark_label.set_padding (5,0);
406 transport_mark_label.set_name ("EditorTimeButton");
407 transport_mark_label.set_size_request (-1, (int)timebar_height);
408 transport_mark_label.set_alignment (1.0, 0.5);
409 transport_mark_label.set_padding (5,0);
411 time_button_vbox.pack_start (minsec_label, false, false);
412 time_button_vbox.pack_start (smpte_label, false, false);
413 time_button_vbox.pack_start (frame_label, false, false);
414 time_button_vbox.pack_start (bbt_label, false, false);
415 time_button_vbox.pack_start (meter_label, false, false);
416 time_button_vbox.pack_start (tempo_label, false, false);
417 time_button_vbox.pack_start (mark_label, false, false);
419 time_button_event_box.add (time_button_vbox);
421 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
422 time_button_event_box.set_name ("TimebarLabelBase");
423 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
425 /* these enable us to have a dedicated window (for cursor setting, etc.)
426 for the canvas areas.
429 track_canvas_event_box.add (track_canvas_scroller);
431 time_canvas_event_box.add (time_canvas_vbox);
432 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
435 edit_packer.set_col_spacings (0);
436 edit_packer.set_row_spacings (0);
437 edit_packer.set_homogeneous (false);
438 edit_packer.set_name ("EditorWindow");
440 // edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, Gtk::FILL, 0, 0, 0);
441 // edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, 0, 0, 0);
442 // edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, Gtk::FILL, 0, 0, 0);
443 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
445 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
446 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
448 edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
449 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
450 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
452 edit_frame.set_name ("BaseFrame");
453 edit_frame.set_shadow_type (SHADOW_IN);
454 edit_frame.add (edit_packer);
456 zoom_in_button.set_name ("EditorTimeButton");
457 zoom_out_button.set_name ("EditorTimeButton");
458 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
459 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
461 // zoom_onetoone_button.set_name ("EditorTimeButton");
462 zoom_out_full_button.set_name ("EditorTimeButton");
463 // ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1"));
464 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
466 zoom_in_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(zoom_in_button_xpm)))));
467 zoom_out_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_button_xpm)))));
468 zoom_out_full_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_full_button_xpm)))));
469 // zoom_onetoone_button.add (*(manage (new Gtk::Image (zoom_onetoone_button_xpm))));
472 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
473 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
474 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
475 // zoom_onetoone_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom), 1.0));
477 zoom_indicator_box.pack_start (zoom_out_button, false, false);
478 zoom_indicator_box.pack_start (zoom_in_button, false, false);
479 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
480 // zoom_indicator_box.pack_start (zoom_onetoone_button, false, false);
481 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
483 zoom_indicator_label.set_text (_("Zoom Span"));
484 zoom_indicator_label.set_name ("ToolBarLabel");
487 zoom_indicator_vbox.set_spacing (3);
488 zoom_indicator_vbox.set_border_width (3);
489 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
490 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
493 bottom_hbox.set_border_width (3);
494 bottom_hbox.set_spacing (3);
496 route_display_model = ListStore::create(route_display_columns);
497 route_list.set_model (route_display_model);
498 route_list.append_column (_("Tracks"), route_display_columns.text);
499 route_list.set_name ("TrackListDisplay");
500 route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
501 route_list.set_reorderable (true);
503 route_list.set_size_request (75,-1);
504 route_list.set_headers_visible (true);
505 route_list.set_headers_clickable (true);
508 // route_list.signal_rows_reordered().connect (mem_fun (*this, &Editor::queue_route_list_reordered));
511 // route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func));
514 //route_list.set_shadow_type (Gtk::SHADOW_IN);
516 route_list_scroller.add (route_list);
517 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
519 route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed));
520 route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click));
522 edit_group_list_button_label.set_text (_("Edit Groups"));
523 edit_group_list_button_label.set_name ("EditGroupTitleButton");
524 edit_group_list_button.add (edit_group_list_button_label);
525 edit_group_list_button.set_name ("EditGroupTitleButton");
527 group_model = ListStore::create(group_columns);
528 edit_group_list.set_model (group_model);
529 edit_group_list.append_column (_("active"), group_columns.is_active);
530 edit_group_list.append_column (_("groupname"), group_columns.text);
531 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
532 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
534 /* use checkbox for the active column */
536 CellRendererToggle *active_cell = dynamic_cast<CellRendererToggle*>(edit_group_list.get_column_cell_renderer (0));
537 active_cell->property_activatable() = true;
538 active_cell->property_radio() = false;
540 edit_group_list.set_name ("MixerGroupList");
541 //edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
542 route_list.set_headers_visible (false);
543 edit_group_list.set_reorderable (false);
544 edit_group_list.set_size_request (75, -1);
545 edit_group_list.columns_autosize ();
546 edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
548 edit_group_list_scroller.add (edit_group_list);
549 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
551 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
552 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
553 edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed));
555 TreeModel::Row row = *(group_model->append());
556 row[group_columns.is_active] = false;
557 row[group_columns.text] = (_("-all-"));
558 edit_group_list.get_selection()->select (row);
559 /* GTK2FIX is set_data(0) setting the is_active to false here?
560 list<string> stupid_list;
562 stupid_list.push_back ("*");
563 stupid_list.push_back (_("-all-"));
565 edit_group_list.rows().push_back (stupid_list);
566 edit_group_list.rows().back().set_data (0);
567 edit_group_list.rows().back().select();
570 edit_group_vbox.pack_start (edit_group_list_button, false, false);
571 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
573 route_list_frame.set_name ("BaseFrame");
574 route_list_frame.set_shadow_type (Gtk::SHADOW_IN);
575 route_list_frame.add (route_list_scroller);
577 edit_group_list_frame.set_name ("BaseFrame");
578 edit_group_list_frame.set_shadow_type (Gtk::SHADOW_IN);
579 edit_group_list_frame.add (edit_group_vbox);
581 route_group_vpane.add1 (route_list_frame);
582 route_group_vpane.add2 (edit_group_list_frame);
584 list_vpacker.pack_start (route_group_vpane, true, true);
586 region_list_model = TreeStore::create (region_list_columns);
587 region_list_sort_model = TreeModelSort::create (region_list_model);
588 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
590 region_list_display.set_model (region_list_sort_model);
591 region_list_display.append_column (_("Regions"), region_list_columns.name);
592 region_list_display.set_reorderable (true);
593 region_list_display.set_size_request (100, -1);
594 region_list_display.set_data ("editor", this);
595 region_list_display.set_flags (Gtk::CAN_FOCUS);
596 region_list_display.set_name ("RegionListDisplay");
598 region_list_scroller.add (region_list_display);
599 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
601 list<Gtk::TargetEntry> region_list_target_table;
603 region_list_target_table.push_back (TargetEntry ("STRING"));
604 region_list_target_table.push_back (TargetEntry ("text/plain"));
605 region_list_target_table.push_back (TargetEntry ("text/uri-list"));
606 region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
609 // region_list_display.drag_dest_set (region_list_target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
610 // region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
612 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
613 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
614 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
615 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
616 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
618 //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
619 //region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click));
621 named_selection_scroller.add (named_selection_display);
622 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
624 named_selection_model = TreeStore::create (named_selection_columns);
625 named_selection_display.set_model (named_selection_model);
626 named_selection_display.set_name ("RegionListDisplay");
627 named_selection_display.set_size_request (100, -1);
628 named_selection_display.set_headers_visible (true);
629 named_selection_display.set_headers_clickable (true);
630 named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
631 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
632 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
634 region_selection_vpane.pack1 (region_list_scroller, true, true);
635 region_selection_vpane.pack2 (named_selection_scroller, true, true);
637 canvas_region_list_pane.pack1 (edit_frame, true, true);
638 canvas_region_list_pane.pack2 (region_selection_vpane, true, true);
640 track_list_canvas_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
641 static_cast<Gtk::Paned*> (&track_list_canvas_pane)));
642 canvas_region_list_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
643 static_cast<Gtk::Paned*> (&canvas_region_list_pane)));
644 route_group_vpane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
645 static_cast<Gtk::Paned*> (&route_group_vpane)));
646 region_selection_vpane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
647 static_cast<Gtk::Paned*> (®ion_selection_vpane)));
649 track_list_canvas_pane.pack1 (list_vpacker, true, true);
650 track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true);
652 /* provide special pane-handle event handling for easy "hide" action */
654 /* 0: collapse to show left/upper child
655 1: collapse to show right/lower child
658 route_group_vpane.set_data ("collapse-direction", (gpointer) 0);
659 region_selection_vpane.set_data ("collapse-direction", (gpointer) 0);
660 canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0);
661 track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1);
663 route_group_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&route_group_vpane)));
664 region_selection_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (®ion_selection_vpane)));
665 canvas_region_list_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&canvas_region_list_pane)));
666 track_list_canvas_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&track_list_canvas_pane)));
668 top_hbox.pack_start (toolbar_frame, true, true);
670 HBox *hbox = manage (new HBox);
671 hbox->pack_start (track_list_canvas_pane, true, true);
673 global_vpacker.pack_start (top_hbox, false, false);
674 global_vpacker.pack_start (*hbox, true, true);
676 global_hpacker.pack_start (global_vpacker, true, true);
678 set_name ("EditorWindow");
680 vpacker.pack_end (global_hpacker, true, true);
682 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
685 _playlist_selector = new PlaylistSelector();
686 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
688 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
692 nudge_forward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
693 nudge_backward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
695 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
696 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
698 nudge_forward_button.set_name ("TransportButton");
699 nudge_backward_button.set_name ("TransportButton");
701 fade_context_menu.set_name ("ArdourContextMenu");
703 set_title (_("ardour: editor"));
704 set_wmclass (_("ardour_editor"), "Ardour");
707 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
709 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
710 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
718 /* <CMT Additions> */
719 if(image_socket_listener)
721 if(image_socket_listener->is_connected())
723 image_socket_listener->close_connection() ;
726 delete image_socket_listener ;
727 image_socket_listener = 0 ;
729 /* </CMT Additions> */
733 Editor::add_toplevel_controls (Container& cont)
735 vpacker.pack_start (cont, false, false);
740 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
742 /* note: the selection will take care of the vanishing
743 audioregionview by itself.
746 if (clicked_regionview == rv) {
747 clicked_regionview = 0;
750 if (entered_regionview == rv) {
751 set_entered_regionview (0);
756 Editor::set_entered_regionview (AudioRegionView* rv)
758 if (rv == entered_regionview) {
762 if (entered_regionview) {
763 entered_regionview->exited ();
766 if ((entered_regionview = rv) != 0) {
767 entered_regionview->entered ();
772 Editor::set_entered_track (TimeAxisView* tav)
775 entered_track->exited ();
778 if ((entered_track = tav) != 0) {
779 entered_track->entered ();
784 Editor::left_track_canvas (GdkEventCrossing *ev)
786 set_entered_track (0);
787 set_entered_regionview (0);
793 Editor::show_window ()
797 /* now reset all audio_time_axis heights, because widgets might need
803 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
804 tv = (static_cast<TimeAxisView*>(*i));
810 Editor::tie_vertical_scrolling ()
812 edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
814 float y1 = track_canvas_scroller.get_vadjustment()->get_value();
815 playhead_cursor->set_y_axis(y1);
816 edit_cursor->set_y_axis(y1);
820 Editor::set_frames_per_unit (double fpu)
822 jack_nframes_t frames;
824 if (fpu == frames_per_unit) {
832 // convert fpu to frame count
834 frames = (jack_nframes_t) (fpu * canvas_width);
836 /* don't allow zooms that fit more than the maximum number
837 of frames into an 800 pixel wide space.
840 if (max_frames / fpu < 800.0) {
844 frames_per_unit = fpu;
846 if (frames != zoom_range_clock.current_duration()) {
847 zoom_range_clock.set (frames);
850 /* only update these if we not about to call reposition_x_origin,
851 which will do the same updates.
855 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
858 if (!no_zoom_repos_update) {
859 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
861 update_fixed_rulers ();
862 tempo_map_changed (Change (0));
865 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
866 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
867 (*i)->reshow_selection (selection->time);
871 ZoomChanged (); /* EMIT_SIGNAL */
873 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
874 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
881 Editor::instant_save ()
883 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
888 session->add_instant_xml(get_state(), session->path());
890 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
895 Editor::reposition_x_origin (jack_nframes_t frame)
897 if (frame != leftmost_frame) {
898 leftmost_frame = frame;
899 double pixel = frame_to_pixel (frame);
900 if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
901 track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
903 track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
904 XOriginChanged (); /* EMIT_SIGNAL */
909 Editor::edit_cursor_clock_changed()
911 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
912 edit_cursor->set_position (edit_cursor_clock.current_time());
918 Editor::zoom_adjustment_changed ()
920 if (session == 0 || no_zoom_repos_update) {
924 double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width;
928 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
930 else if (fpu > session->current_end_frame() / (double) canvas_width) {
931 fpu = session->current_end_frame() / (double) canvas_width;
932 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
939 Editor::canvas_horizontally_scrolled ()
941 /* XXX note the potential loss of accuracy here caused by
942 adjustments being 32bit floats with only a 24 bit mantissa,
943 whereas jack_nframes_t is at least a 32 bit uint32_teger.
946 leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
949 update_fixed_rulers ();
951 if (!edit_hscroll_dragging) {
952 tempo_map_changed (Change (0));
954 update_tempo_based_rulers();
959 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
961 if (!repos_zoom_queued) {
962 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
963 repos_zoom_queued = true;
968 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
970 /* if we need to force an update to the hscroller stuff,
971 don't set no_zoom_repos_update.
974 no_zoom_repos_update = (frame != leftmost_frame);
976 set_frames_per_unit (nfpu);
977 if (no_zoom_repos_update) {
978 reposition_x_origin (frame);
980 no_zoom_repos_update = false;
981 repos_zoom_queued = false;
987 Editor::on_realize ()
989 Window::on_realize ();
991 /* Even though we're not using acceleration, we want the
995 track_context_menu.accelerate (*this->get_toplevel());
996 track_region_context_menu.accelerate (*this->get_toplevel());
998 Glib::RefPtr<Gdk::Pixmap> empty_pixmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
999 Glib::RefPtr<Gdk::Pixmap> empty_bitmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1000 Gdk::Color white ("#ffffff" );
1002 null_cursor = new Gdk::Cursor(empty_pixmap, empty_bitmap, white, white, 0, 0);
1010 track_canvas_scroller.get_window()->set_cursor (*current_canvas_cursor);
1011 time_canvas_scroller.get_window()->set_cursor (*timebar_cursor);
1015 Editor::track_canvas_allocate (Gtk::Allocation alloc)
1017 canvas_width = alloc.get_width();
1018 canvas_height = alloc.get_height();
1020 if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) {
1022 Pango::FontDescription font = get_font_for_style (N_("FirstActionMessage"));
1024 const char *txt1 = _("Start a new session\n");
1025 const char *txt2 = _("via Session menu");
1027 /* this mess of code is here to find out how wide this text is and
1028 position the message in the center of the editor window. there
1029 are two lines, so we use the longer of the the lines to
1030 compute width, and multiply the height by 2.
1036 /* this is a dummy widget that exists so that we can get the
1037 style from the RC file.
1040 Label foo (_(txt2));
1041 Glib::RefPtr<Pango::Layout> layout;
1042 foo.set_name ("NoSessionMessage");
1043 foo.ensure_style ();
1045 layout = foo.create_pango_layout (_(txt2));
1046 layout->set_font_description (font);
1047 layout->get_pixel_size (pixel_width, pixel_height);
1049 if (first_action_message == 0) {
1051 char txt[strlen(txt1)+strlen(txt2)+1];
1053 /* merge both lines */
1055 strcpy (txt, _(txt1));
1056 strcat (txt, _(txt2));
1058 first_action_message = new ArdourCanvas::Text (*track_canvas.root());
1059 first_action_message->property_font_desc() = font;
1060 first_action_message->property_fill_color_rgba() = color_map[cFirstActionMessage];
1061 first_action_message->property_x() = (gdouble) (canvas_width - pixel_width) / 2.0;
1062 first_action_message->property_y() = (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height));
1063 first_action_message->property_anchor() = ANCHOR_NORTH_WEST;
1064 first_action_message->property_text() = ustring (txt);
1069 first_action_message->property_x() = (gdouble) (canvas_width - pixel_width) / 2.0;
1070 first_action_message->property_y() = (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height));
1074 zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit));
1075 edit_cursor->set_position (edit_cursor->current_frame);
1076 playhead_cursor->set_position (playhead_cursor->current_frame);
1077 reset_scrolling_region (&alloc);
1079 Resized (); /* EMIT_SIGNAL */
1083 Editor::queue_session_control_changed (Session::ControlType t)
1085 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1089 Editor::session_control_changed (Session::ControlType t)
1091 // right now we're only tracking the loop and punch state
1094 case Session::AutoLoop:
1095 update_loop_range_view (true);
1097 case Session::PunchIn:
1098 case Session::PunchOut:
1099 update_punch_range_view (true);
1108 Editor::fake_add_edit_group (RouteGroup *group)
1110 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1114 Editor::fake_handle_new_audio_region (AudioRegion *region)
1116 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1120 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1122 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1126 Editor::fake_handle_new_duration ()
1128 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1132 Editor::start_scrolling ()
1134 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1135 (mem_fun(*this, &Editor::update_current_screen));
1137 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1138 (mem_fun(*this, &Editor::update_slower));
1142 Editor::stop_scrolling ()
1144 scroll_connection.disconnect ();
1145 slower_update_connection.disconnect ();
1149 Editor::map_position_change (jack_nframes_t frame)
1151 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1153 if (session == 0 || !_follow_playhead) {
1157 center_screen (frame);
1158 playhead_cursor->set_position (frame);
1162 Editor::center_screen (jack_nframes_t frame)
1164 float page = canvas_width * frames_per_unit;
1166 /* if we're off the page, then scroll.
1169 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1170 center_screen_internal (frame,page);
1175 Editor::center_screen_internal (jack_nframes_t frame, float page)
1180 frame -= (jack_nframes_t) page;
1185 reposition_x_origin (frame);
1189 Editor::handle_new_duration ()
1191 reset_scrolling_region ();
1194 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1195 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1198 update_hscroller ();
1202 Editor::update_title_s (string snap_name)
1204 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1210 Editor::update_title ()
1212 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1215 bool dirty = session->dirty();
1217 string wintitle = _("ardour: editor: ");
1223 wintitle += session->name();
1225 if (session->snap_name() != session->name()) {
1227 wintitle += session->snap_name();
1234 set_title (wintitle);
1239 Editor::connect_to_session (Session *t)
1243 if (first_action_message) {
1244 first_action_message->hide();
1247 flush_track_canvas();
1251 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1253 /* These signals can all be emitted by a non-GUI thread. Therefore the
1254 handlers for them must not attempt to directly interact with the GUI,
1255 but use Gtkmm2ext::UI::instance()->call_slot();
1258 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1259 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1260 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1261 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1262 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1263 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1264 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1265 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1266 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1267 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1268 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1269 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1270 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1272 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1273 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1275 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1277 session->foreach_edit_group(this, &Editor::add_edit_group);
1279 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1280 editor_mixer_button.set_name (X_("EditorMixerButton"));
1282 edit_cursor_clock.set_session (session);
1283 selection_start_clock.set_session (session);
1284 selection_end_clock.set_session (session);
1285 zoom_range_clock.set_session (session);
1286 _playlist_selector->set_session (session);
1287 nudge_clock.set_session (session);
1289 switch (session->get_edit_mode()) {
1291 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1295 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1299 Location* loc = session->locations()->auto_loop_location();
1301 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1302 if (loc->start() == loc->end()) {
1303 loc->set_end (loc->start() + 1);
1305 session->locations()->add (loc, false);
1306 session->set_auto_loop_location (loc);
1310 loc->set_name (_("Loop"));
1313 loc = session->locations()->auto_punch_location();
1315 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1316 if (loc->start() == loc->end()) {
1317 loc->set_end (loc->start() + 1);
1319 session->locations()->add (loc, false);
1320 session->set_auto_punch_location (loc);
1324 loc->set_name (_("Punch"));
1327 update_loop_range_view (true);
1328 update_punch_range_view (true);
1330 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1333 refresh_location_display ();
1334 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1335 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1336 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1337 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1338 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1340 reset_scrolling_region ();
1342 redisplay_regions ();
1343 redisplay_named_selections ();
1345 //route_list.freeze (); GTK2FIX
1346 route_display_model->clear ();
1347 session->foreach_route (this, &Editor::handle_new_route);
1348 // route_list.select_all ();
1350 //route_list.sort ();
1351 route_list_reordered ();
1352 //route_list.thaw ();
1354 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1355 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1358 /* ::reposition_x_origin() doesn't work right here, since the old
1359 position may be zero already, and it does nothing in such
1365 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1366 track_canvas_scroller.get_hadjustment()->set_value (0);
1368 update_hscroller ();
1369 restore_ruler_visibility ();
1370 tempo_map_changed (Change (0));
1372 edit_cursor->set_position (0);
1373 playhead_cursor->set_position (0);
1377 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1380 /* don't show master bus in a new session */
1382 if (ARDOUR_UI::instance()->session_is_new ()) {
1384 TreeModel::Children rows = route_display_model->children();
1385 TreeModel::Children::iterator i;
1387 //route_list.freeze ();
1389 for (i = rows.begin(); i != rows.end(); ++i) {
1390 TimeAxisView *tv = (*i)[route_display_columns.tv];
1391 AudioTimeAxisView *atv;
1393 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1394 if (atv->route().master()) {
1395 route_list.get_selection()->unselect (i);
1396 //(*i)->unselect ();
1401 //route_list.thaw ();
1406 Editor::build_cursors ()
1408 using namespace Gdk;
1410 Gdk::Color fg ("#ff0000"); /* Red. */
1411 Gdk::Color bg ("#0000ff"); /* Blue. */
1414 RefPtr<Bitmap> source, mask;
1415 source = Bitmap::create (hand_bits, hand_width, hand_height);
1416 mask = Bitmap::create (handmask_bits, handmask_width, handmask_height);
1417 grabber_cursor = new Gdk::Cursor (source, mask, fg, bg, hand_x_hot, hand_y_hot);
1420 Gdk::Color mbg ("#000000" ); /* Black */
1421 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1424 RefPtr<Bitmap> source, mask;
1425 source = Bitmap::create (mag_bits, mag_width, mag_height);
1426 mask = Bitmap::create (magmask_bits, mag_width, mag_height);
1427 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1430 Gdk::Color fbg ("#ffffff" );
1431 Gdk::Color ffg ("#000000" );
1434 RefPtr<Bitmap> source, mask;
1436 source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
1437 mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
1438 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1442 RefPtr<Bitmap> source, mask;
1443 source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
1444 mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
1445 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1448 cross_hair_cursor = new Gdk::Cursor (Gdk::CROSSHAIR);
1449 trimmer_cursor = new Gdk::Cursor (Gdk::SB_H_DOUBLE_ARROW);
1450 selector_cursor = new Gdk::Cursor (Gdk::XTERM);
1451 time_fx_cursor = new Gdk::Cursor (Gdk::SIZING);
1452 wait_cursor = new Gdk::Cursor (Gdk::WATCH);
1453 timebar_cursor = new Gdk::Cursor(Gdk::LEFT_PTR);
1457 Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
1459 using namespace Menu_Helpers;
1460 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1463 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1467 MenuList& items (fade_context_menu.items());
1471 switch (item_type) {
1473 case FadeInHandleItem:
1474 if (arv->region.fade_in_active()) {
1475 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1477 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1480 items.push_back (SeparatorElem());
1482 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1483 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1484 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1485 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1486 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1490 case FadeOutHandleItem:
1491 if (arv->region.fade_out_active()) {
1492 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1494 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1497 items.push_back (SeparatorElem());
1499 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1500 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1501 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1502 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1503 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1507 fatal << _("programming error: ")
1508 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1513 fade_context_menu.popup (button, time);
1517 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1519 using namespace Menu_Helpers;
1520 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1523 switch (item_type) {
1525 case AudioRegionViewName:
1526 case AudioRegionViewNameHighlight:
1527 if (with_selection) {
1528 build_menu_function = &Editor::build_track_selection_context_menu;
1530 build_menu_function = &Editor::build_track_region_context_menu;
1535 if (with_selection) {
1536 build_menu_function = &Editor::build_track_selection_context_menu;
1538 build_menu_function = &Editor::build_track_context_menu;
1542 case CrossfadeViewItem:
1543 build_menu_function = &Editor::build_track_crossfade_context_menu;
1547 if (clicked_audio_trackview->get_diskstream()) {
1548 build_menu_function = &Editor::build_track_context_menu;
1550 build_menu_function = &Editor::build_track_bus_context_menu;
1555 /* probably shouldn't happen but if it does, we don't care */
1559 menu = (this->*build_menu_function)(frame);
1560 menu->set_name ("ArdourContextMenu");
1562 /* now handle specific situations */
1564 switch (item_type) {
1566 case AudioRegionViewName:
1567 case AudioRegionViewNameHighlight:
1568 if (!with_selection) {
1569 if (region_edit_menu_split_item) {
1570 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1571 // GTK2FIX find the action, change its sensitivity
1572 // region_edit_menu_split_item->set_sensitive (true);
1574 // GTK2FIX see above
1575 // region_edit_menu_split_item->set_sensitive (false);
1578 if (region_edit_menu_split_multichannel_item) {
1579 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1580 // GTK2FIX find the action, change its sensitivity
1581 // region_edit_menu_split_multichannel_item->set_sensitive (true);
1583 // GTK2FIX see above
1584 // region_edit_menu_split_multichannel_item->set_sensitive (false);
1593 case CrossfadeViewItem:
1600 /* probably shouldn't happen but if it does, we don't care */
1604 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1606 /* Bounce to disk */
1608 using namespace Menu_Helpers;
1609 MenuList& edit_items = menu->items();
1611 edit_items.push_back (SeparatorElem());
1613 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1614 case AudioTrack::NoFreeze:
1615 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1618 case AudioTrack::Frozen:
1619 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1622 case AudioTrack::UnFrozen:
1623 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1629 menu->popup (button, time);
1633 Editor::build_track_context_menu (jack_nframes_t ignored)
1635 using namespace Menu_Helpers;
1637 MenuList& edit_items = track_context_menu.items();
1640 add_dstream_context_items (edit_items);
1641 return &track_context_menu;
1645 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1647 using namespace Menu_Helpers;
1649 MenuList& edit_items = track_context_menu.items();
1652 add_bus_context_items (edit_items);
1653 return &track_context_menu;
1657 Editor::build_track_region_context_menu (jack_nframes_t frame)
1659 using namespace Menu_Helpers;
1660 MenuList& edit_items = track_region_context_menu.items();
1663 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1669 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1670 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1671 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1672 add_region_context_items (atv->view, (*i), edit_items);
1678 add_dstream_context_items (edit_items);
1680 return &track_region_context_menu;
1684 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1686 using namespace Menu_Helpers;
1687 MenuList& edit_items = track_crossfade_context_menu.items();
1688 edit_items.clear ();
1690 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1697 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
1699 Playlist::RegionList* regions = pl->regions_at (frame);
1700 AudioPlaylist::Crossfades xfades;
1702 apl->crossfades_at (frame, xfades);
1704 bool many = xfades.size() > 1;
1706 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
1707 add_crossfade_context_items (atv->view, (*i), edit_items, many);
1710 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1711 add_region_context_items (atv->view, (*i), edit_items);
1718 add_dstream_context_items (edit_items);
1720 return &track_crossfade_context_menu;
1724 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
1726 using namespace Menu_Helpers;
1727 MenuList& edit_items = track_selection_context_menu.items();
1728 edit_items.clear ();
1730 add_selection_context_items (edit_items);
1731 add_dstream_context_items (edit_items);
1733 return &track_selection_context_menu;
1737 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
1739 using namespace Menu_Helpers;
1740 Menu *xfade_menu = manage (new Menu);
1741 MenuList& items = xfade_menu->items();
1742 xfade_menu->set_name ("ArdourContextMenu");
1745 if (xfade->active()) {
1751 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
1752 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
1754 if (xfade->can_follow_overlap()) {
1756 if (xfade->following_overlap()) {
1757 str = _("Convert to short");
1759 str = _("Convert to full");
1762 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
1766 str = xfade->out().name();
1768 str += xfade->in().name();
1770 str = _("Crossfade");
1773 edit_items.push_back (MenuElem (str, *xfade_menu));
1774 edit_items.push_back (SeparatorElem());
1778 Editor::xfade_edit_left_region ()
1780 if (clicked_crossfadeview) {
1781 clicked_crossfadeview->left_view.show_region_editor ();
1786 Editor::xfade_edit_right_region ()
1788 if (clicked_crossfadeview) {
1789 clicked_crossfadeview->right_view.show_region_editor ();
1794 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
1796 using namespace Menu_Helpers;
1797 Menu *region_menu = manage (new Menu);
1798 MenuList& items = region_menu->items();
1799 region_menu->set_name ("ArdourContextMenu");
1801 AudioRegion* ar = 0;
1804 ar = dynamic_cast<AudioRegion*> (region);
1807 /* when this particular menu pops up, make the relevant region
1811 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
1813 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
1814 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
1815 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
1816 items.push_back (SeparatorElem());
1817 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
1818 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
1819 items.push_back (SeparatorElem());
1821 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
1822 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
1823 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
1824 items.push_back (SeparatorElem());
1826 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
1827 might be able to figure out which overloaded member function to use in
1831 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
1833 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
1834 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
1835 items.push_back (SeparatorElem());
1837 if (region->muted()) {
1838 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
1840 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
1842 items.push_back (SeparatorElem());
1844 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
1845 items.push_back (SeparatorElem());
1850 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
1851 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
1852 items.push_back (SeparatorElem());
1854 if (ar->scale_amplitude() != 1.0f) {
1855 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
1857 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
1860 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
1861 items.push_back (SeparatorElem());
1865 Menu *nudge_menu = manage (new Menu());
1866 MenuList& nudge_items = nudge_menu->items();
1867 nudge_menu->set_name ("ArdourContextMenu");
1869 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
1870 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
1871 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
1872 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
1874 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1875 items.push_back (SeparatorElem());
1877 Menu *trim_menu = manage (new Menu);
1878 MenuList& trim_items = trim_menu->items();
1879 trim_menu->set_name ("ArdourContextMenu");
1881 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
1882 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
1884 items.push_back (MenuElem (_("Trim"), *trim_menu));
1885 items.push_back (SeparatorElem());
1887 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
1888 region_edit_menu_split_item = &items.back();
1890 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
1891 region_edit_menu_split_multichannel_item = &items.back();
1893 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
1894 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
1895 items.push_back (SeparatorElem());
1896 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
1897 items.push_back (SeparatorElem());
1898 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
1900 /* OK, stick the region submenu at the top of the list, and then add
1904 /* we have to hack up the region name because "_" has a special
1905 meaning for menu titles.
1908 string::size_type pos = 0;
1909 string menu_item_name = region->name();
1911 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1912 menu_item_name.replace (pos, 1, "__");
1916 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
1917 edit_items.push_back (SeparatorElem());
1921 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1923 using namespace Menu_Helpers;
1924 Menu *selection_menu = manage (new Menu);
1925 MenuList& items = selection_menu->items();
1926 selection_menu->set_name ("ArdourContextMenu");
1928 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
1929 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
1930 items.push_back (SeparatorElem());
1931 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
1932 items.push_back (SeparatorElem());
1933 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
1934 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
1935 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
1936 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
1937 items.push_back (SeparatorElem());
1938 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
1939 items.push_back (SeparatorElem());
1940 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
1941 items.push_back (SeparatorElem());
1942 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
1944 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
1945 edit_items.push_back (SeparatorElem());
1949 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1951 using namespace Menu_Helpers;
1955 Menu *play_menu = manage (new Menu);
1956 MenuList& play_items = play_menu->items();
1957 play_menu->set_name ("ArdourContextMenu");
1959 play_items.push_back (MenuElem (_("Play from edit cursor")));
1960 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1961 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
1962 play_items.push_back (SeparatorElem());
1963 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
1965 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1969 Menu *select_menu = manage (new Menu);
1970 MenuList& select_items = select_menu->items();
1971 select_menu->set_name ("ArdourContextMenu");
1973 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
1974 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
1975 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1976 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
1977 select_items.push_back (SeparatorElem());
1978 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1979 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1980 select_items.push_back (SeparatorElem());
1982 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1986 Menu *cutnpaste_menu = manage (new Menu);
1987 MenuList& cutnpaste_items = cutnpaste_menu->items();
1988 cutnpaste_menu->set_name ("ArdourContextMenu");
1990 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
1991 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
1992 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
1993 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
1995 cutnpaste_items.push_back (SeparatorElem());
1997 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
1998 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
2000 cutnpaste_items.push_back (SeparatorElem());
2002 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
2004 cutnpaste_items.push_back (SeparatorElem());
2006 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
2007 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
2009 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2011 /* Adding new material */
2013 Menu *import_menu = manage (new Menu());
2014 MenuList& import_items = import_menu->items();
2015 import_menu->set_name ("ArdourContextMenu");
2017 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2018 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
2020 edit_items.push_back (MenuElem (_("Import"), *import_menu));
2024 Menu *nudge_menu = manage (new Menu());
2025 MenuList& nudge_items = nudge_menu->items();
2026 nudge_menu->set_name ("ArdourContextMenu");
2028 edit_items.push_back (SeparatorElem());
2029 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2030 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2031 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2032 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2034 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2038 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2040 using namespace Menu_Helpers;
2044 Menu *play_menu = manage (new Menu);
2045 MenuList& play_items = play_menu->items();
2046 play_menu->set_name ("ArdourContextMenu");
2048 play_items.push_back (MenuElem (_("Play from edit cursor")));
2049 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2050 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2054 Menu *select_menu = manage (new Menu);
2055 MenuList& select_items = select_menu->items();
2056 select_menu->set_name ("ArdourContextMenu");
2058 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2059 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2060 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2061 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2062 select_items.push_back (SeparatorElem());
2063 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2064 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2065 select_items.push_back (SeparatorElem());
2067 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2071 Menu *cutnpaste_menu = manage (new Menu);
2072 MenuList& cutnpaste_items = cutnpaste_menu->items();
2073 cutnpaste_menu->set_name ("ArdourContextMenu");
2075 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2076 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2077 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2079 Menu *nudge_menu = manage (new Menu());
2080 MenuList& nudge_items = nudge_menu->items();
2081 nudge_menu->set_name ("ArdourContextMenu");
2083 edit_items.push_back (SeparatorElem());
2084 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2085 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2086 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2087 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2089 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2092 /* CURSOR SETTING AND MARKS AND STUFF */
2095 Editor::set_snap_to (SnapType st)
2098 vector<string> txt = internationalize (snap_type_strings);
2099 snap_type_selector.set_active_text (txt[(int)st]);
2103 switch (snap_type) {
2104 case SnapToAThirtysecondBeat:
2105 case SnapToASixteenthBeat:
2106 case SnapToAEighthBeat:
2107 case SnapToAQuarterBeat:
2108 case SnapToAThirdBeat:
2109 update_tempo_based_rulers ();
2117 Editor::set_snap_mode (SnapMode mode)
2120 vector<string> txt = internationalize (snap_mode_strings);
2121 snap_mode_selector.set_active_text (txt[(int)mode]);
2127 Editor::add_location_from_selection ()
2129 if (selection->time.empty()) {
2133 if (session == 0 || clicked_trackview == 0) {
2137 jack_nframes_t start = selection->time[clicked_selection].start;
2138 jack_nframes_t end = selection->time[clicked_selection].end;
2140 Location *location = new Location (start, end, "selection");
2142 session->begin_reversible_command (_("add marker"));
2143 session->add_undo (session->locations()->get_memento());
2144 session->locations()->add (location, true);
2145 session->add_redo_no_execute (session->locations()->get_memento());
2146 session->commit_reversible_command ();
2150 Editor::add_location_from_playhead_cursor ()
2152 jack_nframes_t where = session->audible_frame();
2154 Location *location = new Location (where, where, "mark", Location::IsMark);
2155 session->begin_reversible_command (_("add marker"));
2156 session->add_undo (session->locations()->get_memento());
2157 session->locations()->add (location, true);
2158 session->add_redo_no_execute (session->locations()->get_memento());
2159 session->commit_reversible_command ();
2164 Editor::set_state (const XMLNode& node)
2166 const XMLProperty* prop;
2168 int x, y, width, height, xoff, yoff;
2170 if ((geometry = find_named_node (node, "geometry")) == 0) {
2172 width = default_width;
2173 height = default_height;
2181 width = atoi(geometry->property("x_size")->value());
2182 height = atoi(geometry->property("y_size")->value());
2183 x = atoi(geometry->property("x_pos")->value());
2184 y = atoi(geometry->property("y_pos")->value());
2185 xoff = atoi(geometry->property("x_off")->value());
2186 yoff = atoi(geometry->property("y_off")->value());
2189 set_default_size(width, height);
2191 // set_position(x, y-yoff);
2193 if ((prop = node.property ("zoom-focus"))) {
2194 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2197 if ((prop = node.property ("zoom"))) {
2198 set_frames_per_unit (atof (prop->value()));
2201 if ((prop = node.property ("snap-to"))) {
2202 set_snap_to ((SnapType) atoi (prop->value()));
2205 if ((prop = node.property ("snap-mode"))) {
2206 set_snap_mode ((SnapMode) atoi (prop->value()));
2209 if ((prop = node.property ("show-waveforms"))) {
2210 bool yn = (prop->value() == "yes");
2211 _show_waveforms = !yn;
2212 set_show_waveforms (yn);
2215 if ((prop = node.property ("show-waveforms-recording"))) {
2216 bool yn = (prop->value() == "yes");
2217 _show_waveforms_recording = !yn;
2218 set_show_waveforms_recording (yn);
2221 if ((prop = node.property ("show-measures"))) {
2222 bool yn = (prop->value() == "yes");
2223 _show_measures = !yn;
2224 set_show_measures (yn);
2227 if ((prop = node.property ("follow-playhead"))) {
2228 bool yn = (prop->value() == "yes");
2229 _follow_playhead = !yn;
2230 set_follow_playhead (yn);
2233 if ((prop = node.property ("xfades-visible"))) {
2234 bool yn = (prop->value() == "yes");
2235 _xfade_visibility = !yn;
2236 set_xfade_visibility (yn);
2239 if ((prop = node.property ("region-list-sort-type"))) {
2240 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2241 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2244 if ((prop = node.property ("mouse-mode"))) {
2245 MouseMode m = str2mousemode(prop->value());
2246 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2247 set_mouse_mode (m, true);
2249 mouse_mode = MouseGain; /* lie, to force the mode switch */
2250 set_mouse_mode (MouseObject, true);
2253 if ((prop = node.property ("editor-mixer-button"))) {
2254 editor_mixer_button.set_active(prop->value() == "yes");
2261 Editor::get_state ()
2263 XMLNode* node = new XMLNode ("Editor");
2266 if (is_realized()) {
2267 Glib::RefPtr<Gdk::Window> win = get_window();
2269 int x, y, xoff, yoff, width, height;
2270 win->get_root_origin(x, y);
2271 win->get_position(xoff, yoff);
2272 win->get_size(width, height);
2274 XMLNode* geometry = new XMLNode ("geometry");
2276 snprintf(buf, sizeof(buf), "%d", width);
2277 geometry->add_property("x_size", string(buf));
2278 snprintf(buf, sizeof(buf), "%d", height);
2279 geometry->add_property("y_size", string(buf));
2280 snprintf(buf, sizeof(buf), "%d", x);
2281 geometry->add_property("x_pos", string(buf));
2282 snprintf(buf, sizeof(buf), "%d", y);
2283 geometry->add_property("y_pos", string(buf));
2284 snprintf(buf, sizeof(buf), "%d", xoff);
2285 geometry->add_property("x_off", string(buf));
2286 snprintf(buf, sizeof(buf), "%d", yoff);
2287 geometry->add_property("y_off", string(buf));
2288 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gobj()));
2289 geometry->add_property("canvas_region_list_pane_pos", string(buf));
2290 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gobj()));
2291 geometry->add_property("track_list_canvas_pane_pos", string(buf));
2292 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(®ion_selection_vpane)->gobj()));
2293 geometry->add_property("region_selection_pane_pos", string(buf));
2294 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gobj()));
2295 geometry->add_property("route_group_pane_pos", string(buf));
2297 node->add_child_nocopy (*geometry);
2300 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2301 node->add_property ("zoom-focus", buf);
2302 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2303 node->add_property ("zoom", buf);
2304 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2305 node->add_property ("snap-to", buf);
2306 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2307 node->add_property ("snap-mode", buf);
2309 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2310 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2311 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2312 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2313 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2314 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2315 node->add_property ("mouse-mode", enum2str(mouse_mode));
2316 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2324 Editor::trackview_by_y_position (double y)
2326 TrackViewList::iterator iter;
2329 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2337 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2346 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2348 Location* before = 0;
2349 Location* after = 0;
2355 const jack_nframes_t one_second = session->frame_rate();
2356 const jack_nframes_t one_minute = session->frame_rate() * 60;
2358 jack_nframes_t presnap = start;
2360 switch (snap_type) {
2366 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2368 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2371 case SnapToSMPTEFrame:
2373 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2375 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2379 case SnapToSMPTESeconds:
2380 if (session->smpte_offset_negative())
2382 start += session->smpte_offset ();
2384 start -= session->smpte_offset ();
2386 if (direction > 0) {
2387 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2389 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2392 if (session->smpte_offset_negative())
2394 start -= session->smpte_offset ();
2396 start += session->smpte_offset ();
2400 case SnapToSMPTEMinutes:
2401 if (session->smpte_offset_negative())
2403 start += session->smpte_offset ();
2405 start -= session->smpte_offset ();
2408 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2410 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2412 if (session->smpte_offset_negative())
2414 start -= session->smpte_offset ();
2416 start += session->smpte_offset ();
2422 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2424 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2430 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2432 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2437 start = session->tempo_map().round_to_bar (start, direction);
2441 start = session->tempo_map().round_to_beat (start, direction);
2444 case SnapToAThirtysecondBeat:
2445 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2448 case SnapToASixteenthBeat:
2449 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2452 case SnapToAEighthBeat:
2453 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2456 case SnapToAQuarterBeat:
2457 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2460 case SnapToAThirdBeat:
2461 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2464 case SnapToEditCursor:
2465 start = edit_cursor->current_frame;
2473 before = session->locations()->first_location_before (start);
2474 after = session->locations()->first_location_after (start);
2476 if (direction < 0) {
2478 start = before->start();
2482 } else if (direction > 0) {
2484 start = after->start();
2486 start = session->current_end_frame();
2491 /* find nearest of the two */
2492 if ((start - before->start()) < (after->start() - start)) {
2493 start = before->start();
2495 start = after->start();
2498 start = before->start();
2501 start = after->start();
2508 case SnapToRegionStart:
2509 case SnapToRegionEnd:
2510 case SnapToRegionSync:
2511 case SnapToRegionBoundary:
2512 if (!region_boundary_cache.empty()) {
2513 vector<jack_nframes_t>::iterator i;
2515 if (direction > 0) {
2516 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2518 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2521 if (i != region_boundary_cache.end()) {
2524 start = region_boundary_cache.back();
2530 switch (snap_mode) {
2536 if (presnap > start) {
2537 if (presnap > (start + unit_to_frame(snap_threshold))) {
2541 } else if (presnap < start) {
2542 if (presnap < (start - unit_to_frame(snap_threshold))) {
2554 Editor::setup_toolbar ()
2557 vector<ToggleButton *> mouse_mode_buttons;
2559 mouse_mode_buttons.push_back (&mouse_move_button);
2560 mouse_mode_buttons.push_back (&mouse_select_button);
2561 mouse_mode_buttons.push_back (&mouse_gain_button);
2562 mouse_mode_buttons.push_back (&mouse_zoom_button);
2563 mouse_mode_buttons.push_back (&mouse_timefx_button);
2564 mouse_mode_buttons.push_back (&mouse_audition_button);
2565 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2567 mouse_mode_button_table.set_homogeneous (true);
2568 mouse_mode_button_table.set_col_spacings (2);
2569 mouse_mode_button_table.set_row_spacings (2);
2570 mouse_mode_button_table.set_border_width (5);
2572 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2573 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2574 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2576 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2577 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2578 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2580 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2581 mouse_mode_tearoff->set_name ("MouseModeBase");
2583 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2584 mouse_mode_tearoff->tearoff_window()));
2585 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2586 mouse_mode_tearoff->tearoff_window(), 1));
2588 mouse_move_button.set_name ("MouseModeButton");
2589 mouse_select_button.set_name ("MouseModeButton");
2590 mouse_gain_button.set_name ("MouseModeButton");
2591 mouse_zoom_button.set_name ("MouseModeButton");
2592 mouse_timefx_button.set_name ("MouseModeButton");
2593 mouse_audition_button.set_name ("MouseModeButton");
2595 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2596 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2597 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2598 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2599 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2600 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2602 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2603 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2604 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2605 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2606 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2607 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2609 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2610 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2612 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2613 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2614 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2615 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2616 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2618 // mouse_move_button.set_active (true);
2620 /* automation control */
2622 global_automation_button.set_name ("MouseModeButton");
2623 automation_mode_button.set_name ("MouseModeButton");
2625 automation_box.set_spacing (2);
2626 automation_box.set_border_width (2);
2627 automation_box.pack_start (global_automation_button, false, false);
2628 automation_box.pack_start (automation_mode_button, false, false);
2632 edit_mode_label.set_name ("ToolBarLabel");
2634 edit_mode_selector.set_name ("EditModeSelector");
2636 edit_mode_box.set_spacing (3);
2637 edit_mode_box.set_border_width (3);
2639 /* XXX another disgusting hack because of the way combo boxes size themselves */
2641 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2, 10);
2642 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2643 edit_mode_box.pack_start (edit_mode_label, false, false);
2644 edit_mode_box.pack_start (edit_mode_selector, false, false);
2646 edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2650 snap_type_label.set_name ("ToolBarLabel");
2652 snap_type_selector.set_name ("SnapTypeSelector");
2654 snap_type_box.set_spacing (3);
2655 snap_type_box.set_border_width (3);
2657 /* XXX another disgusting hack because of the way combo boxes size themselves */
2659 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2660 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "Region bounds", 2+FUDGE, 10);
2661 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2663 snap_type_box.pack_start (snap_type_label, false, false);
2664 snap_type_box.pack_start (snap_type_selector, false, false);
2666 snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2668 /* Snap mode, not snap type */
2670 snap_mode_label.set_name ("ToolBarLabel");
2672 snap_mode_selector.set_name ("SnapModeSelector");
2674 snap_mode_box.set_spacing (3);
2675 snap_mode_box.set_border_width (3);
2677 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2, 10);
2678 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2680 snap_mode_box.pack_start (snap_mode_label, false, false);
2681 snap_mode_box.pack_start (snap_mode_selector, false, false);
2683 snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2685 /* Zoom focus mode */
2687 zoom_focus_label.set_name ("ToolBarLabel");
2689 zoom_focus_selector.set_name ("ZoomFocusSelector");
2691 zoom_focus_box.set_spacing (3);
2692 zoom_focus_box.set_border_width (3);
2694 /* XXX another disgusting hack because of the way combo boxes size themselves */
2696 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2, 10);
2697 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
2699 zoom_focus_box.pack_start (zoom_focus_label, false, false);
2700 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
2702 zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
2704 /* selection/cursor clocks */
2706 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
2707 selection_start_clock_label.set_name ("ToolBarLabel");
2708 selection_end_clock_label.set_name ("ToolBarLabel");
2709 edit_cursor_clock_label.set_name ("ToolBarLabel");
2711 selection_start_clock_label.set_text (_("Start:"));
2712 selection_end_clock_label.set_text (_("End:"));
2713 edit_cursor_clock_label.set_text (_("Edit:"));
2715 toolbar_selection_clock_table.set_border_width (5);
2716 toolbar_selection_clock_table.set_col_spacings (2);
2717 toolbar_selection_clock_table.set_homogeneous (false);
2719 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
2720 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
2721 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
2723 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
2724 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
2725 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
2728 // toolbar_clock_vbox.set_spacing (2);
2729 // toolbar_clock_vbox.set_border_width (10);
2730 /* the editor/mixer button will be enabled at session connect */
2732 editor_mixer_button.set_active(false);
2733 editor_mixer_button.set_sensitive(false);
2735 HBox* hbox = new HBox;
2737 hbox->pack_start (editor_mixer_button, false, false);
2738 hbox->pack_start (toolbar_selection_clock_table, false, false);
2739 hbox->pack_start (zoom_indicator_vbox, false, false);
2740 hbox->pack_start (zoom_focus_box, false, false);
2741 hbox->pack_start (snap_type_box, false, false);
2742 hbox->pack_start (snap_mode_box, false, false);
2743 hbox->pack_start (edit_mode_box, false, false);
2745 VBox *vbox = manage (new VBox);
2747 vbox->set_spacing (3);
2748 vbox->set_border_width (3);
2750 HBox *nbox = manage (new HBox);
2752 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
2753 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
2755 nbox->pack_start (nudge_backward_button, false, false);
2756 nbox->pack_start (nudge_forward_button, false, false);
2757 nbox->pack_start (nudge_clock, false, false, 5);
2759 nudge_label.set_name ("ToolBarLabel");
2761 vbox->pack_start (nudge_label, false, false);
2762 vbox->pack_start (*nbox, false, false);
2764 hbox->pack_start (*vbox, false, false);
2768 tools_tearoff = new TearOff (*hbox);
2769 tools_tearoff->set_name ("MouseModeBase");
2771 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2772 tools_tearoff->tearoff_window()));
2773 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2774 tools_tearoff->tearoff_window(), 0));
2777 toolbar_hbox.set_spacing (8);
2778 toolbar_hbox.set_border_width (2);
2780 toolbar_hbox.pack_start (*tools_tearoff, false, false);
2781 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
2783 toolbar_base.set_name ("ToolBarBase");
2784 toolbar_base.add (toolbar_hbox);
2786 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
2787 toolbar_frame.set_name ("BaseFrame");
2788 toolbar_frame.add (toolbar_base);
2792 Editor::_autoscroll_canvas (void *arg)
2794 return ((Editor *) arg)->autoscroll_canvas ();
2798 Editor::autoscroll_canvas ()
2800 jack_nframes_t new_frame;
2801 bool keep_calling = true;
2803 if (autoscroll_direction < 0) {
2804 if (leftmost_frame < autoscroll_distance) {
2807 new_frame = leftmost_frame - autoscroll_distance;
2810 if (leftmost_frame > max_frames - autoscroll_distance) {
2811 new_frame = max_frames;
2813 new_frame = leftmost_frame + autoscroll_distance;
2817 if (new_frame != leftmost_frame) {
2818 reposition_x_origin (new_frame);
2821 if (new_frame == 0 || new_frame == max_frames) {
2828 if (autoscroll_cnt == 1) {
2830 /* connect the timeout so that we get called repeatedly */
2832 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
2833 keep_calling = false;
2835 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
2837 /* after about a while, speed up a bit by changing the timeout interval */
2839 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
2840 keep_calling = false;
2842 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
2844 /* after about another while, speed up some more */
2846 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
2847 keep_calling = false;
2849 } else if (autoscroll_cnt >= 30) {
2851 /* we've been scrolling for a while ... crank it up */
2853 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
2856 return keep_calling;
2860 Editor::start_canvas_autoscroll (int dir)
2866 stop_canvas_autoscroll ();
2868 autoscroll_direction = dir;
2869 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
2872 /* do it right now, which will start the repeated callbacks */
2874 autoscroll_canvas ();
2878 Editor::stop_canvas_autoscroll ()
2880 if (autoscroll_timeout_tag >= 0) {
2881 gtk_timeout_remove (autoscroll_timeout_tag);
2882 autoscroll_timeout_tag = -1;
2887 Editor::convert_drop_to_paths (vector<string>& paths,
2888 GdkDragContext *context,
2891 GtkSelectionData *data,
2899 gchar *tname = gdk_atom_name (data->type);
2901 if (session == 0 || strcmp (tname, "text/plain") != 0) {
2905 /* Parse the "uri-list" format that Nautilus provides,
2906 where each pathname is delimited by \r\n
2909 path = (char *) data->data;
2912 for (int n = 0; n < data->length; ++n) {
2916 if (path[n] == '\r') {
2923 if (path[n] == '\n') {
2924 paths.push_back (spath);
2928 warning << _("incorrectly formatted URI list, ignored")
2936 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
2938 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
2940 // cerr << "dropped text was " << *p << endl;
2944 // cerr << "decoded was " << *p << endl;
2946 if ((*p).substr (0,7) == "file://") {
2947 (*p) = (*p).substr (7);
2955 Editor::track_canvas_drag_data_received (GdkDragContext *context,
2958 GtkSelectionData *data,
2963 AudioTimeAxisView* tv;
2965 vector<string> paths;
2968 jack_nframes_t frame;
2970 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
2974 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
2980 track_canvas.c2w( x, y, wx, wy);
2982 ev.type = GDK_BUTTON_RELEASE;
2986 frame = event_frame (&ev, 0, &cy);
2990 if ((tvp = trackview_by_y_position (cy)) == 0) {
2992 /* drop onto canvas background: create a new track */
2994 insert_paths_as_new_tracks (paths, false);
2997 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
2999 /* check that its an audio track, not a bus */
3001 if (tv->get_diskstream()) {
3003 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3004 insert_sndfile_into (*p, true, tv, frame);
3011 gtk_drag_finish (context, TRUE, FALSE, time);
3015 Editor::new_tempo_section ()
3021 Editor::map_transport_state ()
3023 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3025 if (session->transport_stopped()) {
3026 have_pending_keyboard_selection = false;
3032 Editor::State::State ()
3034 selection = new Selection;
3037 Editor::State::~State ()
3043 Editor::get_memento () const
3045 State *state = new State;
3047 store_state (*state);
3048 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3052 Editor::store_state (State& state) const
3054 *state.selection = *selection;
3058 Editor::restore_state (State *state)
3060 if (*selection == *state->selection) {
3064 *selection = *state->selection;
3065 time_selection_changed ();
3066 region_selection_changed ();
3068 /* XXX other selection change handlers? */
3072 Editor::begin_reversible_command (string name)
3075 UndoAction ua = get_memento();
3076 session->begin_reversible_command (name, &ua);
3081 Editor::commit_reversible_command ()
3084 UndoAction ua = get_memento();
3085 session->commit_reversible_command (&ua);
3090 Editor::flush_track_canvas ()
3092 /* I don't think this is necessary, and only causes more problems.
3093 I'm commenting it out
3094 and if the imageframe folks don't have any issues, we can take
3095 out this method entirely
3098 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
3099 //gtk_main_iteration ();
3103 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3105 if (!clicked_trackview) {
3110 begin_reversible_command (_("set selected trackview"));
3115 if (selection->selected (clicked_trackview)) {
3117 selection->remove (clicked_trackview);
3120 selection->add (clicked_trackview);
3125 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3126 /* no commit necessary */
3130 selection->set (clicked_trackview);
3134 commit_reversible_command ();
3139 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3141 if (!clicked_control_point) {
3146 begin_reversible_command (_("set selected control point"));
3156 commit_reversible_command ();
3161 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3163 if (!clicked_regionview) {
3167 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3173 RouteGroup* group = atv->route().edit_group();
3174 vector<AudioRegionView*> all_equivalent_regions;
3176 if (group && group->is_active()) {
3178 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3180 AudioTimeAxisView* tatv;
3182 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3184 if (tatv->route().edit_group() != group) {
3189 vector<AudioRegion*> results;
3190 AudioRegionView* marv;
3193 if ((ds = tatv->get_diskstream()) == 0) {
3198 if ((pl = ds->playlist()) != 0) {
3199 pl->get_equivalent_regions (clicked_regionview->region,
3203 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3204 if ((marv = tatv->view->find_view (**ir)) != 0) {
3205 all_equivalent_regions.push_back (marv);
3214 all_equivalent_regions.push_back (clicked_regionview);
3218 begin_reversible_command (_("set selected regionview"));
3222 if (clicked_regionview->get_selected()) {
3223 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3224 /* reduce selection down to just the one clicked */
3225 selection->set (clicked_regionview);
3227 selection->remove (clicked_regionview);
3230 selection->add (all_equivalent_regions);
3233 set_selected_track_from_click (add, false, no_track_remove);
3237 // karsten wiese suggested these two lines to make
3238 // a selected region rise to the top. but this
3239 // leads to a mismatch between actual layering
3240 // and visual layering. resolution required ....
3242 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3243 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3245 if (clicked_regionview->get_selected()) {
3246 /* no commit necessary: we are the one selected. */
3251 selection->set (all_equivalent_regions);
3252 set_selected_track_from_click (add, false, false);
3256 commit_reversible_command () ;
3260 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3262 vector<AudioRegionView*> all_equivalent_regions;
3263 AudioRegion* region;
3265 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3269 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3271 AudioTimeAxisView* tatv;
3273 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3276 vector<AudioRegion*> results;
3277 AudioRegionView* marv;
3280 if ((ds = tatv->get_diskstream()) == 0) {
3285 if ((pl = ds->playlist()) != 0) {
3286 pl->get_region_list_equivalent_regions (*region, results);
3289 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3290 if ((marv = tatv->view->find_view (**ir)) != 0) {
3291 all_equivalent_regions.push_back (marv);
3298 begin_reversible_command (_("set selected regions"));
3302 selection->add (all_equivalent_regions);
3306 selection->set (all_equivalent_regions);
3309 commit_reversible_command () ;
3313 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3315 AudioRegionView* rv;
3318 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3322 if ((rv = sv->find_view (*ar)) == 0) {
3326 /* don't reset the selection if its something other than
3327 a single other region.
3330 if (selection->audio_regions.size() > 1) {
3334 begin_reversible_command (_("set selected regions"));
3336 selection->set (rv);
3338 commit_reversible_command () ;
3344 Editor::set_edit_group_solo (Route& route, bool yn)
3346 RouteGroup *edit_group;
3348 if ((edit_group = route.edit_group()) != 0) {
3349 edit_group->apply (&Route::set_solo, yn, this);
3351 route.set_solo (yn, this);
3356 Editor::set_edit_group_mute (Route& route, bool yn)
3358 RouteGroup *edit_group = 0;
3360 if ((edit_group == route.edit_group()) != 0) {
3361 edit_group->apply (&Route::set_mute, yn, this);
3363 route.set_mute (yn, this);
3368 Editor::set_edit_menu (Menu& menu)
3371 edit_menu->signal_map_event().connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3375 Editor::edit_menu_map_handler (GdkEventAny* ev)
3377 using namespace Menu_Helpers;
3378 MenuList& edit_items = edit_menu->items();
3381 /* Nuke all the old items */
3383 edit_items.clear ();
3389 if (session->undo_depth() == 0) {
3392 label = string_compose(_("Undo (%1)"), session->next_undo());
3395 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3397 if (session->undo_depth() == 0) {
3398 edit_items.back().set_sensitive (false);
3401 if (session->redo_depth() == 0) {
3404 label = string_compose(_("Redo (%1)"), session->next_redo());
3407 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3408 if (session->redo_depth() == 0) {
3409 edit_items.back().set_sensitive (false);
3412 vector<MenuItem*> mitems;
3414 edit_items.push_back (SeparatorElem());
3415 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3416 mitems.push_back (&edit_items.back());
3417 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3418 mitems.push_back (&edit_items.back());
3419 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3420 mitems.push_back (&edit_items.back());
3421 edit_items.push_back (SeparatorElem());
3422 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3423 mitems.push_back (&edit_items.back());
3424 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3425 mitems.push_back (&edit_items.back());
3426 edit_items.push_back (SeparatorElem());
3428 if (selection->empty()) {
3429 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3430 (*i)->set_sensitive (false);
3434 Menu* import_menu = manage (new Menu());
3435 import_menu->set_name ("ArdourContextMenu");
3436 MenuList& import_items = import_menu->items();
3438 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3439 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3441 Menu* embed_menu = manage (new Menu());
3442 embed_menu->set_name ("ArdourContextMenu");
3443 MenuList& embed_items = embed_menu->items();
3445 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3446 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3448 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3449 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3450 edit_items.push_back (SeparatorElem());
3452 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3453 if (!session->have_captured()) {
3454 edit_items.back().set_sensitive (false);
3461 Editor::duplicate_dialog (bool dup_region)
3464 if (clicked_regionview == 0) {
3468 if (selection->time.length() == 0) {
3473 ArdourDialog win ("duplicate dialog");
3475 Label label (_("Duplicate how many times?"));
3477 win.get_vbox()->pack_start (label);
3478 win.add_action_widget (entry, RESPONSE_ACCEPT);
3479 win.add_button (Stock::OK, RESPONSE_ACCEPT);
3480 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3482 win.set_position (Gtk::WIN_POS_MOUSE);
3484 entry.set_text ("1");
3485 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3486 entry.select_region (0, entry.get_text_length());
3487 entry.grab_focus ();
3490 // win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3493 switch (win.run ()) {
3494 case RESPONSE_ACCEPT:
3500 string text = entry.get_text();
3503 if (sscanf (text.c_str(), "%f", ×) == 1) {
3505 AudioRegionSelection regions;
3506 regions.add (clicked_regionview);
3507 duplicate_some_regions (regions, times);
3509 duplicate_selection (times);
3515 Editor::show_verbose_canvas_cursor ()
3517 verbose_canvas_cursor->raise_to_top();
3518 verbose_canvas_cursor->show();
3519 verbose_cursor_visible = true;
3523 Editor::hide_verbose_canvas_cursor ()
3525 verbose_canvas_cursor->hide();
3526 verbose_cursor_visible = false;
3530 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3532 /* XXX get origin of canvas relative to root window,
3533 add x and y and check compared to gdk_screen_{width,height}
3535 verbose_canvas_cursor->property_text() = txt.c_str();
3536 verbose_canvas_cursor->property_x() = x;
3537 verbose_canvas_cursor->property_y() = y;
3541 Editor::set_verbose_canvas_cursor_text (string txt)
3543 verbose_canvas_cursor->property_text() = txt.c_str();
3547 Editor::edit_mode_selection_done ()
3553 string choice = edit_mode_selector.get_active_text();
3554 EditMode mode = Slide;
3556 if (choice == _("Splice")) {
3558 } else if (choice == _("Slide")) {
3562 session->set_edit_mode (mode);
3566 Editor::snap_type_selection_done ()
3572 string choice = snap_type_selector.get_active_text();
3573 SnapType snaptype = SnapToFrame;
3575 if (choice == _("Beats/3")) {
3576 snaptype = SnapToAThirdBeat;
3577 } else if (choice == _("Beats/4")) {
3578 snaptype = SnapToAQuarterBeat;
3579 } else if (choice == _("Beats/8")) {
3580 snaptype = SnapToAEighthBeat;
3581 } else if (choice == _("Beats/16")) {
3582 snaptype = SnapToASixteenthBeat;
3583 } else if (choice == _("Beats/32")) {
3584 snaptype = SnapToAThirtysecondBeat;
3585 } else if (choice == _("Beats")) {
3586 snaptype = SnapToBeat;
3587 } else if (choice == _("Bars")) {
3588 snaptype = SnapToBar;
3589 } else if (choice == _("Marks")) {
3590 snaptype = SnapToMark;
3591 } else if (choice == _("Edit Cursor")) {
3592 snaptype = SnapToEditCursor;
3593 } else if (choice == _("Region starts")) {
3594 snaptype = SnapToRegionStart;
3595 } else if (choice == _("Region ends")) {
3596 snaptype = SnapToRegionEnd;
3597 } else if (choice == _("Region bounds")) {
3598 snaptype = SnapToRegionBoundary;
3599 } else if (choice == _("Region syncs")) {
3600 snaptype = SnapToRegionSync;
3601 } else if (choice == _("CD Frames")) {
3602 snaptype = SnapToCDFrame;
3603 } else if (choice == _("SMPTE Frames")) {
3604 snaptype = SnapToSMPTEFrame;
3605 } else if (choice == _("SMPTE Seconds")) {
3606 snaptype = SnapToSMPTESeconds;
3607 } else if (choice == _("SMPTE Minutes")) {
3608 snaptype = SnapToSMPTEMinutes;
3609 } else if (choice == _("Seconds")) {
3610 snaptype = SnapToSeconds;
3611 } else if (choice == _("Minutes")) {
3612 snaptype = SnapToMinutes;
3613 } else if (choice == _("None")) {
3614 snaptype = SnapToFrame;
3617 set_snap_to (snaptype);
3621 Editor::snap_mode_selection_done ()
3627 string choice = snap_mode_selector.get_active_text();
3628 SnapMode mode = SnapNormal;
3630 if (choice == _("Normal")) {
3632 } else if (choice == _("Magnetic")) {
3633 mode = SnapMagnetic;
3636 set_snap_mode (mode);
3640 Editor::zoom_focus_selection_done ()
3646 string choice = zoom_focus_selector.get_active_text();
3647 ZoomFocus focus_type = ZoomFocusLeft;
3649 if (choice == _("Left")) {
3650 focus_type = ZoomFocusLeft;
3651 } else if (choice == _("Right")) {
3652 focus_type = ZoomFocusRight;
3653 } else if (choice == _("Center")) {
3654 focus_type = ZoomFocusCenter;
3655 } else if (choice == _("Playhead")) {
3656 focus_type = ZoomFocusPlayhead;
3657 } else if (choice == _("Edit Cursor")) {
3658 focus_type = ZoomFocusEdit;
3661 set_zoom_focus (focus_type);
3665 Editor::edit_controls_button_release (GdkEventButton* ev)
3667 if (Keyboard::is_context_menu_event (ev)) {
3668 ARDOUR_UI::instance()->add_route ();
3674 Editor::track_selection_changed ()
3676 switch (selection->tracks.size()){
3680 set_selected_mixer_strip (*(selection->tracks.front()));
3684 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3685 (*i)->set_selected (false);
3686 if (mouse_mode == MouseRange) {
3687 (*i)->hide_selection ();
3691 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3692 (*i)->set_selected (true);
3693 if (mouse_mode == MouseRange) {
3694 (*i)->show_selection (selection->time);
3700 Editor::time_selection_changed ()
3702 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3703 (*i)->hide_selection ();
3706 if (selection->tracks.empty()) {
3707 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3708 (*i)->show_selection (selection->time);
3711 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3712 (*i)->show_selection (selection->time);
3718 Editor::region_selection_changed ()
3720 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3721 (*i)->set_selected_regionviews (selection->audio_regions);
3726 Editor::point_selection_changed ()
3728 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3729 (*i)->set_selected_points (selection->points);
3734 Editor::run_sub_event_loop ()
3736 sub_event_loop_status = 0;
3741 Editor::finish_sub_event_loop (int status)
3744 sub_event_loop_status = status;
3748 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
3750 finish_sub_event_loop (status);
3755 Editor::mouse_select_button_release (GdkEventButton* ev)
3757 /* this handles just right-clicks */
3759 if (ev->button != 3) {
3766 Editor::TrackViewList *
3767 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
3770 TrackViewList::iterator i;
3772 v = new TrackViewList;
3774 if (track == 0 && group == 0) {
3778 for (i = track_views.begin(); i != track_views.end (); ++i) {
3782 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
3784 /* just the view for this track
3787 v->push_back (track);
3791 /* views for all tracks in the edit group */
3793 for (i = track_views.begin(); i != track_views.end (); ++i) {
3795 if (group == 0 || (*i)->edit_group() == group) {
3805 Editor::set_zoom_focus (ZoomFocus f)
3807 if (zoom_focus != f) {
3809 vector<string> txt = internationalize (zoom_focus_strings);
3810 zoom_focus_selector.set_active_text (txt[(int)f]);
3811 ZoomFocusChanged (); /* EMIT_SIGNAL */
3818 Editor::ensure_float (Window& win)
3820 win.set_transient_for (*this);
3824 Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which)
3826 /* recover or initialize pane positions. do this here rather than earlier because
3827 we don't want the positions to change the child allocations, which they seem to do.
3833 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3835 static int32_t done[4] = { 0, 0, 0, 0 };
3838 if ((geometry = find_named_node (*node, "geometry")) == 0) {
3839 width = default_width;
3840 height = default_height;
3842 width = atoi(geometry->property("x_size")->value());
3843 height = atoi(geometry->property("y_size")->value());
3846 if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
3852 if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
3854 snprintf (buf, sizeof(buf), "%d", pos);
3856 pos = atoi (prop->value());
3859 if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gobj())->allocation.width > pos)) {
3860 track_list_canvas_pane.set_position (pos);
3863 } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
3869 if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
3870 pos = width - (95 * 2);
3871 snprintf (buf, sizeof(buf), "%d", pos);
3873 pos = atoi (prop->value());
3876 if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gobj())->allocation.width > pos)) {
3877 canvas_region_list_pane.set_position (pos);
3880 } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
3886 if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
3887 pos = width - (95 * 2);
3888 snprintf (buf, sizeof(buf), "%d", pos);
3890 pos = atoi (prop->value());
3893 if ((done[2] = GTK_WIDGET(route_group_vpane.gobj())->allocation.height > pos)) {
3894 route_group_vpane.set_position (pos);
3897 } else if (which == static_cast<Gtk::Paned*> (®ion_selection_vpane)) {
3903 if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
3904 pos = width - (95 * 2);
3905 snprintf (buf, sizeof(buf), "%d", pos);
3907 pos = atoi (prop->value());
3910 if ((done[3] = GTK_WIDGET(region_selection_vpane.gobj())->allocation.height > pos)) {
3911 region_selection_vpane.set_position (pos);
3917 Editor::detach_tearoff (Gtk::Box* b, Gtk::Window* w)
3919 if (tools_tearoff->torn_off() &&
3920 mouse_mode_tearoff->torn_off()) {
3921 top_hbox.remove (toolbar_frame);
3928 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Window* w, int32_t n)
3930 if (toolbar_frame.get_parent() == 0) {
3931 top_hbox.pack_end (toolbar_frame);
3936 Editor::set_show_measures (bool yn)
3938 if (_show_measures != yn) {
3941 if ((_show_measures = yn) == true) {
3944 DisplayControlChanged (ShowMeasures);
3950 Editor::set_follow_playhead (bool yn)
3952 if (_follow_playhead != yn) {
3953 if ((_follow_playhead = yn) == true) {
3955 update_current_screen ();
3957 DisplayControlChanged (FollowPlayhead);
3963 Editor::toggle_xfade_active (Crossfade* xfade)
3965 xfade->set_active (!xfade->active());
3969 Editor::toggle_xfade_length (Crossfade* xfade)
3971 xfade->set_follow_overlap (!xfade->following_overlap());
3975 Editor::edit_xfade (Crossfade* xfade)
3977 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
3982 // cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
3984 switch (cew.run ()) {
3985 case RESPONSE_ACCEPT:
3992 xfade->StateChanged (Change (~0));
3996 Editor::playlist_selector () const
3998 return *_playlist_selector;
4002 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
4006 ret = nudge_clock.current_duration (pos);
4007 next = ret + 1; /* XXXX fix me */
4013 Editor::end_location_changed (Location* location)
4015 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
4016 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
4020 Editor::playlist_deletion_dialog (Playlist* pl)
4022 ArdourDialog dialog ("playlist deletion dialog");
4023 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4024 "If left alone, no audio files used by it will be cleaned.\n"
4025 "If deleted, audio files used by it alone by will cleaned."),
4028 dialog.set_position (Gtk::WIN_POS_CENTER);
4029 dialog.get_vbox()->pack_start (label);
4031 dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT);
4032 dialog.add_button (_("Keep playlist"), RESPONSE_CANCEL);
4033 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4035 switch (dialog.run ()) {
4036 case RESPONSE_ACCEPT:
4037 /* delete the playlist */
4041 case RESPONSE_REJECT:
4042 /* keep the playlist */
4054 Editor::audio_region_selection_covers (jack_nframes_t where)
4056 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
4057 if ((*a)->region.covers (where)) {
4066 Editor::prepare_for_cleanup ()
4068 cut_buffer->clear_audio_regions ();
4069 cut_buffer->clear_playlists ();
4071 selection->clear_audio_regions ();
4072 selection->clear_playlists ();
4076 Editor::init_colormap ()
4078 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
4079 pair<ColorID,int> newpair;
4081 newpair.first = (ColorID) x;
4082 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
4083 color_map.insert (newpair);
4088 Editor::transport_loop_location()
4091 return session->locations()->auto_loop_location();
4098 Editor::transport_punch_location()
4101 return session->locations()->auto_punch_location();