2 Copyright (C) 2000-2004 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.
28 #include <pbd/error.h>
29 #include <pbd/basename.h>
30 #include <pbd/pthread_utils.h>
32 #include <gtkmm2ext/utils.h>
33 #include <gtkmm2ext/choice.h>
35 #include <ardour/audioengine.h>
36 #include <ardour/session.h>
37 #include <ardour/audioplaylist.h>
38 #include <ardour/audioregion.h>
39 #include <ardour/diskstream.h>
40 #include <ardour/filesource.h>
41 #include <ardour/externalsource.h>
42 #include <ardour/utils.h>
43 #include <ardour/location.h>
44 #include <ardour/named_selection.h>
45 #include <ardour/audio_track.h>
46 #include <ardour/audioplaylist.h>
47 #include <ardour/region_factory.h>
48 #include <ardour/reverse.h>
50 #include "ardour_ui.h"
52 #include "time_axis_view.h"
53 #include "audio_time_axis.h"
54 #include "automation_time_axis.h"
55 #include "streamview.h"
56 #include "regionview.h"
57 #include "rgb_macros.h"
58 #include "selection_templates.h"
59 #include "selection.h"
62 #include "gtk-custom-hruler.h"
67 using namespace ARDOUR;
70 using namespace Editing;
72 /***********************************************************************
74 ***********************************************************************/
77 Editor::undo (uint32_t n)
85 Editor::redo (uint32_t n)
93 Editor::set_meter_hold (int32_t cnt)
96 session->set_meter_hold (cnt);
101 Editor::set_meter_falloff (float val)
104 session->set_meter_falloff (val);
110 Editor::ensure_cursor (jack_nframes_t *pos)
112 *pos = edit_cursor->current_frame;
117 Editor::split_region ()
119 split_region_at (edit_cursor->current_frame);
123 Editor::split_region_at (jack_nframes_t where)
125 split_regions_at (where, selection->audio_regions);
129 Editor::split_regions_at (jack_nframes_t where, AudioRegionSelection& regions)
131 begin_reversible_command (_("split"));
134 for (AudioRegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
136 AudioRegionSelection::iterator tmp;
141 Playlist* pl = (*a)->region.playlist();
143 _new_regionviews_show_envelope = (*a)->envelope_visible();
146 session->add_undo (pl->get_memento());
147 pl->split_region ((*a)->region, where);
148 session->add_redo_no_execute (pl->get_memento());
154 commit_reversible_command ();
155 _new_regionviews_show_envelope = false;
159 Editor::remove_clicked_region ()
161 if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
165 Playlist* playlist = clicked_audio_trackview->playlist();
167 begin_reversible_command (_("remove region"));
168 session->add_undo (playlist->get_memento());
169 playlist->remove_region (&clicked_regionview->region);
170 session->add_redo_no_execute (playlist->get_memento());
171 commit_reversible_command ();
175 Editor::destroy_clicked_region ()
177 int32_t selected = selection->audio_regions.size();
179 if (!session || clicked_regionview == 0 && selected == 0) {
183 vector<string> choices;
186 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
187 It cannot be undone\n\
188 Do you really want to destroy %1 ?"),
190 _("these regions") : _("this region")));
193 choices.push_back (_("Yes, destroy them."));
195 choices.push_back (_("Yes, destroy it."));
198 choices.push_back (_("No, do nothing."));
200 Gtkmm2ext::Choice prompter (prompt, choices);
202 prompter.chosen.connect (ptr_fun (Main::quit));
203 prompter.show_all ();
207 if (prompter.get_choice() != 0) {
214 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
215 r.push_back (&(*i)->region);
218 session->destroy_regions (r);
220 } else if (clicked_regionview) {
221 session->destroy_region (&clicked_regionview->region);
226 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
230 jack_nframes_t start = 0;
232 if (selection->time.start () == selection->time.end_frame ()) {
234 /* no current selection-> is there a selected regionview? */
236 if (selection->audio_regions.empty()) {
244 if (!selection->audio_regions.empty()) {
246 rv = *(selection->audio_regions.begin());
247 (*tv) = &rv->get_time_axis_view();
248 region = &rv->region;
250 } else if (!selection->tracks.empty()) {
252 (*tv) = selection->tracks.front();
254 AudioTimeAxisView* atv;
256 if ((atv = dynamic_cast<AudioTimeAxisView*> (*tv)) != 0) {
259 if ((pl = atv->playlist()) == 0) {
263 region = dynamic_cast<AudioRegion*> (pl->top_region_at (start));
271 Editor::extend_selection_to_end_of_region (bool next)
275 jack_nframes_t start;
277 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
281 if (region && selection->time.start () == selection->time.end_frame ()) {
282 start = region->position();
284 start = selection->time.start ();
287 /* Try to leave the selection with the same route if possible */
289 if ((tv = selection->time.track) == 0) {
293 begin_reversible_command (_("extend selection"));
294 selection->set (tv, start, region->position() + region->length());
295 commit_reversible_command ();
299 Editor::extend_selection_to_start_of_region (bool previous)
305 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
309 if (region && selection->time.start () == selection->time.end_frame ()) {
310 end = region->position() + region->length();
312 end = selection->time.end_frame ();
315 /* Try to leave the selection with the same route if possible */
317 if ((tv = selection->time.track) == 0) {
321 begin_reversible_command (_("extend selection"));
322 selection->set (tv, region->position(), end);
323 commit_reversible_command ();
328 Editor::nudge_forward (bool next)
330 jack_nframes_t distance;
331 jack_nframes_t next_distance;
333 if (!session) return;
335 if (!selection->audio_regions.empty()) {
337 begin_reversible_command (_("nudge forward"));
339 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
340 AudioRegion& r ((*i)->region);
342 distance = get_nudge_distance (r.position(), next_distance);
345 distance = next_distance;
348 session->add_undo (r.playlist()->get_memento());
349 r.set_position (r.position() + distance, this);
350 session->add_redo_no_execute (r.playlist()->get_memento());
353 commit_reversible_command ();
356 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
357 session->request_locate (playhead_cursor->current_frame + distance);
362 Editor::nudge_backward (bool next)
364 jack_nframes_t distance;
365 jack_nframes_t next_distance;
367 if (!session) return;
369 if (!selection->audio_regions.empty()) {
371 begin_reversible_command (_("nudge forward"));
373 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
374 AudioRegion& r ((*i)->region);
376 distance = get_nudge_distance (r.position(), next_distance);
379 distance = next_distance;
382 session->add_undo (r.playlist()->get_memento());
384 if (r.position() > distance) {
385 r.set_position (r.position() - distance, this);
387 r.set_position (0, this);
389 session->add_redo_no_execute (r.playlist()->get_memento());
392 commit_reversible_command ();
396 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
398 if (playhead_cursor->current_frame > distance) {
399 session->request_locate (playhead_cursor->current_frame - distance);
401 session->request_locate (0);
407 Editor::nudge_forward_capture_offset ()
409 jack_nframes_t distance;
411 if (!session) return;
413 if (!selection->audio_regions.empty()) {
415 begin_reversible_command (_("nudge forward"));
417 distance = session->worst_output_latency();
419 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
420 AudioRegion& r ((*i)->region);
422 session->add_undo (r.playlist()->get_memento());
423 r.set_position (r.position() + distance, this);
424 session->add_redo_no_execute (r.playlist()->get_memento());
427 commit_reversible_command ();
433 Editor::nudge_backward_capture_offset ()
435 jack_nframes_t distance;
437 if (!session) return;
439 if (!selection->audio_regions.empty()) {
441 begin_reversible_command (_("nudge forward"));
443 distance = session->worst_output_latency();
445 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
446 AudioRegion& r ((*i)->region);
448 session->add_undo (r.playlist()->get_memento());
450 if (r.position() > distance) {
451 r.set_position (r.position() - distance, this);
453 r.set_position (0, this);
455 session->add_redo_no_execute (r.playlist()->get_memento());
458 commit_reversible_command ();
465 Editor::move_to_start ()
467 session->request_locate (0);
471 Editor::move_to_end ()
474 session->request_locate (session->current_end_frame());
478 Editor::build_region_boundary_cache ()
480 jack_nframes_t pos = 0;
483 TrackViewList tracks;
485 region_boundary_cache.clear ();
492 case SnapToRegionStart:
495 case SnapToRegionEnd:
498 case SnapToRegionSync:
501 case SnapToRegionBoundary:
505 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
510 TimeAxisView *ontrack = 0;
512 while (pos < session->current_end_frame()) {
514 if (!selection->tracks.empty()) {
516 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
520 } else if (clicked_trackview) {
523 t.push_back (clicked_trackview);
525 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
531 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
539 case SnapToRegionStart:
540 rpos = r->first_frame();
542 case SnapToRegionEnd:
543 rpos = r->last_frame();
545 case SnapToRegionSync:
546 rpos = r->adjust_to_sync (r->first_frame());
549 case SnapToRegionBoundary:
550 rpos = r->last_frame();
557 AudioTimeAxisView *atav;
559 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
560 if (atav->get_diskstream() != 0) {
561 speed = atav->get_diskstream()->speed();
565 rpos = track_frame_to_session_frame(rpos, speed);
567 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
568 if (snap_type == SnapToRegionBoundary) {
569 region_boundary_cache.push_back (r->first_frame());
571 region_boundary_cache.push_back (rpos);
579 Editor::find_next_region (jack_nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
581 TrackViewList::iterator i;
582 jack_nframes_t closest = max_frames;
584 jack_nframes_t rpos = 0;
587 jack_nframes_t track_frame;
588 AudioTimeAxisView *atav;
590 for (i = tracks.begin(); i != tracks.end(); ++i) {
592 jack_nframes_t distance;
596 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
597 if (atav->get_diskstream()!=0)
598 track_speed = atav->get_diskstream()->speed();
601 track_frame = session_frame_to_track_frame(frame, track_speed);
603 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
609 rpos = r->first_frame ();
613 rpos = r->last_frame ();
617 rpos = r->adjust_to_sync (r->first_frame());
620 // rpos is a "track frame", converting it to "session frame"
621 rpos = track_frame_to_session_frame(rpos, track_speed);
624 distance = rpos - frame;
626 distance = frame - rpos;
629 if (distance < closest) {
641 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
644 jack_nframes_t pos = cursor->current_frame;
650 TimeAxisView *ontrack = 0;
652 // so we don't find the current region again..
656 if (!selection->tracks.empty()) {
658 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
660 } else if (clicked_trackview) {
663 t.push_back (clicked_trackview);
665 r = find_next_region (pos, point, dir, t, &ontrack);
669 r = find_next_region (pos, point, dir, track_views, &ontrack);
678 pos = r->first_frame ();
682 pos = r->last_frame ();
686 pos = r->adjust_to_sync (r->first_frame());
691 AudioTimeAxisView *atav;
693 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
694 if (atav->get_diskstream() != 0) {
695 speed = atav->get_diskstream()->speed();
699 pos = track_frame_to_session_frame(pos, speed);
701 if (cursor == playhead_cursor) {
702 session->request_locate (pos);
704 cursor->set_position (pos);
709 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
711 cursor_to_region_point (cursor, point, 1);
715 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
717 cursor_to_region_point (cursor, point, -1);
721 Editor::cursor_to_selection_start (Cursor *cursor)
723 jack_nframes_t pos = 0;
724 switch (mouse_mode) {
726 if (!selection->audio_regions.empty()) {
727 pos = selection->audio_regions.start();
732 if (!selection->time.empty()) {
733 pos = selection->time.start ();
741 if (cursor == playhead_cursor) {
742 session->request_locate (pos);
744 cursor->set_position (pos);
749 Editor::cursor_to_selection_end (Cursor *cursor)
751 jack_nframes_t pos = 0;
753 switch (mouse_mode) {
755 if (!selection->audio_regions.empty()) {
756 pos = selection->audio_regions.end_frame();
761 if (!selection->time.empty()) {
762 pos = selection->time.end_frame ();
770 if (cursor == playhead_cursor) {
771 session->request_locate (pos);
773 cursor->set_position (pos);
778 Editor::playhead_backward ()
785 if (get_prefix (prefix, was_floating)) {
789 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
791 cnt = (jack_nframes_t) prefix;
795 pos = playhead_cursor->current_frame;
797 if ((jack_nframes_t) pos < cnt) {
803 /* XXX this is completely insane. with the current buffering
804 design, we'll force a complete track buffer flush and
805 reload, just to move 1 sample !!!
808 session->request_locate (pos);
812 Editor::playhead_forward ()
819 if (get_prefix (prefix, was_floating)) {
823 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
825 cnt = (jack_nframes_t) floor (prefix);
829 pos = playhead_cursor->current_frame;
831 /* XXX this is completely insane. with the current buffering
832 design, we'll force a complete track buffer flush and
833 reload, just to move 1 sample !!!
836 session->request_locate (pos+cnt);
840 Editor::cursor_align (bool playhead_to_edit)
842 if (playhead_to_edit) {
844 session->request_locate (edit_cursor->current_frame);
847 edit_cursor->set_position (playhead_cursor->current_frame);
852 Editor::edit_cursor_backward ()
859 if (get_prefix (prefix, was_floating)) {
863 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
865 cnt = (jack_nframes_t) prefix;
869 pos = edit_cursor->current_frame;
871 if ((jack_nframes_t) pos < cnt) {
877 edit_cursor->set_position (pos);
881 Editor::edit_cursor_forward ()
888 if (get_prefix (prefix, was_floating)) {
892 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
894 cnt = (jack_nframes_t) floor (prefix);
898 pos = edit_cursor->current_frame;
899 edit_cursor->set_position (pos+cnt);
903 Editor::goto_frame ()
907 jack_nframes_t frame;
909 if (get_prefix (prefix, was_floating)) {
914 frame = (jack_nframes_t) floor (prefix * session->frame_rate());
916 frame = (jack_nframes_t) floor (prefix);
919 session->request_locate (frame);
923 Editor::scroll_backward (float pages)
925 jack_nframes_t frame;
926 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
931 if (get_prefix (prefix, was_floating)) {
932 cnt = (jack_nframes_t) floor (pages * one_page);
935 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
937 cnt = (jack_nframes_t) floor (prefix * one_page);
941 if (leftmost_frame < cnt) {
944 frame = leftmost_frame - cnt;
947 reposition_x_origin (frame);
951 Editor::scroll_forward (float pages)
953 jack_nframes_t frame;
954 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
959 if (get_prefix (prefix, was_floating)) {
960 cnt = (jack_nframes_t) floor (pages * one_page);
963 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
965 cnt = (jack_nframes_t) floor (prefix * one_page);
969 if (ULONG_MAX - cnt < leftmost_frame) {
970 frame = ULONG_MAX - cnt;
972 frame = leftmost_frame + cnt;
975 reposition_x_origin (frame);
979 Editor::scroll_tracks_down ()
985 if (get_prefix (prefix, was_floating)) {
988 cnt = (int) floor (prefix);
991 vertical_adjustment.set_value (vertical_adjustment.get_value() + (cnt * vertical_adjustment.get_page_size()));
995 Editor::scroll_tracks_up ()
1001 if (get_prefix (prefix, was_floating)) {
1004 cnt = (int) floor (prefix);
1007 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1011 Editor::scroll_tracks_down_line ()
1013 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1014 adj->set_value (adj->get_value() + 10);
1018 Editor::scroll_tracks_up_line ()
1020 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1021 adj->set_value (adj->get_value() - 10);
1027 Editor::temporal_zoom_step (bool coarser)
1031 nfpu = frames_per_unit;
1036 nfpu = max(1.0,(nfpu/2.0));
1039 temporal_zoom (nfpu);
1043 Editor::temporal_zoom (gdouble fpu)
1045 if (!session) return;
1047 jack_nframes_t current_page = current_page_frames();
1048 jack_nframes_t current_leftmost = leftmost_frame;
1049 jack_nframes_t current_rightmost;
1050 jack_nframes_t current_center;
1051 jack_nframes_t new_page;
1052 jack_nframes_t leftmost_after_zoom = 0;
1057 new_page = (jack_nframes_t) floor (canvas_width * nfpu);
1059 switch (zoom_focus) {
1061 leftmost_after_zoom = current_leftmost;
1064 case ZoomFocusRight:
1065 current_rightmost = leftmost_frame + current_page;
1066 if (current_rightmost > new_page) {
1067 leftmost_after_zoom = current_rightmost - new_page;
1069 leftmost_after_zoom = 0;
1073 case ZoomFocusCenter:
1074 current_center = current_leftmost + (current_page/2);
1075 if (current_center > (new_page/2)) {
1076 leftmost_after_zoom = current_center - (new_page / 2);
1078 leftmost_after_zoom = 0;
1082 case ZoomFocusPlayhead:
1083 /* try to keep the playhead in the center */
1084 if (playhead_cursor->current_frame > new_page/2) {
1085 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1087 leftmost_after_zoom = 0;
1092 /* try to keep the edit cursor in the center */
1093 if (edit_cursor->current_frame > leftmost_frame + (new_page/2)) {
1094 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1096 leftmost_after_zoom = 0;
1102 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1104 // begin_reversible_command (_("zoom"));
1105 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1106 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1107 // commit_reversible_command ();
1109 reposition_and_zoom (leftmost_after_zoom, nfpu);
1113 Editor::temporal_zoom_selection ()
1115 if (!selection) return;
1117 if (selection->time.empty()) {
1121 jack_nframes_t start = selection->time[clicked_selection].start;
1122 jack_nframes_t end = selection->time[clicked_selection].end;
1124 temporal_zoom_by_frame (start, end, "zoom to selection");
1128 Editor::temporal_zoom_session ()
1131 temporal_zoom_by_frame (0, session->current_end_frame(), "zoom to session");
1136 Editor::temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, const string & op)
1138 if (!session) return;
1140 if ((start == 0 && end == 0) || end < start) {
1144 jack_nframes_t range = end - start;
1146 double new_fpu = (double)range / (double)canvas_width;
1149 // while (p2 < new_fpu) {
1154 jack_nframes_t new_page = (jack_nframes_t) floor (canvas_width * new_fpu);
1155 jack_nframes_t middle = (jack_nframes_t) floor( (double)start + ((double)range / 2.0f ));
1156 jack_nframes_t new_leftmost = (jack_nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1158 if (new_leftmost > middle) new_leftmost = 0;
1160 // begin_reversible_command (op);
1161 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1162 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1163 // commit_reversible_command ();
1165 reposition_and_zoom (new_leftmost, new_fpu);
1169 Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
1171 if (!session) return;
1173 jack_nframes_t range_before = frame - leftmost_frame;
1176 new_fpu = frames_per_unit;
1182 new_fpu = max(1.0,(new_fpu/2.0));
1186 if (new_fpu == frames_per_unit) return;
1188 jack_nframes_t new_leftmost = frame - range_before;
1190 if (new_leftmost > frame) new_leftmost = 0;
1192 // begin_reversible_command (_("zoom to frame"));
1193 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1194 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1195 // commit_reversible_command ();
1197 reposition_and_zoom (new_leftmost, new_fpu);
1201 Editor::select_all_in_track (Selection::Operation op)
1203 list<Selectable *> touched;
1205 if (!clicked_trackview) {
1209 clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1212 case Selection::Toggle:
1213 selection->add (touched);
1215 case Selection::Set:
1216 selection->set (touched);
1218 case Selection::Extend:
1219 /* not defined yet */
1225 Editor::select_all (Selection::Operation op)
1227 list<Selectable *> touched;
1229 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1230 if ((*iter)->hidden()) {
1233 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1235 begin_reversible_command (_("select all"));
1237 case Selection::Toggle:
1238 selection->add (touched);
1240 case Selection::Set:
1241 selection->set (touched);
1243 case Selection::Extend:
1244 /* not defined yet */
1247 commit_reversible_command ();
1251 Editor::invert_selection_in_track ()
1253 list<Selectable *> touched;
1255 if (!clicked_trackview) {
1259 clicked_trackview->get_inverted_selectables (*selection, touched);
1260 selection->set (touched);
1264 Editor::invert_selection ()
1266 list<Selectable *> touched;
1268 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1269 if ((*iter)->hidden()) {
1272 (*iter)->get_inverted_selectables (*selection, touched);
1275 selection->set (touched);
1279 Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, Selection::Operation op)
1281 list<Selectable *> touched;
1283 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1284 if ((*iter)->hidden()) {
1287 (*iter)->get_selectables (start, end, top, bot, touched);
1289 begin_reversible_command (_("select all within"));
1291 case Selection::Toggle:
1292 selection->add (touched);
1294 case Selection::Set:
1295 selection->set (touched);
1297 case Selection::Extend:
1298 /* not defined yet */
1301 commit_reversible_command ();
1302 return !touched.empty();
1306 Editor::set_selection_from_punch()
1310 if ((location = session->locations()->auto_punch_location()) == 0) {
1314 set_selection_from_range (*location);
1318 Editor::set_selection_from_loop()
1322 if ((location = session->locations()->auto_loop_location()) == 0) {
1325 set_selection_from_range (*location);
1329 Editor::set_selection_from_range (Location& loc)
1331 if (clicked_trackview == 0) {
1335 begin_reversible_command (_("set selection from range"));
1336 selection->set (0, loc.start(), loc.end());
1337 commit_reversible_command ();
1341 Editor::select_all_selectables_using_time_selection ()
1344 list<Selectable *> touched;
1346 if (clicked_trackview == 0) {
1350 if (selection->time.empty()) {
1354 jack_nframes_t start = selection->time[clicked_selection].start;
1355 jack_nframes_t end = selection->time[clicked_selection].end;
1357 if (end - start < 1) {
1361 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1362 if ((*iter)->hidden()) {
1365 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1367 begin_reversible_command (_("select all from range"));
1368 selection->set (touched);
1369 commit_reversible_command ();
1375 Editor::select_all_selectables_using_punch()
1377 Location* location = session->locations()->auto_punch_location();
1378 list<Selectable *> touched;
1380 if (location == 0 || (location->end() - location->start() <= 1)) {
1384 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1385 if ((*iter)->hidden()) {
1388 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1390 begin_reversible_command (_("select all from punch"));
1391 selection->set (touched);
1392 commit_reversible_command ();
1397 Editor::select_all_selectables_using_loop()
1399 Location* location = session->locations()->auto_loop_location();
1400 list<Selectable *> touched;
1402 if (location == 0 || (location->end() - location->start() <= 1)) {
1406 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1407 if ((*iter)->hidden()) {
1410 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1412 begin_reversible_command (_("select all from loop"));
1413 selection->set (touched);
1414 commit_reversible_command ();
1419 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1421 jack_nframes_t start;
1423 list<Selectable *> touched;
1426 begin_reversible_command (_("select all after cursor"));
1427 start = cursor->current_frame ;
1428 end = session->current_end_frame();
1430 if (cursor->current_frame > 0) {
1431 begin_reversible_command (_("select all before cursor"));
1433 end = cursor->current_frame - 1;
1438 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1439 if ((*iter)->hidden()) {
1442 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1444 selection->set (touched);
1445 commit_reversible_command ();
1449 Editor::amplitude_zoom_step (bool in)
1463 #ifdef FIX_FOR_CANVAS
1464 /* XXX DO SOMETHING */
1473 Editor::delete_sample_forward ()
1478 Editor::delete_sample_backward ()
1483 Editor::delete_screen ()
1490 Editor::search_backwards ()
1496 Editor::search_forwards ()
1504 Editor::jump_forward_to_mark ()
1510 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1513 session->request_locate (location->start(), session->transport_rolling());
1515 session->request_locate (session->current_end_frame());
1520 Editor::jump_backward_to_mark ()
1526 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1529 session->request_locate (location->start(), session->transport_rolling());
1531 session->request_locate (0);
1542 if (get_prefix (prefix, was_floating)) {
1543 pos = session->audible_frame ();
1546 pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
1548 pos = (jack_nframes_t) floor (prefix);
1552 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1556 Editor::clear_markers ()
1559 session->begin_reversible_command (_("clear markers"));
1560 session->add_undo (session->locations()->get_memento());
1561 session->locations()->clear_markers ();
1562 session->add_redo_no_execute (session->locations()->get_memento());
1563 session->commit_reversible_command ();
1568 Editor::clear_ranges ()
1571 session->begin_reversible_command (_("clear ranges"));
1572 session->add_undo (session->locations()->get_memento());
1574 Location * looploc = session->locations()->auto_loop_location();
1575 Location * punchloc = session->locations()->auto_punch_location();
1577 session->locations()->clear_ranges ();
1579 if (looploc) session->locations()->add (looploc);
1580 if (punchloc) session->locations()->add (punchloc);
1582 session->add_redo_no_execute (session->locations()->get_memento());
1583 session->commit_reversible_command ();
1588 Editor::clear_locations ()
1590 session->begin_reversible_command (_("clear locations"));
1591 session->add_undo (session->locations()->get_memento());
1592 session->locations()->clear ();
1593 session->add_redo_no_execute (session->locations()->get_memento());
1594 session->commit_reversible_command ();
1595 session->locations()->clear ();
1598 /* INSERT/REPLACE */
1601 Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
1606 jack_nframes_t where;
1607 AudioTimeAxisView *atv = 0;
1610 track_canvas.window_to_world (x, y, wx, wy);
1611 wx += horizontal_adjustment.get_value();
1612 wy += vertical_adjustment.get_value();
1615 event.type = GDK_BUTTON_RELEASE;
1616 event.button.x = wx;
1617 event.button.y = wy;
1619 where = event_frame (&event, &cx, &cy);
1621 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1622 /* clearly outside canvas area */
1626 if ((tv = trackview_by_y_position (cy)) == 0) {
1630 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1634 if ((playlist = atv->playlist()) == 0) {
1640 begin_reversible_command (_("insert dragged region"));
1641 session->add_undo (playlist->get_memento());
1642 playlist->add_region (*(new AudioRegion (region)), where, 1.0);
1643 session->add_redo_no_execute (playlist->get_memento());
1644 commit_reversible_command ();
1648 Editor::insert_region_list_selection (float times)
1650 AudioTimeAxisView *tv = 0;
1653 if (clicked_audio_trackview != 0) {
1654 tv = clicked_audio_trackview;
1655 } else if (!selection->tracks.empty()) {
1656 if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
1663 if ((playlist = tv->playlist()) == 0) {
1667 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1669 if (selected->count_selected_rows() != 1) {
1673 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
1674 Region* region = (*i)[region_list_columns.region];
1676 begin_reversible_command (_("insert region"));
1677 session->add_undo (playlist->get_memento());
1678 playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
1679 session->add_redo_no_execute (playlist->get_memento());
1680 commit_reversible_command ();
1684 /* BUILT-IN EFFECTS */
1687 Editor::reverse_selection ()
1692 /* GAIN ENVELOPE EDITING */
1695 Editor::edit_envelope ()
1702 Editor::toggle_playback (bool with_abort)
1708 switch (session->slave_source()) {
1713 /* transport controlled by the master */
1717 if (session->is_auditioning()) {
1718 session->cancel_audition ();
1722 if (session->transport_rolling()) {
1723 session->request_stop (with_abort);
1724 if (session->get_auto_loop()) {
1725 session->request_auto_loop (false);
1728 session->request_transport_speed (1.0f);
1733 Editor::play_from_start ()
1735 session->request_locate (0, true);
1739 Editor::play_selection ()
1741 if (selection->time.empty()) {
1745 session->request_play_range (true);
1749 Editor::play_selected_region ()
1751 if (!selection->audio_regions.empty()) {
1752 AudioRegionView *rv = *(selection->audio_regions.begin());
1754 session->request_bounded_roll (rv->region.position(), rv->region.last_frame());
1759 Editor::loop_selected_region ()
1761 if (!selection->audio_regions.empty()) {
1762 AudioRegionView *rv = *(selection->audio_regions.begin());
1765 if ((tll = transport_loop_location()) != 0) {
1767 tll->set (rv->region.position(), rv->region.last_frame());
1769 // enable looping, reposition and start rolling
1771 session->request_auto_loop (true);
1772 session->request_locate (tll->start(), false);
1773 session->request_transport_speed (1.0f);
1779 Editor::play_location (Location& location)
1781 if (location.start() <= location.end()) {
1785 session->request_bounded_roll (location.start(), location.end());
1789 Editor::loop_location (Location& location)
1791 if (location.start() <= location.end()) {
1797 if ((tll = transport_loop_location()) != 0) {
1798 tll->set (location.start(), location.end());
1800 // enable looping, reposition and start rolling
1801 session->request_auto_loop (true);
1802 session->request_locate (tll->start(), true);
1807 Editor::toggle_region_mute ()
1809 if (clicked_regionview) {
1810 clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
1811 } else if (!selection->audio_regions.empty()) {
1812 bool yn = ! (*selection->audio_regions.begin())->region.muted();
1813 selection->foreach_audio_region (&AudioRegion::set_muted, yn);
1818 Editor::toggle_region_opaque ()
1820 if (clicked_regionview) {
1821 clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
1822 } else if (!selection->audio_regions.empty()) {
1823 bool yn = ! (*selection->audio_regions.begin())->region.opaque();
1824 selection->foreach_audio_region (&Region::set_opaque, yn);
1829 Editor::raise_region ()
1831 selection->foreach_audio_region (&Region::raise);
1835 Editor::raise_region_to_top ()
1837 selection->foreach_audio_region (&Region::raise_to_top);
1841 Editor::lower_region ()
1843 selection->foreach_audio_region (&Region::lower);
1847 Editor::lower_region_to_bottom ()
1849 selection->foreach_audio_region (&Region::lower_to_bottom);
1853 Editor::edit_region ()
1855 if (clicked_regionview == 0) {
1859 clicked_regionview->show_region_editor ();
1863 Editor::rename_region ()
1867 Button ok_button (_("OK"));
1868 Button cancel_button (_("Cancel"));
1870 if (selection->audio_regions.empty()) {
1874 dialog.set_title (_("ardour: rename region"));
1875 dialog.set_name ("RegionRenameWindow");
1876 dialog.set_size_request (300, -1);
1877 dialog.set_position (Gtk::WIN_POS_MOUSE);
1878 dialog.set_modal (true);
1880 dialog.get_vbox()->set_border_width (10);
1881 dialog.get_vbox()->pack_start (entry);
1882 dialog.get_action_area()->pack_start (ok_button);
1883 dialog.get_action_area()->pack_start (cancel_button);
1885 entry.set_name ("RegionNameDisplay");
1886 ok_button.set_name ("EditorGTKButton");
1887 cancel_button.set_name ("EditorGTKButton");
1889 region_renamed = false;
1891 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1892 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1893 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
1900 if (region_renamed) {
1901 (*selection->audio_regions.begin())->region.set_name (entry.get_text());
1902 redisplay_regions ();
1907 Editor::rename_region_finished (bool status)
1910 region_renamed = status;
1915 Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
1917 if (session->is_auditioning()) {
1918 session->cancel_audition ();
1921 // note: some potential for creativity here, because region doesn't
1922 // have to belong to the playlist that Route is handling
1924 // bool was_soloed = route.soloed();
1926 route.set_solo (true, this);
1928 session->request_bounded_roll (region.position(), region.position() + region.length());
1930 /* XXX how to unset the solo state ? */
1934 Editor::audition_selected_region ()
1936 if (!selection->audio_regions.empty()) {
1937 AudioRegionView* rv = *(selection->audio_regions.begin());
1938 session->audition_region (rv->region);
1943 Editor::audition_playlist_region_standalone (AudioRegion& region)
1945 session->audition_region (region);
1949 Editor::build_interthread_progress_window ()
1951 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
1953 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
1955 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
1956 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
1958 // GTK2FIX: this button needs a modifiable label
1960 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1961 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
1963 interthread_cancel_button.add (interthread_cancel_label);
1965 interthread_progress_window->set_default_size (200, 100);
1969 Editor::interthread_cancel_clicked ()
1971 if (current_interthread_info) {
1972 current_interthread_info->cancel = true;
1977 Editor::_import_thread (void *arg)
1979 PBD::ThreadCreated (pthread_self(), X_("Import"));
1981 Editor *ed = (Editor *) arg;
1982 return ed->import_thread ();
1986 Editor::import_thread ()
1988 session->import_audiofile (import_status);
1993 Editor::import_progress_timeout (void *arg)
1995 interthread_progress_label.set_text (import_status.doing_what);
1997 if (import_status.freeze) {
1998 interthread_cancel_button.set_sensitive(false);
2000 interthread_cancel_button.set_sensitive(true);
2003 if (import_status.doing_what == "building peak files") {
2004 interthread_progress_bar.pulse ();
2007 interthread_progress_bar.set_fraction (import_status.progress/100);
2010 return !(import_status.done || import_status.cancel);
2014 Editor::import_audio (bool as_tracks)
2017 warning << _("You can't import an audiofile until you have a session loaded.") << endmsg;
2024 str =_("Import selected as tracks");
2026 str = _("Import selected to region list");
2029 SoundFileOmega sfdb (str);
2030 sfdb.Imported.connect (bind (mem_fun (*this, &Editor::do_import), as_tracks));
2036 Editor::catch_new_audio_region (AudioRegion* ar)
2038 last_audio_region = ar;
2042 Editor::do_import (vector<string> paths, bool split, bool as_tracks)
2046 /* SFDB sets "multichan" to true to indicate "split channels"
2047 so reverse the setting to match the way libardour
2051 import_status.multichan = !split;
2053 if (interthread_progress_window == 0) {
2054 build_interthread_progress_window ();
2057 interthread_progress_window->set_title (_("ardour: audio import in progress"));
2058 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2059 interthread_progress_window->show_all ();
2060 interthread_progress_bar.set_fraction (0.0f);
2061 interthread_cancel_label.set_text (_("Cancel Import"));
2062 current_interthread_info = &import_status;
2064 c = session->AudioRegionAdded.connect (mem_fun(*this, &Editor::catch_new_audio_region));
2066 for (vector<string>::iterator i = paths.begin(); i != paths.end(); ++i ) {
2068 interthread_progress_window->set_title (string_compose (_("ardour: importing %1"), (*i)));
2070 import_status.pathname = (*i);
2071 import_status.done = false;
2072 import_status.cancel = false;
2073 import_status.freeze = false;
2074 import_status.done = 0.0;
2076 interthread_progress_connection =
2077 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::import_progress_timeout), (gpointer) 0), 100);
2079 last_audio_region = 0;
2081 pthread_create_and_store ("import", &import_status.thread, 0, _import_thread, this);
2082 pthread_detach (import_status.thread);
2084 while (!(import_status.done || import_status.cancel)) {
2085 gtk_main_iteration ();
2088 import_status.done = true;
2089 interthread_progress_connection.disconnect ();
2091 if (as_tracks && last_audio_region != 0) {
2092 uint32_t channels = last_audio_region->n_channels();
2094 AudioTrack* at = session->new_audio_track (channels, channels);
2095 AudioRegion* copy = new AudioRegion (*last_audio_region);
2096 at->disk_stream().playlist()->add_region (*copy, 0);
2101 interthread_progress_window->hide_all ();
2105 Editor::reject_because_rate_differs (const string & path, SoundFileInfo& finfo, const string & action, bool multiple_pending)
2111 if (finfo.samplerate != (int) session->frame_rate()) {
2112 vector<string> choices;
2114 choices.push_back (string_compose (_("%1 it anyway"), action));
2116 if (multiple_pending) {
2117 /* XXX assumptions about sentence structure
2118 here for translators. Sorry.
2120 choices.push_back (string_compose (_("Don't %1 it"), action));
2121 choices.push_back (string_compose (_("%1 all without questions"), action));
2122 choices.push_back (_("Cancel entire import"));
2124 choices.push_back (_("Cancel"));
2127 Gtkmm2ext::Choice rate_choice (
2128 string_compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path),
2131 rate_choice.chosen.connect (ptr_fun (Main::quit));
2132 rate_choice.show_all ();
2136 switch (rate_choice.get_choice()) {
2137 case 0: /* do it anyway */
2139 case 1: /* don't import this one */
2141 case 2: /* do the rest without asking */
2143 case 3: /* stop a multi-file import */
2153 Editor::embed_audio ()
2156 warning << _("You can't embed an audiofile until you have a session loaded.") << endmsg;
2160 SoundFileOmega sfdb (_("Add to External Region list"));
2161 sfdb.Embedded.connect (mem_fun (*this, &Editor::do_embed_sndfiles));
2167 Editor::do_embed_sndfiles (vector<string> paths, bool split)
2169 bool multiple_files = paths.size() > 1;
2170 bool check_sample_rate = true;
2172 for (vector<string>::iterator i = paths.begin(); i != paths.end(); ++i) {
2173 embed_sndfile (*i, split, multiple_files, check_sample_rate);
2176 session->save_state ("");
2180 Editor::embed_sndfile (string path, bool split, bool multiple_files, bool& check_sample_rate)
2182 ExternalSource *source = 0; /* keep g++ quiet */
2183 AudioRegion::SourceList sources;
2186 SoundFileInfo finfo;
2188 /* lets see if we can link it into the session */
2190 linked_path = session->sound_dir();
2191 linked_path += PBD::basename (path);
2193 if (link (path.c_str(), linked_path.c_str()) == 0) {
2195 /* there are many reasons why link(2) might have failed.
2196 but if it succeeds, we now have a link in the
2197 session sound dir that will protect against
2198 unlinking of the original path. nice.
2204 /* note that we temporarily truncated _id at the colon */
2206 if (!ExternalSource::get_soundfile_info (path, finfo, error_msg)) {
2207 error << string_compose(_("Editor: cannot open file \"%1\", (%2)"), selection, error_msg ) << endmsg;
2211 if (check_sample_rate) {
2212 switch (reject_because_rate_differs (path, finfo, "Embed", multiple_files)) {
2218 check_sample_rate = false;
2227 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2228 ARDOUR_UI::instance()->flush_pending ();
2230 /* make the proper number of channels in the region */
2232 for (int n=0; n < finfo.channels; ++n)
2235 idspec += string_compose(":%1", n);
2238 source = ExternalSource::create (idspec.c_str());
2239 sources.push_back(source);
2242 catch (failed_constructor& err) {
2243 error << string_compose(_("could not open %1"), path) << endmsg;
2247 ARDOUR_UI::instance()->flush_pending ();
2250 if (sources.size() > 0) {
2252 string region_name = PBD::basename_nosuffix (path);
2253 region_name += "-0";
2255 /* The created region isn't dropped. It emits a signal
2256 that is picked up by the session.
2259 new AudioRegion (sources, 0, sources[0]->length(), region_name, 0,
2260 Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External));
2262 /* make sure we can see it in the list */
2264 /* its the second node, always */
2266 // GTK2FIX ?? is it still always the 2nd node
2268 TreeModel::Path path ("2");
2269 region_list_display.expand_row (path, true);
2271 ARDOUR_UI::instance()->flush_pending ();
2275 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2279 Editor::insert_sndfile (bool as_tracks)
2281 // SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window());
2287 // c = sfdb.Action.connect (mem_fun(*this, &Editor::insert_paths_as_new_tracks));
2288 str = _("Insert selected as new tracks");
2294 if (clicked_audio_trackview == 0) {
2298 if (ensure_cursor (&pos)) {
2302 // c = sfdb.Action.connect (bind (mem_fun(*this, &Editor::do_insert_sndfile), pos));
2303 str = _("Insert selected");
2306 // sfdb.run (str, false);
2311 Editor::insert_paths_as_new_tracks (vector<string> paths, bool split)
2313 SoundFileInfo finfo;
2314 bool multiple_files;
2315 bool check_sample_rate = true;
2318 multiple_files = paths.size() > 1;
2320 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
2322 if (!ExternalSource::get_soundfile_info((*p), finfo, error_msg)) {
2323 error << string_compose(_("Editor: cannot open file \"%1\" (%2)"), (*p), error_msg) << endmsg;
2327 /* add a new track */
2329 if (check_sample_rate) {
2330 switch (reject_because_rate_differs (*p, finfo, "Insert", multiple_files)) {
2336 check_sample_rate = false;
2344 uint32_t input_chan = finfo.channels;
2345 uint32_t output_chan;
2347 if (session->get_output_auto_connect() & Session::AutoConnectMaster) {
2348 output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan);
2350 output_chan = input_chan;
2353 (void) session->new_audio_track (input_chan, output_chan);
2356 /* get the last (most recently added) track view */
2358 AudioTimeAxisView* tv;
2360 if ((tv = dynamic_cast<AudioTimeAxisView*>(track_views.back())) == 0) {
2361 fatal << _("programming error: ")
2362 << X_("last trackview after new_audio_track is not an audio track!")
2367 jack_nframes_t pos = 0;
2368 insert_sndfile_into (*p, true, tv, pos, false);
2373 Editor::do_insert_sndfile (vector<string> paths, bool split, jack_nframes_t pos)
2375 for (vector<string>::iterator x = paths.begin(); x != paths.end(); ++x) {
2376 insert_sndfile_into (*x, !split, clicked_audio_trackview, pos);
2381 Editor::insert_sndfile_into (const string & path, bool multi, AudioTimeAxisView* tv, jack_nframes_t& pos, bool prompt)
2383 ExternalSource *source = 0; /* keep g++ quiet */
2384 AudioRegion::SourceList sources;
2386 SoundFileInfo finfo;
2389 /* note that we temporarily truncated _id at the colon */
2391 if (!ExternalSource::get_soundfile_info (path, finfo, error_msg)) {
2392 error << string_compose(_("Editor: cannot open file \"%1\" (%2)"), path, error_msg) << endmsg;
2396 if (prompt && (reject_because_rate_differs (path, finfo, "Insert", false) != 0)) {
2400 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2401 ARDOUR_UI::instance()->flush_pending ();
2403 /* make the proper number of channels in the region */
2405 for (int n=0; n < finfo.channels; ++n)
2408 idspec += string_compose(":%1", n);
2411 source = ExternalSource::create (idspec.c_str());
2412 sources.push_back(source);
2415 catch (failed_constructor& err) {
2416 error << string_compose(_("could not open %1"), path) << endmsg;
2420 ARDOUR_UI::instance()->flush_pending ();
2423 if (sources.size() > 0) {
2425 string region_name = region_name_from_path (PBD::basename (path));
2427 AudioRegion *region = new AudioRegion (sources, 0, sources[0]->length(), region_name,
2428 0, /* irrelevant these days */
2429 Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External));
2431 begin_reversible_command (_("insert sndfile"));
2432 session->add_undo (tv->playlist()->get_memento());
2433 tv->playlist()->add_region (*region, pos);
2434 session->add_redo_no_execute (tv->playlist()->get_memento());
2435 commit_reversible_command ();
2437 pos += sources[0]->length();
2439 ARDOUR_UI::instance()->flush_pending ();
2443 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2448 Editor::region_from_selection ()
2450 if (clicked_trackview == 0) {
2454 if (selection->time.empty()) {
2458 jack_nframes_t start = selection->time[clicked_selection].start;
2459 jack_nframes_t end = selection->time[clicked_selection].end;
2461 jack_nframes_t selection_cnt = end - start + 1;
2463 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2465 AudioRegion *region;
2466 AudioRegion *current;
2470 jack_nframes_t internal_start;
2473 if ((pl = (*i)->playlist()) == 0) {
2477 if ((current_r = pl->top_region_at (start)) == 0) {
2481 if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
2482 internal_start = start - current->position();
2483 session->region_name (new_name, current->name(), true);
2484 region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
2490 Editor::create_region_from_selection (vector<AudioRegion *>& new_regions)
2492 if (selection->time.empty() || selection->tracks.empty()) {
2496 jack_nframes_t start = selection->time[clicked_selection].start;
2497 jack_nframes_t end = selection->time[clicked_selection].end;
2499 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2501 AudioRegion* current;
2504 jack_nframes_t internal_start;
2507 if ((playlist = (*i)->playlist()) == 0) {
2511 if ((current_r = playlist->top_region_at(start)) == 0) {
2515 if ((current = dynamic_cast<AudioRegion*>(current_r)) == 0) {
2519 internal_start = start - current->position();
2520 session->region_name (new_name, current->name(), true);
2522 new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name));
2527 Editor::split_multichannel_region ()
2529 vector<AudioRegion*> v;
2531 if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
2535 clicked_regionview->region.separate_by_channel (*session, v);
2537 /* nothing else to do, really */
2541 Editor::new_region_from_selection ()
2543 region_from_selection ();
2544 cancel_selection ();
2548 Editor::separate_region_from_selection ()
2550 bool doing_undo = false;
2552 if (selection->time.empty()) {
2558 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2560 AudioTimeAxisView* atv;
2562 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2564 if (atv->is_audio_track()) {
2566 if ((playlist = atv->playlist()) != 0) {
2568 begin_reversible_command (_("separate"));
2571 if (doing_undo) session->add_undo ((playlist)->get_memento());
2573 /* XXX need to consider musical time selections here at some point */
2575 double speed = atv->get_diskstream()->speed();
2577 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2578 playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
2581 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2587 if (doing_undo) commit_reversible_command ();
2591 Editor::crop_region_to_selection ()
2593 if (selection->time.empty()) {
2597 vector<Playlist*> playlists;
2600 if (clicked_trackview != 0) {
2602 if ((playlist = clicked_trackview->playlist()) == 0) {
2606 playlists.push_back (playlist);
2610 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2612 AudioTimeAxisView* atv;
2614 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2616 if (atv->is_audio_track()) {
2618 if ((playlist = atv->playlist()) != 0) {
2619 playlists.push_back (playlist);
2626 if (!playlists.empty()) {
2628 jack_nframes_t start;
2632 begin_reversible_command (_("trim to selection"));
2634 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2638 start = selection->time.start();
2640 if ((region = (*i)->top_region_at(start)) == 0) {
2644 /* now adjust lengths to that we do the right thing
2645 if the selection extends beyond the region
2648 start = max (start, region->position());
2649 end = min (selection->time.end_frame(), start + region->length() - 1);
2650 cnt = end - start + 1;
2652 session->add_undo ((*i)->get_memento());
2653 region->trim_to (start, cnt, this);
2654 session->add_redo_no_execute ((*i)->get_memento());
2657 commit_reversible_command ();
2662 Editor::region_fill_track ()
2666 if (!session || selection->audio_regions.empty()) {
2670 end = session->current_end_frame ();
2672 begin_reversible_command (_("region fill"));
2674 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2676 AudioRegion& region ((*i)->region);
2677 Playlist* pl = region.playlist();
2679 if (end <= region.last_frame()) {
2683 double times = (double) (end - region.last_frame()) / (double) region.length();
2689 session->add_undo (pl->get_memento());
2690 pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
2691 session->add_redo_no_execute (pl->get_memento());
2694 commit_reversible_command ();
2698 Editor::region_fill_selection ()
2700 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2704 if (selection->time.empty()) {
2710 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2712 if (selected->count_selected_rows() != 1) {
2716 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2717 region = (*i)[region_list_columns.region];
2719 jack_nframes_t start = selection->time[clicked_selection].start;
2720 jack_nframes_t end = selection->time[clicked_selection].end;
2724 if (selection->tracks.empty()) {
2728 jack_nframes_t selection_length = end - start;
2729 float times = (float)selection_length / region->length();
2731 begin_reversible_command (_("fill selection"));
2733 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2735 if ((playlist = (*i)->playlist()) == 0) {
2739 session->add_undo (playlist->get_memento());
2740 playlist->add_region (*(createRegion (*region)), start, times);
2741 session->add_redo_no_execute (playlist->get_memento());
2744 commit_reversible_command ();
2748 Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
2751 if (!region.covers (position)) {
2752 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2755 begin_reversible_command (_("set region sync position"));
2756 session->add_undo (region.playlist()->get_memento());
2757 region.set_sync_position (position);
2758 session->add_redo_no_execute (region.playlist()->get_memento());
2759 commit_reversible_command ();
2763 Editor::set_region_sync_from_edit_cursor ()
2765 if (clicked_regionview == 0) {
2769 if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
2770 error << _("Place the edit cursor at the desired sync point") << endmsg;
2774 Region& region (clicked_regionview->region);
2775 begin_reversible_command (_("set sync from edit cursor"));
2776 session->add_undo (region.playlist()->get_memento());
2777 region.set_sync_position (edit_cursor->current_frame);
2778 session->add_redo_no_execute (region.playlist()->get_memento());
2779 commit_reversible_command ();
2783 Editor::remove_region_sync ()
2785 if (clicked_regionview) {
2786 Region& region (clicked_regionview->region);
2787 begin_reversible_command (_("remove sync"));
2788 session->add_undo (region.playlist()->get_memento());
2789 region.clear_sync_position ();
2790 session->add_redo_no_execute (region.playlist()->get_memento());
2791 commit_reversible_command ();
2796 Editor::naturalize ()
2798 if (selection->audio_regions.empty()) {
2801 begin_reversible_command (_("naturalize"));
2802 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2803 session->add_undo ((*i)->region.get_memento());
2804 (*i)->region.move_to_natural_position (this);
2805 session->add_redo_no_execute ((*i)->region.get_memento());
2807 commit_reversible_command ();
2811 Editor::align (RegionPoint what)
2813 align_selection (what, edit_cursor->current_frame);
2817 Editor::align_relative (RegionPoint what)
2819 align_selection_relative (what, edit_cursor->current_frame);
2822 struct RegionSortByTime {
2823 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2824 return a->region.position() < b->region.position();
2829 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
2831 if (selection->audio_regions.empty()) {
2835 jack_nframes_t distance;
2836 jack_nframes_t pos = 0;
2839 list<AudioRegionView*> sorted;
2840 selection->audio_regions.by_position (sorted);
2841 Region& r ((*sorted.begin())->region);
2845 pos = r.first_frame ();
2849 pos = r.last_frame();
2853 pos = r.adjust_to_sync (r.first_frame());
2857 if (pos > position) {
2858 distance = pos - position;
2861 distance = position - pos;
2865 begin_reversible_command (_("align selection (relative)"));
2867 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2869 Region& region ((*i)->region);
2871 session->add_undo (region.playlist()->get_memento());
2874 region.set_position (region.position() + distance, this);
2876 region.set_position (region.position() - distance, this);
2879 session->add_redo_no_execute (region.playlist()->get_memento());
2883 commit_reversible_command ();
2887 Editor::align_selection (RegionPoint point, jack_nframes_t position)
2889 if (selection->audio_regions.empty()) {
2893 begin_reversible_command (_("align selection"));
2895 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2896 align_region_internal ((*i)->region, point, position);
2899 commit_reversible_command ();
2903 Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position)
2905 begin_reversible_command (_("align region"));
2906 align_region_internal (region, point, position);
2907 commit_reversible_command ();
2911 Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
2913 session->add_undo (region.playlist()->get_memento());
2917 region.set_position (region.adjust_to_sync (position), this);
2921 if (position > region.length()) {
2922 region.set_position (position - region.length(), this);
2927 region.set_position (position, this);
2931 session->add_redo_no_execute (region.playlist()->get_memento());
2935 Editor::trim_region_to_edit_cursor ()
2937 if (clicked_regionview == 0) {
2941 Region& region (clicked_regionview->region);
2944 AudioTimeAxisView *atav;
2946 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2947 if (atav->get_diskstream() != 0) {
2948 speed = atav->get_diskstream()->speed();
2952 begin_reversible_command (_("trim to edit"));
2953 session->add_undo (region.playlist()->get_memento());
2954 region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2955 session->add_redo_no_execute (region.playlist()->get_memento());
2956 commit_reversible_command ();
2960 Editor::trim_region_from_edit_cursor ()
2962 if (clicked_regionview == 0) {
2966 Region& region (clicked_regionview->region);
2969 AudioTimeAxisView *atav;
2971 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2972 if (atav->get_diskstream() != 0) {
2973 speed = atav->get_diskstream()->speed();
2977 begin_reversible_command (_("trim to edit"));
2978 session->add_undo (region.playlist()->get_memento());
2979 region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2980 session->add_redo_no_execute (region.playlist()->get_memento());
2981 commit_reversible_command ();
2985 Editor::unfreeze_route ()
2987 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2991 clicked_audio_trackview->audio_track()->unfreeze ();
2995 Editor::_freeze_thread (void* arg)
2997 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2998 return static_cast<Editor*>(arg)->freeze_thread ();
3002 Editor::freeze_thread ()
3004 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
3009 Editor::freeze_progress_timeout (void *arg)
3011 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
3012 return !(current_interthread_info->done || current_interthread_info->cancel);
3016 Editor::freeze_route ()
3018 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
3022 InterThreadInfo itt;
3024 if (interthread_progress_window == 0) {
3025 build_interthread_progress_window ();
3028 interthread_progress_window->set_title (_("ardour: freeze"));
3029 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
3030 interthread_progress_window->show_all ();
3031 interthread_progress_bar.set_fraction (0.0f);
3032 interthread_progress_label.set_text ("");
3033 interthread_cancel_label.set_text (_("Cancel Freeze"));
3034 current_interthread_info = &itt;
3036 interthread_progress_connection =
3037 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
3041 itt.progress = 0.0f;
3043 pthread_create (&itt.thread, 0, _freeze_thread, this);
3045 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
3047 while (!itt.done && !itt.cancel) {
3048 gtk_main_iteration ();
3051 interthread_progress_connection.disconnect ();
3052 interthread_progress_window->hide_all ();
3053 current_interthread_info = 0;
3054 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3058 Editor::bounce_range_selection ()
3060 if (selection->time.empty()) {
3064 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
3066 jack_nframes_t start = selection->time[clicked_selection].start;
3067 jack_nframes_t end = selection->time[clicked_selection].end;
3068 jack_nframes_t cnt = end - start + 1;
3070 begin_reversible_command (_("bounce range"));
3072 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
3074 AudioTimeAxisView* atv;
3076 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
3082 if ((playlist = atv->playlist()) == 0) {
3086 InterThreadInfo itt;
3090 itt.progress = false;
3092 session->add_undo (playlist->get_memento());
3093 atv->audio_track()->bounce_range (start, cnt, itt);
3094 session->add_redo_no_execute (playlist->get_memento());
3097 commit_reversible_command ();
3115 Editor::cut_copy (CutCopyOp op)
3117 /* only cancel selection if cut/copy is successful.*/
3129 opname = _("clear");
3133 cut_buffer->clear ();
3135 switch (current_mouse_mode()) {
3137 if (!selection->audio_regions.empty() || !selection->points.empty()) {
3139 begin_reversible_command (opname + _(" objects"));
3141 if (!selection->audio_regions.empty()) {
3143 cut_copy_regions (op);
3146 selection->clear_audio_regions ();
3150 if (!selection->points.empty()) {
3151 cut_copy_points (op);
3154 selection->clear_points ();
3158 commit_reversible_command ();
3163 if (!selection->time.empty()) {
3165 begin_reversible_command (opname + _(" range"));
3166 cut_copy_ranges (op);
3167 commit_reversible_command ();
3170 selection->clear_time ();
3182 Editor::cut_copy_points (CutCopyOp op)
3184 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3186 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3189 atv->cut_copy_clear_objects (selection->points, op);
3195 Editor::cut_copy_regions (CutCopyOp op)
3197 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
3198 PlaylistMapping pmap;
3199 jack_nframes_t first_position = max_frames;
3200 set<Playlist*> freezelist;
3201 pair<set<Playlist*>::iterator,bool> insert_result;
3203 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
3204 first_position = min ((*x)->region.position(), first_position);
3206 if (op == Cut || op == Clear) {
3207 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
3209 insert_result = freezelist.insert (pl);
3210 if (insert_result.second) {
3212 session->add_undo (pl->get_memento());
3218 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
3220 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
3222 AudioRegionSelection::iterator tmp;
3229 PlaylistMapping::iterator pi = pmap.find (pl);
3231 if (pi == pmap.end()) {
3232 npl = new AudioPlaylist (*session, "cutlist", true);
3241 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
3242 pl->remove_region (&((*x)->region));
3246 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
3250 pl->remove_region (&((*x)->region));
3258 list<Playlist*> foo;
3260 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
3261 foo.push_back (i->second);
3265 cut_buffer->set (foo);
3268 for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
3270 session->add_redo_no_execute ((*pl)->get_memento());
3275 Editor::cut_copy_ranges (CutCopyOp op)
3277 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3278 (*i)->cut_copy_clear (*selection, op);
3283 Editor::paste (float times)
3285 paste_internal (edit_cursor->current_frame, times);
3289 Editor::mouse_paste ()
3294 track_canvas.get_pointer (x, y);
3295 track_canvas.window_to_world (x, y, wx, wy);
3296 wx += horizontal_adjustment.get_value();
3297 wy += vertical_adjustment.get_value();
3300 event.type = GDK_BUTTON_RELEASE;
3301 event.button.x = wx;
3302 event.button.y = wy;
3304 jack_nframes_t where = event_frame (&event, 0, 0);
3306 paste_internal (where, 1);
3310 Editor::paste_internal (jack_nframes_t position, float times)
3312 bool commit = false;
3314 if (cut_buffer->empty() || selection->tracks.empty()) {
3318 if (position == max_frames) {
3319 position = edit_cursor->current_frame;
3322 begin_reversible_command (_("paste"));
3324 TrackSelection::iterator i;
3327 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
3329 /* undo/redo is handled by individual tracks */
3331 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3337 commit_reversible_command ();
3342 Editor::paste_named_selection (float times)
3344 TrackSelection::iterator t;
3346 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3348 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3352 TreeModel::iterator i = selected->get_selected();
3353 NamedSelection* ns = (*i)[named_selection_columns.selection];
3355 list<Playlist*>::iterator chunk;
3356 list<Playlist*>::iterator tmp;
3358 chunk = ns->playlists.begin();
3360 begin_reversible_command (_("paste chunk"));
3362 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3364 AudioTimeAxisView* atv;
3368 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3372 if ((pl = atv->playlist()) == 0) {
3376 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
3383 session->add_undo (apl->get_memento());
3384 apl->paste (**chunk, edit_cursor->current_frame, times);
3385 session->add_redo_no_execute (apl->get_memento());
3387 if (tmp != ns->playlists.end()) {
3392 commit_reversible_command();
3396 Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
3399 AudioRegionSelection sel = regions; // clear (below) will clear the argument list
3401 begin_reversible_command (_("duplicate region"));
3403 selection->clear_audio_regions ();
3405 for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3407 Region& r ((*i)->region);
3409 TimeAxisView& tv = (*i)->get_time_axis_view();
3410 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3411 sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3413 playlist = (*i)->region.playlist();
3414 session->add_undo (playlist->get_memento());
3415 playlist->duplicate (r, r.last_frame(), times);
3416 session->add_redo_no_execute (playlist->get_memento());
3420 if (latest_regionview) {
3421 selection->add (latest_regionview);
3426 commit_reversible_command ();
3430 Editor::duplicate_selection (float times)
3432 if (selection->time.empty() || selection->tracks.empty()) {
3437 vector<AudioRegion*> new_regions;
3438 vector<AudioRegion*>::iterator ri;
3440 create_region_from_selection (new_regions);
3442 if (new_regions.empty()) {
3446 begin_reversible_command (_("duplicate selection"));
3448 ri = new_regions.begin();
3450 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3451 if ((playlist = (*i)->playlist()) == 0) {
3454 session->add_undo (playlist->get_memento());
3455 playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
3456 session->add_redo_no_execute (playlist->get_memento());
3459 if (ri == new_regions.end()) {
3464 commit_reversible_command ();
3468 Editor::center_playhead ()
3470 float page = canvas_width * frames_per_unit;
3472 center_screen_internal (playhead_cursor->current_frame, page);
3476 Editor::center_edit_cursor ()
3478 float page = canvas_width * frames_per_unit;
3480 center_screen_internal (edit_cursor->current_frame, page);
3484 Editor::clear_playlist (Playlist& playlist)
3486 begin_reversible_command (_("clear playlist"));
3487 session->add_undo (playlist.get_memento());
3489 session->add_redo_no_execute (playlist.get_memento());
3490 commit_reversible_command ();
3494 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3497 jack_nframes_t distance;
3498 jack_nframes_t next_distance;
3499 jack_nframes_t start;
3501 if (use_edit_cursor) {
3502 start = edit_cursor->current_frame;
3507 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3511 if (selection->tracks.empty()) {
3515 begin_reversible_command (_("nudge track"));
3517 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3519 if ((playlist = (*i)->playlist()) == 0) {
3523 session->add_undo (playlist->get_memento());
3524 playlist->nudge_after (start, distance, forwards);
3525 session->add_redo_no_execute (playlist->get_memento());
3528 commit_reversible_command ();
3532 Editor::toggle_xfades_active ()
3535 session->set_crossfades_active (!session->get_crossfades_active());
3540 Editor::set_xfade_visibility (bool yn)
3546 Editor::toggle_xfade_visibility ()
3548 set_xfade_visibility (!xfade_visibility());
3552 Editor::remove_last_capture ()
3554 vector<string> choices;
3561 if (Config->get_verify_remove_last_capture()) {
3562 prompt = _("Do you really want to destroy the last capture?"
3563 "\n(This is destructive and cannot be undone)");
3565 choices.push_back (_("Yes, destroy it."));
3566 choices.push_back (_("No, do nothing."));
3568 Gtkmm2ext::Choice prompter (prompt, choices);
3569 prompter.chosen.connect (ptr_fun (Main::quit));
3570 prompter.show_all ();
3574 if (prompter.get_choice() == 0) {
3575 session->remove_last_capture ();
3579 session->remove_last_capture();
3584 Editor::normalize_region ()
3590 if (selection->audio_regions.empty()) {
3594 begin_reversible_command (_("normalize"));
3596 track_canvas.get_window()->set_cursor (*wait_cursor);
3599 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3600 session->add_undo ((*r)->region.get_memento());
3601 (*r)->region.normalize_to (0.0f);
3602 session->add_redo_no_execute ((*r)->region.get_memento());
3605 commit_reversible_command ();
3606 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3611 Editor::denormalize_region ()
3617 if (selection->audio_regions.empty()) {
3621 begin_reversible_command ("denormalize");
3623 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3624 session->add_undo ((*r)->region.get_memento());
3625 (*r)->region.set_scale_amplitude (1.0f);
3626 session->add_redo_no_execute ((*r)->region.get_memento());
3629 commit_reversible_command ();
3634 Editor::reverse_region ()
3640 Reverse rev (*session);
3641 apply_filter (rev, _("reverse regions"));
3645 Editor::apply_filter (AudioFilter& filter, string command)
3647 if (selection->audio_regions.empty()) {
3651 begin_reversible_command (command);
3653 track_canvas.get_window()->set_cursor (*wait_cursor);
3656 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
3658 AudioRegion& region ((*r)->region);
3659 Playlist* playlist = region.playlist();
3661 AudioRegionSelection::iterator tmp;
3666 if (region.apply (filter) == 0) {
3668 session->add_undo (playlist->get_memento());
3669 playlist->replace_region (region, *(filter.results.front()), region.position());
3670 session->add_redo_no_execute (playlist->get_memento());
3678 commit_reversible_command ();
3679 selection->audio_regions.clear ();
3682 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3686 Editor::region_selection_op (void (Region::*pmf)(void))
3688 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3689 ((*i)->region.*pmf)();
3695 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3697 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3698 ((*i)->region.*pmf)(arg);
3703 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3705 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3706 ((*i)->region.*pmf)(yn);
3711 Editor::external_edit_region ()
3713 if (!clicked_regionview) {
3721 Editor::brush (jack_nframes_t pos)
3723 AudioRegionSelection sel;
3726 if (selection->audio_regions.empty()) {
3727 /* XXX get selection from region list */
3729 sel = selection->audio_regions;
3736 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3737 mouse_brush_insert_region ((*i), pos);
3742 Editor::toggle_gain_envelope_visibility ()
3744 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3745 (*i)->set_envelope_visible (!(*i)->envelope_visible());
3750 Editor::toggle_gain_envelope_active ()
3752 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3753 AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
3755 ar->set_envelope_active (true);