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"
63 #include "gui_thread.h"
68 using namespace ARDOUR;
71 using namespace Editing;
73 /***********************************************************************
75 ***********************************************************************/
78 Editor::undo (uint32_t n)
86 Editor::redo (uint32_t n)
94 Editor::set_meter_hold (int32_t cnt)
97 session->set_meter_hold (cnt);
102 Editor::set_meter_falloff (float val)
105 session->set_meter_falloff (val);
111 Editor::ensure_cursor (jack_nframes_t *pos)
113 *pos = edit_cursor->current_frame;
118 Editor::split_region ()
120 split_region_at (edit_cursor->current_frame);
124 Editor::split_region_at (jack_nframes_t where)
126 split_regions_at (where, selection->audio_regions);
130 Editor::split_regions_at (jack_nframes_t where, AudioRegionSelection& regions)
132 begin_reversible_command (_("split"));
135 for (AudioRegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
137 AudioRegionSelection::iterator tmp;
142 Playlist* pl = (*a)->region.playlist();
144 _new_regionviews_show_envelope = (*a)->envelope_visible();
147 session->add_undo (pl->get_memento());
148 pl->split_region ((*a)->region, where);
149 session->add_redo_no_execute (pl->get_memento());
155 commit_reversible_command ();
156 _new_regionviews_show_envelope = false;
160 Editor::remove_clicked_region ()
162 if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
166 Playlist* playlist = clicked_audio_trackview->playlist();
168 begin_reversible_command (_("remove region"));
169 session->add_undo (playlist->get_memento());
170 playlist->remove_region (&clicked_regionview->region);
171 session->add_redo_no_execute (playlist->get_memento());
172 commit_reversible_command ();
176 Editor::destroy_clicked_region ()
178 int32_t selected = selection->audio_regions.size();
180 if (!session || clicked_regionview == 0 && selected == 0) {
184 vector<string> choices;
187 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
188 It cannot be undone\n\
189 Do you really want to destroy %1 ?"),
191 _("these regions") : _("this region")));
194 choices.push_back (_("Yes, destroy them."));
196 choices.push_back (_("Yes, destroy it."));
199 choices.push_back (_("No, do nothing."));
201 Gtkmm2ext::Choice prompter (prompt, choices);
203 if (prompter.run() != 0) { /* first choice */
210 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
211 r.push_back (&(*i)->region);
214 session->destroy_regions (r);
216 } else if (clicked_regionview) {
217 session->destroy_region (&clicked_regionview->region);
222 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
226 jack_nframes_t start = 0;
228 if (selection->time.start () == selection->time.end_frame ()) {
230 /* no current selection-> is there a selected regionview? */
232 if (selection->audio_regions.empty()) {
240 if (!selection->audio_regions.empty()) {
242 rv = *(selection->audio_regions.begin());
243 (*tv) = &rv->get_time_axis_view();
244 region = &rv->region;
246 } else if (!selection->tracks.empty()) {
248 (*tv) = selection->tracks.front();
250 AudioTimeAxisView* atv;
252 if ((atv = dynamic_cast<AudioTimeAxisView*> (*tv)) != 0) {
255 if ((pl = atv->playlist()) == 0) {
259 region = dynamic_cast<AudioRegion*> (pl->top_region_at (start));
267 Editor::extend_selection_to_end_of_region (bool next)
271 jack_nframes_t start;
273 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
277 if (region && selection->time.start () == selection->time.end_frame ()) {
278 start = region->position();
280 start = selection->time.start ();
283 /* Try to leave the selection with the same route if possible */
285 if ((tv = selection->time.track) == 0) {
289 begin_reversible_command (_("extend selection"));
290 selection->set (tv, start, region->position() + region->length());
291 commit_reversible_command ();
295 Editor::extend_selection_to_start_of_region (bool previous)
301 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
305 if (region && selection->time.start () == selection->time.end_frame ()) {
306 end = region->position() + region->length();
308 end = selection->time.end_frame ();
311 /* Try to leave the selection with the same route if possible */
313 if ((tv = selection->time.track) == 0) {
317 begin_reversible_command (_("extend selection"));
318 selection->set (tv, region->position(), end);
319 commit_reversible_command ();
324 Editor::nudge_forward (bool next)
326 jack_nframes_t distance;
327 jack_nframes_t next_distance;
329 if (!session) return;
331 if (!selection->audio_regions.empty()) {
333 begin_reversible_command (_("nudge forward"));
335 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
336 AudioRegion& r ((*i)->region);
338 distance = get_nudge_distance (r.position(), next_distance);
341 distance = next_distance;
344 session->add_undo (r.playlist()->get_memento());
345 r.set_position (r.position() + distance, this);
346 session->add_redo_no_execute (r.playlist()->get_memento());
349 commit_reversible_command ();
352 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
353 session->request_locate (playhead_cursor->current_frame + distance);
358 Editor::nudge_backward (bool next)
360 jack_nframes_t distance;
361 jack_nframes_t next_distance;
363 if (!session) return;
365 if (!selection->audio_regions.empty()) {
367 begin_reversible_command (_("nudge forward"));
369 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
370 AudioRegion& r ((*i)->region);
372 distance = get_nudge_distance (r.position(), next_distance);
375 distance = next_distance;
378 session->add_undo (r.playlist()->get_memento());
380 if (r.position() > distance) {
381 r.set_position (r.position() - distance, this);
383 r.set_position (0, this);
385 session->add_redo_no_execute (r.playlist()->get_memento());
388 commit_reversible_command ();
392 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
394 if (playhead_cursor->current_frame > distance) {
395 session->request_locate (playhead_cursor->current_frame - distance);
397 session->goto_start();
403 Editor::nudge_forward_capture_offset ()
405 jack_nframes_t distance;
407 if (!session) return;
409 if (!selection->audio_regions.empty()) {
411 begin_reversible_command (_("nudge forward"));
413 distance = session->worst_output_latency();
415 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
416 AudioRegion& r ((*i)->region);
418 session->add_undo (r.playlist()->get_memento());
419 r.set_position (r.position() + distance, this);
420 session->add_redo_no_execute (r.playlist()->get_memento());
423 commit_reversible_command ();
429 Editor::nudge_backward_capture_offset ()
431 jack_nframes_t distance;
433 if (!session) return;
435 if (!selection->audio_regions.empty()) {
437 begin_reversible_command (_("nudge forward"));
439 distance = session->worst_output_latency();
441 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
442 AudioRegion& r ((*i)->region);
444 session->add_undo (r.playlist()->get_memento());
446 if (r.position() > distance) {
447 r.set_position (r.position() - distance, this);
449 r.set_position (0, this);
451 session->add_redo_no_execute (r.playlist()->get_memento());
454 commit_reversible_command ();
461 Editor::move_to_start ()
463 session->goto_start ();
467 Editor::move_to_end ()
470 session->request_locate (session->current_end_frame());
474 Editor::build_region_boundary_cache ()
476 jack_nframes_t pos = 0;
479 TrackViewList tracks;
481 region_boundary_cache.clear ();
488 case SnapToRegionStart:
491 case SnapToRegionEnd:
494 case SnapToRegionSync:
497 case SnapToRegionBoundary:
501 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
506 TimeAxisView *ontrack = 0;
508 while (pos < session->current_end_frame()) {
510 if (!selection->tracks.empty()) {
512 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
516 } else if (clicked_trackview) {
519 t.push_back (clicked_trackview);
521 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
527 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
535 case SnapToRegionStart:
536 rpos = r->first_frame();
538 case SnapToRegionEnd:
539 rpos = r->last_frame();
541 case SnapToRegionSync:
542 rpos = r->adjust_to_sync (r->first_frame());
545 case SnapToRegionBoundary:
546 rpos = r->last_frame();
553 AudioTimeAxisView *atav;
555 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
556 if (atav->get_diskstream() != 0) {
557 speed = atav->get_diskstream()->speed();
561 rpos = track_frame_to_session_frame(rpos, speed);
563 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
564 if (snap_type == SnapToRegionBoundary) {
565 region_boundary_cache.push_back (r->first_frame());
567 region_boundary_cache.push_back (rpos);
575 Editor::find_next_region (jack_nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
577 TrackViewList::iterator i;
578 jack_nframes_t closest = max_frames;
580 jack_nframes_t rpos = 0;
583 jack_nframes_t track_frame;
584 AudioTimeAxisView *atav;
586 for (i = tracks.begin(); i != tracks.end(); ++i) {
588 jack_nframes_t distance;
592 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
593 if (atav->get_diskstream()!=0)
594 track_speed = atav->get_diskstream()->speed();
597 track_frame = session_frame_to_track_frame(frame, track_speed);
599 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
605 rpos = r->first_frame ();
609 rpos = r->last_frame ();
613 rpos = r->adjust_to_sync (r->first_frame());
616 // rpos is a "track frame", converting it to "session frame"
617 rpos = track_frame_to_session_frame(rpos, track_speed);
620 distance = rpos - frame;
622 distance = frame - rpos;
625 if (distance < closest) {
637 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
640 jack_nframes_t pos = cursor->current_frame;
646 TimeAxisView *ontrack = 0;
648 // so we don't find the current region again..
652 if (!selection->tracks.empty()) {
654 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
656 } else if (clicked_trackview) {
659 t.push_back (clicked_trackview);
661 r = find_next_region (pos, point, dir, t, &ontrack);
665 r = find_next_region (pos, point, dir, track_views, &ontrack);
674 pos = r->first_frame ();
678 pos = r->last_frame ();
682 pos = r->adjust_to_sync (r->first_frame());
687 AudioTimeAxisView *atav;
689 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
690 if (atav->get_diskstream() != 0) {
691 speed = atav->get_diskstream()->speed();
695 pos = track_frame_to_session_frame(pos, speed);
697 if (cursor == playhead_cursor) {
698 session->request_locate (pos);
700 cursor->set_position (pos);
705 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
707 cursor_to_region_point (cursor, point, 1);
711 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
713 cursor_to_region_point (cursor, point, -1);
717 Editor::cursor_to_selection_start (Cursor *cursor)
719 jack_nframes_t pos = 0;
720 switch (mouse_mode) {
722 if (!selection->audio_regions.empty()) {
723 pos = selection->audio_regions.start();
728 if (!selection->time.empty()) {
729 pos = selection->time.start ();
737 if (cursor == playhead_cursor) {
738 session->request_locate (pos);
740 cursor->set_position (pos);
745 Editor::cursor_to_selection_end (Cursor *cursor)
747 jack_nframes_t pos = 0;
749 switch (mouse_mode) {
751 if (!selection->audio_regions.empty()) {
752 pos = selection->audio_regions.end_frame();
757 if (!selection->time.empty()) {
758 pos = selection->time.end_frame ();
766 if (cursor == playhead_cursor) {
767 session->request_locate (pos);
769 cursor->set_position (pos);
774 Editor::playhead_backward ()
781 if (get_prefix (prefix, was_floating)) {
785 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
787 cnt = (jack_nframes_t) prefix;
791 pos = playhead_cursor->current_frame;
793 if ((jack_nframes_t) pos < cnt) {
799 /* XXX this is completely insane. with the current buffering
800 design, we'll force a complete track buffer flush and
801 reload, just to move 1 sample !!!
804 session->request_locate (pos);
808 Editor::playhead_forward ()
815 if (get_prefix (prefix, was_floating)) {
819 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
821 cnt = (jack_nframes_t) floor (prefix);
825 pos = playhead_cursor->current_frame;
827 /* XXX this is completely insane. with the current buffering
828 design, we'll force a complete track buffer flush and
829 reload, just to move 1 sample !!!
832 session->request_locate (pos+cnt);
836 Editor::cursor_align (bool playhead_to_edit)
838 if (playhead_to_edit) {
840 session->request_locate (edit_cursor->current_frame);
843 edit_cursor->set_position (playhead_cursor->current_frame);
848 Editor::edit_cursor_backward ()
855 if (get_prefix (prefix, was_floating)) {
859 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
861 cnt = (jack_nframes_t) prefix;
865 pos = edit_cursor->current_frame;
867 if ((jack_nframes_t) pos < cnt) {
873 edit_cursor->set_position (pos);
877 Editor::edit_cursor_forward ()
884 if (get_prefix (prefix, was_floating)) {
888 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
890 cnt = (jack_nframes_t) floor (prefix);
894 pos = edit_cursor->current_frame;
895 edit_cursor->set_position (pos+cnt);
899 Editor::goto_frame ()
903 jack_nframes_t frame;
905 if (get_prefix (prefix, was_floating)) {
910 frame = (jack_nframes_t) floor (prefix * session->frame_rate());
912 frame = (jack_nframes_t) floor (prefix);
915 session->request_locate (frame);
919 Editor::scroll_backward (float pages)
921 jack_nframes_t frame;
922 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
927 if (get_prefix (prefix, was_floating)) {
928 cnt = (jack_nframes_t) floor (pages * one_page);
931 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
933 cnt = (jack_nframes_t) floor (prefix * one_page);
937 if (leftmost_frame < cnt) {
940 frame = leftmost_frame - cnt;
943 reposition_x_origin (frame);
947 Editor::scroll_forward (float pages)
949 jack_nframes_t frame;
950 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
955 if (get_prefix (prefix, was_floating)) {
956 cnt = (jack_nframes_t) floor (pages * one_page);
959 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
961 cnt = (jack_nframes_t) floor (prefix * one_page);
965 if (ULONG_MAX - cnt < leftmost_frame) {
966 frame = ULONG_MAX - cnt;
968 frame = leftmost_frame + cnt;
971 reposition_x_origin (frame);
975 Editor::scroll_tracks_down ()
981 if (get_prefix (prefix, was_floating)) {
984 cnt = (int) floor (prefix);
987 double vert_value = vertical_adjustment.get_value() + (cnt *
988 vertical_adjustment.get_page_size());
989 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
990 vert_value = vertical_adjustment.get_upper() - canvas_height;
992 vertical_adjustment.set_value (vert_value);
996 Editor::scroll_tracks_up ()
1002 if (get_prefix (prefix, was_floating)) {
1005 cnt = (int) floor (prefix);
1008 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1012 Editor::scroll_tracks_down_line ()
1015 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1016 double vert_value = adj->get_value() + 20;
1018 if (vert_value>adj->get_upper() - canvas_height) {
1019 vert_value = adj->get_upper() - canvas_height;
1021 adj->set_value (vert_value);
1025 Editor::scroll_tracks_up_line ()
1027 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1028 adj->set_value (adj->get_value() - 20);
1034 Editor::temporal_zoom_step (bool coarser)
1036 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1040 nfpu = frames_per_unit;
1045 nfpu = max(1.0,(nfpu/2.0));
1048 temporal_zoom (nfpu);
1052 Editor::temporal_zoom (gdouble fpu)
1054 if (!session) return;
1056 jack_nframes_t current_page = current_page_frames();
1057 jack_nframes_t current_leftmost = leftmost_frame;
1058 jack_nframes_t current_rightmost;
1059 jack_nframes_t current_center;
1060 jack_nframes_t new_page;
1061 jack_nframes_t leftmost_after_zoom = 0;
1066 new_page = (jack_nframes_t) floor (canvas_width * nfpu);
1068 switch (zoom_focus) {
1070 leftmost_after_zoom = current_leftmost;
1073 case ZoomFocusRight:
1074 current_rightmost = leftmost_frame + current_page;
1075 if (current_rightmost > new_page) {
1076 leftmost_after_zoom = current_rightmost - new_page;
1078 leftmost_after_zoom = 0;
1082 case ZoomFocusCenter:
1083 current_center = current_leftmost + (current_page/2);
1084 if (current_center > (new_page/2)) {
1085 leftmost_after_zoom = current_center - (new_page / 2);
1087 leftmost_after_zoom = 0;
1091 case ZoomFocusPlayhead:
1092 /* try to keep the playhead in the center */
1093 if (playhead_cursor->current_frame > new_page/2) {
1094 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1096 leftmost_after_zoom = 0;
1101 /* try to keep the edit cursor in the center */
1102 if (edit_cursor->current_frame > leftmost_frame + (new_page/2)) {
1103 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1105 leftmost_after_zoom = 0;
1111 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1113 // begin_reversible_command (_("zoom"));
1114 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1115 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1116 // commit_reversible_command ();
1118 reposition_and_zoom (leftmost_after_zoom, nfpu);
1122 Editor::temporal_zoom_selection ()
1124 if (!selection) return;
1126 if (selection->time.empty()) {
1130 jack_nframes_t start = selection->time[clicked_selection].start;
1131 jack_nframes_t end = selection->time[clicked_selection].end;
1133 temporal_zoom_by_frame (start, end, "zoom to selection");
1137 Editor::temporal_zoom_session ()
1139 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1142 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1147 Editor::temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, const string & op)
1149 if (!session) return;
1151 if ((start == 0 && end == 0) || end < start) {
1155 jack_nframes_t range = end - start;
1157 double new_fpu = (double)range / (double)canvas_width;
1160 // while (p2 < new_fpu) {
1165 jack_nframes_t new_page = (jack_nframes_t) floor (canvas_width * new_fpu);
1166 jack_nframes_t middle = (jack_nframes_t) floor( (double)start + ((double)range / 2.0f ));
1167 jack_nframes_t new_leftmost = (jack_nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1169 if (new_leftmost > middle) new_leftmost = 0;
1171 // begin_reversible_command (op);
1172 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1173 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1174 // commit_reversible_command ();
1176 reposition_and_zoom (new_leftmost, new_fpu);
1180 Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
1182 if (!session) return;
1184 jack_nframes_t range_before = frame - leftmost_frame;
1187 new_fpu = frames_per_unit;
1193 new_fpu = max(1.0,(new_fpu/2.0));
1197 if (new_fpu == frames_per_unit) return;
1199 jack_nframes_t new_leftmost = frame - range_before;
1201 if (new_leftmost > frame) new_leftmost = 0;
1203 // begin_reversible_command (_("zoom to frame"));
1204 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1205 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1206 // commit_reversible_command ();
1208 reposition_and_zoom (new_leftmost, new_fpu);
1212 Editor::add_location_from_selection ()
1214 if (selection->time.empty()) {
1218 if (session == 0 || clicked_trackview == 0) {
1222 jack_nframes_t start = selection->time[clicked_selection].start;
1223 jack_nframes_t end = selection->time[clicked_selection].end;
1225 Location *location = new Location (start, end, "selection");
1227 session->begin_reversible_command (_("add marker"));
1228 session->add_undo (session->locations()->get_memento());
1229 session->locations()->add (location, true);
1230 session->add_redo_no_execute (session->locations()->get_memento());
1231 session->commit_reversible_command ();
1235 Editor::add_location_from_playhead_cursor ()
1237 jack_nframes_t where = session->audible_frame();
1239 Location *location = new Location (where, where, "mark", Location::IsMark);
1240 session->begin_reversible_command (_("add marker"));
1241 session->add_undo (session->locations()->get_memento());
1242 session->locations()->add (location, true);
1243 session->add_redo_no_execute (session->locations()->get_memento());
1244 session->commit_reversible_command ();
1248 Editor::add_location_from_audio_region ()
1250 if (selection->audio_regions.empty()) {
1254 AudioRegionView* rv = *(selection->audio_regions.begin());
1255 Region& region = rv->region;
1257 Location *location = new Location (region.position(), region.last_frame(), region.name());
1258 session->begin_reversible_command (_("add marker"));
1259 session->add_undo (session->locations()->get_memento());
1260 session->locations()->add (location, true);
1261 session->add_redo_no_execute (session->locations()->get_memento());
1262 session->commit_reversible_command ();
1266 Editor::select_all_in_track (Selection::Operation op)
1268 list<Selectable *> touched;
1270 if (!clicked_trackview) {
1274 clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1277 case Selection::Toggle:
1278 selection->add (touched);
1280 case Selection::Set:
1281 selection->set (touched);
1283 case Selection::Extend:
1284 /* not defined yet */
1290 Editor::select_all (Selection::Operation op)
1292 list<Selectable *> touched;
1294 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1295 if ((*iter)->hidden()) {
1298 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1300 begin_reversible_command (_("select all"));
1302 case Selection::Toggle:
1303 selection->add (touched);
1305 case Selection::Set:
1306 selection->set (touched);
1308 case Selection::Extend:
1309 /* not defined yet */
1312 commit_reversible_command ();
1316 Editor::invert_selection_in_track ()
1318 list<Selectable *> touched;
1320 if (!clicked_trackview) {
1324 clicked_trackview->get_inverted_selectables (*selection, touched);
1325 selection->set (touched);
1329 Editor::invert_selection ()
1331 list<Selectable *> touched;
1333 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1334 if ((*iter)->hidden()) {
1337 (*iter)->get_inverted_selectables (*selection, touched);
1340 selection->set (touched);
1344 Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, Selection::Operation op)
1346 list<Selectable *> touched;
1348 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1349 if ((*iter)->hidden()) {
1352 (*iter)->get_selectables (start, end, top, bot, touched);
1354 begin_reversible_command (_("select all within"));
1356 case Selection::Toggle:
1357 selection->add (touched);
1359 case Selection::Set:
1360 selection->set (touched);
1362 case Selection::Extend:
1363 /* not defined yet */
1366 commit_reversible_command ();
1367 return !touched.empty();
1371 Editor::set_selection_from_audio_region ()
1373 if (selection->audio_regions.empty()) {
1377 AudioRegionView* rv = *(selection->audio_regions.begin());
1378 Region& region = rv->region;
1380 begin_reversible_command (_("set selection from region"));
1381 selection->set (0, region.position(), region.last_frame());
1382 commit_reversible_command ();
1384 set_mouse_mode (Editing::MouseRange, false);
1388 Editor::set_selection_from_punch()
1392 if ((location = session->locations()->auto_punch_location()) == 0) {
1396 set_selection_from_range (*location);
1400 Editor::set_selection_from_loop()
1404 if ((location = session->locations()->auto_loop_location()) == 0) {
1407 set_selection_from_range (*location);
1411 Editor::set_selection_from_range (Location& loc)
1413 begin_reversible_command (_("set selection from range"));
1414 selection->set (0, loc.start(), loc.end());
1415 commit_reversible_command ();
1417 set_mouse_mode (Editing::MouseRange, false);
1421 Editor::select_all_selectables_using_time_selection ()
1423 list<Selectable *> touched;
1425 if (selection->time.empty()) {
1429 jack_nframes_t start = selection->time[clicked_selection].start;
1430 jack_nframes_t end = selection->time[clicked_selection].end;
1432 if (end - start < 1) {
1436 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1437 if ((*iter)->hidden()) {
1440 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1443 begin_reversible_command (_("select all from range"));
1444 selection->set (touched);
1445 commit_reversible_command ();
1450 Editor::select_all_selectables_using_punch()
1452 Location* location = session->locations()->auto_punch_location();
1453 list<Selectable *> touched;
1455 if (location == 0 || (location->end() - location->start() <= 1)) {
1459 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1460 if ((*iter)->hidden()) {
1463 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1465 begin_reversible_command (_("select all from punch"));
1466 selection->set (touched);
1467 commit_reversible_command ();
1472 Editor::select_all_selectables_using_loop()
1474 Location* location = session->locations()->auto_loop_location();
1475 list<Selectable *> touched;
1477 if (location == 0 || (location->end() - location->start() <= 1)) {
1481 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1482 if ((*iter)->hidden()) {
1485 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1487 begin_reversible_command (_("select all from loop"));
1488 selection->set (touched);
1489 commit_reversible_command ();
1494 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1496 jack_nframes_t start;
1498 list<Selectable *> touched;
1501 begin_reversible_command (_("select all after cursor"));
1502 start = cursor->current_frame ;
1503 end = session->current_end_frame();
1505 if (cursor->current_frame > 0) {
1506 begin_reversible_command (_("select all before cursor"));
1508 end = cursor->current_frame - 1;
1514 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1515 if ((*iter)->hidden()) {
1518 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1520 selection->set (touched);
1521 commit_reversible_command ();
1525 Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
1527 jack_nframes_t start;
1529 list<Selectable *> touched;
1530 bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
1532 if (cursor->current_frame == other_cursor->current_frame) {
1536 begin_reversible_command (_("select all between cursors"));
1537 if (other_cursor_is_first) {
1538 start = other_cursor->current_frame;
1539 end = cursor->current_frame - 1;
1542 start = cursor->current_frame;
1543 end = other_cursor->current_frame - 1;
1546 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1547 if ((*iter)->hidden()) {
1550 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1552 selection->set (touched);
1553 commit_reversible_command ();
1557 Editor::amplitude_zoom_step (bool in)
1571 #ifdef FIX_FOR_CANVAS
1572 /* XXX DO SOMETHING */
1581 Editor::delete_sample_forward ()
1586 Editor::delete_sample_backward ()
1591 Editor::delete_screen ()
1598 Editor::search_backwards ()
1604 Editor::search_forwards ()
1612 Editor::jump_forward_to_mark ()
1618 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1621 session->request_locate (location->start(), session->transport_rolling());
1623 session->request_locate (session->current_end_frame());
1628 Editor::jump_backward_to_mark ()
1634 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1637 session->request_locate (location->start(), session->transport_rolling());
1639 session->goto_start ();
1650 if (get_prefix (prefix, was_floating)) {
1651 pos = session->audible_frame ();
1654 pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
1656 pos = (jack_nframes_t) floor (prefix);
1660 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1664 Editor::clear_markers ()
1667 session->begin_reversible_command (_("clear markers"));
1668 session->add_undo (session->locations()->get_memento());
1669 session->locations()->clear_markers ();
1670 session->add_redo_no_execute (session->locations()->get_memento());
1671 session->commit_reversible_command ();
1676 Editor::clear_ranges ()
1679 session->begin_reversible_command (_("clear ranges"));
1680 session->add_undo (session->locations()->get_memento());
1682 Location * looploc = session->locations()->auto_loop_location();
1683 Location * punchloc = session->locations()->auto_punch_location();
1685 session->locations()->clear_ranges ();
1687 if (looploc) session->locations()->add (looploc);
1688 if (punchloc) session->locations()->add (punchloc);
1690 session->add_redo_no_execute (session->locations()->get_memento());
1691 session->commit_reversible_command ();
1696 Editor::clear_locations ()
1698 session->begin_reversible_command (_("clear locations"));
1699 session->add_undo (session->locations()->get_memento());
1700 session->locations()->clear ();
1701 session->add_redo_no_execute (session->locations()->get_memento());
1702 session->commit_reversible_command ();
1703 session->locations()->clear ();
1706 /* INSERT/REPLACE */
1709 Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
1714 jack_nframes_t where;
1715 AudioTimeAxisView *atv = 0;
1718 track_canvas.window_to_world (x, y, wx, wy);
1719 wx += horizontal_adjustment.get_value();
1720 wy += vertical_adjustment.get_value();
1723 event.type = GDK_BUTTON_RELEASE;
1724 event.button.x = wx;
1725 event.button.y = wy;
1727 where = event_frame (&event, &cx, &cy);
1729 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1730 /* clearly outside canvas area */
1734 if ((tv = trackview_by_y_position (cy)) == 0) {
1738 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1742 if ((playlist = atv->playlist()) == 0) {
1748 begin_reversible_command (_("insert dragged region"));
1749 session->add_undo (playlist->get_memento());
1750 playlist->add_region (*(new AudioRegion (region)), where, 1.0);
1751 session->add_redo_no_execute (playlist->get_memento());
1752 commit_reversible_command ();
1756 Editor::insert_region_list_selection (float times)
1758 AudioTimeAxisView *tv = 0;
1761 if (clicked_audio_trackview != 0) {
1762 tv = clicked_audio_trackview;
1763 } else if (!selection->tracks.empty()) {
1764 if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
1771 if ((playlist = tv->playlist()) == 0) {
1775 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1777 if (selected->count_selected_rows() != 1) {
1781 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
1782 Region* region = (*i)[region_list_columns.region];
1784 begin_reversible_command (_("insert region"));
1785 session->add_undo (playlist->get_memento());
1786 playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
1787 session->add_redo_no_execute (playlist->get_memento());
1788 commit_reversible_command ();
1792 /* BUILT-IN EFFECTS */
1795 Editor::reverse_selection ()
1800 /* GAIN ENVELOPE EDITING */
1803 Editor::edit_envelope ()
1810 Editor::toggle_playback (bool with_abort)
1816 switch (session->slave_source()) {
1821 /* transport controlled by the master */
1825 if (session->is_auditioning()) {
1826 session->cancel_audition ();
1830 if (session->transport_rolling()) {
1831 session->request_stop (with_abort);
1832 if (session->get_auto_loop()) {
1833 session->request_auto_loop (false);
1836 session->request_transport_speed (1.0f);
1841 Editor::play_from_start ()
1843 session->request_locate (session->current_start_frame(), true);
1847 Editor::play_selection ()
1849 if (selection->time.empty()) {
1853 session->request_play_range (true);
1857 Editor::play_selected_region ()
1859 if (!selection->audio_regions.empty()) {
1860 AudioRegionView *rv = *(selection->audio_regions.begin());
1862 session->request_bounded_roll (rv->region.position(), rv->region.last_frame());
1867 Editor::loop_selected_region ()
1869 if (!selection->audio_regions.empty()) {
1870 AudioRegionView *rv = *(selection->audio_regions.begin());
1873 if ((tll = transport_loop_location()) != 0) {
1875 tll->set (rv->region.position(), rv->region.last_frame());
1877 // enable looping, reposition and start rolling
1879 session->request_auto_loop (true);
1880 session->request_locate (tll->start(), false);
1881 session->request_transport_speed (1.0f);
1887 Editor::play_location (Location& location)
1889 if (location.start() <= location.end()) {
1893 session->request_bounded_roll (location.start(), location.end());
1897 Editor::loop_location (Location& location)
1899 if (location.start() <= location.end()) {
1905 if ((tll = transport_loop_location()) != 0) {
1906 tll->set (location.start(), location.end());
1908 // enable looping, reposition and start rolling
1909 session->request_auto_loop (true);
1910 session->request_locate (tll->start(), true);
1915 Editor::toggle_region_mute ()
1917 if (clicked_regionview) {
1918 clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
1919 } else if (!selection->audio_regions.empty()) {
1920 bool yn = ! (*selection->audio_regions.begin())->region.muted();
1921 selection->foreach_audio_region (&AudioRegion::set_muted, yn);
1926 Editor::toggle_region_opaque ()
1928 if (clicked_regionview) {
1929 clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
1930 } else if (!selection->audio_regions.empty()) {
1931 bool yn = ! (*selection->audio_regions.begin())->region.opaque();
1932 selection->foreach_audio_region (&Region::set_opaque, yn);
1937 Editor::raise_region ()
1939 selection->foreach_audio_region (&Region::raise);
1943 Editor::raise_region_to_top ()
1945 selection->foreach_audio_region (&Region::raise_to_top);
1949 Editor::lower_region ()
1951 selection->foreach_audio_region (&Region::lower);
1955 Editor::lower_region_to_bottom ()
1957 selection->foreach_audio_region (&Region::lower_to_bottom);
1961 Editor::edit_region ()
1963 if (clicked_regionview == 0) {
1967 clicked_regionview->show_region_editor ();
1971 Editor::rename_region ()
1975 Button ok_button (_("OK"));
1976 Button cancel_button (_("Cancel"));
1978 if (selection->audio_regions.empty()) {
1982 dialog.set_title (_("ardour: rename region"));
1983 dialog.set_name ("RegionRenameWindow");
1984 dialog.set_size_request (300, -1);
1985 dialog.set_position (Gtk::WIN_POS_MOUSE);
1986 dialog.set_modal (true);
1988 dialog.get_vbox()->set_border_width (10);
1989 dialog.get_vbox()->pack_start (entry);
1990 dialog.get_action_area()->pack_start (ok_button);
1991 dialog.get_action_area()->pack_start (cancel_button);
1993 entry.set_name ("RegionNameDisplay");
1994 ok_button.set_name ("EditorGTKButton");
1995 cancel_button.set_name ("EditorGTKButton");
1997 region_renamed = false;
1999 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2000 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2001 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
2008 if (region_renamed) {
2009 (*selection->audio_regions.begin())->region.set_name (entry.get_text());
2010 redisplay_regions ();
2015 Editor::rename_region_finished (bool status)
2018 region_renamed = status;
2023 Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
2025 if (session->is_auditioning()) {
2026 session->cancel_audition ();
2029 // note: some potential for creativity here, because region doesn't
2030 // have to belong to the playlist that Route is handling
2032 // bool was_soloed = route.soloed();
2034 route.set_solo (true, this);
2036 session->request_bounded_roll (region.position(), region.position() + region.length());
2038 /* XXX how to unset the solo state ? */
2042 Editor::audition_selected_region ()
2044 if (!selection->audio_regions.empty()) {
2045 AudioRegionView* rv = *(selection->audio_regions.begin());
2046 session->audition_region (rv->region);
2051 Editor::audition_playlist_region_standalone (AudioRegion& region)
2053 session->audition_region (region);
2057 Editor::build_interthread_progress_window ()
2059 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
2061 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
2063 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
2064 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
2066 // GTK2FIX: this button needs a modifiable label
2068 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
2069 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
2071 interthread_cancel_button.add (interthread_cancel_label);
2073 interthread_progress_window->set_default_size (200, 100);
2077 Editor::interthread_cancel_clicked ()
2079 if (current_interthread_info) {
2080 current_interthread_info->cancel = true;
2085 Editor::region_from_selection ()
2087 if (clicked_trackview == 0) {
2091 if (selection->time.empty()) {
2095 jack_nframes_t start = selection->time[clicked_selection].start;
2096 jack_nframes_t end = selection->time[clicked_selection].end;
2098 jack_nframes_t selection_cnt = end - start + 1;
2100 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2102 AudioRegion *region;
2103 AudioRegion *current;
2107 jack_nframes_t internal_start;
2110 if ((pl = (*i)->playlist()) == 0) {
2114 if ((current_r = pl->top_region_at (start)) == 0) {
2118 if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
2119 internal_start = start - current->position();
2120 session->region_name (new_name, current->name(), true);
2121 region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
2127 Editor::create_region_from_selection (vector<AudioRegion *>& new_regions)
2129 if (selection->time.empty() || selection->tracks.empty()) {
2133 jack_nframes_t start = selection->time[clicked_selection].start;
2134 jack_nframes_t end = selection->time[clicked_selection].end;
2136 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2138 AudioRegion* current;
2141 jack_nframes_t internal_start;
2144 if ((playlist = (*i)->playlist()) == 0) {
2148 if ((current_r = playlist->top_region_at(start)) == 0) {
2152 if ((current = dynamic_cast<AudioRegion*>(current_r)) == 0) {
2156 internal_start = start - current->position();
2157 session->region_name (new_name, current->name(), true);
2159 new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name));
2164 Editor::split_multichannel_region ()
2166 vector<AudioRegion*> v;
2168 if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
2172 clicked_regionview->region.separate_by_channel (*session, v);
2174 /* nothing else to do, really */
2178 Editor::new_region_from_selection ()
2180 region_from_selection ();
2181 cancel_selection ();
2185 Editor::separate_region_from_selection ()
2187 bool doing_undo = false;
2189 if (selection->time.empty()) {
2195 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2197 AudioTimeAxisView* atv;
2199 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2201 if (atv->is_audio_track()) {
2203 if ((playlist = atv->playlist()) != 0) {
2205 begin_reversible_command (_("separate"));
2208 if (doing_undo) session->add_undo ((playlist)->get_memento());
2210 /* XXX need to consider musical time selections here at some point */
2212 double speed = atv->get_diskstream()->speed();
2214 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2215 playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
2218 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2224 if (doing_undo) commit_reversible_command ();
2228 Editor::separate_regions_using_location (Location& loc)
2230 bool doing_undo = false;
2232 if (loc.is_mark()) {
2238 /* XXX i'm unsure as to whether this should operate on selected tracks only
2239 or the entire enchillada. uncomment the below line to correct the behaviour
2240 (currently set for all tracks)
2243 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2244 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2246 AudioTimeAxisView* atv;
2248 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2250 if (atv->is_audio_track()) {
2252 if ((playlist = atv->playlist()) != 0) {
2254 begin_reversible_command (_("separate"));
2257 if (doing_undo) session->add_undo ((playlist)->get_memento());
2259 /* XXX need to consider musical time selections here at some point */
2261 double speed = atv->get_diskstream()->speed();
2264 playlist->partition ((jack_nframes_t)(loc.start() * speed), (jack_nframes_t)(loc.end() * speed), true);
2265 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2271 if (doing_undo) commit_reversible_command ();
2275 Editor::crop_region_to_selection ()
2277 if (selection->time.empty()) {
2281 vector<Playlist*> playlists;
2284 if (clicked_trackview != 0) {
2286 if ((playlist = clicked_trackview->playlist()) == 0) {
2290 playlists.push_back (playlist);
2294 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2296 AudioTimeAxisView* atv;
2298 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2300 if (atv->is_audio_track()) {
2302 if ((playlist = atv->playlist()) != 0) {
2303 playlists.push_back (playlist);
2310 if (!playlists.empty()) {
2312 jack_nframes_t start;
2316 begin_reversible_command (_("trim to selection"));
2318 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2322 start = selection->time.start();
2324 if ((region = (*i)->top_region_at(start)) == 0) {
2328 /* now adjust lengths to that we do the right thing
2329 if the selection extends beyond the region
2332 start = max (start, region->position());
2333 end = min (selection->time.end_frame(), start + region->length() - 1);
2334 cnt = end - start + 1;
2336 session->add_undo ((*i)->get_memento());
2337 region->trim_to (start, cnt, this);
2338 session->add_redo_no_execute ((*i)->get_memento());
2341 commit_reversible_command ();
2346 Editor::region_fill_track ()
2350 if (!session || selection->audio_regions.empty()) {
2354 end = session->current_end_frame ();
2356 begin_reversible_command (_("region fill"));
2358 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2360 AudioRegion& region ((*i)->region);
2361 Playlist* pl = region.playlist();
2363 if (end <= region.last_frame()) {
2367 double times = (double) (end - region.last_frame()) / (double) region.length();
2373 session->add_undo (pl->get_memento());
2374 pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
2375 session->add_redo_no_execute (pl->get_memento());
2378 commit_reversible_command ();
2382 Editor::region_fill_selection ()
2384 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2388 if (selection->time.empty()) {
2394 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2396 if (selected->count_selected_rows() != 1) {
2400 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2401 region = (*i)[region_list_columns.region];
2403 jack_nframes_t start = selection->time[clicked_selection].start;
2404 jack_nframes_t end = selection->time[clicked_selection].end;
2408 if (selection->tracks.empty()) {
2412 jack_nframes_t selection_length = end - start;
2413 float times = (float)selection_length / region->length();
2415 begin_reversible_command (_("fill selection"));
2417 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2419 if ((playlist = (*i)->playlist()) == 0) {
2423 session->add_undo (playlist->get_memento());
2424 playlist->add_region (*(createRegion (*region)), start, times);
2425 session->add_redo_no_execute (playlist->get_memento());
2428 commit_reversible_command ();
2432 Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
2435 if (!region.covers (position)) {
2436 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2439 begin_reversible_command (_("set region sync position"));
2440 session->add_undo (region.playlist()->get_memento());
2441 region.set_sync_position (position);
2442 session->add_redo_no_execute (region.playlist()->get_memento());
2443 commit_reversible_command ();
2447 Editor::set_region_sync_from_edit_cursor ()
2449 if (clicked_regionview == 0) {
2453 if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
2454 error << _("Place the edit cursor at the desired sync point") << endmsg;
2458 Region& region (clicked_regionview->region);
2459 begin_reversible_command (_("set sync from edit cursor"));
2460 session->add_undo (region.playlist()->get_memento());
2461 region.set_sync_position (edit_cursor->current_frame);
2462 session->add_redo_no_execute (region.playlist()->get_memento());
2463 commit_reversible_command ();
2467 Editor::remove_region_sync ()
2469 if (clicked_regionview) {
2470 Region& region (clicked_regionview->region);
2471 begin_reversible_command (_("remove sync"));
2472 session->add_undo (region.playlist()->get_memento());
2473 region.clear_sync_position ();
2474 session->add_redo_no_execute (region.playlist()->get_memento());
2475 commit_reversible_command ();
2480 Editor::naturalize ()
2482 if (selection->audio_regions.empty()) {
2485 begin_reversible_command (_("naturalize"));
2486 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2487 session->add_undo ((*i)->region.get_memento());
2488 (*i)->region.move_to_natural_position (this);
2489 session->add_redo_no_execute ((*i)->region.get_memento());
2491 commit_reversible_command ();
2495 Editor::align (RegionPoint what)
2497 align_selection (what, edit_cursor->current_frame);
2501 Editor::align_relative (RegionPoint what)
2503 align_selection_relative (what, edit_cursor->current_frame);
2506 struct RegionSortByTime {
2507 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2508 return a->region.position() < b->region.position();
2513 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
2515 if (selection->audio_regions.empty()) {
2519 jack_nframes_t distance;
2520 jack_nframes_t pos = 0;
2523 list<AudioRegionView*> sorted;
2524 selection->audio_regions.by_position (sorted);
2525 Region& r ((*sorted.begin())->region);
2529 pos = r.first_frame ();
2533 pos = r.last_frame();
2537 pos = r.adjust_to_sync (r.first_frame());
2541 if (pos > position) {
2542 distance = pos - position;
2545 distance = position - pos;
2549 begin_reversible_command (_("align selection (relative)"));
2551 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2553 Region& region ((*i)->region);
2555 session->add_undo (region.playlist()->get_memento());
2558 region.set_position (region.position() + distance, this);
2560 region.set_position (region.position() - distance, this);
2563 session->add_redo_no_execute (region.playlist()->get_memento());
2567 commit_reversible_command ();
2571 Editor::align_selection (RegionPoint point, jack_nframes_t position)
2573 if (selection->audio_regions.empty()) {
2577 begin_reversible_command (_("align selection"));
2579 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2580 align_region_internal ((*i)->region, point, position);
2583 commit_reversible_command ();
2587 Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position)
2589 begin_reversible_command (_("align region"));
2590 align_region_internal (region, point, position);
2591 commit_reversible_command ();
2595 Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
2597 session->add_undo (region.playlist()->get_memento());
2601 region.set_position (region.adjust_to_sync (position), this);
2605 if (position > region.length()) {
2606 region.set_position (position - region.length(), this);
2611 region.set_position (position, this);
2615 session->add_redo_no_execute (region.playlist()->get_memento());
2619 Editor::trim_region_to_edit_cursor ()
2621 if (clicked_regionview == 0) {
2625 Region& region (clicked_regionview->region);
2628 AudioTimeAxisView *atav;
2630 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2631 if (atav->get_diskstream() != 0) {
2632 speed = atav->get_diskstream()->speed();
2636 begin_reversible_command (_("trim to edit"));
2637 session->add_undo (region.playlist()->get_memento());
2638 region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2639 session->add_redo_no_execute (region.playlist()->get_memento());
2640 commit_reversible_command ();
2644 Editor::trim_region_from_edit_cursor ()
2646 if (clicked_regionview == 0) {
2650 Region& region (clicked_regionview->region);
2653 AudioTimeAxisView *atav;
2655 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2656 if (atav->get_diskstream() != 0) {
2657 speed = atav->get_diskstream()->speed();
2661 begin_reversible_command (_("trim to edit"));
2662 session->add_undo (region.playlist()->get_memento());
2663 region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2664 session->add_redo_no_execute (region.playlist()->get_memento());
2665 commit_reversible_command ();
2669 Editor::unfreeze_route ()
2671 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2675 clicked_audio_trackview->audio_track()->unfreeze ();
2679 Editor::_freeze_thread (void* arg)
2681 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2682 return static_cast<Editor*>(arg)->freeze_thread ();
2686 Editor::freeze_thread ()
2688 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2693 Editor::freeze_progress_timeout (void *arg)
2695 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2696 return !(current_interthread_info->done || current_interthread_info->cancel);
2700 Editor::freeze_route ()
2702 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2706 InterThreadInfo itt;
2708 if (interthread_progress_window == 0) {
2709 build_interthread_progress_window ();
2712 interthread_progress_window->set_title (_("ardour: freeze"));
2713 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2714 interthread_progress_window->show_all ();
2715 interthread_progress_bar.set_fraction (0.0f);
2716 interthread_progress_label.set_text ("");
2717 interthread_cancel_label.set_text (_("Cancel Freeze"));
2718 current_interthread_info = &itt;
2720 interthread_progress_connection =
2721 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2725 itt.progress = 0.0f;
2727 pthread_create (&itt.thread, 0, _freeze_thread, this);
2729 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2731 while (!itt.done && !itt.cancel) {
2732 gtk_main_iteration ();
2735 interthread_progress_connection.disconnect ();
2736 interthread_progress_window->hide_all ();
2737 current_interthread_info = 0;
2738 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2742 Editor::bounce_range_selection ()
2744 if (selection->time.empty()) {
2748 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2750 jack_nframes_t start = selection->time[clicked_selection].start;
2751 jack_nframes_t end = selection->time[clicked_selection].end;
2752 jack_nframes_t cnt = end - start + 1;
2754 begin_reversible_command (_("bounce range"));
2756 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2758 AudioTimeAxisView* atv;
2760 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2766 if ((playlist = atv->playlist()) == 0) {
2770 InterThreadInfo itt;
2774 itt.progress = false;
2776 session->add_undo (playlist->get_memento());
2777 atv->audio_track()->bounce_range (start, cnt, itt);
2778 session->add_redo_no_execute (playlist->get_memento());
2781 commit_reversible_command ();
2799 Editor::cut_copy (CutCopyOp op)
2801 /* only cancel selection if cut/copy is successful.*/
2813 opname = _("clear");
2817 cut_buffer->clear ();
2819 switch (current_mouse_mode()) {
2821 if (!selection->audio_regions.empty() || !selection->points.empty()) {
2823 begin_reversible_command (opname + _(" objects"));
2825 if (!selection->audio_regions.empty()) {
2827 cut_copy_regions (op);
2830 selection->clear_audio_regions ();
2834 if (!selection->points.empty()) {
2835 cut_copy_points (op);
2838 selection->clear_points ();
2842 commit_reversible_command ();
2847 if (!selection->time.empty()) {
2849 begin_reversible_command (opname + _(" range"));
2850 cut_copy_ranges (op);
2851 commit_reversible_command ();
2854 selection->clear_time ();
2866 Editor::cut_copy_points (CutCopyOp op)
2868 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2870 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2873 atv->cut_copy_clear_objects (selection->points, op);
2879 Editor::cut_copy_regions (CutCopyOp op)
2881 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
2882 PlaylistMapping pmap;
2883 jack_nframes_t first_position = max_frames;
2884 set<Playlist*> freezelist;
2885 pair<set<Playlist*>::iterator,bool> insert_result;
2887 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
2888 first_position = min ((*x)->region.position(), first_position);
2890 if (op == Cut || op == Clear) {
2891 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2893 insert_result = freezelist.insert (pl);
2894 if (insert_result.second) {
2896 session->add_undo (pl->get_memento());
2902 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
2904 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2906 AudioRegionSelection::iterator tmp;
2913 PlaylistMapping::iterator pi = pmap.find (pl);
2915 if (pi == pmap.end()) {
2916 npl = new AudioPlaylist (*session, "cutlist", true);
2925 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
2926 pl->remove_region (&((*x)->region));
2930 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
2934 pl->remove_region (&((*x)->region));
2942 list<Playlist*> foo;
2944 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2945 foo.push_back (i->second);
2949 cut_buffer->set (foo);
2952 for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2954 session->add_redo_no_execute ((*pl)->get_memento());
2959 Editor::cut_copy_ranges (CutCopyOp op)
2961 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2962 (*i)->cut_copy_clear (*selection, op);
2967 Editor::paste (float times)
2969 paste_internal (edit_cursor->current_frame, times);
2973 Editor::mouse_paste ()
2978 track_canvas.get_pointer (x, y);
2979 track_canvas.window_to_world (x, y, wx, wy);
2980 wx += horizontal_adjustment.get_value();
2981 wy += vertical_adjustment.get_value();
2984 event.type = GDK_BUTTON_RELEASE;
2985 event.button.x = wx;
2986 event.button.y = wy;
2988 jack_nframes_t where = event_frame (&event, 0, 0);
2990 paste_internal (where, 1);
2994 Editor::paste_internal (jack_nframes_t position, float times)
2996 bool commit = false;
2998 if (cut_buffer->empty() || selection->tracks.empty()) {
3002 if (position == max_frames) {
3003 position = edit_cursor->current_frame;
3006 begin_reversible_command (_("paste"));
3008 TrackSelection::iterator i;
3011 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
3013 /* undo/redo is handled by individual tracks */
3015 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3021 commit_reversible_command ();
3026 Editor::paste_named_selection (float times)
3028 TrackSelection::iterator t;
3030 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3032 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3036 TreeModel::iterator i = selected->get_selected();
3037 NamedSelection* ns = (*i)[named_selection_columns.selection];
3039 list<Playlist*>::iterator chunk;
3040 list<Playlist*>::iterator tmp;
3042 chunk = ns->playlists.begin();
3044 begin_reversible_command (_("paste chunk"));
3046 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3048 AudioTimeAxisView* atv;
3052 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3056 if ((pl = atv->playlist()) == 0) {
3060 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
3067 session->add_undo (apl->get_memento());
3068 apl->paste (**chunk, edit_cursor->current_frame, times);
3069 session->add_redo_no_execute (apl->get_memento());
3071 if (tmp != ns->playlists.end()) {
3076 commit_reversible_command();
3080 Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
3083 AudioRegionSelection sel = regions; // clear (below) will clear the argument list
3085 begin_reversible_command (_("duplicate region"));
3087 selection->clear_audio_regions ();
3089 for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3091 Region& r ((*i)->region);
3093 TimeAxisView& tv = (*i)->get_time_axis_view();
3094 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3095 sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3097 playlist = (*i)->region.playlist();
3098 session->add_undo (playlist->get_memento());
3099 playlist->duplicate (r, r.last_frame(), times);
3100 session->add_redo_no_execute (playlist->get_memento());
3104 if (latest_regionview) {
3105 selection->add (latest_regionview);
3110 commit_reversible_command ();
3114 Editor::duplicate_selection (float times)
3116 if (selection->time.empty() || selection->tracks.empty()) {
3121 vector<AudioRegion*> new_regions;
3122 vector<AudioRegion*>::iterator ri;
3124 create_region_from_selection (new_regions);
3126 if (new_regions.empty()) {
3130 begin_reversible_command (_("duplicate selection"));
3132 ri = new_regions.begin();
3134 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3135 if ((playlist = (*i)->playlist()) == 0) {
3138 session->add_undo (playlist->get_memento());
3139 playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
3140 session->add_redo_no_execute (playlist->get_memento());
3143 if (ri == new_regions.end()) {
3148 commit_reversible_command ();
3152 Editor::center_playhead ()
3154 float page = canvas_width * frames_per_unit;
3156 center_screen_internal (playhead_cursor->current_frame, page);
3160 Editor::center_edit_cursor ()
3162 float page = canvas_width * frames_per_unit;
3164 center_screen_internal (edit_cursor->current_frame, page);
3168 Editor::clear_playlist (Playlist& playlist)
3170 begin_reversible_command (_("clear playlist"));
3171 session->add_undo (playlist.get_memento());
3173 session->add_redo_no_execute (playlist.get_memento());
3174 commit_reversible_command ();
3178 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3181 jack_nframes_t distance;
3182 jack_nframes_t next_distance;
3183 jack_nframes_t start;
3185 if (use_edit_cursor) {
3186 start = edit_cursor->current_frame;
3191 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3195 if (selection->tracks.empty()) {
3199 begin_reversible_command (_("nudge track"));
3201 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3203 if ((playlist = (*i)->playlist()) == 0) {
3207 session->add_undo (playlist->get_memento());
3208 playlist->nudge_after (start, distance, forwards);
3209 session->add_redo_no_execute (playlist->get_memento());
3212 commit_reversible_command ();
3216 Editor::remove_last_capture ()
3218 vector<string> choices;
3225 if (Config->get_verify_remove_last_capture()) {
3226 prompt = _("Do you really want to destroy the last capture?"
3227 "\n(This is destructive and cannot be undone)");
3229 choices.push_back (_("Yes, destroy it."));
3230 choices.push_back (_("No, do nothing."));
3232 Gtkmm2ext::Choice prompter (prompt, choices);
3234 if (prompter.run () == 0) {
3235 session->remove_last_capture ();
3239 session->remove_last_capture();
3244 Editor::normalize_region ()
3250 if (selection->audio_regions.empty()) {
3254 begin_reversible_command (_("normalize"));
3256 track_canvas.get_window()->set_cursor (*wait_cursor);
3259 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3260 session->add_undo ((*r)->region.get_memento());
3261 (*r)->region.normalize_to (0.0f);
3262 session->add_redo_no_execute ((*r)->region.get_memento());
3265 commit_reversible_command ();
3266 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3271 Editor::denormalize_region ()
3277 if (selection->audio_regions.empty()) {
3281 begin_reversible_command ("denormalize");
3283 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3284 session->add_undo ((*r)->region.get_memento());
3285 (*r)->region.set_scale_amplitude (1.0f);
3286 session->add_redo_no_execute ((*r)->region.get_memento());
3289 commit_reversible_command ();
3294 Editor::reverse_region ()
3300 Reverse rev (*session);
3301 apply_filter (rev, _("reverse regions"));
3305 Editor::apply_filter (AudioFilter& filter, string command)
3307 if (selection->audio_regions.empty()) {
3311 begin_reversible_command (command);
3313 track_canvas.get_window()->set_cursor (*wait_cursor);
3316 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
3318 AudioRegion& region ((*r)->region);
3319 Playlist* playlist = region.playlist();
3321 AudioRegionSelection::iterator tmp;
3326 if (region.apply (filter) == 0) {
3328 session->add_undo (playlist->get_memento());
3329 playlist->replace_region (region, *(filter.results.front()), region.position());
3330 session->add_redo_no_execute (playlist->get_memento());
3338 commit_reversible_command ();
3339 selection->audio_regions.clear ();
3342 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3346 Editor::region_selection_op (void (Region::*pmf)(void))
3348 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3349 ((*i)->region.*pmf)();
3355 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3357 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3358 ((*i)->region.*pmf)(arg);
3363 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3365 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3366 ((*i)->region.*pmf)(yn);
3371 Editor::external_edit_region ()
3373 if (!clicked_regionview) {
3381 Editor::brush (jack_nframes_t pos)
3383 AudioRegionSelection sel;
3386 if (selection->audio_regions.empty()) {
3387 /* XXX get selection from region list */
3389 sel = selection->audio_regions;
3396 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3397 mouse_brush_insert_region ((*i), pos);
3402 Editor::toggle_gain_envelope_visibility ()
3404 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3405 (*i)->set_envelope_visible (!(*i)->envelope_visible());
3410 Editor::toggle_gain_envelope_active ()
3412 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3413 AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
3415 ar->set_envelope_active (true);