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 track_canvas_scroller.signal_map_event().connect (mem_fun (*this, &Editor::track_canvas_map_handler));
350 time_canvas_scroller.signal_map_event().connect (mem_fun (*this, &Editor::time_canvas_map_handler));
352 edit_controls_vbox.set_spacing (track_spacing);
353 edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
354 edit_controls_scroller.add (edit_controls_hbox);
355 edit_controls_scroller.set_name ("EditControlsBase");
356 edit_controls_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
358 Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
360 viewport->set_shadow_type (Gtk::SHADOW_NONE);
361 viewport->set_name ("EditControlsBase");
362 viewport->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
363 viewport->signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
368 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
370 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
371 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
372 time_canvas_vbox.pack_start (*frames_ruler, false, false);
373 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
374 time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
375 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
377 bbt_label.set_name ("EditorTimeButton");
378 bbt_label.set_size_request (-1, (int)timebar_height);
379 bbt_label.set_alignment (1.0, 0.5);
380 bbt_label.set_padding (5,0);
381 minsec_label.set_name ("EditorTimeButton");
382 minsec_label.set_size_request (-1, (int)timebar_height);
383 minsec_label.set_alignment (1.0, 0.5);
384 minsec_label.set_padding (5,0);
385 smpte_label.set_name ("EditorTimeButton");
386 smpte_label.set_size_request (-1, (int)timebar_height);
387 smpte_label.set_alignment (1.0, 0.5);
388 smpte_label.set_padding (5,0);
389 frame_label.set_name ("EditorTimeButton");
390 frame_label.set_size_request (-1, (int)timebar_height);
391 frame_label.set_alignment (1.0, 0.5);
392 frame_label.set_padding (5,0);
393 tempo_label.set_name ("EditorTimeButton");
394 tempo_label.set_size_request (-1, (int)timebar_height);
395 tempo_label.set_alignment (1.0, 0.5);
396 tempo_label.set_padding (5,0);
397 meter_label.set_name ("EditorTimeButton");
398 meter_label.set_size_request (-1, (int)timebar_height);
399 meter_label.set_alignment (1.0, 0.5);
400 meter_label.set_padding (5,0);
401 mark_label.set_name ("EditorTimeButton");
402 mark_label.set_size_request (-1, (int)timebar_height);
403 mark_label.set_alignment (1.0, 0.5);
404 mark_label.set_padding (5,0);
405 range_mark_label.set_name ("EditorTimeButton");
406 range_mark_label.set_size_request (-1, (int)timebar_height);
407 range_mark_label.set_alignment (1.0, 0.5);
408 range_mark_label.set_padding (5,0);
409 transport_mark_label.set_name ("EditorTimeButton");
410 transport_mark_label.set_size_request (-1, (int)timebar_height);
411 transport_mark_label.set_alignment (1.0, 0.5);
412 transport_mark_label.set_padding (5,0);
414 time_button_vbox.pack_start (minsec_label, false, false);
415 time_button_vbox.pack_start (smpte_label, false, false);
416 time_button_vbox.pack_start (frame_label, false, false);
417 time_button_vbox.pack_start (bbt_label, false, false);
418 time_button_vbox.pack_start (meter_label, false, false);
419 time_button_vbox.pack_start (tempo_label, false, false);
420 time_button_vbox.pack_start (mark_label, false, false);
422 time_button_event_box.add (time_button_vbox);
424 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
425 time_button_event_box.set_name ("TimebarLabelBase");
426 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
428 /* these enable us to have a dedicated window (for cursor setting, etc.)
429 for the canvas areas.
432 track_canvas_event_box.add (track_canvas_scroller);
434 time_canvas_event_box.add (time_canvas_vbox);
435 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
438 edit_packer.set_col_spacings (0);
439 edit_packer.set_row_spacings (0);
440 edit_packer.set_homogeneous (false);
441 edit_packer.set_name ("EditorWindow");
443 // edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, Gtk::FILL, 0, 0, 0);
444 // edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, 0, 0, 0);
445 // edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, Gtk::FILL, 0, 0, 0);
446 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
448 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
449 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
451 edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
452 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
453 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
455 edit_frame.set_name ("BaseFrame");
456 edit_frame.set_shadow_type (SHADOW_IN);
457 edit_frame.add (edit_packer);
459 zoom_in_button.set_name ("EditorTimeButton");
460 zoom_out_button.set_name ("EditorTimeButton");
461 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
462 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
464 // zoom_onetoone_button.set_name ("EditorTimeButton");
465 zoom_out_full_button.set_name ("EditorTimeButton");
466 // ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1"));
467 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
469 zoom_in_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(zoom_in_button_xpm)))));
470 zoom_out_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_button_xpm)))));
471 zoom_out_full_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_full_button_xpm)))));
472 // zoom_onetoone_button.add (*(manage (new Gtk::Image (zoom_onetoone_button_xpm))));
475 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
476 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
477 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
478 // zoom_onetoone_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom), 1.0));
480 zoom_indicator_box.pack_start (zoom_out_button, false, false);
481 zoom_indicator_box.pack_start (zoom_in_button, false, false);
482 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
483 // zoom_indicator_box.pack_start (zoom_onetoone_button, false, false);
484 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
486 zoom_indicator_label.set_text (_("Zoom Span"));
487 zoom_indicator_label.set_name ("ToolBarLabel");
490 zoom_indicator_vbox.set_spacing (3);
491 zoom_indicator_vbox.set_border_width (3);
492 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
493 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
496 bottom_hbox.set_border_width (3);
497 bottom_hbox.set_spacing (3);
499 route_display_model = ListStore::create(route_display_columns);
500 route_list.set_model (route_display_model);
501 route_list.append_column (_("Tracks"), route_display_columns.text);
502 route_list.set_name ("TrackListDisplay");
503 route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
504 route_list.set_reorderable (true);
506 route_list.set_size_request (75,-1);
507 route_list.set_headers_visible (true);
508 route_list.set_headers_clickable (true);
511 // route_list.signal_rows_reordered().connect (mem_fun (*this, &Editor::queue_route_list_reordered));
514 // route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func));
517 //route_list.set_shadow_type (Gtk::SHADOW_IN);
519 route_list_scroller.add (route_list);
520 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
522 route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed));
523 route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click));
525 edit_group_list_button_label.set_text (_("Edit Groups"));
526 edit_group_list_button_label.set_name ("EditGroupTitleButton");
527 edit_group_list_button.add (edit_group_list_button_label);
528 edit_group_list_button.set_name ("EditGroupTitleButton");
530 group_model = ListStore::create(group_columns);
531 edit_group_list.set_model (group_model);
532 edit_group_list.append_column (_("active"), group_columns.is_active);
533 edit_group_list.append_column (_("groupname"), group_columns.text);
534 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
535 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
537 /* use checkbox for the active column */
539 CellRendererToggle *active_cell = dynamic_cast<CellRendererToggle*>(edit_group_list.get_column_cell_renderer (0));
540 active_cell->property_activatable() = true;
541 active_cell->property_radio() = false;
543 edit_group_list.set_name ("MixerGroupList");
544 //edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
545 route_list.set_headers_visible (false);
546 edit_group_list.set_reorderable (false);
547 edit_group_list.set_size_request (75, -1);
548 edit_group_list.columns_autosize ();
549 edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
551 edit_group_list_scroller.add (edit_group_list);
552 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
554 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
555 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
556 edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed));
558 TreeModel::Row row = *(group_model->append());
559 row[group_columns.is_active] = false;
560 row[group_columns.text] = (_("-all-"));
561 edit_group_list.get_selection()->select (row);
562 /* GTK2FIX is set_data(0) setting the is_active to false here?
563 list<string> stupid_list;
565 stupid_list.push_back ("*");
566 stupid_list.push_back (_("-all-"));
568 edit_group_list.rows().push_back (stupid_list);
569 edit_group_list.rows().back().set_data (0);
570 edit_group_list.rows().back().select();
573 edit_group_vbox.pack_start (edit_group_list_button, false, false);
574 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
576 route_list_frame.set_name ("BaseFrame");
577 route_list_frame.set_shadow_type (Gtk::SHADOW_IN);
578 route_list_frame.add (route_list_scroller);
580 edit_group_list_frame.set_name ("BaseFrame");
581 edit_group_list_frame.set_shadow_type (Gtk::SHADOW_IN);
582 edit_group_list_frame.add (edit_group_vbox);
584 route_group_vpane.add1 (route_list_frame);
585 route_group_vpane.add2 (edit_group_list_frame);
587 list_vpacker.pack_start (route_group_vpane, true, true);
589 region_list_model = TreeStore::create (region_list_columns);
590 region_list_sort_model = TreeModelSort::create (region_list_model);
591 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
593 region_list_display.set_model (region_list_sort_model);
594 region_list_display.append_column (_("Regions"), region_list_columns.name);
595 region_list_display.set_reorderable (true);
596 region_list_display.set_size_request (100, -1);
597 region_list_display.set_data ("editor", this);
598 region_list_display.set_flags (Gtk::CAN_FOCUS);
599 region_list_display.set_name ("RegionListDisplay");
601 region_list_scroller.add (region_list_display);
602 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
604 list<Gtk::TargetEntry> region_list_target_table;
606 region_list_target_table.push_back (TargetEntry ("STRING"));
607 region_list_target_table.push_back (TargetEntry ("text/plain"));
608 region_list_target_table.push_back (TargetEntry ("text/uri-list"));
609 region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
612 // region_list_display.drag_dest_set (region_list_target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
613 // region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
615 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
616 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
617 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
618 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
619 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
621 //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
622 //region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click));
624 named_selection_scroller.add (named_selection_display);
625 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
627 named_selection_model = TreeStore::create (named_selection_columns);
628 named_selection_display.set_model (named_selection_model);
629 named_selection_display.set_name ("RegionListDisplay");
630 named_selection_display.set_size_request (100, -1);
631 named_selection_display.set_headers_visible (true);
632 named_selection_display.set_headers_clickable (true);
633 named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
634 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
635 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
637 region_selection_vpane.pack1 (region_list_scroller, true, true);
638 region_selection_vpane.pack2 (named_selection_scroller, true, true);
640 canvas_region_list_pane.pack1 (edit_frame, true, true);
641 canvas_region_list_pane.pack2 (region_selection_vpane, true, true);
643 track_list_canvas_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
644 static_cast<Gtk::Paned*> (&track_list_canvas_pane)));
645 canvas_region_list_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
646 static_cast<Gtk::Paned*> (&canvas_region_list_pane)));
647 route_group_vpane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
648 static_cast<Gtk::Paned*> (&route_group_vpane)));
649 region_selection_vpane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
650 static_cast<Gtk::Paned*> (®ion_selection_vpane)));
652 track_list_canvas_pane.pack1 (list_vpacker, true, true);
653 track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true);
655 /* provide special pane-handle event handling for easy "hide" action */
657 /* 0: collapse to show left/upper child
658 1: collapse to show right/lower child
661 route_group_vpane.set_data ("collapse-direction", (gpointer) 0);
662 region_selection_vpane.set_data ("collapse-direction", (gpointer) 0);
663 canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0);
664 track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1);
666 route_group_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&route_group_vpane)));
667 region_selection_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (®ion_selection_vpane)));
668 canvas_region_list_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&canvas_region_list_pane)));
669 track_list_canvas_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&track_list_canvas_pane)));
671 top_hbox.pack_start (toolbar_frame, true, true);
673 HBox *hbox = manage (new HBox);
674 hbox->pack_start (track_list_canvas_pane, true, true);
676 global_vpacker.pack_start (top_hbox, false, false);
677 global_vpacker.pack_start (*hbox, true, true);
679 global_hpacker.pack_start (global_vpacker, true, true);
681 set_name ("EditorWindow");
683 vpacker.pack_end (global_hpacker, true, true);
685 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
688 _playlist_selector = new PlaylistSelector();
689 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
691 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
695 nudge_forward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
696 nudge_backward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
698 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
699 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
701 nudge_forward_button.set_name ("TransportButton");
702 nudge_backward_button.set_name ("TransportButton");
704 fade_context_menu.set_name ("ArdourContextMenu");
706 set_title (_("ardour: editor"));
707 set_wmclass (_("ardour_editor"), "Ardour");
710 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
712 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
713 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
721 /* <CMT Additions> */
722 if(image_socket_listener)
724 if(image_socket_listener->is_connected())
726 image_socket_listener->close_connection() ;
729 delete image_socket_listener ;
730 image_socket_listener = 0 ;
732 /* </CMT Additions> */
736 Editor::add_toplevel_controls (Container& cont)
738 vpacker.pack_start (cont, false, false);
743 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
745 /* note: the selection will take care of the vanishing
746 audioregionview by itself.
749 if (clicked_regionview == rv) {
750 clicked_regionview = 0;
753 if (entered_regionview == rv) {
754 set_entered_regionview (0);
759 Editor::set_entered_regionview (AudioRegionView* rv)
761 if (rv == entered_regionview) {
765 if (entered_regionview) {
766 entered_regionview->exited ();
769 if ((entered_regionview = rv) != 0) {
770 entered_regionview->entered ();
775 Editor::set_entered_track (TimeAxisView* tav)
778 entered_track->exited ();
781 if ((entered_track = tav) != 0) {
782 entered_track->entered ();
787 Editor::left_track_canvas (GdkEventCrossing *ev)
789 set_entered_track (0);
790 set_entered_regionview (0);
796 Editor::show_window ()
800 /* now reset all audio_time_axis heights, because widgets might need
806 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
807 tv = (static_cast<TimeAxisView*>(*i));
813 Editor::tie_vertical_scrolling ()
815 edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
817 float y1 = track_canvas_scroller.get_vadjustment()->get_value();
818 playhead_cursor->set_y_axis(y1);
819 edit_cursor->set_y_axis(y1);
823 Editor::set_frames_per_unit (double fpu)
825 jack_nframes_t frames;
827 if (fpu == frames_per_unit) {
835 // convert fpu to frame count
837 frames = (jack_nframes_t) (fpu * canvas_width);
839 /* don't allow zooms that fit more than the maximum number
840 of frames into an 800 pixel wide space.
843 if (max_frames / fpu < 800.0) {
847 frames_per_unit = fpu;
849 if (frames != zoom_range_clock.current_duration()) {
850 zoom_range_clock.set (frames);
853 /* only update these if we not about to call reposition_x_origin,
854 which will do the same updates.
858 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
861 if (!no_zoom_repos_update) {
862 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
864 update_fixed_rulers ();
865 tempo_map_changed (Change (0));
868 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
869 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
870 (*i)->reshow_selection (selection->time);
874 ZoomChanged (); /* EMIT_SIGNAL */
876 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
877 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
884 Editor::instant_save ()
886 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
891 session->add_instant_xml(get_state(), session->path());
893 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
898 Editor::reposition_x_origin (jack_nframes_t frame)
900 if (frame != leftmost_frame) {
901 leftmost_frame = frame;
902 double pixel = frame_to_pixel (frame);
903 if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
904 track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
906 track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
907 XOriginChanged (); /* EMIT_SIGNAL */
912 Editor::edit_cursor_clock_changed()
914 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
915 edit_cursor->set_position (edit_cursor_clock.current_time());
921 Editor::zoom_adjustment_changed ()
923 if (session == 0 || no_zoom_repos_update) {
927 double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width;
931 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
933 else if (fpu > session->current_end_frame() / (double) canvas_width) {
934 fpu = session->current_end_frame() / (double) canvas_width;
935 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
942 Editor::canvas_horizontally_scrolled ()
944 /* XXX note the potential loss of accuracy here caused by
945 adjustments being 32bit floats with only a 24 bit mantissa,
946 whereas jack_nframes_t is at least a 32 bit uint32_teger.
949 leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
952 update_fixed_rulers ();
954 if (!edit_hscroll_dragging) {
955 tempo_map_changed (Change (0));
957 update_tempo_based_rulers();
962 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
964 if (!repos_zoom_queued) {
965 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
966 repos_zoom_queued = true;
971 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
973 /* if we need to force an update to the hscroller stuff,
974 don't set no_zoom_repos_update.
977 no_zoom_repos_update = (frame != leftmost_frame);
979 set_frames_per_unit (nfpu);
980 if (no_zoom_repos_update) {
981 reposition_x_origin (frame);
983 no_zoom_repos_update = false;
984 repos_zoom_queued = false;
990 Editor::on_realize ()
992 Window::on_realize ();
994 /* Even though we're not using acceleration, we want the
998 track_context_menu.accelerate (*this->get_toplevel());
999 track_region_context_menu.accelerate (*this->get_toplevel());
1001 Glib::RefPtr<Gdk::Pixmap> empty_pixmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1002 Glib::RefPtr<Gdk::Pixmap> empty_bitmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1003 Gdk::Color white ("#ffffff" );
1005 null_cursor = new Gdk::Cursor(empty_pixmap, empty_bitmap, white, white, 0, 0);
1009 Editor::track_canvas_allocate (Gtk::Allocation alloc)
1011 canvas_width = alloc.get_width();
1012 canvas_height = alloc.get_height();
1014 if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) {
1016 Pango::FontDescription font = get_font_for_style (N_("FirstActionMessage"));
1018 const char *txt1 = _("Start a new session\n");
1019 const char *txt2 = _("via Session menu");
1021 /* this mess of code is here to find out how wide this text is and
1022 position the message in the center of the editor window. there
1023 are two lines, so we use the longer of the the lines to
1024 compute width, and multiply the height by 2.
1030 /* this is a dummy widget that exists so that we can get the
1031 style from the RC file.
1034 Label foo (_(txt2));
1035 Glib::RefPtr<Pango::Layout> layout;
1036 foo.set_name ("NoSessionMessage");
1037 foo.ensure_style ();
1039 layout = foo.create_pango_layout (_(txt2));
1040 layout->set_font_description (font);
1041 layout->get_pixel_size (pixel_width, pixel_height);
1043 if (first_action_message == 0) {
1045 char txt[strlen(txt1)+strlen(txt2)+1];
1047 /* merge both lines */
1049 strcpy (txt, _(txt1));
1050 strcat (txt, _(txt2));
1052 first_action_message = new ArdourCanvas::Text (*track_canvas.root());
1053 first_action_message->property_font_desc() = font;
1054 first_action_message->property_fill_color_rgba() = color_map[cFirstActionMessage];
1055 first_action_message->property_x() = (gdouble) (canvas_width - pixel_width) / 2.0;
1056 first_action_message->property_y() = (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height));
1057 first_action_message->property_anchor() = ANCHOR_NORTH_WEST;
1058 first_action_message->property_text() = ustring (txt);
1063 first_action_message->property_x() = (gdouble) (canvas_width - pixel_width) / 2.0;
1064 first_action_message->property_y() = (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height));
1068 zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit));
1069 edit_cursor->set_position (edit_cursor->current_frame);
1070 playhead_cursor->set_position (playhead_cursor->current_frame);
1071 reset_scrolling_region (&alloc);
1073 Resized (); /* EMIT_SIGNAL */
1077 Editor::queue_session_control_changed (Session::ControlType t)
1079 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1083 Editor::session_control_changed (Session::ControlType t)
1085 // right now we're only tracking the loop and punch state
1088 case Session::AutoLoop:
1089 update_loop_range_view (true);
1091 case Session::PunchIn:
1092 case Session::PunchOut:
1093 update_punch_range_view (true);
1102 Editor::fake_add_edit_group (RouteGroup *group)
1104 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1108 Editor::fake_handle_new_audio_region (AudioRegion *region)
1110 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1114 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1116 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1120 Editor::fake_handle_new_duration ()
1122 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1126 Editor::start_scrolling ()
1128 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1129 (mem_fun(*this, &Editor::update_current_screen));
1131 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1132 (mem_fun(*this, &Editor::update_slower));
1136 Editor::stop_scrolling ()
1138 scroll_connection.disconnect ();
1139 slower_update_connection.disconnect ();
1143 Editor::map_position_change (jack_nframes_t frame)
1145 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1147 if (session == 0 || !_follow_playhead) {
1151 center_screen (frame);
1152 playhead_cursor->set_position (frame);
1156 Editor::center_screen (jack_nframes_t frame)
1158 float page = canvas_width * frames_per_unit;
1160 /* if we're off the page, then scroll.
1163 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1164 center_screen_internal (frame,page);
1169 Editor::center_screen_internal (jack_nframes_t frame, float page)
1174 frame -= (jack_nframes_t) page;
1179 reposition_x_origin (frame);
1183 Editor::handle_new_duration ()
1185 reset_scrolling_region ();
1188 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1189 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1192 update_hscroller ();
1196 Editor::update_title_s (string snap_name)
1198 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1204 Editor::update_title ()
1206 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1209 bool dirty = session->dirty();
1211 string wintitle = _("ardour: editor: ");
1217 wintitle += session->name();
1219 if (session->snap_name() != session->name()) {
1221 wintitle += session->snap_name();
1228 set_title (wintitle);
1233 Editor::connect_to_session (Session *t)
1237 if (first_action_message) {
1238 first_action_message->hide();
1241 flush_track_canvas();
1245 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1247 /* These signals can all be emitted by a non-GUI thread. Therefore the
1248 handlers for them must not attempt to directly interact with the GUI,
1249 but use Gtkmm2ext::UI::instance()->call_slot();
1252 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1253 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1254 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1255 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1256 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1257 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1258 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1259 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1260 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1261 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1262 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1263 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1264 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1266 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1267 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1269 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1271 session->foreach_edit_group(this, &Editor::add_edit_group);
1273 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1274 editor_mixer_button.set_name (X_("EditorMixerButton"));
1276 edit_cursor_clock.set_session (session);
1277 selection_start_clock.set_session (session);
1278 selection_end_clock.set_session (session);
1279 zoom_range_clock.set_session (session);
1280 _playlist_selector->set_session (session);
1281 nudge_clock.set_session (session);
1283 switch (session->get_edit_mode()) {
1285 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1289 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1293 Location* loc = session->locations()->auto_loop_location();
1295 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1296 if (loc->start() == loc->end()) {
1297 loc->set_end (loc->start() + 1);
1299 session->locations()->add (loc, false);
1300 session->set_auto_loop_location (loc);
1304 loc->set_name (_("Loop"));
1307 loc = session->locations()->auto_punch_location();
1309 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1310 if (loc->start() == loc->end()) {
1311 loc->set_end (loc->start() + 1);
1313 session->locations()->add (loc, false);
1314 session->set_auto_punch_location (loc);
1318 loc->set_name (_("Punch"));
1321 update_loop_range_view (true);
1322 update_punch_range_view (true);
1324 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1327 refresh_location_display ();
1328 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1329 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1330 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1331 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1332 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1334 reset_scrolling_region ();
1336 redisplay_regions ();
1337 redisplay_named_selections ();
1339 //route_list.freeze (); GTK2FIX
1340 route_display_model->clear ();
1341 session->foreach_route (this, &Editor::handle_new_route);
1342 // route_list.select_all ();
1344 //route_list.sort ();
1345 route_list_reordered ();
1346 //route_list.thaw ();
1348 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1349 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1352 /* ::reposition_x_origin() doesn't work right here, since the old
1353 position may be zero already, and it does nothing in such
1359 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1360 track_canvas_scroller.get_hadjustment()->set_value (0);
1362 update_hscroller ();
1363 restore_ruler_visibility ();
1364 tempo_map_changed (Change (0));
1366 edit_cursor->set_position (0);
1367 playhead_cursor->set_position (0);
1371 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1374 /* don't show master bus in a new session */
1376 if (ARDOUR_UI::instance()->session_is_new ()) {
1378 TreeModel::Children rows = route_display_model->children();
1379 TreeModel::Children::iterator i;
1381 //route_list.freeze ();
1383 for (i = rows.begin(); i != rows.end(); ++i) {
1384 TimeAxisView *tv = (*i)[route_display_columns.tv];
1385 AudioTimeAxisView *atv;
1387 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1388 if (atv->route().master()) {
1389 route_list.get_selection()->unselect (i);
1390 //(*i)->unselect ();
1395 //route_list.thaw ();
1400 Editor::build_cursors ()
1402 using namespace Gdk;
1404 Gdk::Color fg ("#ff0000"); /* Red. */
1405 Gdk::Color bg ("#0000ff"); /* Blue. */
1408 RefPtr<Bitmap> source, mask;
1409 source = Bitmap::create (hand_bits, hand_width, hand_height);
1410 mask = Bitmap::create (handmask_bits, handmask_width, handmask_height);
1411 grabber_cursor = new Gdk::Cursor (source, mask, fg, bg, hand_x_hot, hand_y_hot);
1414 Gdk::Color mbg ("#000000" ); /* Black */
1415 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1418 RefPtr<Bitmap> source, mask;
1419 source = Bitmap::create (mag_bits, mag_width, mag_height);
1420 mask = Bitmap::create (magmask_bits, mag_width, mag_height);
1421 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1424 Gdk::Color fbg ("#ffffff" );
1425 Gdk::Color ffg ("#000000" );
1428 RefPtr<Bitmap> source, mask;
1430 source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
1431 mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
1432 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1436 RefPtr<Bitmap> source, mask;
1437 source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
1438 mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
1439 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1442 cross_hair_cursor = new Gdk::Cursor (Gdk::CROSSHAIR);
1443 trimmer_cursor = new Gdk::Cursor (Gdk::SB_H_DOUBLE_ARROW);
1444 selector_cursor = new Gdk::Cursor (Gdk::XTERM);
1445 time_fx_cursor = new Gdk::Cursor (Gdk::SIZING);
1446 wait_cursor = new Gdk::Cursor (Gdk::WATCH);
1447 timebar_cursor = new Gdk::Cursor(Gdk::LEFT_PTR);
1451 Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
1453 using namespace Menu_Helpers;
1454 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1457 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1461 MenuList& items (fade_context_menu.items());
1465 switch (item_type) {
1467 case FadeInHandleItem:
1468 if (arv->region.fade_in_active()) {
1469 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1471 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1474 items.push_back (SeparatorElem());
1476 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1477 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1478 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1479 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1480 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1484 case FadeOutHandleItem:
1485 if (arv->region.fade_out_active()) {
1486 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1488 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1491 items.push_back (SeparatorElem());
1493 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1494 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1495 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1496 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1497 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1501 fatal << _("programming error: ")
1502 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1507 fade_context_menu.popup (button, time);
1511 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1513 using namespace Menu_Helpers;
1514 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1517 switch (item_type) {
1519 case AudioRegionViewName:
1520 case AudioRegionViewNameHighlight:
1521 if (with_selection) {
1522 build_menu_function = &Editor::build_track_selection_context_menu;
1524 build_menu_function = &Editor::build_track_region_context_menu;
1529 if (with_selection) {
1530 build_menu_function = &Editor::build_track_selection_context_menu;
1532 build_menu_function = &Editor::build_track_context_menu;
1536 case CrossfadeViewItem:
1537 build_menu_function = &Editor::build_track_crossfade_context_menu;
1541 if (clicked_audio_trackview->get_diskstream()) {
1542 build_menu_function = &Editor::build_track_context_menu;
1544 build_menu_function = &Editor::build_track_bus_context_menu;
1549 /* probably shouldn't happen but if it does, we don't care */
1553 menu = (this->*build_menu_function)(frame);
1554 menu->set_name ("ArdourContextMenu");
1556 /* now handle specific situations */
1558 switch (item_type) {
1560 case AudioRegionViewName:
1561 case AudioRegionViewNameHighlight:
1562 if (!with_selection) {
1563 if (region_edit_menu_split_item) {
1564 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1565 // GTK2FIX find the action, change its sensitivity
1566 // region_edit_menu_split_item->set_sensitive (true);
1568 // GTK2FIX see above
1569 // region_edit_menu_split_item->set_sensitive (false);
1572 if (region_edit_menu_split_multichannel_item) {
1573 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1574 // GTK2FIX find the action, change its sensitivity
1575 // region_edit_menu_split_multichannel_item->set_sensitive (true);
1577 // GTK2FIX see above
1578 // region_edit_menu_split_multichannel_item->set_sensitive (false);
1587 case CrossfadeViewItem:
1594 /* probably shouldn't happen but if it does, we don't care */
1598 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1600 /* Bounce to disk */
1602 using namespace Menu_Helpers;
1603 MenuList& edit_items = menu->items();
1605 edit_items.push_back (SeparatorElem());
1607 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1608 case AudioTrack::NoFreeze:
1609 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1612 case AudioTrack::Frozen:
1613 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1616 case AudioTrack::UnFrozen:
1617 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1623 menu->popup (button, time);
1627 Editor::build_track_context_menu (jack_nframes_t ignored)
1629 using namespace Menu_Helpers;
1631 MenuList& edit_items = track_context_menu.items();
1634 add_dstream_context_items (edit_items);
1635 return &track_context_menu;
1639 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1641 using namespace Menu_Helpers;
1643 MenuList& edit_items = track_context_menu.items();
1646 add_bus_context_items (edit_items);
1647 return &track_context_menu;
1651 Editor::build_track_region_context_menu (jack_nframes_t frame)
1653 using namespace Menu_Helpers;
1654 MenuList& edit_items = track_region_context_menu.items();
1657 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1663 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1664 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1665 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1666 add_region_context_items (atv->view, (*i), edit_items);
1672 add_dstream_context_items (edit_items);
1674 return &track_region_context_menu;
1678 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1680 using namespace Menu_Helpers;
1681 MenuList& edit_items = track_crossfade_context_menu.items();
1682 edit_items.clear ();
1684 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1691 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
1693 Playlist::RegionList* regions = pl->regions_at (frame);
1694 AudioPlaylist::Crossfades xfades;
1696 apl->crossfades_at (frame, xfades);
1698 bool many = xfades.size() > 1;
1700 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
1701 add_crossfade_context_items (atv->view, (*i), edit_items, many);
1704 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1705 add_region_context_items (atv->view, (*i), edit_items);
1712 add_dstream_context_items (edit_items);
1714 return &track_crossfade_context_menu;
1718 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
1720 using namespace Menu_Helpers;
1721 MenuList& edit_items = track_selection_context_menu.items();
1722 edit_items.clear ();
1724 add_selection_context_items (edit_items);
1725 add_dstream_context_items (edit_items);
1727 return &track_selection_context_menu;
1731 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
1733 using namespace Menu_Helpers;
1734 Menu *xfade_menu = manage (new Menu);
1735 MenuList& items = xfade_menu->items();
1736 xfade_menu->set_name ("ArdourContextMenu");
1739 if (xfade->active()) {
1745 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
1746 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
1748 if (xfade->can_follow_overlap()) {
1750 if (xfade->following_overlap()) {
1751 str = _("Convert to short");
1753 str = _("Convert to full");
1756 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
1760 str = xfade->out().name();
1762 str += xfade->in().name();
1764 str = _("Crossfade");
1767 edit_items.push_back (MenuElem (str, *xfade_menu));
1768 edit_items.push_back (SeparatorElem());
1772 Editor::xfade_edit_left_region ()
1774 if (clicked_crossfadeview) {
1775 clicked_crossfadeview->left_view.show_region_editor ();
1780 Editor::xfade_edit_right_region ()
1782 if (clicked_crossfadeview) {
1783 clicked_crossfadeview->right_view.show_region_editor ();
1788 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
1790 using namespace Menu_Helpers;
1791 Menu *region_menu = manage (new Menu);
1792 MenuList& items = region_menu->items();
1793 region_menu->set_name ("ArdourContextMenu");
1795 AudioRegion* ar = 0;
1798 ar = dynamic_cast<AudioRegion*> (region);
1801 /* when this particular menu pops up, make the relevant region
1805 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
1807 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
1808 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
1809 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
1810 items.push_back (SeparatorElem());
1811 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
1812 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
1813 items.push_back (SeparatorElem());
1815 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
1816 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
1817 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
1818 items.push_back (SeparatorElem());
1820 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
1821 might be able to figure out which overloaded member function to use in
1825 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
1827 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
1828 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
1829 items.push_back (SeparatorElem());
1831 if (region->muted()) {
1832 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
1834 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
1836 items.push_back (SeparatorElem());
1838 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
1839 items.push_back (SeparatorElem());
1844 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
1845 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
1846 items.push_back (SeparatorElem());
1848 if (ar->scale_amplitude() != 1.0f) {
1849 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
1851 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
1854 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
1855 items.push_back (SeparatorElem());
1859 Menu *nudge_menu = manage (new Menu());
1860 MenuList& nudge_items = nudge_menu->items();
1861 nudge_menu->set_name ("ArdourContextMenu");
1863 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
1864 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
1865 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
1866 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
1868 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1869 items.push_back (SeparatorElem());
1871 Menu *trim_menu = manage (new Menu);
1872 MenuList& trim_items = trim_menu->items();
1873 trim_menu->set_name ("ArdourContextMenu");
1875 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
1876 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
1878 items.push_back (MenuElem (_("Trim"), *trim_menu));
1879 items.push_back (SeparatorElem());
1881 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
1882 region_edit_menu_split_item = &items.back();
1884 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
1885 region_edit_menu_split_multichannel_item = &items.back();
1887 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
1888 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
1889 items.push_back (SeparatorElem());
1890 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
1891 items.push_back (SeparatorElem());
1892 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
1894 /* OK, stick the region submenu at the top of the list, and then add
1898 /* we have to hack up the region name because "_" has a special
1899 meaning for menu titles.
1902 string::size_type pos = 0;
1903 string menu_item_name = region->name();
1905 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1906 menu_item_name.replace (pos, 1, "__");
1910 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
1911 edit_items.push_back (SeparatorElem());
1915 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1917 using namespace Menu_Helpers;
1918 Menu *selection_menu = manage (new Menu);
1919 MenuList& items = selection_menu->items();
1920 selection_menu->set_name ("ArdourContextMenu");
1922 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
1923 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
1924 items.push_back (SeparatorElem());
1925 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
1926 items.push_back (SeparatorElem());
1927 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
1928 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
1929 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
1930 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
1931 items.push_back (SeparatorElem());
1932 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
1933 items.push_back (SeparatorElem());
1934 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
1935 items.push_back (SeparatorElem());
1936 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
1938 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
1939 edit_items.push_back (SeparatorElem());
1943 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1945 using namespace Menu_Helpers;
1949 Menu *play_menu = manage (new Menu);
1950 MenuList& play_items = play_menu->items();
1951 play_menu->set_name ("ArdourContextMenu");
1953 play_items.push_back (MenuElem (_("Play from edit cursor")));
1954 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1955 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
1956 play_items.push_back (SeparatorElem());
1957 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
1959 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1963 Menu *select_menu = manage (new Menu);
1964 MenuList& select_items = select_menu->items();
1965 select_menu->set_name ("ArdourContextMenu");
1967 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
1968 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
1969 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1970 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
1971 select_items.push_back (SeparatorElem());
1972 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1973 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1974 select_items.push_back (SeparatorElem());
1976 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1980 Menu *cutnpaste_menu = manage (new Menu);
1981 MenuList& cutnpaste_items = cutnpaste_menu->items();
1982 cutnpaste_menu->set_name ("ArdourContextMenu");
1984 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
1985 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
1986 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
1987 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
1989 cutnpaste_items.push_back (SeparatorElem());
1991 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
1992 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
1994 cutnpaste_items.push_back (SeparatorElem());
1996 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
1998 cutnpaste_items.push_back (SeparatorElem());
2000 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
2001 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
2003 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2005 /* Adding new material */
2007 Menu *import_menu = manage (new Menu());
2008 MenuList& import_items = import_menu->items();
2009 import_menu->set_name ("ArdourContextMenu");
2011 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2012 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
2014 edit_items.push_back (MenuElem (_("Import"), *import_menu));
2018 Menu *nudge_menu = manage (new Menu());
2019 MenuList& nudge_items = nudge_menu->items();
2020 nudge_menu->set_name ("ArdourContextMenu");
2022 edit_items.push_back (SeparatorElem());
2023 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2024 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2025 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2026 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2028 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2032 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2034 using namespace Menu_Helpers;
2038 Menu *play_menu = manage (new Menu);
2039 MenuList& play_items = play_menu->items();
2040 play_menu->set_name ("ArdourContextMenu");
2042 play_items.push_back (MenuElem (_("Play from edit cursor")));
2043 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2044 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2048 Menu *select_menu = manage (new Menu);
2049 MenuList& select_items = select_menu->items();
2050 select_menu->set_name ("ArdourContextMenu");
2052 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2053 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2054 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2055 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2056 select_items.push_back (SeparatorElem());
2057 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2058 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2059 select_items.push_back (SeparatorElem());
2061 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2065 Menu *cutnpaste_menu = manage (new Menu);
2066 MenuList& cutnpaste_items = cutnpaste_menu->items();
2067 cutnpaste_menu->set_name ("ArdourContextMenu");
2069 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2070 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2071 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2073 Menu *nudge_menu = manage (new Menu());
2074 MenuList& nudge_items = nudge_menu->items();
2075 nudge_menu->set_name ("ArdourContextMenu");
2077 edit_items.push_back (SeparatorElem());
2078 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2079 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2080 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2081 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2083 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2086 /* CURSOR SETTING AND MARKS AND STUFF */
2089 Editor::set_snap_to (SnapType st)
2092 vector<string> txt = internationalize (snap_type_strings);
2093 snap_type_selector.set_active_text (txt[(int)st]);
2097 switch (snap_type) {
2098 case SnapToAThirtysecondBeat:
2099 case SnapToASixteenthBeat:
2100 case SnapToAEighthBeat:
2101 case SnapToAQuarterBeat:
2102 case SnapToAThirdBeat:
2103 update_tempo_based_rulers ();
2111 Editor::set_snap_mode (SnapMode mode)
2114 vector<string> txt = internationalize (snap_mode_strings);
2115 snap_mode_selector.set_active_text (txt[(int)mode]);
2121 Editor::add_location_from_selection ()
2123 if (selection->time.empty()) {
2127 if (session == 0 || clicked_trackview == 0) {
2131 jack_nframes_t start = selection->time[clicked_selection].start;
2132 jack_nframes_t end = selection->time[clicked_selection].end;
2134 Location *location = new Location (start, end, "selection");
2136 session->begin_reversible_command (_("add marker"));
2137 session->add_undo (session->locations()->get_memento());
2138 session->locations()->add (location, true);
2139 session->add_redo_no_execute (session->locations()->get_memento());
2140 session->commit_reversible_command ();
2144 Editor::add_location_from_playhead_cursor ()
2146 jack_nframes_t where = session->audible_frame();
2148 Location *location = new Location (where, where, "mark", Location::IsMark);
2149 session->begin_reversible_command (_("add marker"));
2150 session->add_undo (session->locations()->get_memento());
2151 session->locations()->add (location, true);
2152 session->add_redo_no_execute (session->locations()->get_memento());
2153 session->commit_reversible_command ();
2158 Editor::set_state (const XMLNode& node)
2160 const XMLProperty* prop;
2162 int x, y, width, height, xoff, yoff;
2164 if ((geometry = find_named_node (node, "geometry")) == 0) {
2166 width = default_width;
2167 height = default_height;
2175 width = atoi(geometry->property("x_size")->value());
2176 height = atoi(geometry->property("y_size")->value());
2177 x = atoi(geometry->property("x_pos")->value());
2178 y = atoi(geometry->property("y_pos")->value());
2179 xoff = atoi(geometry->property("x_off")->value());
2180 yoff = atoi(geometry->property("y_off")->value());
2183 set_default_size(width, height);
2185 // set_position(x, y-yoff);
2187 if ((prop = node.property ("zoom-focus"))) {
2188 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2191 if ((prop = node.property ("zoom"))) {
2192 set_frames_per_unit (atof (prop->value()));
2195 if ((prop = node.property ("snap-to"))) {
2196 set_snap_to ((SnapType) atoi (prop->value()));
2199 if ((prop = node.property ("snap-mode"))) {
2200 set_snap_mode ((SnapMode) atoi (prop->value()));
2203 if ((prop = node.property ("show-waveforms"))) {
2204 bool yn = (prop->value() == "yes");
2205 _show_waveforms = !yn;
2206 set_show_waveforms (yn);
2209 if ((prop = node.property ("show-waveforms-recording"))) {
2210 bool yn = (prop->value() == "yes");
2211 _show_waveforms_recording = !yn;
2212 set_show_waveforms_recording (yn);
2215 if ((prop = node.property ("show-measures"))) {
2216 bool yn = (prop->value() == "yes");
2217 _show_measures = !yn;
2218 set_show_measures (yn);
2221 if ((prop = node.property ("follow-playhead"))) {
2222 bool yn = (prop->value() == "yes");
2223 _follow_playhead = !yn;
2224 set_follow_playhead (yn);
2227 if ((prop = node.property ("xfades-visible"))) {
2228 bool yn = (prop->value() == "yes");
2229 _xfade_visibility = !yn;
2230 set_xfade_visibility (yn);
2233 if ((prop = node.property ("region-list-sort-type"))) {
2234 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2235 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2238 if ((prop = node.property ("mouse-mode"))) {
2239 MouseMode m = str2mousemode(prop->value());
2240 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2241 set_mouse_mode (m, true);
2243 mouse_mode = MouseGain; /* lie, to force the mode switch */
2244 set_mouse_mode (MouseObject, true);
2247 if ((prop = node.property ("editor-mixer-button"))) {
2248 editor_mixer_button.set_active(prop->value() == "yes");
2255 Editor::get_state ()
2257 XMLNode* node = new XMLNode ("Editor");
2260 if (is_realized()) {
2261 Glib::RefPtr<Gdk::Window> win = get_window();
2263 int x, y, xoff, yoff, width, height;
2264 win->get_root_origin(x, y);
2265 win->get_position(xoff, yoff);
2266 win->get_size(width, height);
2268 XMLNode* geometry = new XMLNode ("geometry");
2270 snprintf(buf, sizeof(buf), "%d", width);
2271 geometry->add_property("x_size", string(buf));
2272 snprintf(buf, sizeof(buf), "%d", height);
2273 geometry->add_property("y_size", string(buf));
2274 snprintf(buf, sizeof(buf), "%d", x);
2275 geometry->add_property("x_pos", string(buf));
2276 snprintf(buf, sizeof(buf), "%d", y);
2277 geometry->add_property("y_pos", string(buf));
2278 snprintf(buf, sizeof(buf), "%d", xoff);
2279 geometry->add_property("x_off", string(buf));
2280 snprintf(buf, sizeof(buf), "%d", yoff);
2281 geometry->add_property("y_off", string(buf));
2282 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gobj()));
2283 geometry->add_property("canvas_region_list_pane_pos", string(buf));
2284 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gobj()));
2285 geometry->add_property("track_list_canvas_pane_pos", string(buf));
2286 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(®ion_selection_vpane)->gobj()));
2287 geometry->add_property("region_selection_pane_pos", string(buf));
2288 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gobj()));
2289 geometry->add_property("route_group_pane_pos", string(buf));
2291 node->add_child_nocopy (*geometry);
2294 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2295 node->add_property ("zoom-focus", buf);
2296 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2297 node->add_property ("zoom", buf);
2298 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2299 node->add_property ("snap-to", buf);
2300 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2301 node->add_property ("snap-mode", buf);
2303 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2304 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2305 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2306 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2307 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2308 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2309 node->add_property ("mouse-mode", enum2str(mouse_mode));
2310 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2318 Editor::trackview_by_y_position (double y)
2320 TrackViewList::iterator iter;
2323 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2331 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2340 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2342 Location* before = 0;
2343 Location* after = 0;
2349 const jack_nframes_t one_second = session->frame_rate();
2350 const jack_nframes_t one_minute = session->frame_rate() * 60;
2352 jack_nframes_t presnap = start;
2354 switch (snap_type) {
2360 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2362 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2365 case SnapToSMPTEFrame:
2367 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2369 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2373 case SnapToSMPTESeconds:
2374 if (session->smpte_offset_negative())
2376 start += session->smpte_offset ();
2378 start -= session->smpte_offset ();
2380 if (direction > 0) {
2381 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2383 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2386 if (session->smpte_offset_negative())
2388 start -= session->smpte_offset ();
2390 start += session->smpte_offset ();
2394 case SnapToSMPTEMinutes:
2395 if (session->smpte_offset_negative())
2397 start += session->smpte_offset ();
2399 start -= session->smpte_offset ();
2402 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2404 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2406 if (session->smpte_offset_negative())
2408 start -= session->smpte_offset ();
2410 start += session->smpte_offset ();
2416 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2418 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2424 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2426 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2431 start = session->tempo_map().round_to_bar (start, direction);
2435 start = session->tempo_map().round_to_beat (start, direction);
2438 case SnapToAThirtysecondBeat:
2439 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2442 case SnapToASixteenthBeat:
2443 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2446 case SnapToAEighthBeat:
2447 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2450 case SnapToAQuarterBeat:
2451 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2454 case SnapToAThirdBeat:
2455 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2458 case SnapToEditCursor:
2459 start = edit_cursor->current_frame;
2467 before = session->locations()->first_location_before (start);
2468 after = session->locations()->first_location_after (start);
2470 if (direction < 0) {
2472 start = before->start();
2476 } else if (direction > 0) {
2478 start = after->start();
2480 start = session->current_end_frame();
2485 /* find nearest of the two */
2486 if ((start - before->start()) < (after->start() - start)) {
2487 start = before->start();
2489 start = after->start();
2492 start = before->start();
2495 start = after->start();
2502 case SnapToRegionStart:
2503 case SnapToRegionEnd:
2504 case SnapToRegionSync:
2505 case SnapToRegionBoundary:
2506 if (!region_boundary_cache.empty()) {
2507 vector<jack_nframes_t>::iterator i;
2509 if (direction > 0) {
2510 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2512 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2515 if (i != region_boundary_cache.end()) {
2518 start = region_boundary_cache.back();
2524 switch (snap_mode) {
2530 if (presnap > start) {
2531 if (presnap > (start + unit_to_frame(snap_threshold))) {
2535 } else if (presnap < start) {
2536 if (presnap < (start - unit_to_frame(snap_threshold))) {
2548 Editor::setup_toolbar ()
2551 vector<ToggleButton *> mouse_mode_buttons;
2553 mouse_mode_buttons.push_back (&mouse_move_button);
2554 mouse_mode_buttons.push_back (&mouse_select_button);
2555 mouse_mode_buttons.push_back (&mouse_gain_button);
2556 mouse_mode_buttons.push_back (&mouse_zoom_button);
2557 mouse_mode_buttons.push_back (&mouse_timefx_button);
2558 mouse_mode_buttons.push_back (&mouse_audition_button);
2559 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2561 mouse_mode_button_table.set_homogeneous (true);
2562 mouse_mode_button_table.set_col_spacings (2);
2563 mouse_mode_button_table.set_row_spacings (2);
2564 mouse_mode_button_table.set_border_width (5);
2566 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2567 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2568 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2570 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2571 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2572 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2574 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2575 mouse_mode_tearoff->set_name ("MouseModeBase");
2577 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2578 mouse_mode_tearoff->tearoff_window()));
2579 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2580 mouse_mode_tearoff->tearoff_window(), 1));
2582 mouse_move_button.set_name ("MouseModeButton");
2583 mouse_select_button.set_name ("MouseModeButton");
2584 mouse_gain_button.set_name ("MouseModeButton");
2585 mouse_zoom_button.set_name ("MouseModeButton");
2586 mouse_timefx_button.set_name ("MouseModeButton");
2587 mouse_audition_button.set_name ("MouseModeButton");
2589 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2590 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2591 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2592 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2593 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2594 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2596 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2597 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2598 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2599 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2600 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2601 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2603 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2604 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2606 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2607 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2608 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2609 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2610 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2612 // mouse_move_button.set_active (true);
2614 /* automation control */
2616 global_automation_button.set_name ("MouseModeButton");
2617 automation_mode_button.set_name ("MouseModeButton");
2619 automation_box.set_spacing (2);
2620 automation_box.set_border_width (2);
2621 automation_box.pack_start (global_automation_button, false, false);
2622 automation_box.pack_start (automation_mode_button, false, false);
2626 edit_mode_label.set_name ("ToolBarLabel");
2628 edit_mode_selector.set_name ("EditModeSelector");
2630 edit_mode_box.set_spacing (3);
2631 edit_mode_box.set_border_width (3);
2633 /* XXX another disgusting hack because of the way combo boxes size themselves */
2635 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2, 10);
2636 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2637 edit_mode_box.pack_start (edit_mode_label, false, false);
2638 edit_mode_box.pack_start (edit_mode_selector, false, false);
2640 edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2644 snap_type_label.set_name ("ToolBarLabel");
2646 snap_type_selector.set_name ("SnapTypeSelector");
2648 snap_type_box.set_spacing (3);
2649 snap_type_box.set_border_width (3);
2651 /* XXX another disgusting hack because of the way combo boxes size themselves */
2653 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2654 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "Region bounds", 2+FUDGE, 10);
2655 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2657 snap_type_box.pack_start (snap_type_label, false, false);
2658 snap_type_box.pack_start (snap_type_selector, false, false);
2660 snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2662 /* Snap mode, not snap type */
2664 snap_mode_label.set_name ("ToolBarLabel");
2666 snap_mode_selector.set_name ("SnapModeSelector");
2668 snap_mode_box.set_spacing (3);
2669 snap_mode_box.set_border_width (3);
2671 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2, 10);
2672 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2674 snap_mode_box.pack_start (snap_mode_label, false, false);
2675 snap_mode_box.pack_start (snap_mode_selector, false, false);
2677 snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2679 /* Zoom focus mode */
2681 zoom_focus_label.set_name ("ToolBarLabel");
2683 zoom_focus_selector.set_name ("ZoomFocusSelector");
2685 zoom_focus_box.set_spacing (3);
2686 zoom_focus_box.set_border_width (3);
2688 /* XXX another disgusting hack because of the way combo boxes size themselves */
2690 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2, 10);
2691 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
2693 zoom_focus_box.pack_start (zoom_focus_label, false, false);
2694 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
2696 zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
2698 /* selection/cursor clocks */
2700 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
2701 selection_start_clock_label.set_name ("ToolBarLabel");
2702 selection_end_clock_label.set_name ("ToolBarLabel");
2703 edit_cursor_clock_label.set_name ("ToolBarLabel");
2705 selection_start_clock_label.set_text (_("Start:"));
2706 selection_end_clock_label.set_text (_("End:"));
2707 edit_cursor_clock_label.set_text (_("Edit:"));
2709 toolbar_selection_clock_table.set_border_width (5);
2710 toolbar_selection_clock_table.set_col_spacings (2);
2711 toolbar_selection_clock_table.set_homogeneous (false);
2713 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
2714 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
2715 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
2717 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
2718 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
2719 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
2722 // toolbar_clock_vbox.set_spacing (2);
2723 // toolbar_clock_vbox.set_border_width (10);
2724 /* the editor/mixer button will be enabled at session connect */
2726 editor_mixer_button.set_active(false);
2727 editor_mixer_button.set_sensitive(false);
2729 HBox* hbox = new HBox;
2731 hbox->pack_start (editor_mixer_button, false, false);
2732 hbox->pack_start (toolbar_selection_clock_table, false, false);
2733 hbox->pack_start (zoom_indicator_vbox, false, false);
2734 hbox->pack_start (zoom_focus_box, false, false);
2735 hbox->pack_start (snap_type_box, false, false);
2736 hbox->pack_start (snap_mode_box, false, false);
2737 hbox->pack_start (edit_mode_box, false, false);
2739 VBox *vbox = manage (new VBox);
2741 vbox->set_spacing (3);
2742 vbox->set_border_width (3);
2744 HBox *nbox = manage (new HBox);
2746 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
2747 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
2749 nbox->pack_start (nudge_backward_button, false, false);
2750 nbox->pack_start (nudge_forward_button, false, false);
2751 nbox->pack_start (nudge_clock, false, false, 5);
2753 nudge_label.set_name ("ToolBarLabel");
2755 vbox->pack_start (nudge_label, false, false);
2756 vbox->pack_start (*nbox, false, false);
2758 hbox->pack_start (*vbox, false, false);
2762 tools_tearoff = new TearOff (*hbox);
2763 tools_tearoff->set_name ("MouseModeBase");
2765 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2766 tools_tearoff->tearoff_window()));
2767 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2768 tools_tearoff->tearoff_window(), 0));
2771 toolbar_hbox.set_spacing (8);
2772 toolbar_hbox.set_border_width (2);
2774 toolbar_hbox.pack_start (*tools_tearoff, false, false);
2775 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
2777 toolbar_base.set_name ("ToolBarBase");
2778 toolbar_base.add (toolbar_hbox);
2780 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
2781 toolbar_frame.set_name ("BaseFrame");
2782 toolbar_frame.add (toolbar_base);
2786 Editor::_autoscroll_canvas (void *arg)
2788 return ((Editor *) arg)->autoscroll_canvas ();
2792 Editor::autoscroll_canvas ()
2794 jack_nframes_t new_frame;
2795 bool keep_calling = true;
2797 if (autoscroll_direction < 0) {
2798 if (leftmost_frame < autoscroll_distance) {
2801 new_frame = leftmost_frame - autoscroll_distance;
2804 if (leftmost_frame > max_frames - autoscroll_distance) {
2805 new_frame = max_frames;
2807 new_frame = leftmost_frame + autoscroll_distance;
2811 if (new_frame != leftmost_frame) {
2812 reposition_x_origin (new_frame);
2815 if (new_frame == 0 || new_frame == max_frames) {
2822 if (autoscroll_cnt == 1) {
2824 /* connect the timeout so that we get called repeatedly */
2826 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
2827 keep_calling = false;
2829 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
2831 /* after about a while, speed up a bit by changing the timeout interval */
2833 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
2834 keep_calling = false;
2836 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
2838 /* after about another while, speed up some more */
2840 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
2841 keep_calling = false;
2843 } else if (autoscroll_cnt >= 30) {
2845 /* we've been scrolling for a while ... crank it up */
2847 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
2850 return keep_calling;
2854 Editor::start_canvas_autoscroll (int dir)
2860 stop_canvas_autoscroll ();
2862 autoscroll_direction = dir;
2863 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
2866 /* do it right now, which will start the repeated callbacks */
2868 autoscroll_canvas ();
2872 Editor::stop_canvas_autoscroll ()
2874 if (autoscroll_timeout_tag >= 0) {
2875 gtk_timeout_remove (autoscroll_timeout_tag);
2876 autoscroll_timeout_tag = -1;
2881 Editor::convert_drop_to_paths (vector<string>& paths,
2882 GdkDragContext *context,
2885 GtkSelectionData *data,
2893 gchar *tname = gdk_atom_name (data->type);
2895 if (session == 0 || strcmp (tname, "text/plain") != 0) {
2899 /* Parse the "uri-list" format that Nautilus provides,
2900 where each pathname is delimited by \r\n
2903 path = (char *) data->data;
2906 for (int n = 0; n < data->length; ++n) {
2910 if (path[n] == '\r') {
2917 if (path[n] == '\n') {
2918 paths.push_back (spath);
2922 warning << _("incorrectly formatted URI list, ignored")
2930 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
2932 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
2934 // cerr << "dropped text was " << *p << endl;
2938 // cerr << "decoded was " << *p << endl;
2940 if ((*p).substr (0,7) == "file://") {
2941 (*p) = (*p).substr (7);
2949 Editor::track_canvas_drag_data_received (GdkDragContext *context,
2952 GtkSelectionData *data,
2957 AudioTimeAxisView* tv;
2959 vector<string> paths;
2962 jack_nframes_t frame;
2964 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
2968 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
2974 track_canvas.c2w( x, y, wx, wy);
2976 ev.type = GDK_BUTTON_RELEASE;
2980 frame = event_frame (&ev, 0, &cy);
2984 if ((tvp = trackview_by_y_position (cy)) == 0) {
2986 /* drop onto canvas background: create a new track */
2988 insert_paths_as_new_tracks (paths, false);
2991 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
2993 /* check that its an audio track, not a bus */
2995 if (tv->get_diskstream()) {
2997 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
2998 insert_sndfile_into (*p, true, tv, frame);
3005 gtk_drag_finish (context, TRUE, FALSE, time);
3009 Editor::new_tempo_section ()
3015 Editor::map_transport_state ()
3017 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3019 if (session->transport_stopped()) {
3020 have_pending_keyboard_selection = false;
3026 Editor::State::State ()
3028 selection = new Selection;
3031 Editor::State::~State ()
3037 Editor::get_memento () const
3039 State *state = new State;
3041 store_state (*state);
3042 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3046 Editor::store_state (State& state) const
3048 *state.selection = *selection;
3052 Editor::restore_state (State *state)
3054 if (*selection == *state->selection) {
3058 *selection = *state->selection;
3059 time_selection_changed ();
3060 region_selection_changed ();
3062 /* XXX other selection change handlers? */
3066 Editor::begin_reversible_command (string name)
3069 UndoAction ua = get_memento();
3070 session->begin_reversible_command (name, &ua);
3075 Editor::commit_reversible_command ()
3078 UndoAction ua = get_memento();
3079 session->commit_reversible_command (&ua);
3084 Editor::flush_track_canvas ()
3086 /* I don't think this is necessary, and only causes more problems.
3087 I'm commenting it out
3088 and if the imageframe folks don't have any issues, we can take
3089 out this method entirely
3092 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
3093 //gtk_main_iteration ();
3097 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3099 if (!clicked_trackview) {
3104 begin_reversible_command (_("set selected trackview"));
3109 if (selection->selected (clicked_trackview)) {
3111 selection->remove (clicked_trackview);
3114 selection->add (clicked_trackview);
3119 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3120 /* no commit necessary */
3124 selection->set (clicked_trackview);
3128 commit_reversible_command ();
3133 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3135 if (!clicked_control_point) {
3140 begin_reversible_command (_("set selected control point"));
3150 commit_reversible_command ();
3155 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3157 if (!clicked_regionview) {
3161 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3167 RouteGroup* group = atv->route().edit_group();
3168 vector<AudioRegionView*> all_equivalent_regions;
3170 if (group && group->is_active()) {
3172 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3174 AudioTimeAxisView* tatv;
3176 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3178 if (tatv->route().edit_group() != group) {
3183 vector<AudioRegion*> results;
3184 AudioRegionView* marv;
3187 if ((ds = tatv->get_diskstream()) == 0) {
3192 if ((pl = ds->playlist()) != 0) {
3193 pl->get_equivalent_regions (clicked_regionview->region,
3197 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3198 if ((marv = tatv->view->find_view (**ir)) != 0) {
3199 all_equivalent_regions.push_back (marv);
3208 all_equivalent_regions.push_back (clicked_regionview);
3212 begin_reversible_command (_("set selected regionview"));
3216 if (clicked_regionview->get_selected()) {
3217 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3218 /* reduce selection down to just the one clicked */
3219 selection->set (clicked_regionview);
3221 selection->remove (clicked_regionview);
3224 selection->add (all_equivalent_regions);
3227 set_selected_track_from_click (add, false, no_track_remove);
3231 // karsten wiese suggested these two lines to make
3232 // a selected region rise to the top. but this
3233 // leads to a mismatch between actual layering
3234 // and visual layering. resolution required ....
3236 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3237 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3239 if (clicked_regionview->get_selected()) {
3240 /* no commit necessary: we are the one selected. */
3245 selection->set (all_equivalent_regions);
3246 set_selected_track_from_click (add, false, false);
3250 commit_reversible_command () ;
3254 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3256 vector<AudioRegionView*> all_equivalent_regions;
3257 AudioRegion* region;
3259 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3263 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3265 AudioTimeAxisView* tatv;
3267 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3270 vector<AudioRegion*> results;
3271 AudioRegionView* marv;
3274 if ((ds = tatv->get_diskstream()) == 0) {
3279 if ((pl = ds->playlist()) != 0) {
3280 pl->get_region_list_equivalent_regions (*region, results);
3283 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3284 if ((marv = tatv->view->find_view (**ir)) != 0) {
3285 all_equivalent_regions.push_back (marv);
3292 begin_reversible_command (_("set selected regions"));
3296 selection->add (all_equivalent_regions);
3300 selection->set (all_equivalent_regions);
3303 commit_reversible_command () ;
3307 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3309 AudioRegionView* rv;
3312 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3316 if ((rv = sv->find_view (*ar)) == 0) {
3320 /* don't reset the selection if its something other than
3321 a single other region.
3324 if (selection->audio_regions.size() > 1) {
3328 begin_reversible_command (_("set selected regions"));
3330 selection->set (rv);
3332 commit_reversible_command () ;
3338 Editor::set_edit_group_solo (Route& route, bool yn)
3340 RouteGroup *edit_group;
3342 if ((edit_group = route.edit_group()) != 0) {
3343 edit_group->apply (&Route::set_solo, yn, this);
3345 route.set_solo (yn, this);
3350 Editor::set_edit_group_mute (Route& route, bool yn)
3352 RouteGroup *edit_group = 0;
3354 if ((edit_group == route.edit_group()) != 0) {
3355 edit_group->apply (&Route::set_mute, yn, this);
3357 route.set_mute (yn, this);
3362 Editor::set_edit_menu (Menu& menu)
3365 edit_menu->signal_map_event().connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3369 Editor::edit_menu_map_handler (GdkEventAny* ev)
3371 using namespace Menu_Helpers;
3372 MenuList& edit_items = edit_menu->items();
3375 /* Nuke all the old items */
3377 edit_items.clear ();
3383 if (session->undo_depth() == 0) {
3386 label = string_compose(_("Undo (%1)"), session->next_undo());
3389 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3391 if (session->undo_depth() == 0) {
3392 edit_items.back().set_sensitive (false);
3395 if (session->redo_depth() == 0) {
3398 label = string_compose(_("Redo (%1)"), session->next_redo());
3401 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3402 if (session->redo_depth() == 0) {
3403 edit_items.back().set_sensitive (false);
3406 vector<MenuItem*> mitems;
3408 edit_items.push_back (SeparatorElem());
3409 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3410 mitems.push_back (&edit_items.back());
3411 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3412 mitems.push_back (&edit_items.back());
3413 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3414 mitems.push_back (&edit_items.back());
3415 edit_items.push_back (SeparatorElem());
3416 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3417 mitems.push_back (&edit_items.back());
3418 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3419 mitems.push_back (&edit_items.back());
3420 edit_items.push_back (SeparatorElem());
3422 if (selection->empty()) {
3423 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3424 (*i)->set_sensitive (false);
3428 Menu* import_menu = manage (new Menu());
3429 import_menu->set_name ("ArdourContextMenu");
3430 MenuList& import_items = import_menu->items();
3432 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3433 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3435 Menu* embed_menu = manage (new Menu());
3436 embed_menu->set_name ("ArdourContextMenu");
3437 MenuList& embed_items = embed_menu->items();
3439 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3440 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3442 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3443 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3444 edit_items.push_back (SeparatorElem());
3446 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3447 if (!session->have_captured()) {
3448 edit_items.back().set_sensitive (false);
3455 Editor::duplicate_dialog (bool dup_region)
3458 if (clicked_regionview == 0) {
3462 if (selection->time.length() == 0) {
3467 ArdourDialog win ("duplicate dialog");
3469 Label label (_("Duplicate how many times?"));
3471 win.get_vbox()->pack_start (label);
3472 win.add_action_widget (entry, RESPONSE_ACCEPT);
3473 win.add_button (Stock::OK, RESPONSE_ACCEPT);
3474 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3476 win.set_position (Gtk::WIN_POS_MOUSE);
3478 entry.set_text ("1");
3479 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3480 entry.select_region (0, entry.get_text_length());
3481 entry.grab_focus ();
3484 // win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3487 switch (win.run ()) {
3488 case RESPONSE_ACCEPT:
3494 string text = entry.get_text();
3497 if (sscanf (text.c_str(), "%f", ×) == 1) {
3499 AudioRegionSelection regions;
3500 regions.add (clicked_regionview);
3501 duplicate_some_regions (regions, times);
3503 duplicate_selection (times);
3509 Editor::show_verbose_canvas_cursor ()
3511 verbose_canvas_cursor->raise_to_top();
3512 verbose_canvas_cursor->show();
3513 verbose_cursor_visible = true;
3517 Editor::hide_verbose_canvas_cursor ()
3519 verbose_canvas_cursor->hide();
3520 verbose_cursor_visible = false;
3524 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3526 /* XXX get origin of canvas relative to root window,
3527 add x and y and check compared to gdk_screen_{width,height}
3529 verbose_canvas_cursor->property_text() = txt.c_str();
3530 verbose_canvas_cursor->property_x() = x;
3531 verbose_canvas_cursor->property_y() = y;
3535 Editor::set_verbose_canvas_cursor_text (string txt)
3537 verbose_canvas_cursor->property_text() = txt.c_str();
3541 Editor::edit_mode_selection_done ()
3547 string choice = edit_mode_selector.get_active_text();
3548 EditMode mode = Slide;
3550 if (choice == _("Splice")) {
3552 } else if (choice == _("Slide")) {
3556 session->set_edit_mode (mode);
3560 Editor::snap_type_selection_done ()
3566 string choice = snap_type_selector.get_active_text();
3567 SnapType snaptype = SnapToFrame;
3569 if (choice == _("Beats/3")) {
3570 snaptype = SnapToAThirdBeat;
3571 } else if (choice == _("Beats/4")) {
3572 snaptype = SnapToAQuarterBeat;
3573 } else if (choice == _("Beats/8")) {
3574 snaptype = SnapToAEighthBeat;
3575 } else if (choice == _("Beats/16")) {
3576 snaptype = SnapToASixteenthBeat;
3577 } else if (choice == _("Beats/32")) {
3578 snaptype = SnapToAThirtysecondBeat;
3579 } else if (choice == _("Beats")) {
3580 snaptype = SnapToBeat;
3581 } else if (choice == _("Bars")) {
3582 snaptype = SnapToBar;
3583 } else if (choice == _("Marks")) {
3584 snaptype = SnapToMark;
3585 } else if (choice == _("Edit Cursor")) {
3586 snaptype = SnapToEditCursor;
3587 } else if (choice == _("Region starts")) {
3588 snaptype = SnapToRegionStart;
3589 } else if (choice == _("Region ends")) {
3590 snaptype = SnapToRegionEnd;
3591 } else if (choice == _("Region bounds")) {
3592 snaptype = SnapToRegionBoundary;
3593 } else if (choice == _("Region syncs")) {
3594 snaptype = SnapToRegionSync;
3595 } else if (choice == _("CD Frames")) {
3596 snaptype = SnapToCDFrame;
3597 } else if (choice == _("SMPTE Frames")) {
3598 snaptype = SnapToSMPTEFrame;
3599 } else if (choice == _("SMPTE Seconds")) {
3600 snaptype = SnapToSMPTESeconds;
3601 } else if (choice == _("SMPTE Minutes")) {
3602 snaptype = SnapToSMPTEMinutes;
3603 } else if (choice == _("Seconds")) {
3604 snaptype = SnapToSeconds;
3605 } else if (choice == _("Minutes")) {
3606 snaptype = SnapToMinutes;
3607 } else if (choice == _("None")) {
3608 snaptype = SnapToFrame;
3611 set_snap_to (snaptype);
3615 Editor::snap_mode_selection_done ()
3621 string choice = snap_mode_selector.get_active_text();
3622 SnapMode mode = SnapNormal;
3624 if (choice == _("Normal")) {
3626 } else if (choice == _("Magnetic")) {
3627 mode = SnapMagnetic;
3630 set_snap_mode (mode);
3634 Editor::zoom_focus_selection_done ()
3640 string choice = zoom_focus_selector.get_active_text();
3641 ZoomFocus focus_type = ZoomFocusLeft;
3643 if (choice == _("Left")) {
3644 focus_type = ZoomFocusLeft;
3645 } else if (choice == _("Right")) {
3646 focus_type = ZoomFocusRight;
3647 } else if (choice == _("Center")) {
3648 focus_type = ZoomFocusCenter;
3649 } else if (choice == _("Playhead")) {
3650 focus_type = ZoomFocusPlayhead;
3651 } else if (choice == _("Edit Cursor")) {
3652 focus_type = ZoomFocusEdit;
3655 set_zoom_focus (focus_type);
3659 Editor::edit_controls_button_release (GdkEventButton* ev)
3661 if (Keyboard::is_context_menu_event (ev)) {
3662 ARDOUR_UI::instance()->add_route ();
3668 Editor::track_selection_changed ()
3670 switch (selection->tracks.size()){
3674 set_selected_mixer_strip (*(selection->tracks.front()));
3678 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3679 (*i)->set_selected (false);
3680 if (mouse_mode == MouseRange) {
3681 (*i)->hide_selection ();
3685 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3686 (*i)->set_selected (true);
3687 if (mouse_mode == MouseRange) {
3688 (*i)->show_selection (selection->time);
3694 Editor::time_selection_changed ()
3696 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3697 (*i)->hide_selection ();
3700 if (selection->tracks.empty()) {
3701 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3702 (*i)->show_selection (selection->time);
3705 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3706 (*i)->show_selection (selection->time);
3712 Editor::region_selection_changed ()
3714 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3715 (*i)->set_selected_regionviews (selection->audio_regions);
3720 Editor::point_selection_changed ()
3722 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3723 (*i)->set_selected_points (selection->points);
3728 Editor::run_sub_event_loop ()
3730 sub_event_loop_status = 0;
3735 Editor::finish_sub_event_loop (int status)
3738 sub_event_loop_status = status;
3742 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
3744 finish_sub_event_loop (status);
3749 Editor::mouse_select_button_release (GdkEventButton* ev)
3751 /* this handles just right-clicks */
3753 if (ev->button != 3) {
3760 Editor::TrackViewList *
3761 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
3764 TrackViewList::iterator i;
3766 v = new TrackViewList;
3768 if (track == 0 && group == 0) {
3772 for (i = track_views.begin(); i != track_views.end (); ++i) {
3776 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
3778 /* just the view for this track
3781 v->push_back (track);
3785 /* views for all tracks in the edit group */
3787 for (i = track_views.begin(); i != track_views.end (); ++i) {
3789 if (group == 0 || (*i)->edit_group() == group) {
3799 Editor::set_zoom_focus (ZoomFocus f)
3801 if (zoom_focus != f) {
3803 vector<string> txt = internationalize (zoom_focus_strings);
3804 zoom_focus_selector.set_active_text (txt[(int)f]);
3805 ZoomFocusChanged (); /* EMIT_SIGNAL */
3812 Editor::ensure_float (Window& win)
3814 win.set_transient_for (*this);
3818 Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which)
3820 /* recover or initialize pane positions. do this here rather than earlier because
3821 we don't want the positions to change the child allocations, which they seem to do.
3827 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3829 static int32_t done[4] = { 0, 0, 0, 0 };
3832 if ((geometry = find_named_node (*node, "geometry")) == 0) {
3833 width = default_width;
3834 height = default_height;
3836 width = atoi(geometry->property("x_size")->value());
3837 height = atoi(geometry->property("y_size")->value());
3840 if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
3846 if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
3848 snprintf (buf, sizeof(buf), "%d", pos);
3850 pos = atoi (prop->value());
3853 if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gobj())->allocation.width > pos)) {
3854 track_list_canvas_pane.set_position (pos);
3857 } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
3863 if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
3864 pos = width - (95 * 2);
3865 snprintf (buf, sizeof(buf), "%d", pos);
3867 pos = atoi (prop->value());
3870 if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gobj())->allocation.width > pos)) {
3871 canvas_region_list_pane.set_position (pos);
3874 } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
3880 if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
3881 pos = width - (95 * 2);
3882 snprintf (buf, sizeof(buf), "%d", pos);
3884 pos = atoi (prop->value());
3887 if ((done[2] = GTK_WIDGET(route_group_vpane.gobj())->allocation.height > pos)) {
3888 route_group_vpane.set_position (pos);
3891 } else if (which == static_cast<Gtk::Paned*> (®ion_selection_vpane)) {
3897 if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
3898 pos = width - (95 * 2);
3899 snprintf (buf, sizeof(buf), "%d", pos);
3901 pos = atoi (prop->value());
3904 if ((done[3] = GTK_WIDGET(region_selection_vpane.gobj())->allocation.height > pos)) {
3905 region_selection_vpane.set_position (pos);
3911 Editor::detach_tearoff (Gtk::Box* b, Gtk::Window* w)
3913 if (tools_tearoff->torn_off() &&
3914 mouse_mode_tearoff->torn_off()) {
3915 top_hbox.remove (toolbar_frame);
3922 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Window* w, int32_t n)
3924 if (toolbar_frame.get_parent() == 0) {
3925 top_hbox.pack_end (toolbar_frame);
3930 Editor::set_show_measures (bool yn)
3932 if (_show_measures != yn) {
3935 if ((_show_measures = yn) == true) {
3938 DisplayControlChanged (ShowMeasures);
3944 Editor::set_follow_playhead (bool yn)
3946 if (_follow_playhead != yn) {
3947 if ((_follow_playhead = yn) == true) {
3949 update_current_screen ();
3951 DisplayControlChanged (FollowPlayhead);
3957 Editor::toggle_xfade_active (Crossfade* xfade)
3959 xfade->set_active (!xfade->active());
3963 Editor::toggle_xfade_length (Crossfade* xfade)
3965 xfade->set_follow_overlap (!xfade->following_overlap());
3969 Editor::edit_xfade (Crossfade* xfade)
3971 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
3976 // cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
3978 switch (cew.run ()) {
3979 case RESPONSE_ACCEPT:
3986 xfade->StateChanged (Change (~0));
3990 Editor::playlist_selector () const
3992 return *_playlist_selector;
3996 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
4000 ret = nudge_clock.current_duration (pos);
4001 next = ret + 1; /* XXXX fix me */
4007 Editor::end_location_changed (Location* location)
4009 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
4010 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
4014 Editor::playlist_deletion_dialog (Playlist* pl)
4016 ArdourDialog dialog ("playlist deletion dialog");
4017 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4018 "If left alone, no audio files used by it will be cleaned.\n"
4019 "If deleted, audio files used by it alone by will cleaned."),
4022 dialog.set_position (Gtk::WIN_POS_CENTER);
4023 dialog.get_vbox()->pack_start (label);
4025 dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT);
4026 dialog.add_button (_("Keep playlist"), RESPONSE_CANCEL);
4027 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4029 switch (dialog.run ()) {
4030 case RESPONSE_ACCEPT:
4031 /* delete the playlist */
4035 case RESPONSE_REJECT:
4036 /* keep the playlist */
4048 Editor::audio_region_selection_covers (jack_nframes_t where)
4050 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
4051 if ((*a)->region.covers (where)) {
4060 Editor::prepare_for_cleanup ()
4062 cut_buffer->clear_audio_regions ();
4063 cut_buffer->clear_playlists ();
4065 selection->clear_audio_regions ();
4066 selection->clear_playlists ();
4070 Editor::init_colormap ()
4072 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
4073 pair<ColorID,int> newpair;
4075 newpair.first = (ColorID) x;
4076 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
4077 color_map.insert (newpair);
4082 Editor::transport_loop_location()
4085 return session->locations()->auto_loop_location();
4092 Editor::transport_punch_location()
4095 return session->locations()->auto_punch_location();