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 if (prompter.run() != 0) { /* first choice */
209 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
210 r.push_back (&(*i)->region);
213 session->destroy_regions (r);
215 } else if (clicked_regionview) {
216 session->destroy_region (&clicked_regionview->region);
221 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
225 jack_nframes_t start = 0;
227 if (selection->time.start () == selection->time.end_frame ()) {
229 /* no current selection-> is there a selected regionview? */
231 if (selection->audio_regions.empty()) {
239 if (!selection->audio_regions.empty()) {
241 rv = *(selection->audio_regions.begin());
242 (*tv) = &rv->get_time_axis_view();
243 region = &rv->region;
245 } else if (!selection->tracks.empty()) {
247 (*tv) = selection->tracks.front();
249 AudioTimeAxisView* atv;
251 if ((atv = dynamic_cast<AudioTimeAxisView*> (*tv)) != 0) {
254 if ((pl = atv->playlist()) == 0) {
258 region = dynamic_cast<AudioRegion*> (pl->top_region_at (start));
266 Editor::extend_selection_to_end_of_region (bool next)
270 jack_nframes_t start;
272 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
276 if (region && selection->time.start () == selection->time.end_frame ()) {
277 start = region->position();
279 start = selection->time.start ();
282 /* Try to leave the selection with the same route if possible */
284 if ((tv = selection->time.track) == 0) {
288 begin_reversible_command (_("extend selection"));
289 selection->set (tv, start, region->position() + region->length());
290 commit_reversible_command ();
294 Editor::extend_selection_to_start_of_region (bool previous)
300 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
304 if (region && selection->time.start () == selection->time.end_frame ()) {
305 end = region->position() + region->length();
307 end = selection->time.end_frame ();
310 /* Try to leave the selection with the same route if possible */
312 if ((tv = selection->time.track) == 0) {
316 begin_reversible_command (_("extend selection"));
317 selection->set (tv, region->position(), end);
318 commit_reversible_command ();
323 Editor::nudge_forward (bool next)
325 jack_nframes_t distance;
326 jack_nframes_t next_distance;
328 if (!session) return;
330 if (!selection->audio_regions.empty()) {
332 begin_reversible_command (_("nudge forward"));
334 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
335 AudioRegion& r ((*i)->region);
337 distance = get_nudge_distance (r.position(), next_distance);
340 distance = next_distance;
343 session->add_undo (r.playlist()->get_memento());
344 r.set_position (r.position() + distance, this);
345 session->add_redo_no_execute (r.playlist()->get_memento());
348 commit_reversible_command ();
351 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
352 session->request_locate (playhead_cursor->current_frame + distance);
357 Editor::nudge_backward (bool next)
359 jack_nframes_t distance;
360 jack_nframes_t next_distance;
362 if (!session) return;
364 if (!selection->audio_regions.empty()) {
366 begin_reversible_command (_("nudge forward"));
368 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
369 AudioRegion& r ((*i)->region);
371 distance = get_nudge_distance (r.position(), next_distance);
374 distance = next_distance;
377 session->add_undo (r.playlist()->get_memento());
379 if (r.position() > distance) {
380 r.set_position (r.position() - distance, this);
382 r.set_position (0, this);
384 session->add_redo_no_execute (r.playlist()->get_memento());
387 commit_reversible_command ();
391 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
393 if (playhead_cursor->current_frame > distance) {
394 session->request_locate (playhead_cursor->current_frame - distance);
396 session->goto_start();
402 Editor::nudge_forward_capture_offset ()
404 jack_nframes_t distance;
406 if (!session) return;
408 if (!selection->audio_regions.empty()) {
410 begin_reversible_command (_("nudge forward"));
412 distance = session->worst_output_latency();
414 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
415 AudioRegion& r ((*i)->region);
417 session->add_undo (r.playlist()->get_memento());
418 r.set_position (r.position() + distance, this);
419 session->add_redo_no_execute (r.playlist()->get_memento());
422 commit_reversible_command ();
428 Editor::nudge_backward_capture_offset ()
430 jack_nframes_t distance;
432 if (!session) return;
434 if (!selection->audio_regions.empty()) {
436 begin_reversible_command (_("nudge forward"));
438 distance = session->worst_output_latency();
440 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
441 AudioRegion& r ((*i)->region);
443 session->add_undo (r.playlist()->get_memento());
445 if (r.position() > distance) {
446 r.set_position (r.position() - distance, this);
448 r.set_position (0, this);
450 session->add_redo_no_execute (r.playlist()->get_memento());
453 commit_reversible_command ();
460 Editor::move_to_start ()
462 session->goto_start ();
466 Editor::move_to_end ()
469 session->request_locate (session->current_end_frame());
473 Editor::build_region_boundary_cache ()
475 jack_nframes_t pos = 0;
478 TrackViewList tracks;
480 region_boundary_cache.clear ();
487 case SnapToRegionStart:
490 case SnapToRegionEnd:
493 case SnapToRegionSync:
496 case SnapToRegionBoundary:
500 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
505 TimeAxisView *ontrack = 0;
507 while (pos < session->current_end_frame()) {
509 if (!selection->tracks.empty()) {
511 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
515 } else if (clicked_trackview) {
518 t.push_back (clicked_trackview);
520 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
526 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
534 case SnapToRegionStart:
535 rpos = r->first_frame();
537 case SnapToRegionEnd:
538 rpos = r->last_frame();
540 case SnapToRegionSync:
541 rpos = r->adjust_to_sync (r->first_frame());
544 case SnapToRegionBoundary:
545 rpos = r->last_frame();
552 AudioTimeAxisView *atav;
554 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
555 if (atav->get_diskstream() != 0) {
556 speed = atav->get_diskstream()->speed();
560 rpos = track_frame_to_session_frame(rpos, speed);
562 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
563 if (snap_type == SnapToRegionBoundary) {
564 region_boundary_cache.push_back (r->first_frame());
566 region_boundary_cache.push_back (rpos);
574 Editor::find_next_region (jack_nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
576 TrackViewList::iterator i;
577 jack_nframes_t closest = max_frames;
579 jack_nframes_t rpos = 0;
582 jack_nframes_t track_frame;
583 AudioTimeAxisView *atav;
585 for (i = tracks.begin(); i != tracks.end(); ++i) {
587 jack_nframes_t distance;
591 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
592 if (atav->get_diskstream()!=0)
593 track_speed = atav->get_diskstream()->speed();
596 track_frame = session_frame_to_track_frame(frame, track_speed);
598 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
604 rpos = r->first_frame ();
608 rpos = r->last_frame ();
612 rpos = r->adjust_to_sync (r->first_frame());
615 // rpos is a "track frame", converting it to "session frame"
616 rpos = track_frame_to_session_frame(rpos, track_speed);
619 distance = rpos - frame;
621 distance = frame - rpos;
624 if (distance < closest) {
636 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
639 jack_nframes_t pos = cursor->current_frame;
645 TimeAxisView *ontrack = 0;
647 // so we don't find the current region again..
651 if (!selection->tracks.empty()) {
653 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
655 } else if (clicked_trackview) {
658 t.push_back (clicked_trackview);
660 r = find_next_region (pos, point, dir, t, &ontrack);
664 r = find_next_region (pos, point, dir, track_views, &ontrack);
673 pos = r->first_frame ();
677 pos = r->last_frame ();
681 pos = r->adjust_to_sync (r->first_frame());
686 AudioTimeAxisView *atav;
688 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
689 if (atav->get_diskstream() != 0) {
690 speed = atav->get_diskstream()->speed();
694 pos = track_frame_to_session_frame(pos, speed);
696 if (cursor == playhead_cursor) {
697 session->request_locate (pos);
699 cursor->set_position (pos);
704 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
706 cursor_to_region_point (cursor, point, 1);
710 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
712 cursor_to_region_point (cursor, point, -1);
716 Editor::cursor_to_selection_start (Cursor *cursor)
718 jack_nframes_t pos = 0;
719 switch (mouse_mode) {
721 if (!selection->audio_regions.empty()) {
722 pos = selection->audio_regions.start();
727 if (!selection->time.empty()) {
728 pos = selection->time.start ();
736 if (cursor == playhead_cursor) {
737 session->request_locate (pos);
739 cursor->set_position (pos);
744 Editor::cursor_to_selection_end (Cursor *cursor)
746 jack_nframes_t pos = 0;
748 switch (mouse_mode) {
750 if (!selection->audio_regions.empty()) {
751 pos = selection->audio_regions.end_frame();
756 if (!selection->time.empty()) {
757 pos = selection->time.end_frame ();
765 if (cursor == playhead_cursor) {
766 session->request_locate (pos);
768 cursor->set_position (pos);
773 Editor::playhead_backward ()
780 if (get_prefix (prefix, was_floating)) {
784 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
786 cnt = (jack_nframes_t) prefix;
790 pos = playhead_cursor->current_frame;
792 if ((jack_nframes_t) pos < cnt) {
798 /* XXX this is completely insane. with the current buffering
799 design, we'll force a complete track buffer flush and
800 reload, just to move 1 sample !!!
803 session->request_locate (pos);
807 Editor::playhead_forward ()
814 if (get_prefix (prefix, was_floating)) {
818 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
820 cnt = (jack_nframes_t) floor (prefix);
824 pos = playhead_cursor->current_frame;
826 /* XXX this is completely insane. with the current buffering
827 design, we'll force a complete track buffer flush and
828 reload, just to move 1 sample !!!
831 session->request_locate (pos+cnt);
835 Editor::cursor_align (bool playhead_to_edit)
837 if (playhead_to_edit) {
839 session->request_locate (edit_cursor->current_frame);
842 edit_cursor->set_position (playhead_cursor->current_frame);
847 Editor::edit_cursor_backward ()
854 if (get_prefix (prefix, was_floating)) {
858 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
860 cnt = (jack_nframes_t) prefix;
864 pos = edit_cursor->current_frame;
866 if ((jack_nframes_t) pos < cnt) {
872 edit_cursor->set_position (pos);
876 Editor::edit_cursor_forward ()
883 if (get_prefix (prefix, was_floating)) {
887 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
889 cnt = (jack_nframes_t) floor (prefix);
893 pos = edit_cursor->current_frame;
894 edit_cursor->set_position (pos+cnt);
898 Editor::goto_frame ()
902 jack_nframes_t frame;
904 if (get_prefix (prefix, was_floating)) {
909 frame = (jack_nframes_t) floor (prefix * session->frame_rate());
911 frame = (jack_nframes_t) floor (prefix);
914 session->request_locate (frame);
918 Editor::scroll_backward (float pages)
920 jack_nframes_t frame;
921 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
926 if (get_prefix (prefix, was_floating)) {
927 cnt = (jack_nframes_t) floor (pages * one_page);
930 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
932 cnt = (jack_nframes_t) floor (prefix * one_page);
936 if (leftmost_frame < cnt) {
939 frame = leftmost_frame - cnt;
942 reposition_x_origin (frame);
946 Editor::scroll_forward (float pages)
948 jack_nframes_t frame;
949 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
954 if (get_prefix (prefix, was_floating)) {
955 cnt = (jack_nframes_t) floor (pages * one_page);
958 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
960 cnt = (jack_nframes_t) floor (prefix * one_page);
964 if (ULONG_MAX - cnt < leftmost_frame) {
965 frame = ULONG_MAX - cnt;
967 frame = leftmost_frame + cnt;
970 reposition_x_origin (frame);
974 Editor::scroll_tracks_down ()
980 if (get_prefix (prefix, was_floating)) {
983 cnt = (int) floor (prefix);
986 vertical_adjustment.set_value (vertical_adjustment.get_value() + (cnt * vertical_adjustment.get_page_size()));
990 Editor::scroll_tracks_up ()
996 if (get_prefix (prefix, was_floating)) {
999 cnt = (int) floor (prefix);
1002 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1006 Editor::scroll_tracks_down_line ()
1008 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1009 adj->set_value (adj->get_value() + 10);
1013 Editor::scroll_tracks_up_line ()
1015 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1016 adj->set_value (adj->get_value() - 10);
1022 Editor::temporal_zoom_step (bool coarser)
1026 nfpu = frames_per_unit;
1031 nfpu = max(1.0,(nfpu/2.0));
1034 temporal_zoom (nfpu);
1038 Editor::temporal_zoom (gdouble fpu)
1040 if (!session) return;
1042 jack_nframes_t current_page = current_page_frames();
1043 jack_nframes_t current_leftmost = leftmost_frame;
1044 jack_nframes_t current_rightmost;
1045 jack_nframes_t current_center;
1046 jack_nframes_t new_page;
1047 jack_nframes_t leftmost_after_zoom = 0;
1052 new_page = (jack_nframes_t) floor (canvas_width * nfpu);
1054 switch (zoom_focus) {
1056 leftmost_after_zoom = current_leftmost;
1059 case ZoomFocusRight:
1060 current_rightmost = leftmost_frame + current_page;
1061 if (current_rightmost > new_page) {
1062 leftmost_after_zoom = current_rightmost - new_page;
1064 leftmost_after_zoom = 0;
1068 case ZoomFocusCenter:
1069 current_center = current_leftmost + (current_page/2);
1070 if (current_center > (new_page/2)) {
1071 leftmost_after_zoom = current_center - (new_page / 2);
1073 leftmost_after_zoom = 0;
1077 case ZoomFocusPlayhead:
1078 /* try to keep the playhead in the center */
1079 if (playhead_cursor->current_frame > new_page/2) {
1080 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1082 leftmost_after_zoom = 0;
1087 /* try to keep the edit cursor in the center */
1088 if (edit_cursor->current_frame > leftmost_frame + (new_page/2)) {
1089 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1091 leftmost_after_zoom = 0;
1097 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1099 // begin_reversible_command (_("zoom"));
1100 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1101 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1102 // commit_reversible_command ();
1104 reposition_and_zoom (leftmost_after_zoom, nfpu);
1108 Editor::temporal_zoom_selection ()
1110 if (!selection) return;
1112 if (selection->time.empty()) {
1116 jack_nframes_t start = selection->time[clicked_selection].start;
1117 jack_nframes_t end = selection->time[clicked_selection].end;
1119 temporal_zoom_by_frame (start, end, "zoom to selection");
1123 Editor::temporal_zoom_session ()
1126 temporal_zoom_by_frame (0, session->current_end_frame(), "zoom to session");
1131 Editor::temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, const string & op)
1133 if (!session) return;
1135 if ((start == 0 && end == 0) || end < start) {
1139 jack_nframes_t range = end - start;
1141 double new_fpu = (double)range / (double)canvas_width;
1144 // while (p2 < new_fpu) {
1149 jack_nframes_t new_page = (jack_nframes_t) floor (canvas_width * new_fpu);
1150 jack_nframes_t middle = (jack_nframes_t) floor( (double)start + ((double)range / 2.0f ));
1151 jack_nframes_t new_leftmost = (jack_nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1153 if (new_leftmost > middle) new_leftmost = 0;
1155 // begin_reversible_command (op);
1156 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1157 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1158 // commit_reversible_command ();
1160 reposition_and_zoom (new_leftmost, new_fpu);
1164 Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
1166 if (!session) return;
1168 jack_nframes_t range_before = frame - leftmost_frame;
1171 new_fpu = frames_per_unit;
1177 new_fpu = max(1.0,(new_fpu/2.0));
1181 if (new_fpu == frames_per_unit) return;
1183 jack_nframes_t new_leftmost = frame - range_before;
1185 if (new_leftmost > frame) new_leftmost = 0;
1187 // begin_reversible_command (_("zoom to frame"));
1188 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1189 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1190 // commit_reversible_command ();
1192 reposition_and_zoom (new_leftmost, new_fpu);
1196 Editor::select_all_in_track (Selection::Operation op)
1198 list<Selectable *> touched;
1200 if (!clicked_trackview) {
1204 clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1207 case Selection::Toggle:
1208 selection->add (touched);
1210 case Selection::Set:
1211 selection->set (touched);
1213 case Selection::Extend:
1214 /* not defined yet */
1220 Editor::select_all (Selection::Operation op)
1222 list<Selectable *> touched;
1224 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1225 if ((*iter)->hidden()) {
1228 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1230 begin_reversible_command (_("select all"));
1232 case Selection::Toggle:
1233 selection->add (touched);
1235 case Selection::Set:
1236 selection->set (touched);
1238 case Selection::Extend:
1239 /* not defined yet */
1242 commit_reversible_command ();
1246 Editor::invert_selection_in_track ()
1248 list<Selectable *> touched;
1250 if (!clicked_trackview) {
1254 clicked_trackview->get_inverted_selectables (*selection, touched);
1255 selection->set (touched);
1259 Editor::invert_selection ()
1261 list<Selectable *> touched;
1263 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1264 if ((*iter)->hidden()) {
1267 (*iter)->get_inverted_selectables (*selection, touched);
1270 selection->set (touched);
1274 Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, Selection::Operation op)
1276 list<Selectable *> touched;
1278 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1279 if ((*iter)->hidden()) {
1282 (*iter)->get_selectables (start, end, top, bot, touched);
1284 begin_reversible_command (_("select all within"));
1286 case Selection::Toggle:
1287 selection->add (touched);
1289 case Selection::Set:
1290 selection->set (touched);
1292 case Selection::Extend:
1293 /* not defined yet */
1296 commit_reversible_command ();
1297 return !touched.empty();
1301 Editor::set_selection_from_punch()
1305 if ((location = session->locations()->auto_punch_location()) == 0) {
1309 set_selection_from_range (*location);
1313 Editor::set_selection_from_loop()
1317 if ((location = session->locations()->auto_loop_location()) == 0) {
1320 set_selection_from_range (*location);
1324 Editor::set_selection_from_range (Location& loc)
1326 if (clicked_trackview == 0) {
1330 begin_reversible_command (_("set selection from range"));
1331 selection->set (0, loc.start(), loc.end());
1332 commit_reversible_command ();
1336 Editor::select_all_selectables_using_time_selection ()
1339 list<Selectable *> touched;
1341 if (clicked_trackview == 0) {
1345 if (selection->time.empty()) {
1349 jack_nframes_t start = selection->time[clicked_selection].start;
1350 jack_nframes_t end = selection->time[clicked_selection].end;
1352 if (end - start < 1) {
1356 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1357 if ((*iter)->hidden()) {
1360 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1362 begin_reversible_command (_("select all from range"));
1363 selection->set (touched);
1364 commit_reversible_command ();
1370 Editor::select_all_selectables_using_punch()
1372 Location* location = session->locations()->auto_punch_location();
1373 list<Selectable *> touched;
1375 if (location == 0 || (location->end() - location->start() <= 1)) {
1379 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1380 if ((*iter)->hidden()) {
1383 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1385 begin_reversible_command (_("select all from punch"));
1386 selection->set (touched);
1387 commit_reversible_command ();
1392 Editor::select_all_selectables_using_loop()
1394 Location* location = session->locations()->auto_loop_location();
1395 list<Selectable *> touched;
1397 if (location == 0 || (location->end() - location->start() <= 1)) {
1401 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1402 if ((*iter)->hidden()) {
1405 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1407 begin_reversible_command (_("select all from loop"));
1408 selection->set (touched);
1409 commit_reversible_command ();
1414 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1416 jack_nframes_t start;
1418 list<Selectable *> touched;
1421 begin_reversible_command (_("select all after cursor"));
1422 start = cursor->current_frame ;
1423 end = session->current_end_frame();
1425 if (cursor->current_frame > 0) {
1426 begin_reversible_command (_("select all before cursor"));
1428 end = cursor->current_frame - 1;
1433 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1434 if ((*iter)->hidden()) {
1437 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1439 selection->set (touched);
1440 commit_reversible_command ();
1444 Editor::amplitude_zoom_step (bool in)
1458 #ifdef FIX_FOR_CANVAS
1459 /* XXX DO SOMETHING */
1468 Editor::delete_sample_forward ()
1473 Editor::delete_sample_backward ()
1478 Editor::delete_screen ()
1485 Editor::search_backwards ()
1491 Editor::search_forwards ()
1499 Editor::jump_forward_to_mark ()
1505 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1508 session->request_locate (location->start(), session->transport_rolling());
1510 session->request_locate (session->current_end_frame());
1515 Editor::jump_backward_to_mark ()
1521 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1524 session->request_locate (location->start(), session->transport_rolling());
1526 session->goto_start ();
1537 if (get_prefix (prefix, was_floating)) {
1538 pos = session->audible_frame ();
1541 pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
1543 pos = (jack_nframes_t) floor (prefix);
1547 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1551 Editor::clear_markers ()
1554 session->begin_reversible_command (_("clear markers"));
1555 session->add_undo (session->locations()->get_memento());
1556 session->locations()->clear_markers ();
1557 session->add_redo_no_execute (session->locations()->get_memento());
1558 session->commit_reversible_command ();
1563 Editor::clear_ranges ()
1566 session->begin_reversible_command (_("clear ranges"));
1567 session->add_undo (session->locations()->get_memento());
1569 Location * looploc = session->locations()->auto_loop_location();
1570 Location * punchloc = session->locations()->auto_punch_location();
1572 session->locations()->clear_ranges ();
1574 if (looploc) session->locations()->add (looploc);
1575 if (punchloc) session->locations()->add (punchloc);
1577 session->add_redo_no_execute (session->locations()->get_memento());
1578 session->commit_reversible_command ();
1583 Editor::clear_locations ()
1585 session->begin_reversible_command (_("clear locations"));
1586 session->add_undo (session->locations()->get_memento());
1587 session->locations()->clear ();
1588 session->add_redo_no_execute (session->locations()->get_memento());
1589 session->commit_reversible_command ();
1590 session->locations()->clear ();
1593 /* INSERT/REPLACE */
1596 Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
1601 jack_nframes_t where;
1602 AudioTimeAxisView *atv = 0;
1605 track_canvas.window_to_world (x, y, wx, wy);
1606 wx += horizontal_adjustment.get_value();
1607 wy += vertical_adjustment.get_value();
1610 event.type = GDK_BUTTON_RELEASE;
1611 event.button.x = wx;
1612 event.button.y = wy;
1614 where = event_frame (&event, &cx, &cy);
1616 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1617 /* clearly outside canvas area */
1621 if ((tv = trackview_by_y_position (cy)) == 0) {
1625 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1629 if ((playlist = atv->playlist()) == 0) {
1635 begin_reversible_command (_("insert dragged region"));
1636 session->add_undo (playlist->get_memento());
1637 playlist->add_region (*(new AudioRegion (region)), where, 1.0);
1638 session->add_redo_no_execute (playlist->get_memento());
1639 commit_reversible_command ();
1643 Editor::insert_region_list_selection (float times)
1645 AudioTimeAxisView *tv = 0;
1648 if (clicked_audio_trackview != 0) {
1649 tv = clicked_audio_trackview;
1650 } else if (!selection->tracks.empty()) {
1651 if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
1658 if ((playlist = tv->playlist()) == 0) {
1662 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1664 if (selected->count_selected_rows() != 1) {
1668 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
1669 Region* region = (*i)[region_list_columns.region];
1671 begin_reversible_command (_("insert region"));
1672 session->add_undo (playlist->get_memento());
1673 playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
1674 session->add_redo_no_execute (playlist->get_memento());
1675 commit_reversible_command ();
1679 /* BUILT-IN EFFECTS */
1682 Editor::reverse_selection ()
1687 /* GAIN ENVELOPE EDITING */
1690 Editor::edit_envelope ()
1697 Editor::toggle_playback (bool with_abort)
1703 switch (session->slave_source()) {
1708 /* transport controlled by the master */
1712 if (session->is_auditioning()) {
1713 session->cancel_audition ();
1717 if (session->transport_rolling()) {
1718 session->request_stop (with_abort);
1719 if (session->get_auto_loop()) {
1720 session->request_auto_loop (false);
1723 session->request_transport_speed (1.0f);
1728 Editor::play_from_start ()
1730 session->request_locate (session->current_start_frame(), true);
1734 Editor::play_selection ()
1736 if (selection->time.empty()) {
1740 session->request_play_range (true);
1744 Editor::play_selected_region ()
1746 if (!selection->audio_regions.empty()) {
1747 AudioRegionView *rv = *(selection->audio_regions.begin());
1749 session->request_bounded_roll (rv->region.position(), rv->region.last_frame());
1754 Editor::loop_selected_region ()
1756 if (!selection->audio_regions.empty()) {
1757 AudioRegionView *rv = *(selection->audio_regions.begin());
1760 if ((tll = transport_loop_location()) != 0) {
1762 tll->set (rv->region.position(), rv->region.last_frame());
1764 // enable looping, reposition and start rolling
1766 session->request_auto_loop (true);
1767 session->request_locate (tll->start(), false);
1768 session->request_transport_speed (1.0f);
1774 Editor::play_location (Location& location)
1776 if (location.start() <= location.end()) {
1780 session->request_bounded_roll (location.start(), location.end());
1784 Editor::loop_location (Location& location)
1786 if (location.start() <= location.end()) {
1792 if ((tll = transport_loop_location()) != 0) {
1793 tll->set (location.start(), location.end());
1795 // enable looping, reposition and start rolling
1796 session->request_auto_loop (true);
1797 session->request_locate (tll->start(), true);
1802 Editor::toggle_region_mute ()
1804 if (clicked_regionview) {
1805 clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
1806 } else if (!selection->audio_regions.empty()) {
1807 bool yn = ! (*selection->audio_regions.begin())->region.muted();
1808 selection->foreach_audio_region (&AudioRegion::set_muted, yn);
1813 Editor::toggle_region_opaque ()
1815 if (clicked_regionview) {
1816 clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
1817 } else if (!selection->audio_regions.empty()) {
1818 bool yn = ! (*selection->audio_regions.begin())->region.opaque();
1819 selection->foreach_audio_region (&Region::set_opaque, yn);
1824 Editor::raise_region ()
1826 selection->foreach_audio_region (&Region::raise);
1830 Editor::raise_region_to_top ()
1832 selection->foreach_audio_region (&Region::raise_to_top);
1836 Editor::lower_region ()
1838 selection->foreach_audio_region (&Region::lower);
1842 Editor::lower_region_to_bottom ()
1844 selection->foreach_audio_region (&Region::lower_to_bottom);
1848 Editor::edit_region ()
1850 if (clicked_regionview == 0) {
1854 clicked_regionview->show_region_editor ();
1858 Editor::rename_region ()
1862 Button ok_button (_("OK"));
1863 Button cancel_button (_("Cancel"));
1865 if (selection->audio_regions.empty()) {
1869 dialog.set_title (_("ardour: rename region"));
1870 dialog.set_name ("RegionRenameWindow");
1871 dialog.set_size_request (300, -1);
1872 dialog.set_position (Gtk::WIN_POS_MOUSE);
1873 dialog.set_modal (true);
1875 dialog.get_vbox()->set_border_width (10);
1876 dialog.get_vbox()->pack_start (entry);
1877 dialog.get_action_area()->pack_start (ok_button);
1878 dialog.get_action_area()->pack_start (cancel_button);
1880 entry.set_name ("RegionNameDisplay");
1881 ok_button.set_name ("EditorGTKButton");
1882 cancel_button.set_name ("EditorGTKButton");
1884 region_renamed = false;
1886 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1887 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1888 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
1895 if (region_renamed) {
1896 (*selection->audio_regions.begin())->region.set_name (entry.get_text());
1897 redisplay_regions ();
1902 Editor::rename_region_finished (bool status)
1905 region_renamed = status;
1910 Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
1912 if (session->is_auditioning()) {
1913 session->cancel_audition ();
1916 // note: some potential for creativity here, because region doesn't
1917 // have to belong to the playlist that Route is handling
1919 // bool was_soloed = route.soloed();
1921 route.set_solo (true, this);
1923 session->request_bounded_roll (region.position(), region.position() + region.length());
1925 /* XXX how to unset the solo state ? */
1929 Editor::audition_selected_region ()
1931 if (!selection->audio_regions.empty()) {
1932 AudioRegionView* rv = *(selection->audio_regions.begin());
1933 session->audition_region (rv->region);
1938 Editor::audition_playlist_region_standalone (AudioRegion& region)
1940 session->audition_region (region);
1944 Editor::build_interthread_progress_window ()
1946 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
1948 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
1950 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
1951 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
1953 // GTK2FIX: this button needs a modifiable label
1955 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1956 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
1958 interthread_cancel_button.add (interthread_cancel_label);
1960 interthread_progress_window->set_default_size (200, 100);
1964 Editor::interthread_cancel_clicked ()
1966 if (current_interthread_info) {
1967 current_interthread_info->cancel = true;
1972 Editor::region_from_selection ()
1974 if (clicked_trackview == 0) {
1978 if (selection->time.empty()) {
1982 jack_nframes_t start = selection->time[clicked_selection].start;
1983 jack_nframes_t end = selection->time[clicked_selection].end;
1985 jack_nframes_t selection_cnt = end - start + 1;
1987 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1989 AudioRegion *region;
1990 AudioRegion *current;
1994 jack_nframes_t internal_start;
1997 if ((pl = (*i)->playlist()) == 0) {
2001 if ((current_r = pl->top_region_at (start)) == 0) {
2005 if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
2006 internal_start = start - current->position();
2007 session->region_name (new_name, current->name(), true);
2008 region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
2014 Editor::create_region_from_selection (vector<AudioRegion *>& new_regions)
2016 if (selection->time.empty() || selection->tracks.empty()) {
2020 jack_nframes_t start = selection->time[clicked_selection].start;
2021 jack_nframes_t end = selection->time[clicked_selection].end;
2023 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2025 AudioRegion* current;
2028 jack_nframes_t internal_start;
2031 if ((playlist = (*i)->playlist()) == 0) {
2035 if ((current_r = playlist->top_region_at(start)) == 0) {
2039 if ((current = dynamic_cast<AudioRegion*>(current_r)) == 0) {
2043 internal_start = start - current->position();
2044 session->region_name (new_name, current->name(), true);
2046 new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name));
2051 Editor::split_multichannel_region ()
2053 vector<AudioRegion*> v;
2055 if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
2059 clicked_regionview->region.separate_by_channel (*session, v);
2061 /* nothing else to do, really */
2065 Editor::new_region_from_selection ()
2067 region_from_selection ();
2068 cancel_selection ();
2072 Editor::separate_region_from_selection ()
2074 bool doing_undo = false;
2076 if (selection->time.empty()) {
2082 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2084 AudioTimeAxisView* atv;
2086 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2088 if (atv->is_audio_track()) {
2090 if ((playlist = atv->playlist()) != 0) {
2092 begin_reversible_command (_("separate"));
2095 if (doing_undo) session->add_undo ((playlist)->get_memento());
2097 /* XXX need to consider musical time selections here at some point */
2099 double speed = atv->get_diskstream()->speed();
2101 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2102 playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
2105 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2111 if (doing_undo) commit_reversible_command ();
2115 Editor::crop_region_to_selection ()
2117 if (selection->time.empty()) {
2121 vector<Playlist*> playlists;
2124 if (clicked_trackview != 0) {
2126 if ((playlist = clicked_trackview->playlist()) == 0) {
2130 playlists.push_back (playlist);
2134 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2136 AudioTimeAxisView* atv;
2138 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2140 if (atv->is_audio_track()) {
2142 if ((playlist = atv->playlist()) != 0) {
2143 playlists.push_back (playlist);
2150 if (!playlists.empty()) {
2152 jack_nframes_t start;
2156 begin_reversible_command (_("trim to selection"));
2158 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2162 start = selection->time.start();
2164 if ((region = (*i)->top_region_at(start)) == 0) {
2168 /* now adjust lengths to that we do the right thing
2169 if the selection extends beyond the region
2172 start = max (start, region->position());
2173 end = min (selection->time.end_frame(), start + region->length() - 1);
2174 cnt = end - start + 1;
2176 session->add_undo ((*i)->get_memento());
2177 region->trim_to (start, cnt, this);
2178 session->add_redo_no_execute ((*i)->get_memento());
2181 commit_reversible_command ();
2186 Editor::region_fill_track ()
2190 if (!session || selection->audio_regions.empty()) {
2194 end = session->current_end_frame ();
2196 begin_reversible_command (_("region fill"));
2198 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2200 AudioRegion& region ((*i)->region);
2201 Playlist* pl = region.playlist();
2203 if (end <= region.last_frame()) {
2207 double times = (double) (end - region.last_frame()) / (double) region.length();
2213 session->add_undo (pl->get_memento());
2214 pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
2215 session->add_redo_no_execute (pl->get_memento());
2218 commit_reversible_command ();
2222 Editor::region_fill_selection ()
2224 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2228 if (selection->time.empty()) {
2234 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2236 if (selected->count_selected_rows() != 1) {
2240 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2241 region = (*i)[region_list_columns.region];
2243 jack_nframes_t start = selection->time[clicked_selection].start;
2244 jack_nframes_t end = selection->time[clicked_selection].end;
2248 if (selection->tracks.empty()) {
2252 jack_nframes_t selection_length = end - start;
2253 float times = (float)selection_length / region->length();
2255 begin_reversible_command (_("fill selection"));
2257 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2259 if ((playlist = (*i)->playlist()) == 0) {
2263 session->add_undo (playlist->get_memento());
2264 playlist->add_region (*(createRegion (*region)), start, times);
2265 session->add_redo_no_execute (playlist->get_memento());
2268 commit_reversible_command ();
2272 Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
2275 if (!region.covers (position)) {
2276 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2279 begin_reversible_command (_("set region sync position"));
2280 session->add_undo (region.playlist()->get_memento());
2281 region.set_sync_position (position);
2282 session->add_redo_no_execute (region.playlist()->get_memento());
2283 commit_reversible_command ();
2287 Editor::set_region_sync_from_edit_cursor ()
2289 if (clicked_regionview == 0) {
2293 if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
2294 error << _("Place the edit cursor at the desired sync point") << endmsg;
2298 Region& region (clicked_regionview->region);
2299 begin_reversible_command (_("set sync from edit cursor"));
2300 session->add_undo (region.playlist()->get_memento());
2301 region.set_sync_position (edit_cursor->current_frame);
2302 session->add_redo_no_execute (region.playlist()->get_memento());
2303 commit_reversible_command ();
2307 Editor::remove_region_sync ()
2309 if (clicked_regionview) {
2310 Region& region (clicked_regionview->region);
2311 begin_reversible_command (_("remove sync"));
2312 session->add_undo (region.playlist()->get_memento());
2313 region.clear_sync_position ();
2314 session->add_redo_no_execute (region.playlist()->get_memento());
2315 commit_reversible_command ();
2320 Editor::naturalize ()
2322 if (selection->audio_regions.empty()) {
2325 begin_reversible_command (_("naturalize"));
2326 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2327 session->add_undo ((*i)->region.get_memento());
2328 (*i)->region.move_to_natural_position (this);
2329 session->add_redo_no_execute ((*i)->region.get_memento());
2331 commit_reversible_command ();
2335 Editor::align (RegionPoint what)
2337 align_selection (what, edit_cursor->current_frame);
2341 Editor::align_relative (RegionPoint what)
2343 align_selection_relative (what, edit_cursor->current_frame);
2346 struct RegionSortByTime {
2347 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2348 return a->region.position() < b->region.position();
2353 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
2355 if (selection->audio_regions.empty()) {
2359 jack_nframes_t distance;
2360 jack_nframes_t pos = 0;
2363 list<AudioRegionView*> sorted;
2364 selection->audio_regions.by_position (sorted);
2365 Region& r ((*sorted.begin())->region);
2369 pos = r.first_frame ();
2373 pos = r.last_frame();
2377 pos = r.adjust_to_sync (r.first_frame());
2381 if (pos > position) {
2382 distance = pos - position;
2385 distance = position - pos;
2389 begin_reversible_command (_("align selection (relative)"));
2391 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2393 Region& region ((*i)->region);
2395 session->add_undo (region.playlist()->get_memento());
2398 region.set_position (region.position() + distance, this);
2400 region.set_position (region.position() - distance, this);
2403 session->add_redo_no_execute (region.playlist()->get_memento());
2407 commit_reversible_command ();
2411 Editor::align_selection (RegionPoint point, jack_nframes_t position)
2413 if (selection->audio_regions.empty()) {
2417 begin_reversible_command (_("align selection"));
2419 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2420 align_region_internal ((*i)->region, point, position);
2423 commit_reversible_command ();
2427 Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position)
2429 begin_reversible_command (_("align region"));
2430 align_region_internal (region, point, position);
2431 commit_reversible_command ();
2435 Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
2437 session->add_undo (region.playlist()->get_memento());
2441 region.set_position (region.adjust_to_sync (position), this);
2445 if (position > region.length()) {
2446 region.set_position (position - region.length(), this);
2451 region.set_position (position, this);
2455 session->add_redo_no_execute (region.playlist()->get_memento());
2459 Editor::trim_region_to_edit_cursor ()
2461 if (clicked_regionview == 0) {
2465 Region& region (clicked_regionview->region);
2468 AudioTimeAxisView *atav;
2470 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2471 if (atav->get_diskstream() != 0) {
2472 speed = atav->get_diskstream()->speed();
2476 begin_reversible_command (_("trim to edit"));
2477 session->add_undo (region.playlist()->get_memento());
2478 region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2479 session->add_redo_no_execute (region.playlist()->get_memento());
2480 commit_reversible_command ();
2484 Editor::trim_region_from_edit_cursor ()
2486 if (clicked_regionview == 0) {
2490 Region& region (clicked_regionview->region);
2493 AudioTimeAxisView *atav;
2495 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2496 if (atav->get_diskstream() != 0) {
2497 speed = atav->get_diskstream()->speed();
2501 begin_reversible_command (_("trim to edit"));
2502 session->add_undo (region.playlist()->get_memento());
2503 region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2504 session->add_redo_no_execute (region.playlist()->get_memento());
2505 commit_reversible_command ();
2509 Editor::unfreeze_route ()
2511 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2515 clicked_audio_trackview->audio_track()->unfreeze ();
2519 Editor::_freeze_thread (void* arg)
2521 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2522 return static_cast<Editor*>(arg)->freeze_thread ();
2526 Editor::freeze_thread ()
2528 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2533 Editor::freeze_progress_timeout (void *arg)
2535 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2536 return !(current_interthread_info->done || current_interthread_info->cancel);
2540 Editor::freeze_route ()
2542 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2546 InterThreadInfo itt;
2548 if (interthread_progress_window == 0) {
2549 build_interthread_progress_window ();
2552 interthread_progress_window->set_title (_("ardour: freeze"));
2553 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2554 interthread_progress_window->show_all ();
2555 interthread_progress_bar.set_fraction (0.0f);
2556 interthread_progress_label.set_text ("");
2557 interthread_cancel_label.set_text (_("Cancel Freeze"));
2558 current_interthread_info = &itt;
2560 interthread_progress_connection =
2561 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2565 itt.progress = 0.0f;
2567 pthread_create (&itt.thread, 0, _freeze_thread, this);
2569 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2571 while (!itt.done && !itt.cancel) {
2572 gtk_main_iteration ();
2575 interthread_progress_connection.disconnect ();
2576 interthread_progress_window->hide_all ();
2577 current_interthread_info = 0;
2578 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2582 Editor::bounce_range_selection ()
2584 if (selection->time.empty()) {
2588 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2590 jack_nframes_t start = selection->time[clicked_selection].start;
2591 jack_nframes_t end = selection->time[clicked_selection].end;
2592 jack_nframes_t cnt = end - start + 1;
2594 begin_reversible_command (_("bounce range"));
2596 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2598 AudioTimeAxisView* atv;
2600 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2606 if ((playlist = atv->playlist()) == 0) {
2610 InterThreadInfo itt;
2614 itt.progress = false;
2616 session->add_undo (playlist->get_memento());
2617 atv->audio_track()->bounce_range (start, cnt, itt);
2618 session->add_redo_no_execute (playlist->get_memento());
2621 commit_reversible_command ();
2639 Editor::cut_copy (CutCopyOp op)
2641 /* only cancel selection if cut/copy is successful.*/
2653 opname = _("clear");
2657 cut_buffer->clear ();
2659 switch (current_mouse_mode()) {
2661 if (!selection->audio_regions.empty() || !selection->points.empty()) {
2663 begin_reversible_command (opname + _(" objects"));
2665 if (!selection->audio_regions.empty()) {
2667 cut_copy_regions (op);
2670 selection->clear_audio_regions ();
2674 if (!selection->points.empty()) {
2675 cut_copy_points (op);
2678 selection->clear_points ();
2682 commit_reversible_command ();
2687 if (!selection->time.empty()) {
2689 begin_reversible_command (opname + _(" range"));
2690 cut_copy_ranges (op);
2691 commit_reversible_command ();
2694 selection->clear_time ();
2706 Editor::cut_copy_points (CutCopyOp op)
2708 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2710 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2713 atv->cut_copy_clear_objects (selection->points, op);
2719 Editor::cut_copy_regions (CutCopyOp op)
2721 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
2722 PlaylistMapping pmap;
2723 jack_nframes_t first_position = max_frames;
2724 set<Playlist*> freezelist;
2725 pair<set<Playlist*>::iterator,bool> insert_result;
2727 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
2728 first_position = min ((*x)->region.position(), first_position);
2730 if (op == Cut || op == Clear) {
2731 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2733 insert_result = freezelist.insert (pl);
2734 if (insert_result.second) {
2736 session->add_undo (pl->get_memento());
2742 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
2744 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2746 AudioRegionSelection::iterator tmp;
2753 PlaylistMapping::iterator pi = pmap.find (pl);
2755 if (pi == pmap.end()) {
2756 npl = new AudioPlaylist (*session, "cutlist", true);
2765 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
2766 pl->remove_region (&((*x)->region));
2770 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
2774 pl->remove_region (&((*x)->region));
2782 list<Playlist*> foo;
2784 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2785 foo.push_back (i->second);
2789 cut_buffer->set (foo);
2792 for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2794 session->add_redo_no_execute ((*pl)->get_memento());
2799 Editor::cut_copy_ranges (CutCopyOp op)
2801 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2802 (*i)->cut_copy_clear (*selection, op);
2807 Editor::paste (float times)
2809 paste_internal (edit_cursor->current_frame, times);
2813 Editor::mouse_paste ()
2818 track_canvas.get_pointer (x, y);
2819 track_canvas.window_to_world (x, y, wx, wy);
2820 wx += horizontal_adjustment.get_value();
2821 wy += vertical_adjustment.get_value();
2824 event.type = GDK_BUTTON_RELEASE;
2825 event.button.x = wx;
2826 event.button.y = wy;
2828 jack_nframes_t where = event_frame (&event, 0, 0);
2830 paste_internal (where, 1);
2834 Editor::paste_internal (jack_nframes_t position, float times)
2836 bool commit = false;
2838 if (cut_buffer->empty() || selection->tracks.empty()) {
2842 if (position == max_frames) {
2843 position = edit_cursor->current_frame;
2846 begin_reversible_command (_("paste"));
2848 TrackSelection::iterator i;
2851 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
2853 /* undo/redo is handled by individual tracks */
2855 if ((*i)->paste (position, times, *cut_buffer, nth)) {
2861 commit_reversible_command ();
2866 Editor::paste_named_selection (float times)
2868 TrackSelection::iterator t;
2870 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
2872 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
2876 TreeModel::iterator i = selected->get_selected();
2877 NamedSelection* ns = (*i)[named_selection_columns.selection];
2879 list<Playlist*>::iterator chunk;
2880 list<Playlist*>::iterator tmp;
2882 chunk = ns->playlists.begin();
2884 begin_reversible_command (_("paste chunk"));
2886 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
2888 AudioTimeAxisView* atv;
2892 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
2896 if ((pl = atv->playlist()) == 0) {
2900 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
2907 session->add_undo (apl->get_memento());
2908 apl->paste (**chunk, edit_cursor->current_frame, times);
2909 session->add_redo_no_execute (apl->get_memento());
2911 if (tmp != ns->playlists.end()) {
2916 commit_reversible_command();
2920 Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
2923 AudioRegionSelection sel = regions; // clear (below) will clear the argument list
2925 begin_reversible_command (_("duplicate region"));
2927 selection->clear_audio_regions ();
2929 for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
2931 Region& r ((*i)->region);
2933 TimeAxisView& tv = (*i)->get_time_axis_view();
2934 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
2935 sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
2937 playlist = (*i)->region.playlist();
2938 session->add_undo (playlist->get_memento());
2939 playlist->duplicate (r, r.last_frame(), times);
2940 session->add_redo_no_execute (playlist->get_memento());
2944 if (latest_regionview) {
2945 selection->add (latest_regionview);
2950 commit_reversible_command ();
2954 Editor::duplicate_selection (float times)
2956 if (selection->time.empty() || selection->tracks.empty()) {
2961 vector<AudioRegion*> new_regions;
2962 vector<AudioRegion*>::iterator ri;
2964 create_region_from_selection (new_regions);
2966 if (new_regions.empty()) {
2970 begin_reversible_command (_("duplicate selection"));
2972 ri = new_regions.begin();
2974 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2975 if ((playlist = (*i)->playlist()) == 0) {
2978 session->add_undo (playlist->get_memento());
2979 playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
2980 session->add_redo_no_execute (playlist->get_memento());
2983 if (ri == new_regions.end()) {
2988 commit_reversible_command ();
2992 Editor::center_playhead ()
2994 float page = canvas_width * frames_per_unit;
2996 center_screen_internal (playhead_cursor->current_frame, page);
3000 Editor::center_edit_cursor ()
3002 float page = canvas_width * frames_per_unit;
3004 center_screen_internal (edit_cursor->current_frame, page);
3008 Editor::clear_playlist (Playlist& playlist)
3010 begin_reversible_command (_("clear playlist"));
3011 session->add_undo (playlist.get_memento());
3013 session->add_redo_no_execute (playlist.get_memento());
3014 commit_reversible_command ();
3018 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3021 jack_nframes_t distance;
3022 jack_nframes_t next_distance;
3023 jack_nframes_t start;
3025 if (use_edit_cursor) {
3026 start = edit_cursor->current_frame;
3031 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3035 if (selection->tracks.empty()) {
3039 begin_reversible_command (_("nudge track"));
3041 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3043 if ((playlist = (*i)->playlist()) == 0) {
3047 session->add_undo (playlist->get_memento());
3048 playlist->nudge_after (start, distance, forwards);
3049 session->add_redo_no_execute (playlist->get_memento());
3052 commit_reversible_command ();
3056 Editor::remove_last_capture ()
3058 vector<string> choices;
3065 if (Config->get_verify_remove_last_capture()) {
3066 prompt = _("Do you really want to destroy the last capture?"
3067 "\n(This is destructive and cannot be undone)");
3069 choices.push_back (_("Yes, destroy it."));
3070 choices.push_back (_("No, do nothing."));
3072 Gtkmm2ext::Choice prompter (prompt, choices);
3074 if (prompter.run () == 0) {
3075 session->remove_last_capture ();
3079 session->remove_last_capture();
3084 Editor::normalize_region ()
3090 if (selection->audio_regions.empty()) {
3094 begin_reversible_command (_("normalize"));
3096 track_canvas.get_window()->set_cursor (*wait_cursor);
3099 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3100 session->add_undo ((*r)->region.get_memento());
3101 (*r)->region.normalize_to (0.0f);
3102 session->add_redo_no_execute ((*r)->region.get_memento());
3105 commit_reversible_command ();
3106 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3111 Editor::denormalize_region ()
3117 if (selection->audio_regions.empty()) {
3121 begin_reversible_command ("denormalize");
3123 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3124 session->add_undo ((*r)->region.get_memento());
3125 (*r)->region.set_scale_amplitude (1.0f);
3126 session->add_redo_no_execute ((*r)->region.get_memento());
3129 commit_reversible_command ();
3134 Editor::reverse_region ()
3140 Reverse rev (*session);
3141 apply_filter (rev, _("reverse regions"));
3145 Editor::apply_filter (AudioFilter& filter, string command)
3147 if (selection->audio_regions.empty()) {
3151 begin_reversible_command (command);
3153 track_canvas.get_window()->set_cursor (*wait_cursor);
3156 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
3158 AudioRegion& region ((*r)->region);
3159 Playlist* playlist = region.playlist();
3161 AudioRegionSelection::iterator tmp;
3166 if (region.apply (filter) == 0) {
3168 session->add_undo (playlist->get_memento());
3169 playlist->replace_region (region, *(filter.results.front()), region.position());
3170 session->add_redo_no_execute (playlist->get_memento());
3178 commit_reversible_command ();
3179 selection->audio_regions.clear ();
3182 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3186 Editor::region_selection_op (void (Region::*pmf)(void))
3188 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3189 ((*i)->region.*pmf)();
3195 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3197 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3198 ((*i)->region.*pmf)(arg);
3203 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3205 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3206 ((*i)->region.*pmf)(yn);
3211 Editor::external_edit_region ()
3213 if (!clicked_regionview) {
3221 Editor::brush (jack_nframes_t pos)
3223 AudioRegionSelection sel;
3226 if (selection->audio_regions.empty()) {
3227 /* XXX get selection from region list */
3229 sel = selection->audio_regions;
3236 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3237 mouse_brush_insert_region ((*i), pos);
3242 Editor::toggle_gain_envelope_visibility ()
3244 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3245 (*i)->set_envelope_visible (!(*i)->envelope_visible());
3250 Editor::toggle_gain_envelope_active ()
3252 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3253 AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
3255 ar->set_envelope_active (true);