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 (session->current_start_frame(), 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::add_location_from_selection ()
1198 if (selection->time.empty()) {
1202 if (session == 0 || clicked_trackview == 0) {
1206 jack_nframes_t start = selection->time[clicked_selection].start;
1207 jack_nframes_t end = selection->time[clicked_selection].end;
1209 Location *location = new Location (start, end, "selection");
1211 session->begin_reversible_command (_("add marker"));
1212 session->add_undo (session->locations()->get_memento());
1213 session->locations()->add (location, true);
1214 session->add_redo_no_execute (session->locations()->get_memento());
1215 session->commit_reversible_command ();
1219 Editor::add_location_from_playhead_cursor ()
1221 jack_nframes_t where = session->audible_frame();
1223 Location *location = new Location (where, where, "mark", Location::IsMark);
1224 session->begin_reversible_command (_("add marker"));
1225 session->add_undo (session->locations()->get_memento());
1226 session->locations()->add (location, true);
1227 session->add_redo_no_execute (session->locations()->get_memento());
1228 session->commit_reversible_command ();
1232 Editor::add_location_from_audio_region ()
1234 if (selection->audio_regions.empty()) {
1238 AudioRegionView* rv = *(selection->audio_regions.begin());
1239 Region& region = rv->region;
1241 Location *location = new Location (region.position(), region.last_frame(), region.name());
1242 session->begin_reversible_command (_("add marker"));
1243 session->add_undo (session->locations()->get_memento());
1244 session->locations()->add (location, true);
1245 session->add_redo_no_execute (session->locations()->get_memento());
1246 session->commit_reversible_command ();
1250 Editor::select_all_in_track (Selection::Operation op)
1252 list<Selectable *> touched;
1254 if (!clicked_trackview) {
1258 clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1261 case Selection::Toggle:
1262 selection->add (touched);
1264 case Selection::Set:
1265 selection->set (touched);
1267 case Selection::Extend:
1268 /* not defined yet */
1274 Editor::select_all (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 (0, max_frames, 0, DBL_MAX, touched);
1284 begin_reversible_command (_("select all"));
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 ();
1300 Editor::invert_selection_in_track ()
1302 list<Selectable *> touched;
1304 if (!clicked_trackview) {
1308 clicked_trackview->get_inverted_selectables (*selection, touched);
1309 selection->set (touched);
1313 Editor::invert_selection ()
1315 list<Selectable *> touched;
1317 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1318 if ((*iter)->hidden()) {
1321 (*iter)->get_inverted_selectables (*selection, touched);
1324 selection->set (touched);
1328 Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, Selection::Operation op)
1330 list<Selectable *> touched;
1332 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1333 if ((*iter)->hidden()) {
1336 (*iter)->get_selectables (start, end, top, bot, touched);
1338 begin_reversible_command (_("select all within"));
1340 case Selection::Toggle:
1341 selection->add (touched);
1343 case Selection::Set:
1344 selection->set (touched);
1346 case Selection::Extend:
1347 /* not defined yet */
1350 commit_reversible_command ();
1351 return !touched.empty();
1355 Editor::set_selection_from_audio_region ()
1357 if (selection->audio_regions.empty()) {
1361 AudioRegionView* rv = *(selection->audio_regions.begin());
1362 Region& region = rv->region;
1364 begin_reversible_command (_("set selection from region"));
1365 selection->set (0, region.position(), region.last_frame());
1366 commit_reversible_command ();
1368 set_mouse_mode (Editing::MouseRange, false);
1372 Editor::set_selection_from_punch()
1376 if ((location = session->locations()->auto_punch_location()) == 0) {
1380 set_selection_from_range (*location);
1384 Editor::set_selection_from_loop()
1388 if ((location = session->locations()->auto_loop_location()) == 0) {
1391 set_selection_from_range (*location);
1395 Editor::set_selection_from_range (Location& loc)
1397 if (clicked_trackview == 0) {
1401 begin_reversible_command (_("set selection from range"));
1402 selection->set (0, loc.start(), loc.end());
1403 commit_reversible_command ();
1405 set_mouse_mode (Editing::MouseRange, false);
1409 Editor::select_all_selectables_using_time_selection ()
1412 list<Selectable *> touched;
1414 if (clicked_trackview == 0) {
1418 if (selection->time.empty()) {
1422 jack_nframes_t start = selection->time[clicked_selection].start;
1423 jack_nframes_t end = selection->time[clicked_selection].end;
1425 if (end - start < 1) {
1429 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1430 if ((*iter)->hidden()) {
1433 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1435 begin_reversible_command (_("select all from range"));
1436 selection->set (touched);
1437 commit_reversible_command ();
1443 Editor::select_all_selectables_using_punch()
1445 Location* location = session->locations()->auto_punch_location();
1446 list<Selectable *> touched;
1448 if (location == 0 || (location->end() - location->start() <= 1)) {
1452 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1453 if ((*iter)->hidden()) {
1456 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1458 begin_reversible_command (_("select all from punch"));
1459 selection->set (touched);
1460 commit_reversible_command ();
1465 Editor::select_all_selectables_using_loop()
1467 Location* location = session->locations()->auto_loop_location();
1468 list<Selectable *> touched;
1470 if (location == 0 || (location->end() - location->start() <= 1)) {
1474 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1475 if ((*iter)->hidden()) {
1478 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1480 begin_reversible_command (_("select all from loop"));
1481 selection->set (touched);
1482 commit_reversible_command ();
1487 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1489 jack_nframes_t start;
1491 list<Selectable *> touched;
1494 begin_reversible_command (_("select all after cursor"));
1495 start = cursor->current_frame ;
1496 end = session->current_end_frame();
1498 if (cursor->current_frame > 0) {
1499 begin_reversible_command (_("select all before cursor"));
1501 end = cursor->current_frame - 1;
1506 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1507 if ((*iter)->hidden()) {
1510 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1512 selection->set (touched);
1513 commit_reversible_command ();
1517 Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
1519 jack_nframes_t start;
1521 list<Selectable *> touched;
1522 bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
1523 if (cursor->current_frame == other_cursor->current_frame) {
1526 begin_reversible_command (_("select all between cursors"));
1527 if ( other_cursor_is_first) {
1528 start = other_cursor->current_frame;
1529 end = cursor->current_frame - 1;
1532 start = cursor->current_frame;
1533 end = other_cursor->current_frame - 1;
1536 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1537 if ((*iter)->hidden()) {
1540 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1542 selection->set (touched);
1543 commit_reversible_command ();
1547 Editor::amplitude_zoom_step (bool in)
1561 #ifdef FIX_FOR_CANVAS
1562 /* XXX DO SOMETHING */
1571 Editor::delete_sample_forward ()
1576 Editor::delete_sample_backward ()
1581 Editor::delete_screen ()
1588 Editor::search_backwards ()
1594 Editor::search_forwards ()
1602 Editor::jump_forward_to_mark ()
1608 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1611 session->request_locate (location->start(), session->transport_rolling());
1613 session->request_locate (session->current_end_frame());
1618 Editor::jump_backward_to_mark ()
1624 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1627 session->request_locate (location->start(), session->transport_rolling());
1629 session->goto_start ();
1640 if (get_prefix (prefix, was_floating)) {
1641 pos = session->audible_frame ();
1644 pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
1646 pos = (jack_nframes_t) floor (prefix);
1650 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1654 Editor::clear_markers ()
1657 session->begin_reversible_command (_("clear markers"));
1658 session->add_undo (session->locations()->get_memento());
1659 session->locations()->clear_markers ();
1660 session->add_redo_no_execute (session->locations()->get_memento());
1661 session->commit_reversible_command ();
1666 Editor::clear_ranges ()
1669 session->begin_reversible_command (_("clear ranges"));
1670 session->add_undo (session->locations()->get_memento());
1672 Location * looploc = session->locations()->auto_loop_location();
1673 Location * punchloc = session->locations()->auto_punch_location();
1675 session->locations()->clear_ranges ();
1677 if (looploc) session->locations()->add (looploc);
1678 if (punchloc) session->locations()->add (punchloc);
1680 session->add_redo_no_execute (session->locations()->get_memento());
1681 session->commit_reversible_command ();
1686 Editor::clear_locations ()
1688 session->begin_reversible_command (_("clear locations"));
1689 session->add_undo (session->locations()->get_memento());
1690 session->locations()->clear ();
1691 session->add_redo_no_execute (session->locations()->get_memento());
1692 session->commit_reversible_command ();
1693 session->locations()->clear ();
1696 /* INSERT/REPLACE */
1699 Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
1704 jack_nframes_t where;
1705 AudioTimeAxisView *atv = 0;
1708 track_canvas.window_to_world (x, y, wx, wy);
1709 wx += horizontal_adjustment.get_value();
1710 wy += vertical_adjustment.get_value();
1713 event.type = GDK_BUTTON_RELEASE;
1714 event.button.x = wx;
1715 event.button.y = wy;
1717 where = event_frame (&event, &cx, &cy);
1719 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1720 /* clearly outside canvas area */
1724 if ((tv = trackview_by_y_position (cy)) == 0) {
1728 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1732 if ((playlist = atv->playlist()) == 0) {
1738 begin_reversible_command (_("insert dragged region"));
1739 session->add_undo (playlist->get_memento());
1740 playlist->add_region (*(new AudioRegion (region)), where, 1.0);
1741 session->add_redo_no_execute (playlist->get_memento());
1742 commit_reversible_command ();
1746 Editor::insert_region_list_selection (float times)
1748 AudioTimeAxisView *tv = 0;
1751 if (clicked_audio_trackview != 0) {
1752 tv = clicked_audio_trackview;
1753 } else if (!selection->tracks.empty()) {
1754 if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
1761 if ((playlist = tv->playlist()) == 0) {
1765 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1767 if (selected->count_selected_rows() != 1) {
1771 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
1772 Region* region = (*i)[region_list_columns.region];
1774 begin_reversible_command (_("insert region"));
1775 session->add_undo (playlist->get_memento());
1776 playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
1777 session->add_redo_no_execute (playlist->get_memento());
1778 commit_reversible_command ();
1782 /* BUILT-IN EFFECTS */
1785 Editor::reverse_selection ()
1790 /* GAIN ENVELOPE EDITING */
1793 Editor::edit_envelope ()
1800 Editor::toggle_playback (bool with_abort)
1806 switch (session->slave_source()) {
1811 /* transport controlled by the master */
1815 if (session->is_auditioning()) {
1816 session->cancel_audition ();
1820 if (session->transport_rolling()) {
1821 session->request_stop (with_abort);
1822 if (session->get_auto_loop()) {
1823 session->request_auto_loop (false);
1826 session->request_transport_speed (1.0f);
1831 Editor::play_from_start ()
1833 session->request_locate (session->current_start_frame(), true);
1837 Editor::play_selection ()
1839 if (selection->time.empty()) {
1843 session->request_play_range (true);
1847 Editor::play_selected_region ()
1849 if (!selection->audio_regions.empty()) {
1850 AudioRegionView *rv = *(selection->audio_regions.begin());
1852 session->request_bounded_roll (rv->region.position(), rv->region.last_frame());
1857 Editor::loop_selected_region ()
1859 if (!selection->audio_regions.empty()) {
1860 AudioRegionView *rv = *(selection->audio_regions.begin());
1863 if ((tll = transport_loop_location()) != 0) {
1865 tll->set (rv->region.position(), rv->region.last_frame());
1867 // enable looping, reposition and start rolling
1869 session->request_auto_loop (true);
1870 session->request_locate (tll->start(), false);
1871 session->request_transport_speed (1.0f);
1877 Editor::play_location (Location& location)
1879 if (location.start() <= location.end()) {
1883 session->request_bounded_roll (location.start(), location.end());
1887 Editor::loop_location (Location& location)
1889 if (location.start() <= location.end()) {
1895 if ((tll = transport_loop_location()) != 0) {
1896 tll->set (location.start(), location.end());
1898 // enable looping, reposition and start rolling
1899 session->request_auto_loop (true);
1900 session->request_locate (tll->start(), true);
1905 Editor::toggle_region_mute ()
1907 if (clicked_regionview) {
1908 clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
1909 } else if (!selection->audio_regions.empty()) {
1910 bool yn = ! (*selection->audio_regions.begin())->region.muted();
1911 selection->foreach_audio_region (&AudioRegion::set_muted, yn);
1916 Editor::toggle_region_opaque ()
1918 if (clicked_regionview) {
1919 clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
1920 } else if (!selection->audio_regions.empty()) {
1921 bool yn = ! (*selection->audio_regions.begin())->region.opaque();
1922 selection->foreach_audio_region (&Region::set_opaque, yn);
1927 Editor::raise_region ()
1929 selection->foreach_audio_region (&Region::raise);
1933 Editor::raise_region_to_top ()
1935 selection->foreach_audio_region (&Region::raise_to_top);
1939 Editor::lower_region ()
1941 selection->foreach_audio_region (&Region::lower);
1945 Editor::lower_region_to_bottom ()
1947 selection->foreach_audio_region (&Region::lower_to_bottom);
1951 Editor::edit_region ()
1953 if (clicked_regionview == 0) {
1957 clicked_regionview->show_region_editor ();
1961 Editor::rename_region ()
1965 Button ok_button (_("OK"));
1966 Button cancel_button (_("Cancel"));
1968 if (selection->audio_regions.empty()) {
1972 dialog.set_title (_("ardour: rename region"));
1973 dialog.set_name ("RegionRenameWindow");
1974 dialog.set_size_request (300, -1);
1975 dialog.set_position (Gtk::WIN_POS_MOUSE);
1976 dialog.set_modal (true);
1978 dialog.get_vbox()->set_border_width (10);
1979 dialog.get_vbox()->pack_start (entry);
1980 dialog.get_action_area()->pack_start (ok_button);
1981 dialog.get_action_area()->pack_start (cancel_button);
1983 entry.set_name ("RegionNameDisplay");
1984 ok_button.set_name ("EditorGTKButton");
1985 cancel_button.set_name ("EditorGTKButton");
1987 region_renamed = false;
1989 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1990 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1991 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
1998 if (region_renamed) {
1999 (*selection->audio_regions.begin())->region.set_name (entry.get_text());
2000 redisplay_regions ();
2005 Editor::rename_region_finished (bool status)
2008 region_renamed = status;
2013 Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
2015 if (session->is_auditioning()) {
2016 session->cancel_audition ();
2019 // note: some potential for creativity here, because region doesn't
2020 // have to belong to the playlist that Route is handling
2022 // bool was_soloed = route.soloed();
2024 route.set_solo (true, this);
2026 session->request_bounded_roll (region.position(), region.position() + region.length());
2028 /* XXX how to unset the solo state ? */
2032 Editor::audition_selected_region ()
2034 if (!selection->audio_regions.empty()) {
2035 AudioRegionView* rv = *(selection->audio_regions.begin());
2036 session->audition_region (rv->region);
2041 Editor::audition_playlist_region_standalone (AudioRegion& region)
2043 session->audition_region (region);
2047 Editor::build_interthread_progress_window ()
2049 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
2051 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
2053 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
2054 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
2056 // GTK2FIX: this button needs a modifiable label
2058 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
2059 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
2061 interthread_cancel_button.add (interthread_cancel_label);
2063 interthread_progress_window->set_default_size (200, 100);
2067 Editor::interthread_cancel_clicked ()
2069 if (current_interthread_info) {
2070 current_interthread_info->cancel = true;
2075 Editor::region_from_selection ()
2077 if (clicked_trackview == 0) {
2081 if (selection->time.empty()) {
2085 jack_nframes_t start = selection->time[clicked_selection].start;
2086 jack_nframes_t end = selection->time[clicked_selection].end;
2088 jack_nframes_t selection_cnt = end - start + 1;
2090 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2092 AudioRegion *region;
2093 AudioRegion *current;
2097 jack_nframes_t internal_start;
2100 if ((pl = (*i)->playlist()) == 0) {
2104 if ((current_r = pl->top_region_at (start)) == 0) {
2108 if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
2109 internal_start = start - current->position();
2110 session->region_name (new_name, current->name(), true);
2111 region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
2117 Editor::create_region_from_selection (vector<AudioRegion *>& new_regions)
2119 if (selection->time.empty() || selection->tracks.empty()) {
2123 jack_nframes_t start = selection->time[clicked_selection].start;
2124 jack_nframes_t end = selection->time[clicked_selection].end;
2126 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2128 AudioRegion* current;
2131 jack_nframes_t internal_start;
2134 if ((playlist = (*i)->playlist()) == 0) {
2138 if ((current_r = playlist->top_region_at(start)) == 0) {
2142 if ((current = dynamic_cast<AudioRegion*>(current_r)) == 0) {
2146 internal_start = start - current->position();
2147 session->region_name (new_name, current->name(), true);
2149 new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name));
2154 Editor::split_multichannel_region ()
2156 vector<AudioRegion*> v;
2158 if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
2162 clicked_regionview->region.separate_by_channel (*session, v);
2164 /* nothing else to do, really */
2168 Editor::new_region_from_selection ()
2170 region_from_selection ();
2171 cancel_selection ();
2175 Editor::separate_region_from_selection ()
2177 bool doing_undo = false;
2179 if (selection->time.empty()) {
2185 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2187 AudioTimeAxisView* atv;
2189 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2191 if (atv->is_audio_track()) {
2193 if ((playlist = atv->playlist()) != 0) {
2195 begin_reversible_command (_("separate"));
2198 if (doing_undo) session->add_undo ((playlist)->get_memento());
2200 /* XXX need to consider musical time selections here at some point */
2202 double speed = atv->get_diskstream()->speed();
2204 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2205 playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
2208 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2214 if (doing_undo) commit_reversible_command ();
2218 Editor::separate_regions_using_location (Location& loc)
2220 bool doing_undo = false;
2222 if (loc.is_mark()) {
2228 /* XXX i'm unsure as to whether this should operate on selected tracks only
2229 or the entire enchillada. uncomment the below line to correct the behaviour
2230 (currently set for all tracks)
2233 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2234 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2236 AudioTimeAxisView* atv;
2238 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2240 if (atv->is_audio_track()) {
2242 if ((playlist = atv->playlist()) != 0) {
2244 begin_reversible_command (_("separate"));
2247 if (doing_undo) session->add_undo ((playlist)->get_memento());
2249 /* XXX need to consider musical time selections here at some point */
2251 double speed = atv->get_diskstream()->speed();
2254 playlist->partition ((jack_nframes_t)(loc.start() * speed), (jack_nframes_t)(loc.end() * speed), true);
2255 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2261 if (doing_undo) commit_reversible_command ();
2265 Editor::crop_region_to_selection ()
2267 if (selection->time.empty()) {
2271 vector<Playlist*> playlists;
2274 if (clicked_trackview != 0) {
2276 if ((playlist = clicked_trackview->playlist()) == 0) {
2280 playlists.push_back (playlist);
2284 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2286 AudioTimeAxisView* atv;
2288 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2290 if (atv->is_audio_track()) {
2292 if ((playlist = atv->playlist()) != 0) {
2293 playlists.push_back (playlist);
2300 if (!playlists.empty()) {
2302 jack_nframes_t start;
2306 begin_reversible_command (_("trim to selection"));
2308 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2312 start = selection->time.start();
2314 if ((region = (*i)->top_region_at(start)) == 0) {
2318 /* now adjust lengths to that we do the right thing
2319 if the selection extends beyond the region
2322 start = max (start, region->position());
2323 end = min (selection->time.end_frame(), start + region->length() - 1);
2324 cnt = end - start + 1;
2326 session->add_undo ((*i)->get_memento());
2327 region->trim_to (start, cnt, this);
2328 session->add_redo_no_execute ((*i)->get_memento());
2331 commit_reversible_command ();
2336 Editor::region_fill_track ()
2340 if (!session || selection->audio_regions.empty()) {
2344 end = session->current_end_frame ();
2346 begin_reversible_command (_("region fill"));
2348 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2350 AudioRegion& region ((*i)->region);
2351 Playlist* pl = region.playlist();
2353 if (end <= region.last_frame()) {
2357 double times = (double) (end - region.last_frame()) / (double) region.length();
2363 session->add_undo (pl->get_memento());
2364 pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
2365 session->add_redo_no_execute (pl->get_memento());
2368 commit_reversible_command ();
2372 Editor::region_fill_selection ()
2374 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2378 if (selection->time.empty()) {
2384 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2386 if (selected->count_selected_rows() != 1) {
2390 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2391 region = (*i)[region_list_columns.region];
2393 jack_nframes_t start = selection->time[clicked_selection].start;
2394 jack_nframes_t end = selection->time[clicked_selection].end;
2398 if (selection->tracks.empty()) {
2402 jack_nframes_t selection_length = end - start;
2403 float times = (float)selection_length / region->length();
2405 begin_reversible_command (_("fill selection"));
2407 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2409 if ((playlist = (*i)->playlist()) == 0) {
2413 session->add_undo (playlist->get_memento());
2414 playlist->add_region (*(createRegion (*region)), start, times);
2415 session->add_redo_no_execute (playlist->get_memento());
2418 commit_reversible_command ();
2422 Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
2425 if (!region.covers (position)) {
2426 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2429 begin_reversible_command (_("set region sync position"));
2430 session->add_undo (region.playlist()->get_memento());
2431 region.set_sync_position (position);
2432 session->add_redo_no_execute (region.playlist()->get_memento());
2433 commit_reversible_command ();
2437 Editor::set_region_sync_from_edit_cursor ()
2439 if (clicked_regionview == 0) {
2443 if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
2444 error << _("Place the edit cursor at the desired sync point") << endmsg;
2448 Region& region (clicked_regionview->region);
2449 begin_reversible_command (_("set sync from edit cursor"));
2450 session->add_undo (region.playlist()->get_memento());
2451 region.set_sync_position (edit_cursor->current_frame);
2452 session->add_redo_no_execute (region.playlist()->get_memento());
2453 commit_reversible_command ();
2457 Editor::remove_region_sync ()
2459 if (clicked_regionview) {
2460 Region& region (clicked_regionview->region);
2461 begin_reversible_command (_("remove sync"));
2462 session->add_undo (region.playlist()->get_memento());
2463 region.clear_sync_position ();
2464 session->add_redo_no_execute (region.playlist()->get_memento());
2465 commit_reversible_command ();
2470 Editor::naturalize ()
2472 if (selection->audio_regions.empty()) {
2475 begin_reversible_command (_("naturalize"));
2476 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2477 session->add_undo ((*i)->region.get_memento());
2478 (*i)->region.move_to_natural_position (this);
2479 session->add_redo_no_execute ((*i)->region.get_memento());
2481 commit_reversible_command ();
2485 Editor::align (RegionPoint what)
2487 align_selection (what, edit_cursor->current_frame);
2491 Editor::align_relative (RegionPoint what)
2493 align_selection_relative (what, edit_cursor->current_frame);
2496 struct RegionSortByTime {
2497 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2498 return a->region.position() < b->region.position();
2503 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
2505 if (selection->audio_regions.empty()) {
2509 jack_nframes_t distance;
2510 jack_nframes_t pos = 0;
2513 list<AudioRegionView*> sorted;
2514 selection->audio_regions.by_position (sorted);
2515 Region& r ((*sorted.begin())->region);
2519 pos = r.first_frame ();
2523 pos = r.last_frame();
2527 pos = r.adjust_to_sync (r.first_frame());
2531 if (pos > position) {
2532 distance = pos - position;
2535 distance = position - pos;
2539 begin_reversible_command (_("align selection (relative)"));
2541 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2543 Region& region ((*i)->region);
2545 session->add_undo (region.playlist()->get_memento());
2548 region.set_position (region.position() + distance, this);
2550 region.set_position (region.position() - distance, this);
2553 session->add_redo_no_execute (region.playlist()->get_memento());
2557 commit_reversible_command ();
2561 Editor::align_selection (RegionPoint point, jack_nframes_t position)
2563 if (selection->audio_regions.empty()) {
2567 begin_reversible_command (_("align selection"));
2569 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2570 align_region_internal ((*i)->region, point, position);
2573 commit_reversible_command ();
2577 Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position)
2579 begin_reversible_command (_("align region"));
2580 align_region_internal (region, point, position);
2581 commit_reversible_command ();
2585 Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
2587 session->add_undo (region.playlist()->get_memento());
2591 region.set_position (region.adjust_to_sync (position), this);
2595 if (position > region.length()) {
2596 region.set_position (position - region.length(), this);
2601 region.set_position (position, this);
2605 session->add_redo_no_execute (region.playlist()->get_memento());
2609 Editor::trim_region_to_edit_cursor ()
2611 if (clicked_regionview == 0) {
2615 Region& region (clicked_regionview->region);
2618 AudioTimeAxisView *atav;
2620 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2621 if (atav->get_diskstream() != 0) {
2622 speed = atav->get_diskstream()->speed();
2626 begin_reversible_command (_("trim to edit"));
2627 session->add_undo (region.playlist()->get_memento());
2628 region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2629 session->add_redo_no_execute (region.playlist()->get_memento());
2630 commit_reversible_command ();
2634 Editor::trim_region_from_edit_cursor ()
2636 if (clicked_regionview == 0) {
2640 Region& region (clicked_regionview->region);
2643 AudioTimeAxisView *atav;
2645 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2646 if (atav->get_diskstream() != 0) {
2647 speed = atav->get_diskstream()->speed();
2651 begin_reversible_command (_("trim to edit"));
2652 session->add_undo (region.playlist()->get_memento());
2653 region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2654 session->add_redo_no_execute (region.playlist()->get_memento());
2655 commit_reversible_command ();
2659 Editor::unfreeze_route ()
2661 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2665 clicked_audio_trackview->audio_track()->unfreeze ();
2669 Editor::_freeze_thread (void* arg)
2671 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2672 return static_cast<Editor*>(arg)->freeze_thread ();
2676 Editor::freeze_thread ()
2678 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2683 Editor::freeze_progress_timeout (void *arg)
2685 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2686 return !(current_interthread_info->done || current_interthread_info->cancel);
2690 Editor::freeze_route ()
2692 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2696 InterThreadInfo itt;
2698 if (interthread_progress_window == 0) {
2699 build_interthread_progress_window ();
2702 interthread_progress_window->set_title (_("ardour: freeze"));
2703 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2704 interthread_progress_window->show_all ();
2705 interthread_progress_bar.set_fraction (0.0f);
2706 interthread_progress_label.set_text ("");
2707 interthread_cancel_label.set_text (_("Cancel Freeze"));
2708 current_interthread_info = &itt;
2710 interthread_progress_connection =
2711 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2715 itt.progress = 0.0f;
2717 pthread_create (&itt.thread, 0, _freeze_thread, this);
2719 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2721 while (!itt.done && !itt.cancel) {
2722 gtk_main_iteration ();
2725 interthread_progress_connection.disconnect ();
2726 interthread_progress_window->hide_all ();
2727 current_interthread_info = 0;
2728 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2732 Editor::bounce_range_selection ()
2734 if (selection->time.empty()) {
2738 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2740 jack_nframes_t start = selection->time[clicked_selection].start;
2741 jack_nframes_t end = selection->time[clicked_selection].end;
2742 jack_nframes_t cnt = end - start + 1;
2744 begin_reversible_command (_("bounce range"));
2746 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2748 AudioTimeAxisView* atv;
2750 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2756 if ((playlist = atv->playlist()) == 0) {
2760 InterThreadInfo itt;
2764 itt.progress = false;
2766 session->add_undo (playlist->get_memento());
2767 atv->audio_track()->bounce_range (start, cnt, itt);
2768 session->add_redo_no_execute (playlist->get_memento());
2771 commit_reversible_command ();
2789 Editor::cut_copy (CutCopyOp op)
2791 /* only cancel selection if cut/copy is successful.*/
2803 opname = _("clear");
2807 cut_buffer->clear ();
2809 switch (current_mouse_mode()) {
2811 if (!selection->audio_regions.empty() || !selection->points.empty()) {
2813 begin_reversible_command (opname + _(" objects"));
2815 if (!selection->audio_regions.empty()) {
2817 cut_copy_regions (op);
2820 selection->clear_audio_regions ();
2824 if (!selection->points.empty()) {
2825 cut_copy_points (op);
2828 selection->clear_points ();
2832 commit_reversible_command ();
2837 if (!selection->time.empty()) {
2839 begin_reversible_command (opname + _(" range"));
2840 cut_copy_ranges (op);
2841 commit_reversible_command ();
2844 selection->clear_time ();
2856 Editor::cut_copy_points (CutCopyOp op)
2858 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2860 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2863 atv->cut_copy_clear_objects (selection->points, op);
2869 Editor::cut_copy_regions (CutCopyOp op)
2871 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
2872 PlaylistMapping pmap;
2873 jack_nframes_t first_position = max_frames;
2874 set<Playlist*> freezelist;
2875 pair<set<Playlist*>::iterator,bool> insert_result;
2877 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
2878 first_position = min ((*x)->region.position(), first_position);
2880 if (op == Cut || op == Clear) {
2881 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2883 insert_result = freezelist.insert (pl);
2884 if (insert_result.second) {
2886 session->add_undo (pl->get_memento());
2892 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
2894 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2896 AudioRegionSelection::iterator tmp;
2903 PlaylistMapping::iterator pi = pmap.find (pl);
2905 if (pi == pmap.end()) {
2906 npl = new AudioPlaylist (*session, "cutlist", true);
2915 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
2916 pl->remove_region (&((*x)->region));
2920 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
2924 pl->remove_region (&((*x)->region));
2932 list<Playlist*> foo;
2934 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2935 foo.push_back (i->second);
2939 cut_buffer->set (foo);
2942 for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2944 session->add_redo_no_execute ((*pl)->get_memento());
2949 Editor::cut_copy_ranges (CutCopyOp op)
2951 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2952 (*i)->cut_copy_clear (*selection, op);
2957 Editor::paste (float times)
2959 paste_internal (edit_cursor->current_frame, times);
2963 Editor::mouse_paste ()
2968 track_canvas.get_pointer (x, y);
2969 track_canvas.window_to_world (x, y, wx, wy);
2970 wx += horizontal_adjustment.get_value();
2971 wy += vertical_adjustment.get_value();
2974 event.type = GDK_BUTTON_RELEASE;
2975 event.button.x = wx;
2976 event.button.y = wy;
2978 jack_nframes_t where = event_frame (&event, 0, 0);
2980 paste_internal (where, 1);
2984 Editor::paste_internal (jack_nframes_t position, float times)
2986 bool commit = false;
2988 if (cut_buffer->empty() || selection->tracks.empty()) {
2992 if (position == max_frames) {
2993 position = edit_cursor->current_frame;
2996 begin_reversible_command (_("paste"));
2998 TrackSelection::iterator i;
3001 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
3003 /* undo/redo is handled by individual tracks */
3005 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3011 commit_reversible_command ();
3016 Editor::paste_named_selection (float times)
3018 TrackSelection::iterator t;
3020 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3022 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3026 TreeModel::iterator i = selected->get_selected();
3027 NamedSelection* ns = (*i)[named_selection_columns.selection];
3029 list<Playlist*>::iterator chunk;
3030 list<Playlist*>::iterator tmp;
3032 chunk = ns->playlists.begin();
3034 begin_reversible_command (_("paste chunk"));
3036 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3038 AudioTimeAxisView* atv;
3042 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3046 if ((pl = atv->playlist()) == 0) {
3050 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
3057 session->add_undo (apl->get_memento());
3058 apl->paste (**chunk, edit_cursor->current_frame, times);
3059 session->add_redo_no_execute (apl->get_memento());
3061 if (tmp != ns->playlists.end()) {
3066 commit_reversible_command();
3070 Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
3073 AudioRegionSelection sel = regions; // clear (below) will clear the argument list
3075 begin_reversible_command (_("duplicate region"));
3077 selection->clear_audio_regions ();
3079 for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3081 Region& r ((*i)->region);
3083 TimeAxisView& tv = (*i)->get_time_axis_view();
3084 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3085 sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3087 playlist = (*i)->region.playlist();
3088 session->add_undo (playlist->get_memento());
3089 playlist->duplicate (r, r.last_frame(), times);
3090 session->add_redo_no_execute (playlist->get_memento());
3094 if (latest_regionview) {
3095 selection->add (latest_regionview);
3100 commit_reversible_command ();
3104 Editor::duplicate_selection (float times)
3106 if (selection->time.empty() || selection->tracks.empty()) {
3111 vector<AudioRegion*> new_regions;
3112 vector<AudioRegion*>::iterator ri;
3114 create_region_from_selection (new_regions);
3116 if (new_regions.empty()) {
3120 begin_reversible_command (_("duplicate selection"));
3122 ri = new_regions.begin();
3124 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3125 if ((playlist = (*i)->playlist()) == 0) {
3128 session->add_undo (playlist->get_memento());
3129 playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
3130 session->add_redo_no_execute (playlist->get_memento());
3133 if (ri == new_regions.end()) {
3138 commit_reversible_command ();
3142 Editor::center_playhead ()
3144 float page = canvas_width * frames_per_unit;
3146 center_screen_internal (playhead_cursor->current_frame, page);
3150 Editor::center_edit_cursor ()
3152 float page = canvas_width * frames_per_unit;
3154 center_screen_internal (edit_cursor->current_frame, page);
3158 Editor::clear_playlist (Playlist& playlist)
3160 begin_reversible_command (_("clear playlist"));
3161 session->add_undo (playlist.get_memento());
3163 session->add_redo_no_execute (playlist.get_memento());
3164 commit_reversible_command ();
3168 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3171 jack_nframes_t distance;
3172 jack_nframes_t next_distance;
3173 jack_nframes_t start;
3175 if (use_edit_cursor) {
3176 start = edit_cursor->current_frame;
3181 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3185 if (selection->tracks.empty()) {
3189 begin_reversible_command (_("nudge track"));
3191 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3193 if ((playlist = (*i)->playlist()) == 0) {
3197 session->add_undo (playlist->get_memento());
3198 playlist->nudge_after (start, distance, forwards);
3199 session->add_redo_no_execute (playlist->get_memento());
3202 commit_reversible_command ();
3206 Editor::remove_last_capture ()
3208 vector<string> choices;
3215 if (Config->get_verify_remove_last_capture()) {
3216 prompt = _("Do you really want to destroy the last capture?"
3217 "\n(This is destructive and cannot be undone)");
3219 choices.push_back (_("Yes, destroy it."));
3220 choices.push_back (_("No, do nothing."));
3222 Gtkmm2ext::Choice prompter (prompt, choices);
3224 if (prompter.run () == 0) {
3225 session->remove_last_capture ();
3229 session->remove_last_capture();
3234 Editor::normalize_region ()
3240 if (selection->audio_regions.empty()) {
3244 begin_reversible_command (_("normalize"));
3246 track_canvas.get_window()->set_cursor (*wait_cursor);
3249 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3250 session->add_undo ((*r)->region.get_memento());
3251 (*r)->region.normalize_to (0.0f);
3252 session->add_redo_no_execute ((*r)->region.get_memento());
3255 commit_reversible_command ();
3256 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3261 Editor::denormalize_region ()
3267 if (selection->audio_regions.empty()) {
3271 begin_reversible_command ("denormalize");
3273 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3274 session->add_undo ((*r)->region.get_memento());
3275 (*r)->region.set_scale_amplitude (1.0f);
3276 session->add_redo_no_execute ((*r)->region.get_memento());
3279 commit_reversible_command ();
3284 Editor::reverse_region ()
3290 Reverse rev (*session);
3291 apply_filter (rev, _("reverse regions"));
3295 Editor::apply_filter (AudioFilter& filter, string command)
3297 if (selection->audio_regions.empty()) {
3301 begin_reversible_command (command);
3303 track_canvas.get_window()->set_cursor (*wait_cursor);
3306 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
3308 AudioRegion& region ((*r)->region);
3309 Playlist* playlist = region.playlist();
3311 AudioRegionSelection::iterator tmp;
3316 if (region.apply (filter) == 0) {
3318 session->add_undo (playlist->get_memento());
3319 playlist->replace_region (region, *(filter.results.front()), region.position());
3320 session->add_redo_no_execute (playlist->get_memento());
3328 commit_reversible_command ();
3329 selection->audio_regions.clear ();
3332 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3336 Editor::region_selection_op (void (Region::*pmf)(void))
3338 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3339 ((*i)->region.*pmf)();
3345 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3347 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3348 ((*i)->region.*pmf)(arg);
3353 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3355 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3356 ((*i)->region.*pmf)(yn);
3361 Editor::external_edit_region ()
3363 if (!clicked_regionview) {
3371 Editor::brush (jack_nframes_t pos)
3373 AudioRegionSelection sel;
3376 if (selection->audio_regions.empty()) {
3377 /* XXX get selection from region list */
3379 sel = selection->audio_regions;
3386 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3387 mouse_brush_insert_region ((*i), pos);
3392 Editor::toggle_gain_envelope_visibility ()
3394 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3395 (*i)->set_envelope_visible (!(*i)->envelope_visible());
3400 Editor::toggle_gain_envelope_active ()
3402 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3403 AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
3405 ar->set_envelope_active (true);