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"
52 #include "grouped_buttons.h"
55 #include "playlist_selector.h"
56 #include "regionview.h"
57 #include "rgb_macros.h"
58 #include "selection.h"
59 #include "streamview.h"
60 #include "time_axis_view.h"
62 #include "crossfade_view.h"
64 #include "public_editor.h"
65 #include "crossfade_edit.h"
66 #include "audio_time_axis.h"
67 #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::wait_cursor = 0;
148 Gdk::Cursor* Editor::timebar_cursor = 0;
150 Editor::Editor (AudioEngine& eng)
153 /* time display buttons */
155 minsec_label (_("Mins:Secs")),
156 bbt_label (_("Bars:Beats")),
157 smpte_label (_("SMPTE")),
158 frame_label (_("Frames")),
159 tempo_label (_("Tempo")),
160 meter_label (_("Meter")),
161 mark_label (_("Location Markers")),
162 range_mark_label (_("Range Markers")),
163 transport_mark_label (_("Loop/Punch Ranges")),
165 edit_packer (3, 3, false),
166 edit_hscroll_left_arrow (Gtk::ARROW_LEFT, Gtk::SHADOW_OUT),
167 edit_hscroll_right_arrow (Gtk::ARROW_RIGHT, Gtk::SHADOW_OUT),
169 /* tool bar related */
171 editor_mixer_button (_("editor\nmixer")),
173 selection_start_clock (X_("SelectionStartClock"), true),
174 selection_end_clock (X_("SelectionEndClock"), true),
175 edit_cursor_clock (X_("EditCursorClock"), true),
176 zoom_range_clock (X_("ZoomRangeClock"), true, true),
178 toolbar_selection_clock_table (2,3),
180 mouse_mode_button_table (2, 3),
182 mouse_select_button (_("range")),
183 mouse_move_button (_("object")),
184 mouse_gain_button (_("gain")),
185 mouse_zoom_button (_("zoom")),
186 mouse_timefx_button (_("timefx")),
187 mouse_audition_button (_("listen")),
189 automation_mode_button (_("mode")),
190 global_automation_button (_("automation")),
192 edit_mode_label (_("Edit Mode")),
193 snap_type_label (_("Snap To")),
194 snap_mode_label(_("Snap Mode")),
195 zoom_focus_label (_("Zoom Focus")),
197 /* <CMT Additions> */
198 image_socket_listener(0),
199 /* </CMT Additions> */
203 nudge_label (_("Nudge")),
204 nudge_clock (X_("NudgeClock"), true, true)
209 /* we are a singleton */
211 PublicEditor::_instance = this;
217 selection = new Selection;
218 cut_buffer = new Selection;
220 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
221 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
222 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
223 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
225 clicked_regionview = 0;
226 clicked_trackview = 0;
227 clicked_audio_trackview = 0;
228 clicked_crossfadeview = 0;
229 clicked_control_point = 0;
230 latest_regionview = 0;
231 last_update_frame = 0;
233 last_audition_region = 0;
234 current_mixer_strip = 0;
235 current_bbt_points = 0;
237 snap_type = SnapToFrame;
238 set_snap_to (snap_type);
239 snap_mode = SnapNormal;
240 set_snap_mode (snap_mode);
241 snap_threshold = 5.0;
242 bbt_beat_subdivision = 4;
245 autoscroll_timeout_tag = -1;
246 interthread_progress_window = 0;
247 current_interthread_info = 0;
248 _show_measures = true;
249 _show_waveforms = true;
250 _show_waveforms_recording = true;
251 first_action_message = 0;
253 show_gain_after_trim = false;
254 no_zoom_repos_update = false;
255 ignore_route_list_reorder = false;
256 verbose_cursor_on = true;
257 route_removal = false;
259 show_automatic_regions_in_region_list = true;
260 have_pending_keyboard_selection = false;
261 _follow_playhead = true;
262 _xfade_visibility = true;
263 editor_ruler_menu = 0;
264 no_ruler_shown_update = false;
265 edit_group_list_menu = 0;
267 region_list_menu = 0;
269 marker_menu_item = 0;
271 transport_marker_menu = 0;
272 new_transport_marker_menu = 0;
273 editor_mixer_strip_width = Wide;
274 repos_zoom_queued = false;
275 import_audio_item = 0;
276 embed_audio_item = 0;
277 region_edit_menu_split_item = 0;
279 region_edit_menu_split_multichannel_item = 0;
280 edit_hscroll_dragging = false;
282 ignore_mouse_mode_toggle = false;
283 current_stepping_trackview = 0;
285 entered_regionview = 0;
286 clear_entered_track = false;
287 _new_regionviews_show_envelope = false;
288 current_timestretch = 0;
293 location_marker_color = color_map[cLocationMarker];
294 location_range_color = color_map[cLocationRange];
295 location_cd_marker_color = color_map[cLocationCDMarker];
296 location_loop_color = color_map[cLocationLoop];
297 location_punch_color = color_map[cLocationPunch];
299 range_marker_drag_rect = 0;
300 marker_drag_line = 0;
302 mouse_mode = MouseZoom; /* force change in next call */
303 set_mouse_mode (MouseObject, true);
305 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
306 zoom_focus = ZoomFocusLeft;
307 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
309 initialize_rulers ();
310 initialize_canvas ();
312 track_canvas_scroller.add (track_canvas);
313 track_canvas_scroller.set_policy (POLICY_NEVER, POLICY_NEVER);
314 track_canvas_scroller.set_name ("TrackCanvasScroller");
316 track_canvas_scroller.get_vadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
317 track_canvas_scroller.get_vadjustment()->set_step_increment (10.0);
319 track_canvas_scroller.get_hadjustment()->set_lower (0.0);
320 track_canvas_scroller.get_hadjustment()->set_upper (1200.0);
321 track_canvas_scroller.get_hadjustment()->set_step_increment (20.0);
322 track_canvas_scroller.get_hadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
324 edit_vscrollbar.set_adjustment(*track_canvas_scroller.get_vadjustment());
325 edit_hscrollbar.set_adjustment(*track_canvas_scroller.get_hadjustment());
327 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_press));
328 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_release));
329 edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscroll_slider_allocate));
331 time_canvas_scroller.add (time_canvas);
332 time_canvas_scroller.set_policy (POLICY_NEVER, POLICY_NEVER);
333 time_canvas_scroller.set_hadjustment (*track_canvas_scroller.get_hadjustment());
334 time_canvas_scroller.set_name ("TimeCanvasScroller");
336 track_canvas_scroller.signal_map_event().connect (mem_fun (*this, &Editor::track_canvas_map_handler));
337 time_canvas_scroller.signal_map_event().connect (mem_fun (*this, &Editor::time_canvas_map_handler));
339 edit_controls_vbox.set_spacing (track_spacing);
340 edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
341 edit_controls_scroller.add (edit_controls_hbox);
342 edit_controls_scroller.set_name ("EditControlsBase");
343 edit_controls_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
345 Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
347 viewport->set_shadow_type (Gtk::SHADOW_NONE);
348 viewport->set_name ("EditControlsBase");
349 viewport->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
350 viewport->signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
355 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
357 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
358 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
359 time_canvas_vbox.pack_start (*frames_ruler, false, false);
360 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
361 time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
362 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
364 bbt_label.set_name ("EditorTimeButton");
365 bbt_label.set_size_request (-1, (int)timebar_height);
366 bbt_label.set_alignment (1.0, 0.5);
367 bbt_label.set_padding (5,0);
368 minsec_label.set_name ("EditorTimeButton");
369 minsec_label.set_size_request (-1, (int)timebar_height);
370 minsec_label.set_alignment (1.0, 0.5);
371 minsec_label.set_padding (5,0);
372 smpte_label.set_name ("EditorTimeButton");
373 smpte_label.set_size_request (-1, (int)timebar_height);
374 smpte_label.set_alignment (1.0, 0.5);
375 smpte_label.set_padding (5,0);
376 frame_label.set_name ("EditorTimeButton");
377 frame_label.set_size_request (-1, (int)timebar_height);
378 frame_label.set_alignment (1.0, 0.5);
379 frame_label.set_padding (5,0);
380 tempo_label.set_name ("EditorTimeButton");
381 tempo_label.set_size_request (-1, (int)timebar_height);
382 tempo_label.set_alignment (1.0, 0.5);
383 tempo_label.set_padding (5,0);
384 meter_label.set_name ("EditorTimeButton");
385 meter_label.set_size_request (-1, (int)timebar_height);
386 meter_label.set_alignment (1.0, 0.5);
387 meter_label.set_padding (5,0);
388 mark_label.set_name ("EditorTimeButton");
389 mark_label.set_size_request (-1, (int)timebar_height);
390 mark_label.set_alignment (1.0, 0.5);
391 mark_label.set_padding (5,0);
392 range_mark_label.set_name ("EditorTimeButton");
393 range_mark_label.set_size_request (-1, (int)timebar_height);
394 range_mark_label.set_alignment (1.0, 0.5);
395 range_mark_label.set_padding (5,0);
396 transport_mark_label.set_name ("EditorTimeButton");
397 transport_mark_label.set_size_request (-1, (int)timebar_height);
398 transport_mark_label.set_alignment (1.0, 0.5);
399 transport_mark_label.set_padding (5,0);
401 time_button_vbox.pack_start (minsec_label, false, false);
402 time_button_vbox.pack_start (smpte_label, false, false);
403 time_button_vbox.pack_start (frame_label, false, false);
404 time_button_vbox.pack_start (bbt_label, false, false);
405 time_button_vbox.pack_start (meter_label, false, false);
406 time_button_vbox.pack_start (tempo_label, false, false);
407 time_button_vbox.pack_start (mark_label, false, false);
409 time_button_event_box.add (time_button_vbox);
411 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
412 time_button_event_box.set_name ("TimebarLabelBase");
413 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
415 /* these enable us to have a dedicated window (for cursor setting, etc.)
416 for the canvas areas.
419 track_canvas_event_box.add (track_canvas_scroller);
421 time_canvas_event_box.add (time_canvas_vbox);
422 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
425 edit_packer.set_col_spacings (0);
426 edit_packer.set_row_spacings (0);
427 edit_packer.set_homogeneous (false);
428 edit_packer.set_name ("EditorWindow");
430 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
432 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
433 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
435 edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, FILL,FILL, 0, 0);
436 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
437 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
439 edit_frame.set_name ("BaseFrame");
440 edit_frame.set_shadow_type (SHADOW_IN);
441 edit_frame.add (edit_packer);
443 zoom_in_button.set_name ("EditorTimeButton");
444 zoom_out_button.set_name ("EditorTimeButton");
445 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
446 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
448 zoom_out_full_button.set_name ("EditorTimeButton");
449 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
451 zoom_in_button.add (*(manage (new Gtk::Image (Stock::ZOOM_IN, ICON_SIZE_BUTTON))));
452 zoom_out_button.add (*(manage (new Gtk::Image (Stock::ZOOM_OUT, ICON_SIZE_BUTTON))));
453 zoom_out_full_button.add (*(manage (new Gtk::Image (Stock::ZOOM_FIT, ICON_SIZE_BUTTON))));
455 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
456 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
457 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
459 zoom_indicator_box.pack_start (zoom_out_button, false, false);
460 zoom_indicator_box.pack_start (zoom_in_button, false, false);
461 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
462 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
464 zoom_indicator_label.set_text (_("Zoom Span"));
465 zoom_indicator_label.set_name ("ToolBarLabel");
467 zoom_indicator_vbox.set_spacing (3);
468 zoom_indicator_vbox.set_border_width (3);
469 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
470 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
472 bottom_hbox.set_border_width (3);
473 bottom_hbox.set_spacing (3);
475 route_display_model = ListStore::create(route_display_columns);
476 route_list.set_model (route_display_model);
477 route_list.append_column (_("Tracks"), route_display_columns.text);
478 route_list.set_name ("TrackListDisplay");
479 route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
480 route_list.set_reorderable (true);
482 route_list.set_size_request (75,-1);
483 route_list.set_headers_visible (true);
484 route_list.set_headers_clickable (true);
487 // route_list.signal_rows_reordered().connect (mem_fun (*this, &Editor::queue_route_list_reordered));
490 // route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func));
493 //route_list.set_shadow_type (Gtk::SHADOW_IN);
495 route_list_scroller.add (route_list);
496 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
498 route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed));
499 route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click));
501 edit_group_list_button_label.set_text (_("Edit Groups"));
502 edit_group_list_button_label.set_name ("EditGroupTitleButton");
503 edit_group_list_button.add (edit_group_list_button_label);
504 edit_group_list_button.set_name ("EditGroupTitleButton");
506 group_model = ListStore::create(group_columns);
507 edit_group_list.set_model (group_model);
508 edit_group_list.append_column (_("active"), group_columns.is_active);
509 edit_group_list.append_column (_("groupname"), group_columns.text);
510 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
511 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
513 /* use checkbox for the active column */
515 CellRendererToggle *active_cell = dynamic_cast<CellRendererToggle*>(edit_group_list.get_column_cell_renderer (0));
516 active_cell->property_activatable() = true;
517 active_cell->property_radio() = false;
519 edit_group_list.set_name ("MixerGroupList");
520 //edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
522 edit_group_list.columns_autosize ();
523 edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
524 edit_group_list.set_reorderable (false);
526 edit_group_list.set_size_request (75, -1);
527 edit_group_list.set_headers_visible (true);
529 edit_group_list_scroller.add (edit_group_list);
530 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
532 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
533 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
534 edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed));
536 TreeModel::Row row = *(group_model->append());
537 row[group_columns.is_active] = false;
538 row[group_columns.text] = (_("-all-"));
539 edit_group_list.get_selection()->select (row);
540 /* GTK2FIX is set_data(0) setting the is_active to false here?
541 list<string> stupid_list;
543 stupid_list.push_back ("*");
544 stupid_list.push_back (_("-all-"));
546 edit_group_list.rows().push_back (stupid_list);
547 edit_group_list.rows().back().set_data (0);
548 edit_group_list.rows().back().select();
551 edit_group_vbox.pack_start (edit_group_list_button, false, false);
552 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
554 region_list_model = TreeStore::create (region_list_columns);
555 region_list_sort_model = TreeModelSort::create (region_list_model);
556 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
558 region_list_display.set_model (region_list_sort_model);
559 region_list_display.append_column (_("Regions"), region_list_columns.name);
560 region_list_display.set_reorderable (true);
561 region_list_display.set_size_request (100, -1);
562 region_list_display.set_data ("editor", this);
563 region_list_display.set_flags (Gtk::CAN_FOCUS);
564 region_list_display.set_name ("RegionListDisplay");
566 region_list_scroller.add (region_list_display);
567 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
569 list<Gtk::TargetEntry> region_list_target_table;
571 region_list_target_table.push_back (TargetEntry ("STRING"));
572 region_list_target_table.push_back (TargetEntry ("text/plain"));
573 region_list_target_table.push_back (TargetEntry ("text/uri-list"));
574 region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
577 // region_list_display.drag_dest_set (region_list_target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
578 // region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
580 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
581 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
582 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
583 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
584 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
586 //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
587 //region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click));
589 named_selection_scroller.add (named_selection_display);
590 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
592 named_selection_model = TreeStore::create (named_selection_columns);
593 named_selection_display.set_model (named_selection_model);
594 named_selection_display.append_column (_("Chunks"), named_selection_columns.text);
595 named_selection_display.set_size_request (100, -1);
596 named_selection_display.set_name ("RegionListDisplay");
598 named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
599 named_selection_display.set_size_request (100, -1);
600 named_selection_display.set_headers_visible (true);
601 named_selection_display.set_headers_clickable (true);
602 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
603 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
605 the_notebook.append_page (route_list_scroller, _("Tracks/Busses"));
606 the_notebook.append_page (edit_group_vbox, _("Edit Groups"));
607 the_notebook.append_page (region_list_scroller, _("Regions"));
608 the_notebook.append_page (named_selection_scroller, _("Chunks"));
609 the_notebook.set_show_tabs (true);
611 TearOff *notebook_tearoff = manage (new TearOff (the_notebook));
613 edit_pane.pack1 (edit_frame, true, true);
614 edit_pane.pack2 (*notebook_tearoff, true, true);
616 edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Gtk::Paned*> (&edit_pane)));
618 top_hbox.pack_start (toolbar_frame, true, true);
620 HBox *hbox = manage (new HBox);
621 hbox->pack_start (edit_pane, true, true);
623 global_vpacker.pack_start (top_hbox, false, false);
624 global_vpacker.pack_start (*hbox, true, true);
626 global_hpacker.pack_start (global_vpacker, true, true);
628 set_name ("EditorWindow");
629 add_accel_group (ActionManager::ui_manager->get_accel_group());
631 vpacker.pack_end (global_hpacker, true, true);
633 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
636 _playlist_selector = new PlaylistSelector();
637 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
639 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
643 nudge_forward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
644 nudge_backward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
646 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
647 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
649 nudge_forward_button.set_name ("TransportButton");
650 nudge_backward_button.set_name ("TransportButton");
652 fade_context_menu.set_name ("ArdourContextMenu");
654 set_title (_("ardour: editor"));
655 set_wmclass (_("ardour_editor"), "Ardour");
658 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
660 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
661 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
669 /* <CMT Additions> */
670 if(image_socket_listener)
672 if(image_socket_listener->is_connected())
674 image_socket_listener->close_connection() ;
677 delete image_socket_listener ;
678 image_socket_listener = 0 ;
680 /* </CMT Additions> */
684 Editor::add_toplevel_controls (Container& cont)
686 vpacker.pack_start (cont, false, false);
691 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
693 /* note: the selection will take care of the vanishing
694 audioregionview by itself.
697 if (clicked_regionview == rv) {
698 clicked_regionview = 0;
701 if (entered_regionview == rv) {
702 set_entered_regionview (0);
707 Editor::set_entered_regionview (AudioRegionView* rv)
709 if (rv == entered_regionview) {
713 if (entered_regionview) {
714 entered_regionview->exited ();
717 if ((entered_regionview = rv) != 0) {
718 entered_regionview->entered ();
723 Editor::set_entered_track (TimeAxisView* tav)
726 entered_track->exited ();
729 if ((entered_track = tav) != 0) {
730 entered_track->entered ();
735 Editor::left_track_canvas (GdkEventCrossing *ev)
737 set_entered_track (0);
738 set_entered_regionview (0);
744 Editor::show_window ()
749 /* now reset all audio_time_axis heights, because widgets might need
755 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
756 tv = (static_cast<TimeAxisView*>(*i));
762 Editor::tie_vertical_scrolling ()
764 edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
766 float y1 = track_canvas_scroller.get_vadjustment()->get_value();
767 playhead_cursor->set_y_axis(y1);
768 edit_cursor->set_y_axis(y1);
772 Editor::set_frames_per_unit (double fpu)
774 jack_nframes_t frames;
776 if (fpu == frames_per_unit) {
784 // convert fpu to frame count
786 frames = (jack_nframes_t) floor (fpu * canvas_width);
788 /* don't allow zooms that fit more than the maximum number
789 of frames into an 800 pixel wide space.
792 if (max_frames / fpu < 800.0) {
796 frames_per_unit = fpu;
798 if (frames != zoom_range_clock.current_duration()) {
799 zoom_range_clock.set (frames);
802 /* only update these if we not about to call reposition_x_origin,
803 which will do the same updates.
807 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
810 if (!no_zoom_repos_update) {
811 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
813 update_fixed_rulers ();
814 tempo_map_changed (Change (0));
817 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
818 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
819 (*i)->reshow_selection (selection->time);
823 ZoomChanged (); /* EMIT_SIGNAL */
825 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
826 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
833 Editor::instant_save ()
835 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
840 session->add_instant_xml(get_state(), session->path());
842 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
847 Editor::reposition_x_origin (jack_nframes_t frame)
849 if (frame != leftmost_frame) {
850 leftmost_frame = frame;
851 double pixel = frame_to_pixel (frame);
852 if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
853 track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
855 track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
856 XOriginChanged (); /* EMIT_SIGNAL */
861 Editor::edit_cursor_clock_changed()
863 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
864 edit_cursor->set_position (edit_cursor_clock.current_time());
870 Editor::zoom_adjustment_changed ()
872 if (session == 0 || no_zoom_repos_update) {
876 double fpu = zoom_range_clock.current_duration() / canvas_width;
880 zoom_range_clock.set ((jack_nframes_t) floor (fpu * canvas_width));
881 } else if (fpu > session->current_end_frame() / canvas_width) {
882 fpu = session->current_end_frame() / canvas_width;
883 zoom_range_clock.set ((jack_nframes_t) floor (fpu * canvas_width));
890 Editor::canvas_horizontally_scrolled ()
892 /* XXX note the potential loss of accuracy here caused by
893 adjustments being 32bit floats with only a 24 bit mantissa,
894 whereas jack_nframes_t is at least a 32 bit uint32_teger.
897 leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
900 update_fixed_rulers ();
902 if (!edit_hscroll_dragging) {
903 tempo_map_changed (Change (0));
905 update_tempo_based_rulers();
910 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
912 if (!repos_zoom_queued) {
913 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
914 repos_zoom_queued = true;
919 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
921 /* if we need to force an update to the hscroller stuff,
922 don't set no_zoom_repos_update.
925 no_zoom_repos_update = (frame != leftmost_frame);
927 set_frames_per_unit (nfpu);
928 if (no_zoom_repos_update) {
929 reposition_x_origin (frame);
931 no_zoom_repos_update = false;
932 repos_zoom_queued = false;
938 Editor::on_realize ()
940 Window::on_realize ();
942 /* Even though we're not using acceleration, we want the
946 track_context_menu.accelerate (*this->get_toplevel());
947 track_region_context_menu.accelerate (*this->get_toplevel());
952 Editor::queue_session_control_changed (Session::ControlType t)
954 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
958 Editor::session_control_changed (Session::ControlType t)
960 // right now we're only tracking the loop and punch state
963 case Session::AutoLoop:
964 update_loop_range_view (true);
966 case Session::PunchIn:
967 case Session::PunchOut:
968 update_punch_range_view (true);
977 Editor::fake_add_edit_group (RouteGroup *group)
979 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
983 Editor::fake_handle_new_audio_region (AudioRegion *region)
985 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
989 Editor::fake_handle_audio_region_removed (AudioRegion *region)
991 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
995 Editor::fake_handle_new_duration ()
997 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1001 Editor::start_scrolling ()
1003 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1004 (mem_fun(*this, &Editor::update_current_screen));
1006 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1007 (mem_fun(*this, &Editor::update_slower));
1011 Editor::stop_scrolling ()
1013 scroll_connection.disconnect ();
1014 slower_update_connection.disconnect ();
1018 Editor::map_position_change (jack_nframes_t frame)
1020 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1022 if (session == 0 || !_follow_playhead) {
1026 center_screen (frame);
1027 playhead_cursor->set_position (frame);
1031 Editor::center_screen (jack_nframes_t frame)
1033 double page = canvas_width * frames_per_unit;
1035 /* if we're off the page, then scroll.
1038 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1039 center_screen_internal (frame, page);
1044 Editor::center_screen_internal (jack_nframes_t frame, float page)
1049 frame -= (jack_nframes_t) page;
1054 reposition_x_origin (frame);
1058 Editor::handle_new_duration ()
1060 reset_scrolling_region ();
1063 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1064 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1067 update_hscroller ();
1071 Editor::update_title_s (string snap_name)
1073 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1079 Editor::update_title ()
1081 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1084 bool dirty = session->dirty();
1086 string wintitle = _("ardour: editor: ");
1092 wintitle += session->name();
1094 if (session->snap_name() != session->name()) {
1096 wintitle += session->snap_name();
1103 set_title (wintitle);
1108 Editor::connect_to_session (Session *t)
1112 if (first_action_message) {
1113 first_action_message->hide();
1116 flush_track_canvas();
1120 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1122 /* These signals can all be emitted by a non-GUI thread. Therefore the
1123 handlers for them must not attempt to directly interact with the GUI,
1124 but use Gtkmm2ext::UI::instance()->call_slot();
1127 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1128 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1129 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1130 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1131 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1132 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1133 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1134 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1135 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1136 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1137 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1138 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1139 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1141 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1142 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1144 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1146 session->foreach_edit_group(this, &Editor::add_edit_group);
1148 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1149 editor_mixer_button.set_name (X_("EditorMixerButton"));
1151 edit_cursor_clock.set_session (session);
1152 selection_start_clock.set_session (session);
1153 selection_end_clock.set_session (session);
1154 zoom_range_clock.set_session (session);
1155 _playlist_selector->set_session (session);
1156 nudge_clock.set_session (session);
1158 switch (session->get_edit_mode()) {
1160 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1164 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1168 Location* loc = session->locations()->auto_loop_location();
1170 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1171 if (loc->start() == loc->end()) {
1172 loc->set_end (loc->start() + 1);
1174 session->locations()->add (loc, false);
1175 session->set_auto_loop_location (loc);
1179 loc->set_name (_("Loop"));
1182 loc = session->locations()->auto_punch_location();
1184 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1185 if (loc->start() == loc->end()) {
1186 loc->set_end (loc->start() + 1);
1188 session->locations()->add (loc, false);
1189 session->set_auto_punch_location (loc);
1193 loc->set_name (_("Punch"));
1196 update_loop_range_view (true);
1197 update_punch_range_view (true);
1199 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1202 refresh_location_display ();
1203 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1204 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1205 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1206 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1207 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1209 reset_scrolling_region ();
1211 redisplay_regions ();
1212 redisplay_named_selections ();
1214 //route_list.freeze (); GTK2FIX
1215 route_display_model->clear ();
1216 session->foreach_route (this, &Editor::handle_new_route);
1217 // route_list.select_all ();
1219 //route_list.sort ();
1220 route_list_reordered ();
1221 //route_list.thaw ();
1223 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1224 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1227 /* ::reposition_x_origin() doesn't work right here, since the old
1228 position may be zero already, and it does nothing in such
1234 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1235 track_canvas_scroller.get_hadjustment()->set_value (0);
1237 update_hscroller ();
1238 restore_ruler_visibility ();
1239 tempo_map_changed (Change (0));
1241 edit_cursor->set_position (0);
1242 playhead_cursor->set_position (0);
1246 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1249 /* don't show master bus in a new session */
1251 if (ARDOUR_UI::instance()->session_is_new ()) {
1253 TreeModel::Children rows = route_display_model->children();
1254 TreeModel::Children::iterator i;
1256 //route_list.freeze ();
1258 for (i = rows.begin(); i != rows.end(); ++i) {
1259 TimeAxisView *tv = (*i)[route_display_columns.tv];
1260 AudioTimeAxisView *atv;
1262 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1263 if (atv->route().master()) {
1264 route_list.get_selection()->unselect (i);
1265 //(*i)->unselect ();
1270 //route_list.thaw ();
1275 Editor::build_cursors ()
1277 using namespace Gdk;
1279 Gdk::Color mbg ("#000000" ); /* Black */
1280 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1283 RefPtr<Bitmap> source, mask;
1284 source = Bitmap::create (mag_bits, mag_width, mag_height);
1285 mask = Bitmap::create (magmask_bits, mag_width, mag_height);
1286 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1289 Gdk::Color fbg ("#ffffff" );
1290 Gdk::Color ffg ("#000000" );
1293 RefPtr<Bitmap> source, mask;
1295 source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
1296 mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
1297 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1301 RefPtr<Bitmap> source, mask;
1302 source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
1303 mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
1304 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1307 grabber_cursor = new Gdk::Cursor (HAND2);
1308 cross_hair_cursor = new Gdk::Cursor (CROSSHAIR);
1309 trimmer_cursor = new Gdk::Cursor (SB_H_DOUBLE_ARROW);
1310 selector_cursor = new Gdk::Cursor (XTERM);
1311 time_fx_cursor = new Gdk::Cursor (SIZING);
1312 wait_cursor = new Gdk::Cursor (WATCH);
1313 timebar_cursor = new Gdk::Cursor(LEFT_PTR);
1317 Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
1319 using namespace Menu_Helpers;
1320 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1323 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1327 MenuList& items (fade_context_menu.items());
1331 switch (item_type) {
1333 case FadeInHandleItem:
1334 if (arv->region.fade_in_active()) {
1335 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1337 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1340 items.push_back (SeparatorElem());
1342 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1343 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1344 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1345 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1346 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1350 case FadeOutHandleItem:
1351 if (arv->region.fade_out_active()) {
1352 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1354 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1357 items.push_back (SeparatorElem());
1359 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1360 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1361 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1362 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1363 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1367 fatal << _("programming error: ")
1368 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1373 fade_context_menu.popup (button, time);
1377 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1379 using namespace Menu_Helpers;
1380 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1383 switch (item_type) {
1385 case AudioRegionViewName:
1386 case AudioRegionViewNameHighlight:
1387 if (with_selection) {
1388 build_menu_function = &Editor::build_track_selection_context_menu;
1390 build_menu_function = &Editor::build_track_region_context_menu;
1395 if (with_selection) {
1396 build_menu_function = &Editor::build_track_selection_context_menu;
1398 build_menu_function = &Editor::build_track_context_menu;
1402 case CrossfadeViewItem:
1403 build_menu_function = &Editor::build_track_crossfade_context_menu;
1407 if (clicked_audio_trackview->get_diskstream()) {
1408 build_menu_function = &Editor::build_track_context_menu;
1410 build_menu_function = &Editor::build_track_bus_context_menu;
1415 /* probably shouldn't happen but if it does, we don't care */
1419 menu = (this->*build_menu_function)(frame);
1420 menu->set_name ("ArdourContextMenu");
1422 /* now handle specific situations */
1424 switch (item_type) {
1426 case AudioRegionViewName:
1427 case AudioRegionViewNameHighlight:
1428 if (!with_selection) {
1429 if (region_edit_menu_split_item) {
1430 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1431 // GTK2FIX find the action, change its sensitivity
1432 // region_edit_menu_split_item->set_sensitive (true);
1434 // GTK2FIX see above
1435 // region_edit_menu_split_item->set_sensitive (false);
1438 if (region_edit_menu_split_multichannel_item) {
1439 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1440 // GTK2FIX find the action, change its sensitivity
1441 // region_edit_menu_split_multichannel_item->set_sensitive (true);
1443 // GTK2FIX see above
1444 // region_edit_menu_split_multichannel_item->set_sensitive (false);
1453 case CrossfadeViewItem:
1460 /* probably shouldn't happen but if it does, we don't care */
1464 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1466 /* Bounce to disk */
1468 using namespace Menu_Helpers;
1469 MenuList& edit_items = menu->items();
1471 edit_items.push_back (SeparatorElem());
1473 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1474 case AudioTrack::NoFreeze:
1475 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1478 case AudioTrack::Frozen:
1479 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1482 case AudioTrack::UnFrozen:
1483 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1489 menu->popup (button, time);
1493 Editor::build_track_context_menu (jack_nframes_t ignored)
1495 using namespace Menu_Helpers;
1497 MenuList& edit_items = track_context_menu.items();
1500 add_dstream_context_items (edit_items);
1501 return &track_context_menu;
1505 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1507 using namespace Menu_Helpers;
1509 MenuList& edit_items = track_context_menu.items();
1512 add_bus_context_items (edit_items);
1513 return &track_context_menu;
1517 Editor::build_track_region_context_menu (jack_nframes_t frame)
1519 using namespace Menu_Helpers;
1520 MenuList& edit_items = track_region_context_menu.items();
1523 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1529 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1530 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1531 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1532 add_region_context_items (atv->view, (*i), edit_items);
1538 add_dstream_context_items (edit_items);
1540 return &track_region_context_menu;
1544 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1546 using namespace Menu_Helpers;
1547 MenuList& edit_items = track_crossfade_context_menu.items();
1548 edit_items.clear ();
1550 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1557 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
1559 Playlist::RegionList* regions = pl->regions_at (frame);
1560 AudioPlaylist::Crossfades xfades;
1562 apl->crossfades_at (frame, xfades);
1564 bool many = xfades.size() > 1;
1566 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
1567 add_crossfade_context_items (atv->view, (*i), edit_items, many);
1570 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1571 add_region_context_items (atv->view, (*i), edit_items);
1578 add_dstream_context_items (edit_items);
1580 return &track_crossfade_context_menu;
1584 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
1586 using namespace Menu_Helpers;
1587 MenuList& edit_items = track_selection_context_menu.items();
1588 edit_items.clear ();
1590 add_selection_context_items (edit_items);
1591 add_dstream_context_items (edit_items);
1593 return &track_selection_context_menu;
1597 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
1599 using namespace Menu_Helpers;
1600 Menu *xfade_menu = manage (new Menu);
1601 MenuList& items = xfade_menu->items();
1602 xfade_menu->set_name ("ArdourContextMenu");
1605 if (xfade->active()) {
1611 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
1612 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
1614 if (xfade->can_follow_overlap()) {
1616 if (xfade->following_overlap()) {
1617 str = _("Convert to short");
1619 str = _("Convert to full");
1622 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
1626 str = xfade->out().name();
1628 str += xfade->in().name();
1630 str = _("Crossfade");
1633 edit_items.push_back (MenuElem (str, *xfade_menu));
1634 edit_items.push_back (SeparatorElem());
1638 Editor::xfade_edit_left_region ()
1640 if (clicked_crossfadeview) {
1641 clicked_crossfadeview->left_view.show_region_editor ();
1646 Editor::xfade_edit_right_region ()
1648 if (clicked_crossfadeview) {
1649 clicked_crossfadeview->right_view.show_region_editor ();
1654 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
1656 using namespace Menu_Helpers;
1657 Menu *region_menu = manage (new Menu);
1658 MenuList& items = region_menu->items();
1659 region_menu->set_name ("ArdourContextMenu");
1661 AudioRegion* ar = 0;
1664 ar = dynamic_cast<AudioRegion*> (region);
1667 /* when this particular menu pops up, make the relevant region
1671 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
1673 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
1674 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
1675 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
1676 items.push_back (SeparatorElem());
1677 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
1678 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
1679 items.push_back (SeparatorElem());
1681 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
1682 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
1683 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
1684 items.push_back (SeparatorElem());
1686 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
1687 might be able to figure out which overloaded member function to use in
1691 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
1693 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
1694 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
1695 items.push_back (SeparatorElem());
1697 if (region->muted()) {
1698 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
1700 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
1702 items.push_back (SeparatorElem());
1704 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
1705 items.push_back (SeparatorElem());
1710 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
1711 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
1712 items.push_back (SeparatorElem());
1714 if (ar->scale_amplitude() != 1.0f) {
1715 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
1717 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
1720 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
1721 items.push_back (SeparatorElem());
1725 Menu *nudge_menu = manage (new Menu());
1726 MenuList& nudge_items = nudge_menu->items();
1727 nudge_menu->set_name ("ArdourContextMenu");
1729 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
1730 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
1731 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
1732 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
1734 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1735 items.push_back (SeparatorElem());
1737 Menu *trim_menu = manage (new Menu);
1738 MenuList& trim_items = trim_menu->items();
1739 trim_menu->set_name ("ArdourContextMenu");
1741 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
1742 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
1744 items.push_back (MenuElem (_("Trim"), *trim_menu));
1745 items.push_back (SeparatorElem());
1747 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
1748 region_edit_menu_split_item = &items.back();
1750 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
1751 region_edit_menu_split_multichannel_item = &items.back();
1753 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
1754 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
1755 items.push_back (SeparatorElem());
1756 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
1757 items.push_back (SeparatorElem());
1758 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
1760 /* OK, stick the region submenu at the top of the list, and then add
1764 /* we have to hack up the region name because "_" has a special
1765 meaning for menu titles.
1768 string::size_type pos = 0;
1769 string menu_item_name = region->name();
1771 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1772 menu_item_name.replace (pos, 1, "__");
1776 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
1777 edit_items.push_back (SeparatorElem());
1781 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1783 using namespace Menu_Helpers;
1784 Menu *selection_menu = manage (new Menu);
1785 MenuList& items = selection_menu->items();
1786 selection_menu->set_name ("ArdourContextMenu");
1788 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
1789 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
1790 items.push_back (SeparatorElem());
1791 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
1792 items.push_back (SeparatorElem());
1793 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
1794 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
1795 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
1796 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
1797 items.push_back (SeparatorElem());
1798 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
1799 items.push_back (SeparatorElem());
1800 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
1801 items.push_back (SeparatorElem());
1802 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
1804 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
1805 edit_items.push_back (SeparatorElem());
1809 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1811 using namespace Menu_Helpers;
1815 Menu *play_menu = manage (new Menu);
1816 MenuList& play_items = play_menu->items();
1817 play_menu->set_name ("ArdourContextMenu");
1819 play_items.push_back (MenuElem (_("Play from edit cursor")));
1820 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1821 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
1822 play_items.push_back (SeparatorElem());
1823 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
1825 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1829 Menu *select_menu = manage (new Menu);
1830 MenuList& select_items = select_menu->items();
1831 select_menu->set_name ("ArdourContextMenu");
1833 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
1834 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
1835 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1836 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
1837 select_items.push_back (SeparatorElem());
1838 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1839 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1840 select_items.push_back (SeparatorElem());
1842 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1846 Menu *cutnpaste_menu = manage (new Menu);
1847 MenuList& cutnpaste_items = cutnpaste_menu->items();
1848 cutnpaste_menu->set_name ("ArdourContextMenu");
1850 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
1851 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
1852 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
1853 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
1855 cutnpaste_items.push_back (SeparatorElem());
1857 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
1858 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
1860 cutnpaste_items.push_back (SeparatorElem());
1862 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
1864 cutnpaste_items.push_back (SeparatorElem());
1866 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
1867 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
1869 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1871 /* Adding new material */
1873 Menu *import_menu = manage (new Menu());
1874 MenuList& import_items = import_menu->items();
1875 import_menu->set_name ("ArdourContextMenu");
1877 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1878 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
1880 edit_items.push_back (MenuElem (_("Import"), *import_menu));
1884 Menu *nudge_menu = manage (new Menu());
1885 MenuList& nudge_items = nudge_menu->items();
1886 nudge_menu->set_name ("ArdourContextMenu");
1888 edit_items.push_back (SeparatorElem());
1889 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
1890 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
1891 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
1892 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
1894 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1898 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1900 using namespace Menu_Helpers;
1904 Menu *play_menu = manage (new Menu);
1905 MenuList& play_items = play_menu->items();
1906 play_menu->set_name ("ArdourContextMenu");
1908 play_items.push_back (MenuElem (_("Play from edit cursor")));
1909 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1910 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1914 Menu *select_menu = manage (new Menu);
1915 MenuList& select_items = select_menu->items();
1916 select_menu->set_name ("ArdourContextMenu");
1918 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
1919 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
1920 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1921 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
1922 select_items.push_back (SeparatorElem());
1923 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1924 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1925 select_items.push_back (SeparatorElem());
1927 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1931 Menu *cutnpaste_menu = manage (new Menu);
1932 MenuList& cutnpaste_items = cutnpaste_menu->items();
1933 cutnpaste_menu->set_name ("ArdourContextMenu");
1935 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
1936 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
1937 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
1939 Menu *nudge_menu = manage (new Menu());
1940 MenuList& nudge_items = nudge_menu->items();
1941 nudge_menu->set_name ("ArdourContextMenu");
1943 edit_items.push_back (SeparatorElem());
1944 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
1945 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
1946 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
1947 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
1949 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1952 /* CURSOR SETTING AND MARKS AND STUFF */
1955 Editor::set_snap_to (SnapType st)
1958 vector<string> txt = internationalize (snap_type_strings);
1959 snap_type_selector.set_active_text (txt[(int)st]);
1963 switch (snap_type) {
1964 case SnapToAThirtysecondBeat:
1965 case SnapToASixteenthBeat:
1966 case SnapToAEighthBeat:
1967 case SnapToAQuarterBeat:
1968 case SnapToAThirdBeat:
1969 update_tempo_based_rulers ();
1977 Editor::set_snap_mode (SnapMode mode)
1980 vector<string> txt = internationalize (snap_mode_strings);
1981 snap_mode_selector.set_active_text (txt[(int)mode]);
1987 Editor::add_location_from_selection ()
1989 if (selection->time.empty()) {
1993 if (session == 0 || clicked_trackview == 0) {
1997 jack_nframes_t start = selection->time[clicked_selection].start;
1998 jack_nframes_t end = selection->time[clicked_selection].end;
2000 Location *location = new Location (start, end, "selection");
2002 session->begin_reversible_command (_("add marker"));
2003 session->add_undo (session->locations()->get_memento());
2004 session->locations()->add (location, true);
2005 session->add_redo_no_execute (session->locations()->get_memento());
2006 session->commit_reversible_command ();
2010 Editor::add_location_from_playhead_cursor ()
2012 jack_nframes_t where = session->audible_frame();
2014 Location *location = new Location (where, where, "mark", Location::IsMark);
2015 session->begin_reversible_command (_("add marker"));
2016 session->add_undo (session->locations()->get_memento());
2017 session->locations()->add (location, true);
2018 session->add_redo_no_execute (session->locations()->get_memento());
2019 session->commit_reversible_command ();
2024 Editor::set_state (const XMLNode& node)
2026 const XMLProperty* prop;
2028 int x, y, width, height, xoff, yoff;
2030 if ((geometry = find_named_node (node, "geometry")) == 0) {
2032 width = default_width;
2033 height = default_height;
2041 width = atoi(geometry->property("x_size")->value());
2042 height = atoi(geometry->property("y_size")->value());
2043 x = atoi(geometry->property("x_pos")->value());
2044 y = atoi(geometry->property("y_pos")->value());
2045 xoff = atoi(geometry->property("x_off")->value());
2046 yoff = atoi(geometry->property("y_off")->value());
2049 set_default_size(width, height);
2051 // set_position(x, y-yoff);
2053 if ((prop = node.property ("zoom-focus"))) {
2054 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2057 if ((prop = node.property ("zoom"))) {
2058 set_frames_per_unit (atof (prop->value()));
2061 if ((prop = node.property ("snap-to"))) {
2062 set_snap_to ((SnapType) atoi (prop->value()));
2065 if ((prop = node.property ("snap-mode"))) {
2066 set_snap_mode ((SnapMode) atoi (prop->value()));
2069 if ((prop = node.property ("show-waveforms"))) {
2070 bool yn = (prop->value() == "yes");
2071 _show_waveforms = !yn;
2072 set_show_waveforms (yn);
2075 if ((prop = node.property ("show-waveforms-recording"))) {
2076 bool yn = (prop->value() == "yes");
2077 _show_waveforms_recording = !yn;
2078 set_show_waveforms_recording (yn);
2081 if ((prop = node.property ("show-measures"))) {
2082 bool yn = (prop->value() == "yes");
2083 _show_measures = !yn;
2084 set_show_measures (yn);
2087 if ((prop = node.property ("follow-playhead"))) {
2088 bool yn = (prop->value() == "yes");
2089 _follow_playhead = !yn;
2090 set_follow_playhead (yn);
2093 if ((prop = node.property ("xfades-visible"))) {
2094 bool yn = (prop->value() == "yes");
2095 _xfade_visibility = !yn;
2096 set_xfade_visibility (yn);
2099 if ((prop = node.property ("region-list-sort-type"))) {
2100 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2101 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2104 if ((prop = node.property ("mouse-mode"))) {
2105 MouseMode m = str2mousemode(prop->value());
2106 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2107 set_mouse_mode (m, true);
2109 mouse_mode = MouseGain; /* lie, to force the mode switch */
2110 set_mouse_mode (MouseObject, true);
2113 if ((prop = node.property ("editor-mixer-button"))) {
2114 editor_mixer_button.set_active(prop->value() == "yes");
2121 Editor::get_state ()
2123 XMLNode* node = new XMLNode ("Editor");
2126 if (is_realized()) {
2127 Glib::RefPtr<Gdk::Window> win = get_window();
2129 int x, y, xoff, yoff, width, height;
2130 win->get_root_origin(x, y);
2131 win->get_position(xoff, yoff);
2132 win->get_size(width, height);
2134 XMLNode* geometry = new XMLNode ("geometry");
2136 snprintf(buf, sizeof(buf), "%d", width);
2137 geometry->add_property("x_size", string(buf));
2138 snprintf(buf, sizeof(buf), "%d", height);
2139 geometry->add_property("y_size", string(buf));
2140 snprintf(buf, sizeof(buf), "%d", x);
2141 geometry->add_property("x_pos", string(buf));
2142 snprintf(buf, sizeof(buf), "%d", y);
2143 geometry->add_property("y_pos", string(buf));
2144 snprintf(buf, sizeof(buf), "%d", xoff);
2145 geometry->add_property("x_off", string(buf));
2146 snprintf(buf, sizeof(buf), "%d", yoff);
2147 geometry->add_property("y_off", string(buf));
2148 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2149 geometry->add_property("edit_pane_pos", string(buf));
2151 node->add_child_nocopy (*geometry);
2154 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2155 node->add_property ("zoom-focus", buf);
2156 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2157 node->add_property ("zoom", buf);
2158 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2159 node->add_property ("snap-to", buf);
2160 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2161 node->add_property ("snap-mode", buf);
2163 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2164 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2165 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2166 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2167 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2168 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2169 node->add_property ("mouse-mode", enum2str(mouse_mode));
2170 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2178 Editor::trackview_by_y_position (double y)
2180 TrackViewList::iterator iter;
2183 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2191 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2200 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2202 Location* before = 0;
2203 Location* after = 0;
2209 const jack_nframes_t one_second = session->frame_rate();
2210 const jack_nframes_t one_minute = session->frame_rate() * 60;
2212 jack_nframes_t presnap = start;
2214 switch (snap_type) {
2220 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2222 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2225 case SnapToSMPTEFrame:
2227 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2229 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2233 case SnapToSMPTESeconds:
2234 if (session->smpte_offset_negative())
2236 start += session->smpte_offset ();
2238 start -= session->smpte_offset ();
2240 if (direction > 0) {
2241 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2243 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2246 if (session->smpte_offset_negative())
2248 start -= session->smpte_offset ();
2250 start += session->smpte_offset ();
2254 case SnapToSMPTEMinutes:
2255 if (session->smpte_offset_negative())
2257 start += session->smpte_offset ();
2259 start -= session->smpte_offset ();
2262 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2264 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2266 if (session->smpte_offset_negative())
2268 start -= session->smpte_offset ();
2270 start += session->smpte_offset ();
2276 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2278 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2284 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2286 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2291 start = session->tempo_map().round_to_bar (start, direction);
2295 start = session->tempo_map().round_to_beat (start, direction);
2298 case SnapToAThirtysecondBeat:
2299 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2302 case SnapToASixteenthBeat:
2303 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2306 case SnapToAEighthBeat:
2307 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2310 case SnapToAQuarterBeat:
2311 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2314 case SnapToAThirdBeat:
2315 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2318 case SnapToEditCursor:
2319 start = edit_cursor->current_frame;
2327 before = session->locations()->first_location_before (start);
2328 after = session->locations()->first_location_after (start);
2330 if (direction < 0) {
2332 start = before->start();
2336 } else if (direction > 0) {
2338 start = after->start();
2340 start = session->current_end_frame();
2345 /* find nearest of the two */
2346 if ((start - before->start()) < (after->start() - start)) {
2347 start = before->start();
2349 start = after->start();
2352 start = before->start();
2355 start = after->start();
2362 case SnapToRegionStart:
2363 case SnapToRegionEnd:
2364 case SnapToRegionSync:
2365 case SnapToRegionBoundary:
2366 if (!region_boundary_cache.empty()) {
2367 vector<jack_nframes_t>::iterator i;
2369 if (direction > 0) {
2370 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2372 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2375 if (i != region_boundary_cache.end()) {
2378 start = region_boundary_cache.back();
2384 switch (snap_mode) {
2390 if (presnap > start) {
2391 if (presnap > (start + unit_to_frame(snap_threshold))) {
2395 } else if (presnap < start) {
2396 if (presnap < (start - unit_to_frame(snap_threshold))) {
2408 Editor::setup_toolbar ()
2411 vector<ToggleButton *> mouse_mode_buttons;
2413 mouse_mode_buttons.push_back (&mouse_move_button);
2414 mouse_mode_buttons.push_back (&mouse_select_button);
2415 mouse_mode_buttons.push_back (&mouse_gain_button);
2416 mouse_mode_buttons.push_back (&mouse_zoom_button);
2417 mouse_mode_buttons.push_back (&mouse_timefx_button);
2418 mouse_mode_buttons.push_back (&mouse_audition_button);
2419 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2421 mouse_mode_button_table.set_homogeneous (true);
2422 mouse_mode_button_table.set_col_spacings (2);
2423 mouse_mode_button_table.set_row_spacings (2);
2424 mouse_mode_button_table.set_border_width (5);
2426 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2427 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2428 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2430 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2431 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2432 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2434 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2435 mouse_mode_tearoff->set_name ("MouseModeBase");
2437 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2438 mouse_mode_tearoff->tearoff_window()));
2439 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2440 mouse_mode_tearoff->tearoff_window(), 1));
2442 mouse_move_button.set_name ("MouseModeButton");
2443 mouse_select_button.set_name ("MouseModeButton");
2444 mouse_gain_button.set_name ("MouseModeButton");
2445 mouse_zoom_button.set_name ("MouseModeButton");
2446 mouse_timefx_button.set_name ("MouseModeButton");
2447 mouse_audition_button.set_name ("MouseModeButton");
2449 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2450 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2451 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2452 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2453 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2454 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2456 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2457 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2458 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2459 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2460 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2461 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2463 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2464 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2466 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2467 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2468 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2469 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2470 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2472 // mouse_move_button.set_active (true);
2474 /* automation control */
2476 global_automation_button.set_name ("MouseModeButton");
2477 automation_mode_button.set_name ("MouseModeButton");
2479 automation_box.set_spacing (2);
2480 automation_box.set_border_width (2);
2481 automation_box.pack_start (global_automation_button, false, false);
2482 automation_box.pack_start (automation_mode_button, false, false);
2486 edit_mode_label.set_name ("ToolBarLabel");
2488 edit_mode_selector.set_name ("EditModeSelector");
2490 edit_mode_box.set_spacing (3);
2491 edit_mode_box.set_border_width (3);
2493 /* XXX another disgusting hack because of the way combo boxes size themselves */
2495 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2, 10);
2496 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2497 edit_mode_box.pack_start (edit_mode_label, false, false);
2498 edit_mode_box.pack_start (edit_mode_selector, false, false);
2500 edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2504 snap_type_label.set_name ("ToolBarLabel");
2506 snap_type_selector.set_name ("SnapTypeSelector");
2508 snap_type_box.set_spacing (3);
2509 snap_type_box.set_border_width (3);
2511 /* XXX another disgusting hack because of the way combo boxes size themselves */
2513 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2514 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "Region bounds", 2+FUDGE, 10);
2515 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2517 snap_type_box.pack_start (snap_type_label, false, false);
2518 snap_type_box.pack_start (snap_type_selector, false, false);
2520 snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2522 /* Snap mode, not snap type */
2524 snap_mode_label.set_name ("ToolBarLabel");
2526 snap_mode_selector.set_name ("SnapModeSelector");
2528 snap_mode_box.set_spacing (3);
2529 snap_mode_box.set_border_width (3);
2531 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2, 10);
2532 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2534 snap_mode_box.pack_start (snap_mode_label, false, false);
2535 snap_mode_box.pack_start (snap_mode_selector, false, false);
2537 snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2539 /* Zoom focus mode */
2541 zoom_focus_label.set_name ("ToolBarLabel");
2543 zoom_focus_selector.set_name ("ZoomFocusSelector");
2545 zoom_focus_box.set_spacing (3);
2546 zoom_focus_box.set_border_width (3);
2548 /* XXX another disgusting hack because of the way combo boxes size themselves */
2550 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2, 10);
2551 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
2553 zoom_focus_box.pack_start (zoom_focus_label, false, false);
2554 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
2556 zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
2558 /* selection/cursor clocks */
2560 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
2561 selection_start_clock_label.set_name ("ToolBarLabel");
2562 selection_end_clock_label.set_name ("ToolBarLabel");
2563 edit_cursor_clock_label.set_name ("ToolBarLabel");
2565 selection_start_clock_label.set_text (_("Start:"));
2566 selection_end_clock_label.set_text (_("End:"));
2567 edit_cursor_clock_label.set_text (_("Edit:"));
2569 toolbar_selection_clock_table.set_border_width (5);
2570 toolbar_selection_clock_table.set_col_spacings (2);
2571 toolbar_selection_clock_table.set_homogeneous (false);
2573 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
2574 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
2575 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
2577 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
2578 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
2579 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
2582 // toolbar_clock_vbox.set_spacing (2);
2583 // toolbar_clock_vbox.set_border_width (10);
2584 /* the editor/mixer button will be enabled at session connect */
2586 editor_mixer_button.set_active(false);
2587 editor_mixer_button.set_sensitive(false);
2589 HBox* hbox = new HBox;
2591 hbox->pack_start (editor_mixer_button, false, false);
2592 hbox->pack_start (toolbar_selection_clock_table, false, false);
2593 hbox->pack_start (zoom_indicator_vbox, false, false);
2594 hbox->pack_start (zoom_focus_box, false, false);
2595 hbox->pack_start (snap_type_box, false, false);
2596 hbox->pack_start (snap_mode_box, false, false);
2597 hbox->pack_start (edit_mode_box, false, false);
2599 VBox *vbox = manage (new VBox);
2601 vbox->set_spacing (3);
2602 vbox->set_border_width (3);
2604 HBox *nbox = manage (new HBox);
2606 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
2607 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
2609 nbox->pack_start (nudge_backward_button, false, false);
2610 nbox->pack_start (nudge_forward_button, false, false);
2611 nbox->pack_start (nudge_clock, false, false, 5);
2613 nudge_label.set_name ("ToolBarLabel");
2615 vbox->pack_start (nudge_label, false, false);
2616 vbox->pack_start (*nbox, false, false);
2618 hbox->pack_start (*vbox, false, false);
2622 tools_tearoff = new TearOff (*hbox);
2623 tools_tearoff->set_name ("MouseModeBase");
2625 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2626 tools_tearoff->tearoff_window()));
2627 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2628 tools_tearoff->tearoff_window(), 0));
2631 toolbar_hbox.set_spacing (8);
2632 toolbar_hbox.set_border_width (2);
2634 toolbar_hbox.pack_start (*tools_tearoff, false, false);
2635 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
2637 toolbar_base.set_name ("ToolBarBase");
2638 toolbar_base.add (toolbar_hbox);
2640 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
2641 toolbar_frame.set_name ("BaseFrame");
2642 toolbar_frame.add (toolbar_base);
2646 Editor::_autoscroll_canvas (void *arg)
2648 return ((Editor *) arg)->autoscroll_canvas ();
2652 Editor::autoscroll_canvas ()
2654 jack_nframes_t new_frame;
2655 bool keep_calling = true;
2657 if (autoscroll_direction < 0) {
2658 if (leftmost_frame < autoscroll_distance) {
2661 new_frame = leftmost_frame - autoscroll_distance;
2664 if (leftmost_frame > max_frames - autoscroll_distance) {
2665 new_frame = max_frames;
2667 new_frame = leftmost_frame + autoscroll_distance;
2671 if (new_frame != leftmost_frame) {
2672 reposition_x_origin (new_frame);
2675 if (new_frame == 0 || new_frame == max_frames) {
2682 if (autoscroll_cnt == 1) {
2684 /* connect the timeout so that we get called repeatedly */
2686 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
2687 keep_calling = false;
2689 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
2691 /* after about a while, speed up a bit by changing the timeout interval */
2693 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
2694 keep_calling = false;
2696 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
2698 /* after about another while, speed up some more */
2700 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
2701 keep_calling = false;
2703 } else if (autoscroll_cnt >= 30) {
2705 /* we've been scrolling for a while ... crank it up */
2707 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
2710 return keep_calling;
2714 Editor::start_canvas_autoscroll (int dir)
2720 stop_canvas_autoscroll ();
2722 autoscroll_direction = dir;
2723 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
2726 /* do it right now, which will start the repeated callbacks */
2728 autoscroll_canvas ();
2732 Editor::stop_canvas_autoscroll ()
2734 if (autoscroll_timeout_tag >= 0) {
2735 gtk_timeout_remove (autoscroll_timeout_tag);
2736 autoscroll_timeout_tag = -1;
2741 Editor::convert_drop_to_paths (vector<string>& paths,
2742 GdkDragContext *context,
2745 GtkSelectionData *data,
2753 gchar *tname = gdk_atom_name (data->type);
2755 if (session == 0 || strcmp (tname, "text/plain") != 0) {
2759 /* Parse the "uri-list" format that Nautilus provides,
2760 where each pathname is delimited by \r\n
2763 path = (char *) data->data;
2766 for (int n = 0; n < data->length; ++n) {
2770 if (path[n] == '\r') {
2777 if (path[n] == '\n') {
2778 paths.push_back (spath);
2782 warning << _("incorrectly formatted URI list, ignored")
2790 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
2792 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
2794 // cerr << "dropped text was " << *p << endl;
2798 // cerr << "decoded was " << *p << endl;
2800 if ((*p).substr (0,7) == "file://") {
2801 (*p) = (*p).substr (7);
2809 Editor::track_canvas_drag_data_received (GdkDragContext *context,
2812 GtkSelectionData *data,
2817 AudioTimeAxisView* tv;
2819 vector<string> paths;
2822 jack_nframes_t frame;
2824 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
2828 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
2834 track_canvas.c2w( x, y, wx, wy);
2836 ev.type = GDK_BUTTON_RELEASE;
2840 frame = event_frame (&ev, 0, &cy);
2844 if ((tvp = trackview_by_y_position (cy)) == 0) {
2846 /* drop onto canvas background: create a new track */
2848 insert_paths_as_new_tracks (paths, false);
2851 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
2853 /* check that its an audio track, not a bus */
2855 if (tv->get_diskstream()) {
2857 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
2858 insert_sndfile_into (*p, true, tv, frame);
2865 gtk_drag_finish (context, TRUE, FALSE, time);
2869 Editor::new_tempo_section ()
2875 Editor::map_transport_state ()
2877 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
2879 if (session->transport_stopped()) {
2880 have_pending_keyboard_selection = false;
2886 Editor::State::State ()
2888 selection = new Selection;
2891 Editor::State::~State ()
2897 Editor::get_memento () const
2899 State *state = new State;
2901 store_state (*state);
2902 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
2906 Editor::store_state (State& state) const
2908 *state.selection = *selection;
2912 Editor::restore_state (State *state)
2914 if (*selection == *state->selection) {
2918 *selection = *state->selection;
2919 time_selection_changed ();
2920 region_selection_changed ();
2922 /* XXX other selection change handlers? */
2926 Editor::begin_reversible_command (string name)
2929 UndoAction ua = get_memento();
2930 session->begin_reversible_command (name, &ua);
2935 Editor::commit_reversible_command ()
2938 UndoAction ua = get_memento();
2939 session->commit_reversible_command (&ua);
2944 Editor::flush_track_canvas ()
2946 /* I don't think this is necessary, and only causes more problems.
2947 I'm commenting it out
2948 and if the imageframe folks don't have any issues, we can take
2949 out this method entirely
2952 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
2953 //gtk_main_iteration ();
2957 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
2959 if (!clicked_trackview) {
2964 begin_reversible_command (_("set selected trackview"));
2969 if (selection->selected (clicked_trackview)) {
2971 selection->remove (clicked_trackview);
2974 selection->add (clicked_trackview);
2979 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
2980 /* no commit necessary */
2984 selection->set (clicked_trackview);
2988 commit_reversible_command ();
2993 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
2995 if (!clicked_control_point) {
3000 begin_reversible_command (_("set selected control point"));
3010 commit_reversible_command ();
3015 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3017 if (!clicked_regionview) {
3021 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3027 RouteGroup* group = atv->route().edit_group();
3028 vector<AudioRegionView*> all_equivalent_regions;
3030 if (group && group->is_active()) {
3032 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3034 AudioTimeAxisView* tatv;
3036 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3038 if (tatv->route().edit_group() != group) {
3043 vector<AudioRegion*> results;
3044 AudioRegionView* marv;
3047 if ((ds = tatv->get_diskstream()) == 0) {
3052 if ((pl = ds->playlist()) != 0) {
3053 pl->get_equivalent_regions (clicked_regionview->region,
3057 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3058 if ((marv = tatv->view->find_view (**ir)) != 0) {
3059 all_equivalent_regions.push_back (marv);
3068 all_equivalent_regions.push_back (clicked_regionview);
3072 begin_reversible_command (_("set selected regionview"));
3076 if (clicked_regionview->get_selected()) {
3077 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3078 /* reduce selection down to just the one clicked */
3079 selection->set (clicked_regionview);
3081 selection->remove (clicked_regionview);
3084 selection->add (all_equivalent_regions);
3087 set_selected_track_from_click (add, false, no_track_remove);
3091 // karsten wiese suggested these two lines to make
3092 // a selected region rise to the top. but this
3093 // leads to a mismatch between actual layering
3094 // and visual layering. resolution required ....
3096 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3097 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3099 if (clicked_regionview->get_selected()) {
3100 /* no commit necessary: we are the one selected. */
3105 selection->set (all_equivalent_regions);
3106 set_selected_track_from_click (add, false, false);
3110 commit_reversible_command () ;
3114 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3116 vector<AudioRegionView*> all_equivalent_regions;
3117 AudioRegion* region;
3119 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3123 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3125 AudioTimeAxisView* tatv;
3127 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3130 vector<AudioRegion*> results;
3131 AudioRegionView* marv;
3134 if ((ds = tatv->get_diskstream()) == 0) {
3139 if ((pl = ds->playlist()) != 0) {
3140 pl->get_region_list_equivalent_regions (*region, results);
3143 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3144 if ((marv = tatv->view->find_view (**ir)) != 0) {
3145 all_equivalent_regions.push_back (marv);
3152 begin_reversible_command (_("set selected regions"));
3156 selection->add (all_equivalent_regions);
3160 selection->set (all_equivalent_regions);
3163 commit_reversible_command () ;
3167 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3169 AudioRegionView* rv;
3172 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3176 if ((rv = sv->find_view (*ar)) == 0) {
3180 /* don't reset the selection if its something other than
3181 a single other region.
3184 if (selection->audio_regions.size() > 1) {
3188 begin_reversible_command (_("set selected regions"));
3190 selection->set (rv);
3192 commit_reversible_command () ;
3198 Editor::set_edit_group_solo (Route& route, bool yn)
3200 RouteGroup *edit_group;
3202 if ((edit_group = route.edit_group()) != 0) {
3203 edit_group->apply (&Route::set_solo, yn, this);
3205 route.set_solo (yn, this);
3210 Editor::set_edit_group_mute (Route& route, bool yn)
3212 RouteGroup *edit_group = 0;
3214 if ((edit_group == route.edit_group()) != 0) {
3215 edit_group->apply (&Route::set_mute, yn, this);
3217 route.set_mute (yn, this);
3222 Editor::set_edit_menu (Menu& menu)
3225 edit_menu->signal_map_event().connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3229 Editor::edit_menu_map_handler (GdkEventAny* ev)
3231 using namespace Menu_Helpers;
3232 MenuList& edit_items = edit_menu->items();
3235 /* Nuke all the old items */
3237 edit_items.clear ();
3243 if (session->undo_depth() == 0) {
3246 label = string_compose(_("Undo (%1)"), session->next_undo());
3249 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3251 if (session->undo_depth() == 0) {
3252 edit_items.back().set_sensitive (false);
3255 if (session->redo_depth() == 0) {
3258 label = string_compose(_("Redo (%1)"), session->next_redo());
3261 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3262 if (session->redo_depth() == 0) {
3263 edit_items.back().set_sensitive (false);
3266 vector<MenuItem*> mitems;
3268 edit_items.push_back (SeparatorElem());
3269 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3270 mitems.push_back (&edit_items.back());
3271 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3272 mitems.push_back (&edit_items.back());
3273 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3274 mitems.push_back (&edit_items.back());
3275 edit_items.push_back (SeparatorElem());
3276 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3277 mitems.push_back (&edit_items.back());
3278 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3279 mitems.push_back (&edit_items.back());
3280 edit_items.push_back (SeparatorElem());
3282 if (selection->empty()) {
3283 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3284 (*i)->set_sensitive (false);
3288 Menu* import_menu = manage (new Menu());
3289 import_menu->set_name ("ArdourContextMenu");
3290 MenuList& import_items = import_menu->items();
3292 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3293 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3295 Menu* embed_menu = manage (new Menu());
3296 embed_menu->set_name ("ArdourContextMenu");
3297 MenuList& embed_items = embed_menu->items();
3299 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3300 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3302 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3303 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3304 edit_items.push_back (SeparatorElem());
3306 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3307 if (!session->have_captured()) {
3308 edit_items.back().set_sensitive (false);
3315 Editor::duplicate_dialog (bool dup_region)
3318 if (clicked_regionview == 0) {
3322 if (selection->time.length() == 0) {
3327 ArdourDialog win ("duplicate dialog");
3329 Label label (_("Duplicate how many times?"));
3331 win.get_vbox()->pack_start (label);
3332 win.add_action_widget (entry, RESPONSE_ACCEPT);
3333 win.add_button (Stock::OK, RESPONSE_ACCEPT);
3334 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3336 win.set_position (Gtk::WIN_POS_MOUSE);
3338 entry.set_text ("1");
3339 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3340 entry.select_region (0, entry.get_text_length());
3341 entry.grab_focus ();
3344 // win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3347 switch (win.run ()) {
3348 case RESPONSE_ACCEPT:
3354 string text = entry.get_text();
3357 if (sscanf (text.c_str(), "%f", ×) == 1) {
3359 AudioRegionSelection regions;
3360 regions.add (clicked_regionview);
3361 duplicate_some_regions (regions, times);
3363 duplicate_selection (times);
3369 Editor::show_verbose_canvas_cursor ()
3371 verbose_canvas_cursor->raise_to_top();
3372 verbose_canvas_cursor->show();
3373 verbose_cursor_visible = true;
3377 Editor::hide_verbose_canvas_cursor ()
3379 verbose_canvas_cursor->hide();
3380 verbose_cursor_visible = false;
3384 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3386 /* XXX get origin of canvas relative to root window,
3387 add x and y and check compared to gdk_screen_{width,height}
3389 verbose_canvas_cursor->property_text() = txt.c_str();
3390 verbose_canvas_cursor->property_x() = x;
3391 verbose_canvas_cursor->property_y() = y;
3395 Editor::set_verbose_canvas_cursor_text (string txt)
3397 verbose_canvas_cursor->property_text() = txt.c_str();
3401 Editor::edit_mode_selection_done ()
3407 string choice = edit_mode_selector.get_active_text();
3408 EditMode mode = Slide;
3410 if (choice == _("Splice")) {
3412 } else if (choice == _("Slide")) {
3416 session->set_edit_mode (mode);
3420 Editor::snap_type_selection_done ()
3426 string choice = snap_type_selector.get_active_text();
3427 SnapType snaptype = SnapToFrame;
3429 if (choice == _("Beats/3")) {
3430 snaptype = SnapToAThirdBeat;
3431 } else if (choice == _("Beats/4")) {
3432 snaptype = SnapToAQuarterBeat;
3433 } else if (choice == _("Beats/8")) {
3434 snaptype = SnapToAEighthBeat;
3435 } else if (choice == _("Beats/16")) {
3436 snaptype = SnapToASixteenthBeat;
3437 } else if (choice == _("Beats/32")) {
3438 snaptype = SnapToAThirtysecondBeat;
3439 } else if (choice == _("Beats")) {
3440 snaptype = SnapToBeat;
3441 } else if (choice == _("Bars")) {
3442 snaptype = SnapToBar;
3443 } else if (choice == _("Marks")) {
3444 snaptype = SnapToMark;
3445 } else if (choice == _("Edit Cursor")) {
3446 snaptype = SnapToEditCursor;
3447 } else if (choice == _("Region starts")) {
3448 snaptype = SnapToRegionStart;
3449 } else if (choice == _("Region ends")) {
3450 snaptype = SnapToRegionEnd;
3451 } else if (choice == _("Region bounds")) {
3452 snaptype = SnapToRegionBoundary;
3453 } else if (choice == _("Region syncs")) {
3454 snaptype = SnapToRegionSync;
3455 } else if (choice == _("CD Frames")) {
3456 snaptype = SnapToCDFrame;
3457 } else if (choice == _("SMPTE Frames")) {
3458 snaptype = SnapToSMPTEFrame;
3459 } else if (choice == _("SMPTE Seconds")) {
3460 snaptype = SnapToSMPTESeconds;
3461 } else if (choice == _("SMPTE Minutes")) {
3462 snaptype = SnapToSMPTEMinutes;
3463 } else if (choice == _("Seconds")) {
3464 snaptype = SnapToSeconds;
3465 } else if (choice == _("Minutes")) {
3466 snaptype = SnapToMinutes;
3467 } else if (choice == _("None")) {
3468 snaptype = SnapToFrame;
3471 set_snap_to (snaptype);
3475 Editor::snap_mode_selection_done ()
3481 string choice = snap_mode_selector.get_active_text();
3482 SnapMode mode = SnapNormal;
3484 if (choice == _("Normal")) {
3486 } else if (choice == _("Magnetic")) {
3487 mode = SnapMagnetic;
3490 set_snap_mode (mode);
3494 Editor::zoom_focus_selection_done ()
3500 string choice = zoom_focus_selector.get_active_text();
3501 ZoomFocus focus_type = ZoomFocusLeft;
3503 if (choice == _("Left")) {
3504 focus_type = ZoomFocusLeft;
3505 } else if (choice == _("Right")) {
3506 focus_type = ZoomFocusRight;
3507 } else if (choice == _("Center")) {
3508 focus_type = ZoomFocusCenter;
3509 } else if (choice == _("Playhead")) {
3510 focus_type = ZoomFocusPlayhead;
3511 } else if (choice == _("Edit Cursor")) {
3512 focus_type = ZoomFocusEdit;
3515 set_zoom_focus (focus_type);
3519 Editor::edit_controls_button_release (GdkEventButton* ev)
3521 if (Keyboard::is_context_menu_event (ev)) {
3522 ARDOUR_UI::instance()->add_route ();
3528 Editor::track_selection_changed ()
3530 switch (selection->tracks.size()){
3534 set_selected_mixer_strip (*(selection->tracks.front()));
3538 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3539 (*i)->set_selected (false);
3540 if (mouse_mode == MouseRange) {
3541 (*i)->hide_selection ();
3545 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3546 (*i)->set_selected (true);
3547 if (mouse_mode == MouseRange) {
3548 (*i)->show_selection (selection->time);
3554 Editor::time_selection_changed ()
3556 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3557 (*i)->hide_selection ();
3560 if (selection->tracks.empty()) {
3561 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3562 (*i)->show_selection (selection->time);
3565 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3566 (*i)->show_selection (selection->time);
3572 Editor::region_selection_changed ()
3574 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3575 (*i)->set_selected_regionviews (selection->audio_regions);
3580 Editor::point_selection_changed ()
3582 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3583 (*i)->set_selected_points (selection->points);
3588 Editor::run_sub_event_loop ()
3590 sub_event_loop_status = 0;
3595 Editor::finish_sub_event_loop (int status)
3598 sub_event_loop_status = status;
3602 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
3604 finish_sub_event_loop (status);
3609 Editor::mouse_select_button_release (GdkEventButton* ev)
3611 /* this handles just right-clicks */
3613 if (ev->button != 3) {
3620 Editor::TrackViewList *
3621 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
3624 TrackViewList::iterator i;
3626 v = new TrackViewList;
3628 if (track == 0 && group == 0) {
3632 for (i = track_views.begin(); i != track_views.end (); ++i) {
3636 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
3638 /* just the view for this track
3641 v->push_back (track);
3645 /* views for all tracks in the edit group */
3647 for (i = track_views.begin(); i != track_views.end (); ++i) {
3649 if (group == 0 || (*i)->edit_group() == group) {
3659 Editor::set_zoom_focus (ZoomFocus f)
3661 if (zoom_focus != f) {
3663 vector<string> txt = internationalize (zoom_focus_strings);
3664 zoom_focus_selector.set_active_text (txt[(int)f]);
3665 ZoomFocusChanged (); /* EMIT_SIGNAL */
3672 Editor::ensure_float (Window& win)
3674 win.set_transient_for (*this);
3678 Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which)
3680 /* recover or initialize pane positions. do this here rather than earlier because
3681 we don't want the positions to change the child allocations, which they seem to do.
3687 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3689 static int32_t done[4] = { 0, 0, 0, 0 };
3692 if ((geometry = find_named_node (*node, "geometry")) == 0) {
3693 width = default_width;
3694 height = default_height;
3696 width = atoi(geometry->property("x_size")->value());
3697 height = atoi(geometry->property("y_size")->value());
3700 if (which == static_cast<Gtk::Paned*> (&edit_pane)) {
3706 if (!geometry || (prop = geometry->property ("edit_pane_pos")) == 0) {
3708 snprintf (buf, sizeof(buf), "%d", pos);
3710 pos = atoi (prop->value());
3713 if ((done[0] = GTK_WIDGET(edit_pane.gobj())->allocation.width > pos)) {
3714 edit_pane.set_position (pos);
3720 Editor::detach_tearoff (Gtk::Box* b, Gtk::Window* w)
3722 if (tools_tearoff->torn_off() &&
3723 mouse_mode_tearoff->torn_off()) {
3724 top_hbox.remove (toolbar_frame);
3731 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Window* w, int32_t n)
3733 if (toolbar_frame.get_parent() == 0) {
3734 top_hbox.pack_end (toolbar_frame);
3739 Editor::set_show_measures (bool yn)
3741 if (_show_measures != yn) {
3744 if ((_show_measures = yn) == true) {
3747 DisplayControlChanged (ShowMeasures);
3753 Editor::set_follow_playhead (bool yn)
3755 if (_follow_playhead != yn) {
3756 if ((_follow_playhead = yn) == true) {
3758 update_current_screen ();
3760 DisplayControlChanged (FollowPlayhead);
3766 Editor::toggle_xfade_active (Crossfade* xfade)
3768 xfade->set_active (!xfade->active());
3772 Editor::toggle_xfade_length (Crossfade* xfade)
3774 xfade->set_follow_overlap (!xfade->following_overlap());
3778 Editor::edit_xfade (Crossfade* xfade)
3780 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
3785 // cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
3787 switch (cew.run ()) {
3788 case RESPONSE_ACCEPT:
3795 xfade->StateChanged (Change (~0));
3799 Editor::playlist_selector () const
3801 return *_playlist_selector;
3805 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
3809 ret = nudge_clock.current_duration (pos);
3810 next = ret + 1; /* XXXX fix me */
3816 Editor::end_location_changed (Location* location)
3818 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
3819 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
3823 Editor::playlist_deletion_dialog (Playlist* pl)
3825 ArdourDialog dialog ("playlist deletion dialog");
3826 Label label (string_compose (_("Playlist %1 is currently unused.\n"
3827 "If left alone, no audio files used by it will be cleaned.\n"
3828 "If deleted, audio files used by it alone by will cleaned."),
3831 dialog.set_position (Gtk::WIN_POS_CENTER);
3832 dialog.get_vbox()->pack_start (label);
3834 dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT);
3835 dialog.add_button (_("Keep playlist"), RESPONSE_CANCEL);
3836 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3838 switch (dialog.run ()) {
3839 case RESPONSE_ACCEPT:
3840 /* delete the playlist */
3844 case RESPONSE_REJECT:
3845 /* keep the playlist */
3857 Editor::audio_region_selection_covers (jack_nframes_t where)
3859 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
3860 if ((*a)->region.covers (where)) {
3869 Editor::prepare_for_cleanup ()
3871 cut_buffer->clear_audio_regions ();
3872 cut_buffer->clear_playlists ();
3874 selection->clear_audio_regions ();
3875 selection->clear_playlists ();
3879 Editor::init_colormap ()
3881 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
3882 pair<ColorID,int> newpair;
3884 newpair.first = (ColorID) x;
3885 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
3886 color_map.insert (newpair);
3891 Editor::transport_loop_location()
3894 return session->locations()->auto_loop_location();
3901 Editor::transport_punch_location()
3904 return session->locations()->auto_punch_location();