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 begin_reversible_command (_("set selection from range"));
1398 selection->set (0, loc.start(), loc.end());
1399 commit_reversible_command ();
1401 set_mouse_mode (Editing::MouseRange, false);
1405 Editor::select_all_selectables_using_time_selection ()
1407 list<Selectable *> touched;
1409 if (selection->time.empty()) {
1413 jack_nframes_t start = selection->time[clicked_selection].start;
1414 jack_nframes_t end = selection->time[clicked_selection].end;
1416 if (end - start < 1) {
1420 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1421 if ((*iter)->hidden()) {
1424 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1427 begin_reversible_command (_("select all from range"));
1428 selection->set (touched);
1429 commit_reversible_command ();
1434 Editor::select_all_selectables_using_punch()
1436 Location* location = session->locations()->auto_punch_location();
1437 list<Selectable *> touched;
1439 if (location == 0 || (location->end() - location->start() <= 1)) {
1443 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1444 if ((*iter)->hidden()) {
1447 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1449 begin_reversible_command (_("select all from punch"));
1450 selection->set (touched);
1451 commit_reversible_command ();
1456 Editor::select_all_selectables_using_loop()
1458 Location* location = session->locations()->auto_loop_location();
1459 list<Selectable *> touched;
1461 if (location == 0 || (location->end() - location->start() <= 1)) {
1465 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1466 if ((*iter)->hidden()) {
1469 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1471 begin_reversible_command (_("select all from loop"));
1472 selection->set (touched);
1473 commit_reversible_command ();
1478 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1480 jack_nframes_t start;
1482 list<Selectable *> touched;
1485 begin_reversible_command (_("select all after cursor"));
1486 start = cursor->current_frame ;
1487 end = session->current_end_frame();
1489 if (cursor->current_frame > 0) {
1490 begin_reversible_command (_("select all before cursor"));
1492 end = cursor->current_frame - 1;
1498 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1499 if ((*iter)->hidden()) {
1502 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1504 selection->set (touched);
1505 commit_reversible_command ();
1509 Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
1511 jack_nframes_t start;
1513 list<Selectable *> touched;
1514 bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
1516 if (cursor->current_frame == other_cursor->current_frame) {
1520 begin_reversible_command (_("select all between cursors"));
1521 if (other_cursor_is_first) {
1522 start = other_cursor->current_frame;
1523 end = cursor->current_frame - 1;
1526 start = cursor->current_frame;
1527 end = other_cursor->current_frame - 1;
1530 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1531 if ((*iter)->hidden()) {
1534 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1536 selection->set (touched);
1537 commit_reversible_command ();
1541 Editor::amplitude_zoom_step (bool in)
1555 #ifdef FIX_FOR_CANVAS
1556 /* XXX DO SOMETHING */
1565 Editor::delete_sample_forward ()
1570 Editor::delete_sample_backward ()
1575 Editor::delete_screen ()
1582 Editor::search_backwards ()
1588 Editor::search_forwards ()
1596 Editor::jump_forward_to_mark ()
1602 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1605 session->request_locate (location->start(), session->transport_rolling());
1607 session->request_locate (session->current_end_frame());
1612 Editor::jump_backward_to_mark ()
1618 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1621 session->request_locate (location->start(), session->transport_rolling());
1623 session->goto_start ();
1634 if (get_prefix (prefix, was_floating)) {
1635 pos = session->audible_frame ();
1638 pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
1640 pos = (jack_nframes_t) floor (prefix);
1644 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1648 Editor::clear_markers ()
1651 session->begin_reversible_command (_("clear markers"));
1652 session->add_undo (session->locations()->get_memento());
1653 session->locations()->clear_markers ();
1654 session->add_redo_no_execute (session->locations()->get_memento());
1655 session->commit_reversible_command ();
1660 Editor::clear_ranges ()
1663 session->begin_reversible_command (_("clear ranges"));
1664 session->add_undo (session->locations()->get_memento());
1666 Location * looploc = session->locations()->auto_loop_location();
1667 Location * punchloc = session->locations()->auto_punch_location();
1669 session->locations()->clear_ranges ();
1671 if (looploc) session->locations()->add (looploc);
1672 if (punchloc) session->locations()->add (punchloc);
1674 session->add_redo_no_execute (session->locations()->get_memento());
1675 session->commit_reversible_command ();
1680 Editor::clear_locations ()
1682 session->begin_reversible_command (_("clear locations"));
1683 session->add_undo (session->locations()->get_memento());
1684 session->locations()->clear ();
1685 session->add_redo_no_execute (session->locations()->get_memento());
1686 session->commit_reversible_command ();
1687 session->locations()->clear ();
1690 /* INSERT/REPLACE */
1693 Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
1698 jack_nframes_t where;
1699 AudioTimeAxisView *atv = 0;
1702 track_canvas.window_to_world (x, y, wx, wy);
1703 wx += horizontal_adjustment.get_value();
1704 wy += vertical_adjustment.get_value();
1707 event.type = GDK_BUTTON_RELEASE;
1708 event.button.x = wx;
1709 event.button.y = wy;
1711 where = event_frame (&event, &cx, &cy);
1713 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1714 /* clearly outside canvas area */
1718 if ((tv = trackview_by_y_position (cy)) == 0) {
1722 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1726 if ((playlist = atv->playlist()) == 0) {
1732 begin_reversible_command (_("insert dragged region"));
1733 session->add_undo (playlist->get_memento());
1734 playlist->add_region (*(new AudioRegion (region)), where, 1.0);
1735 session->add_redo_no_execute (playlist->get_memento());
1736 commit_reversible_command ();
1740 Editor::insert_region_list_selection (float times)
1742 AudioTimeAxisView *tv = 0;
1745 if (clicked_audio_trackview != 0) {
1746 tv = clicked_audio_trackview;
1747 } else if (!selection->tracks.empty()) {
1748 if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
1755 if ((playlist = tv->playlist()) == 0) {
1759 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1761 if (selected->count_selected_rows() != 1) {
1765 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
1766 Region* region = (*i)[region_list_columns.region];
1768 begin_reversible_command (_("insert region"));
1769 session->add_undo (playlist->get_memento());
1770 playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
1771 session->add_redo_no_execute (playlist->get_memento());
1772 commit_reversible_command ();
1776 /* BUILT-IN EFFECTS */
1779 Editor::reverse_selection ()
1784 /* GAIN ENVELOPE EDITING */
1787 Editor::edit_envelope ()
1794 Editor::toggle_playback (bool with_abort)
1800 switch (session->slave_source()) {
1805 /* transport controlled by the master */
1809 if (session->is_auditioning()) {
1810 session->cancel_audition ();
1814 if (session->transport_rolling()) {
1815 session->request_stop (with_abort);
1816 if (session->get_auto_loop()) {
1817 session->request_auto_loop (false);
1820 session->request_transport_speed (1.0f);
1825 Editor::play_from_start ()
1827 session->request_locate (session->current_start_frame(), true);
1831 Editor::play_selection ()
1833 if (selection->time.empty()) {
1837 session->request_play_range (true);
1841 Editor::play_selected_region ()
1843 if (!selection->audio_regions.empty()) {
1844 AudioRegionView *rv = *(selection->audio_regions.begin());
1846 session->request_bounded_roll (rv->region.position(), rv->region.last_frame());
1851 Editor::loop_selected_region ()
1853 if (!selection->audio_regions.empty()) {
1854 AudioRegionView *rv = *(selection->audio_regions.begin());
1857 if ((tll = transport_loop_location()) != 0) {
1859 tll->set (rv->region.position(), rv->region.last_frame());
1861 // enable looping, reposition and start rolling
1863 session->request_auto_loop (true);
1864 session->request_locate (tll->start(), false);
1865 session->request_transport_speed (1.0f);
1871 Editor::play_location (Location& location)
1873 if (location.start() <= location.end()) {
1877 session->request_bounded_roll (location.start(), location.end());
1881 Editor::loop_location (Location& location)
1883 if (location.start() <= location.end()) {
1889 if ((tll = transport_loop_location()) != 0) {
1890 tll->set (location.start(), location.end());
1892 // enable looping, reposition and start rolling
1893 session->request_auto_loop (true);
1894 session->request_locate (tll->start(), true);
1899 Editor::toggle_region_mute ()
1901 if (clicked_regionview) {
1902 clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
1903 } else if (!selection->audio_regions.empty()) {
1904 bool yn = ! (*selection->audio_regions.begin())->region.muted();
1905 selection->foreach_audio_region (&AudioRegion::set_muted, yn);
1910 Editor::toggle_region_opaque ()
1912 if (clicked_regionview) {
1913 clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
1914 } else if (!selection->audio_regions.empty()) {
1915 bool yn = ! (*selection->audio_regions.begin())->region.opaque();
1916 selection->foreach_audio_region (&Region::set_opaque, yn);
1921 Editor::raise_region ()
1923 selection->foreach_audio_region (&Region::raise);
1927 Editor::raise_region_to_top ()
1929 selection->foreach_audio_region (&Region::raise_to_top);
1933 Editor::lower_region ()
1935 selection->foreach_audio_region (&Region::lower);
1939 Editor::lower_region_to_bottom ()
1941 selection->foreach_audio_region (&Region::lower_to_bottom);
1945 Editor::edit_region ()
1947 if (clicked_regionview == 0) {
1951 clicked_regionview->show_region_editor ();
1955 Editor::rename_region ()
1959 Button ok_button (_("OK"));
1960 Button cancel_button (_("Cancel"));
1962 if (selection->audio_regions.empty()) {
1966 dialog.set_title (_("ardour: rename region"));
1967 dialog.set_name ("RegionRenameWindow");
1968 dialog.set_size_request (300, -1);
1969 dialog.set_position (Gtk::WIN_POS_MOUSE);
1970 dialog.set_modal (true);
1972 dialog.get_vbox()->set_border_width (10);
1973 dialog.get_vbox()->pack_start (entry);
1974 dialog.get_action_area()->pack_start (ok_button);
1975 dialog.get_action_area()->pack_start (cancel_button);
1977 entry.set_name ("RegionNameDisplay");
1978 ok_button.set_name ("EditorGTKButton");
1979 cancel_button.set_name ("EditorGTKButton");
1981 region_renamed = false;
1983 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1984 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1985 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
1992 if (region_renamed) {
1993 (*selection->audio_regions.begin())->region.set_name (entry.get_text());
1994 redisplay_regions ();
1999 Editor::rename_region_finished (bool status)
2002 region_renamed = status;
2007 Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
2009 if (session->is_auditioning()) {
2010 session->cancel_audition ();
2013 // note: some potential for creativity here, because region doesn't
2014 // have to belong to the playlist that Route is handling
2016 // bool was_soloed = route.soloed();
2018 route.set_solo (true, this);
2020 session->request_bounded_roll (region.position(), region.position() + region.length());
2022 /* XXX how to unset the solo state ? */
2026 Editor::audition_selected_region ()
2028 if (!selection->audio_regions.empty()) {
2029 AudioRegionView* rv = *(selection->audio_regions.begin());
2030 session->audition_region (rv->region);
2035 Editor::audition_playlist_region_standalone (AudioRegion& region)
2037 session->audition_region (region);
2041 Editor::build_interthread_progress_window ()
2043 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
2045 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
2047 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
2048 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
2050 // GTK2FIX: this button needs a modifiable label
2052 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
2053 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
2055 interthread_cancel_button.add (interthread_cancel_label);
2057 interthread_progress_window->set_default_size (200, 100);
2061 Editor::interthread_cancel_clicked ()
2063 if (current_interthread_info) {
2064 current_interthread_info->cancel = true;
2069 Editor::region_from_selection ()
2071 if (clicked_trackview == 0) {
2075 if (selection->time.empty()) {
2079 jack_nframes_t start = selection->time[clicked_selection].start;
2080 jack_nframes_t end = selection->time[clicked_selection].end;
2082 jack_nframes_t selection_cnt = end - start + 1;
2084 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2086 AudioRegion *region;
2087 AudioRegion *current;
2091 jack_nframes_t internal_start;
2094 if ((pl = (*i)->playlist()) == 0) {
2098 if ((current_r = pl->top_region_at (start)) == 0) {
2102 if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
2103 internal_start = start - current->position();
2104 session->region_name (new_name, current->name(), true);
2105 region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
2111 Editor::create_region_from_selection (vector<AudioRegion *>& new_regions)
2113 if (selection->time.empty() || selection->tracks.empty()) {
2117 jack_nframes_t start = selection->time[clicked_selection].start;
2118 jack_nframes_t end = selection->time[clicked_selection].end;
2120 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2122 AudioRegion* current;
2125 jack_nframes_t internal_start;
2128 if ((playlist = (*i)->playlist()) == 0) {
2132 if ((current_r = playlist->top_region_at(start)) == 0) {
2136 if ((current = dynamic_cast<AudioRegion*>(current_r)) == 0) {
2140 internal_start = start - current->position();
2141 session->region_name (new_name, current->name(), true);
2143 new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name));
2148 Editor::split_multichannel_region ()
2150 vector<AudioRegion*> v;
2152 if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
2156 clicked_regionview->region.separate_by_channel (*session, v);
2158 /* nothing else to do, really */
2162 Editor::new_region_from_selection ()
2164 region_from_selection ();
2165 cancel_selection ();
2169 Editor::separate_region_from_selection ()
2171 bool doing_undo = false;
2173 if (selection->time.empty()) {
2179 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2181 AudioTimeAxisView* atv;
2183 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2185 if (atv->is_audio_track()) {
2187 if ((playlist = atv->playlist()) != 0) {
2189 begin_reversible_command (_("separate"));
2192 if (doing_undo) session->add_undo ((playlist)->get_memento());
2194 /* XXX need to consider musical time selections here at some point */
2196 double speed = atv->get_diskstream()->speed();
2198 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2199 playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
2202 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2208 if (doing_undo) commit_reversible_command ();
2212 Editor::separate_regions_using_location (Location& loc)
2214 bool doing_undo = false;
2216 if (loc.is_mark()) {
2222 /* XXX i'm unsure as to whether this should operate on selected tracks only
2223 or the entire enchillada. uncomment the below line to correct the behaviour
2224 (currently set for all tracks)
2227 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2228 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2230 AudioTimeAxisView* atv;
2232 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2234 if (atv->is_audio_track()) {
2236 if ((playlist = atv->playlist()) != 0) {
2238 begin_reversible_command (_("separate"));
2241 if (doing_undo) session->add_undo ((playlist)->get_memento());
2243 /* XXX need to consider musical time selections here at some point */
2245 double speed = atv->get_diskstream()->speed();
2248 playlist->partition ((jack_nframes_t)(loc.start() * speed), (jack_nframes_t)(loc.end() * speed), true);
2249 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2255 if (doing_undo) commit_reversible_command ();
2259 Editor::crop_region_to_selection ()
2261 if (selection->time.empty()) {
2265 vector<Playlist*> playlists;
2268 if (clicked_trackview != 0) {
2270 if ((playlist = clicked_trackview->playlist()) == 0) {
2274 playlists.push_back (playlist);
2278 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2280 AudioTimeAxisView* atv;
2282 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2284 if (atv->is_audio_track()) {
2286 if ((playlist = atv->playlist()) != 0) {
2287 playlists.push_back (playlist);
2294 if (!playlists.empty()) {
2296 jack_nframes_t start;
2300 begin_reversible_command (_("trim to selection"));
2302 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2306 start = selection->time.start();
2308 if ((region = (*i)->top_region_at(start)) == 0) {
2312 /* now adjust lengths to that we do the right thing
2313 if the selection extends beyond the region
2316 start = max (start, region->position());
2317 end = min (selection->time.end_frame(), start + region->length() - 1);
2318 cnt = end - start + 1;
2320 session->add_undo ((*i)->get_memento());
2321 region->trim_to (start, cnt, this);
2322 session->add_redo_no_execute ((*i)->get_memento());
2325 commit_reversible_command ();
2330 Editor::region_fill_track ()
2334 if (!session || selection->audio_regions.empty()) {
2338 end = session->current_end_frame ();
2340 begin_reversible_command (_("region fill"));
2342 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2344 AudioRegion& region ((*i)->region);
2345 Playlist* pl = region.playlist();
2347 if (end <= region.last_frame()) {
2351 double times = (double) (end - region.last_frame()) / (double) region.length();
2357 session->add_undo (pl->get_memento());
2358 pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
2359 session->add_redo_no_execute (pl->get_memento());
2362 commit_reversible_command ();
2366 Editor::region_fill_selection ()
2368 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2372 if (selection->time.empty()) {
2378 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2380 if (selected->count_selected_rows() != 1) {
2384 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2385 region = (*i)[region_list_columns.region];
2387 jack_nframes_t start = selection->time[clicked_selection].start;
2388 jack_nframes_t end = selection->time[clicked_selection].end;
2392 if (selection->tracks.empty()) {
2396 jack_nframes_t selection_length = end - start;
2397 float times = (float)selection_length / region->length();
2399 begin_reversible_command (_("fill selection"));
2401 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2403 if ((playlist = (*i)->playlist()) == 0) {
2407 session->add_undo (playlist->get_memento());
2408 playlist->add_region (*(createRegion (*region)), start, times);
2409 session->add_redo_no_execute (playlist->get_memento());
2412 commit_reversible_command ();
2416 Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
2419 if (!region.covers (position)) {
2420 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2423 begin_reversible_command (_("set region sync position"));
2424 session->add_undo (region.playlist()->get_memento());
2425 region.set_sync_position (position);
2426 session->add_redo_no_execute (region.playlist()->get_memento());
2427 commit_reversible_command ();
2431 Editor::set_region_sync_from_edit_cursor ()
2433 if (clicked_regionview == 0) {
2437 if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
2438 error << _("Place the edit cursor at the desired sync point") << endmsg;
2442 Region& region (clicked_regionview->region);
2443 begin_reversible_command (_("set sync from edit cursor"));
2444 session->add_undo (region.playlist()->get_memento());
2445 region.set_sync_position (edit_cursor->current_frame);
2446 session->add_redo_no_execute (region.playlist()->get_memento());
2447 commit_reversible_command ();
2451 Editor::remove_region_sync ()
2453 if (clicked_regionview) {
2454 Region& region (clicked_regionview->region);
2455 begin_reversible_command (_("remove sync"));
2456 session->add_undo (region.playlist()->get_memento());
2457 region.clear_sync_position ();
2458 session->add_redo_no_execute (region.playlist()->get_memento());
2459 commit_reversible_command ();
2464 Editor::naturalize ()
2466 if (selection->audio_regions.empty()) {
2469 begin_reversible_command (_("naturalize"));
2470 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2471 session->add_undo ((*i)->region.get_memento());
2472 (*i)->region.move_to_natural_position (this);
2473 session->add_redo_no_execute ((*i)->region.get_memento());
2475 commit_reversible_command ();
2479 Editor::align (RegionPoint what)
2481 align_selection (what, edit_cursor->current_frame);
2485 Editor::align_relative (RegionPoint what)
2487 align_selection_relative (what, edit_cursor->current_frame);
2490 struct RegionSortByTime {
2491 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2492 return a->region.position() < b->region.position();
2497 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
2499 if (selection->audio_regions.empty()) {
2503 jack_nframes_t distance;
2504 jack_nframes_t pos = 0;
2507 list<AudioRegionView*> sorted;
2508 selection->audio_regions.by_position (sorted);
2509 Region& r ((*sorted.begin())->region);
2513 pos = r.first_frame ();
2517 pos = r.last_frame();
2521 pos = r.adjust_to_sync (r.first_frame());
2525 if (pos > position) {
2526 distance = pos - position;
2529 distance = position - pos;
2533 begin_reversible_command (_("align selection (relative)"));
2535 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2537 Region& region ((*i)->region);
2539 session->add_undo (region.playlist()->get_memento());
2542 region.set_position (region.position() + distance, this);
2544 region.set_position (region.position() - distance, this);
2547 session->add_redo_no_execute (region.playlist()->get_memento());
2551 commit_reversible_command ();
2555 Editor::align_selection (RegionPoint point, jack_nframes_t position)
2557 if (selection->audio_regions.empty()) {
2561 begin_reversible_command (_("align selection"));
2563 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2564 align_region_internal ((*i)->region, point, position);
2567 commit_reversible_command ();
2571 Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position)
2573 begin_reversible_command (_("align region"));
2574 align_region_internal (region, point, position);
2575 commit_reversible_command ();
2579 Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
2581 session->add_undo (region.playlist()->get_memento());
2585 region.set_position (region.adjust_to_sync (position), this);
2589 if (position > region.length()) {
2590 region.set_position (position - region.length(), this);
2595 region.set_position (position, this);
2599 session->add_redo_no_execute (region.playlist()->get_memento());
2603 Editor::trim_region_to_edit_cursor ()
2605 if (clicked_regionview == 0) {
2609 Region& region (clicked_regionview->region);
2612 AudioTimeAxisView *atav;
2614 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2615 if (atav->get_diskstream() != 0) {
2616 speed = atav->get_diskstream()->speed();
2620 begin_reversible_command (_("trim to edit"));
2621 session->add_undo (region.playlist()->get_memento());
2622 region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2623 session->add_redo_no_execute (region.playlist()->get_memento());
2624 commit_reversible_command ();
2628 Editor::trim_region_from_edit_cursor ()
2630 if (clicked_regionview == 0) {
2634 Region& region (clicked_regionview->region);
2637 AudioTimeAxisView *atav;
2639 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2640 if (atav->get_diskstream() != 0) {
2641 speed = atav->get_diskstream()->speed();
2645 begin_reversible_command (_("trim to edit"));
2646 session->add_undo (region.playlist()->get_memento());
2647 region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2648 session->add_redo_no_execute (region.playlist()->get_memento());
2649 commit_reversible_command ();
2653 Editor::unfreeze_route ()
2655 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2659 clicked_audio_trackview->audio_track()->unfreeze ();
2663 Editor::_freeze_thread (void* arg)
2665 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2666 return static_cast<Editor*>(arg)->freeze_thread ();
2670 Editor::freeze_thread ()
2672 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2677 Editor::freeze_progress_timeout (void *arg)
2679 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2680 return !(current_interthread_info->done || current_interthread_info->cancel);
2684 Editor::freeze_route ()
2686 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2690 InterThreadInfo itt;
2692 if (interthread_progress_window == 0) {
2693 build_interthread_progress_window ();
2696 interthread_progress_window->set_title (_("ardour: freeze"));
2697 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2698 interthread_progress_window->show_all ();
2699 interthread_progress_bar.set_fraction (0.0f);
2700 interthread_progress_label.set_text ("");
2701 interthread_cancel_label.set_text (_("Cancel Freeze"));
2702 current_interthread_info = &itt;
2704 interthread_progress_connection =
2705 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2709 itt.progress = 0.0f;
2711 pthread_create (&itt.thread, 0, _freeze_thread, this);
2713 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2715 while (!itt.done && !itt.cancel) {
2716 gtk_main_iteration ();
2719 interthread_progress_connection.disconnect ();
2720 interthread_progress_window->hide_all ();
2721 current_interthread_info = 0;
2722 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2726 Editor::bounce_range_selection ()
2728 if (selection->time.empty()) {
2732 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2734 jack_nframes_t start = selection->time[clicked_selection].start;
2735 jack_nframes_t end = selection->time[clicked_selection].end;
2736 jack_nframes_t cnt = end - start + 1;
2738 begin_reversible_command (_("bounce range"));
2740 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2742 AudioTimeAxisView* atv;
2744 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2750 if ((playlist = atv->playlist()) == 0) {
2754 InterThreadInfo itt;
2758 itt.progress = false;
2760 session->add_undo (playlist->get_memento());
2761 atv->audio_track()->bounce_range (start, cnt, itt);
2762 session->add_redo_no_execute (playlist->get_memento());
2765 commit_reversible_command ();
2783 Editor::cut_copy (CutCopyOp op)
2785 /* only cancel selection if cut/copy is successful.*/
2797 opname = _("clear");
2801 cut_buffer->clear ();
2803 switch (current_mouse_mode()) {
2805 if (!selection->audio_regions.empty() || !selection->points.empty()) {
2807 begin_reversible_command (opname + _(" objects"));
2809 if (!selection->audio_regions.empty()) {
2811 cut_copy_regions (op);
2814 selection->clear_audio_regions ();
2818 if (!selection->points.empty()) {
2819 cut_copy_points (op);
2822 selection->clear_points ();
2826 commit_reversible_command ();
2831 if (!selection->time.empty()) {
2833 begin_reversible_command (opname + _(" range"));
2834 cut_copy_ranges (op);
2835 commit_reversible_command ();
2838 selection->clear_time ();
2850 Editor::cut_copy_points (CutCopyOp op)
2852 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2854 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2857 atv->cut_copy_clear_objects (selection->points, op);
2863 Editor::cut_copy_regions (CutCopyOp op)
2865 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
2866 PlaylistMapping pmap;
2867 jack_nframes_t first_position = max_frames;
2868 set<Playlist*> freezelist;
2869 pair<set<Playlist*>::iterator,bool> insert_result;
2871 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
2872 first_position = min ((*x)->region.position(), first_position);
2874 if (op == Cut || op == Clear) {
2875 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2877 insert_result = freezelist.insert (pl);
2878 if (insert_result.second) {
2880 session->add_undo (pl->get_memento());
2886 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
2888 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2890 AudioRegionSelection::iterator tmp;
2897 PlaylistMapping::iterator pi = pmap.find (pl);
2899 if (pi == pmap.end()) {
2900 npl = new AudioPlaylist (*session, "cutlist", true);
2909 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
2910 pl->remove_region (&((*x)->region));
2914 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
2918 pl->remove_region (&((*x)->region));
2926 list<Playlist*> foo;
2928 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2929 foo.push_back (i->second);
2933 cut_buffer->set (foo);
2936 for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2938 session->add_redo_no_execute ((*pl)->get_memento());
2943 Editor::cut_copy_ranges (CutCopyOp op)
2945 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2946 (*i)->cut_copy_clear (*selection, op);
2951 Editor::paste (float times)
2953 paste_internal (edit_cursor->current_frame, times);
2957 Editor::mouse_paste ()
2962 track_canvas.get_pointer (x, y);
2963 track_canvas.window_to_world (x, y, wx, wy);
2964 wx += horizontal_adjustment.get_value();
2965 wy += vertical_adjustment.get_value();
2968 event.type = GDK_BUTTON_RELEASE;
2969 event.button.x = wx;
2970 event.button.y = wy;
2972 jack_nframes_t where = event_frame (&event, 0, 0);
2974 paste_internal (where, 1);
2978 Editor::paste_internal (jack_nframes_t position, float times)
2980 bool commit = false;
2982 if (cut_buffer->empty() || selection->tracks.empty()) {
2986 if (position == max_frames) {
2987 position = edit_cursor->current_frame;
2990 begin_reversible_command (_("paste"));
2992 TrackSelection::iterator i;
2995 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
2997 /* undo/redo is handled by individual tracks */
2999 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3005 commit_reversible_command ();
3010 Editor::paste_named_selection (float times)
3012 TrackSelection::iterator t;
3014 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3016 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3020 TreeModel::iterator i = selected->get_selected();
3021 NamedSelection* ns = (*i)[named_selection_columns.selection];
3023 list<Playlist*>::iterator chunk;
3024 list<Playlist*>::iterator tmp;
3026 chunk = ns->playlists.begin();
3028 begin_reversible_command (_("paste chunk"));
3030 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3032 AudioTimeAxisView* atv;
3036 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3040 if ((pl = atv->playlist()) == 0) {
3044 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
3051 session->add_undo (apl->get_memento());
3052 apl->paste (**chunk, edit_cursor->current_frame, times);
3053 session->add_redo_no_execute (apl->get_memento());
3055 if (tmp != ns->playlists.end()) {
3060 commit_reversible_command();
3064 Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
3067 AudioRegionSelection sel = regions; // clear (below) will clear the argument list
3069 begin_reversible_command (_("duplicate region"));
3071 selection->clear_audio_regions ();
3073 for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3075 Region& r ((*i)->region);
3077 TimeAxisView& tv = (*i)->get_time_axis_view();
3078 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3079 sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3081 playlist = (*i)->region.playlist();
3082 session->add_undo (playlist->get_memento());
3083 playlist->duplicate (r, r.last_frame(), times);
3084 session->add_redo_no_execute (playlist->get_memento());
3088 if (latest_regionview) {
3089 selection->add (latest_regionview);
3094 commit_reversible_command ();
3098 Editor::duplicate_selection (float times)
3100 if (selection->time.empty() || selection->tracks.empty()) {
3105 vector<AudioRegion*> new_regions;
3106 vector<AudioRegion*>::iterator ri;
3108 create_region_from_selection (new_regions);
3110 if (new_regions.empty()) {
3114 begin_reversible_command (_("duplicate selection"));
3116 ri = new_regions.begin();
3118 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3119 if ((playlist = (*i)->playlist()) == 0) {
3122 session->add_undo (playlist->get_memento());
3123 playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
3124 session->add_redo_no_execute (playlist->get_memento());
3127 if (ri == new_regions.end()) {
3132 commit_reversible_command ();
3136 Editor::center_playhead ()
3138 float page = canvas_width * frames_per_unit;
3140 center_screen_internal (playhead_cursor->current_frame, page);
3144 Editor::center_edit_cursor ()
3146 float page = canvas_width * frames_per_unit;
3148 center_screen_internal (edit_cursor->current_frame, page);
3152 Editor::clear_playlist (Playlist& playlist)
3154 begin_reversible_command (_("clear playlist"));
3155 session->add_undo (playlist.get_memento());
3157 session->add_redo_no_execute (playlist.get_memento());
3158 commit_reversible_command ();
3162 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3165 jack_nframes_t distance;
3166 jack_nframes_t next_distance;
3167 jack_nframes_t start;
3169 if (use_edit_cursor) {
3170 start = edit_cursor->current_frame;
3175 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3179 if (selection->tracks.empty()) {
3183 begin_reversible_command (_("nudge track"));
3185 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3187 if ((playlist = (*i)->playlist()) == 0) {
3191 session->add_undo (playlist->get_memento());
3192 playlist->nudge_after (start, distance, forwards);
3193 session->add_redo_no_execute (playlist->get_memento());
3196 commit_reversible_command ();
3200 Editor::remove_last_capture ()
3202 vector<string> choices;
3209 if (Config->get_verify_remove_last_capture()) {
3210 prompt = _("Do you really want to destroy the last capture?"
3211 "\n(This is destructive and cannot be undone)");
3213 choices.push_back (_("Yes, destroy it."));
3214 choices.push_back (_("No, do nothing."));
3216 Gtkmm2ext::Choice prompter (prompt, choices);
3218 if (prompter.run () == 0) {
3219 session->remove_last_capture ();
3223 session->remove_last_capture();
3228 Editor::normalize_region ()
3234 if (selection->audio_regions.empty()) {
3238 begin_reversible_command (_("normalize"));
3240 track_canvas.get_window()->set_cursor (*wait_cursor);
3243 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3244 session->add_undo ((*r)->region.get_memento());
3245 (*r)->region.normalize_to (0.0f);
3246 session->add_redo_no_execute ((*r)->region.get_memento());
3249 commit_reversible_command ();
3250 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3255 Editor::denormalize_region ()
3261 if (selection->audio_regions.empty()) {
3265 begin_reversible_command ("denormalize");
3267 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3268 session->add_undo ((*r)->region.get_memento());
3269 (*r)->region.set_scale_amplitude (1.0f);
3270 session->add_redo_no_execute ((*r)->region.get_memento());
3273 commit_reversible_command ();
3278 Editor::reverse_region ()
3284 Reverse rev (*session);
3285 apply_filter (rev, _("reverse regions"));
3289 Editor::apply_filter (AudioFilter& filter, string command)
3291 if (selection->audio_regions.empty()) {
3295 begin_reversible_command (command);
3297 track_canvas.get_window()->set_cursor (*wait_cursor);
3300 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
3302 AudioRegion& region ((*r)->region);
3303 Playlist* playlist = region.playlist();
3305 AudioRegionSelection::iterator tmp;
3310 if (region.apply (filter) == 0) {
3312 session->add_undo (playlist->get_memento());
3313 playlist->replace_region (region, *(filter.results.front()), region.position());
3314 session->add_redo_no_execute (playlist->get_memento());
3322 commit_reversible_command ();
3323 selection->audio_regions.clear ();
3326 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3330 Editor::region_selection_op (void (Region::*pmf)(void))
3332 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3333 ((*i)->region.*pmf)();
3339 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3341 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3342 ((*i)->region.*pmf)(arg);
3347 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3349 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3350 ((*i)->region.*pmf)(yn);
3355 Editor::external_edit_region ()
3357 if (!clicked_regionview) {
3365 Editor::brush (jack_nframes_t pos)
3367 AudioRegionSelection sel;
3370 if (selection->audio_regions.empty()) {
3371 /* XXX get selection from region list */
3373 sel = selection->audio_regions;
3380 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3381 mouse_brush_insert_region ((*i), pos);
3386 Editor::toggle_gain_envelope_visibility ()
3388 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3389 (*i)->set_envelope_visible (!(*i)->envelope_visible());
3394 Editor::toggle_gain_envelope_active ()
3396 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3397 AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
3399 ar->set_envelope_active (true);