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.
27 #include <pbd/error.h>
28 #include <pbd/basename.h>
29 #include <pbd/pthread_utils.h>
30 #include <pbd/memento_command.h>
32 #include <gtkmm2ext/utils.h>
33 #include <gtkmm2ext/choice.h>
34 #include <gtkmm2ext/window_title.h>
36 #include <ardour/audioengine.h>
37 #include <ardour/session.h>
38 #include <ardour/audioplaylist.h>
39 #include <ardour/audioregion.h>
40 #include <ardour/audio_diskstream.h>
41 #include <ardour/utils.h>
42 #include <ardour/location.h>
43 #include <ardour/named_selection.h>
44 #include <ardour/audio_track.h>
45 #include <ardour/audioplaylist.h>
46 #include <ardour/region_factory.h>
47 #include <ardour/playlist_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 "audio_region_view.h"
57 #include "rgb_macros.h"
58 #include "selection_templates.h"
59 #include "selection.h"
61 #include "gtk-custom-hruler.h"
62 #include "gui_thread.h"
67 using namespace ARDOUR;
71 using namespace Gtkmm2ext;
72 using namespace Editing;
74 /***********************************************************************
76 ***********************************************************************/
79 Editor::undo (uint32_t n)
87 Editor::redo (uint32_t n)
95 Editor::ensure_cursor (nframes_t *pos)
97 *pos = edit_cursor->current_frame;
102 Editor::split_region ()
104 split_region_at (edit_cursor->current_frame);
108 Editor::split_region_at (nframes_t where)
110 split_regions_at (where, selection->regions);
114 Editor::split_regions_at (nframes_t where, RegionSelection& regions)
116 begin_reversible_command (_("split"));
119 for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
121 RegionSelection::iterator tmp;
126 boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
128 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
130 _new_regionviews_show_envelope = arv->envelope_visible();
133 XMLNode &before = pl->get_state();
134 pl->split_region ((*a)->region(), where);
135 XMLNode &after = pl->get_state();
136 session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
142 commit_reversible_command ();
143 _new_regionviews_show_envelope = false;
147 Editor::remove_clicked_region ()
149 if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
153 boost::shared_ptr<Playlist> playlist = clicked_audio_trackview->playlist();
155 begin_reversible_command (_("remove region"));
156 XMLNode &before = playlist->get_state();
157 playlist->remove_region (clicked_regionview->region());
158 XMLNode &after = playlist->get_state();
159 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
160 commit_reversible_command ();
164 Editor::destroy_clicked_region ()
166 uint32_t selected = selection->regions.size();
168 if (!session || !selected) {
172 vector<string> choices;
175 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
176 It cannot be undone\n\
177 Do you really want to destroy %1 ?"),
179 _("these regions") : _("this region")));
181 choices.push_back (_("No, do nothing."));
184 choices.push_back (_("Yes, destroy them."));
186 choices.push_back (_("Yes, destroy it."));
189 Gtkmm2ext::Choice prompter (prompt, choices);
191 if (prompter.run() == 0) { /* first choice */
196 list<boost::shared_ptr<Region> > r;
198 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
199 r.push_back ((*i)->region());
202 session->destroy_regions (r);
206 boost::shared_ptr<Region>
207 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
210 boost::shared_ptr<Region> region;
213 if (selection->time.start () == selection->time.end_frame ()) {
215 /* no current selection-> is there a selected regionview? */
217 if (selection->regions.empty()) {
223 if (!selection->regions.empty()) {
225 rv = *(selection->regions.begin());
226 (*tv) = &rv->get_time_axis_view();
227 region = rv->region();
229 } else if (!selection->tracks.empty()) {
231 (*tv) = selection->tracks.front();
233 RouteTimeAxisView* rtv;
235 if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
236 boost::shared_ptr<Playlist> pl;
238 if ((pl = rtv->playlist()) == 0) {
242 region = pl->top_region_at (start);
250 Editor::extend_selection_to_end_of_region (bool next)
253 boost::shared_ptr<Region> region;
256 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
260 if (region && selection->time.start () == selection->time.end_frame ()) {
261 start = region->position();
263 start = selection->time.start ();
266 /* Try to leave the selection with the same route if possible */
268 if ((tv = selection->time.track) == 0) {
272 begin_reversible_command (_("extend selection"));
273 selection->set (tv, start, region->position() + region->length());
274 commit_reversible_command ();
278 Editor::extend_selection_to_start_of_region (bool previous)
281 boost::shared_ptr<Region> region;
284 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
288 if (region && selection->time.start () == selection->time.end_frame ()) {
289 end = region->position() + region->length();
291 end = selection->time.end_frame ();
294 /* Try to leave the selection with the same route if possible */
296 if ((tv = selection->time.track) == 0) {
300 begin_reversible_command (_("extend selection"));
301 selection->set (tv, region->position(), end);
302 commit_reversible_command ();
307 Editor::nudge_forward (bool next)
310 nframes_t next_distance;
312 if (!session) return;
314 if (!selection->regions.empty()) {
316 begin_reversible_command (_("nudge forward"));
318 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
319 boost::shared_ptr<Region> r ((*i)->region());
321 distance = get_nudge_distance (r->position(), next_distance);
324 distance = next_distance;
327 XMLNode &before = r->playlist()->get_state();
328 r->set_position (r->position() + distance, this);
329 XMLNode &after = r->playlist()->get_state();
330 session->add_command (new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
333 commit_reversible_command ();
336 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
337 session->request_locate (playhead_cursor->current_frame + distance);
342 Editor::nudge_backward (bool next)
345 nframes_t next_distance;
347 if (!session) return;
349 if (!selection->regions.empty()) {
351 begin_reversible_command (_("nudge forward"));
353 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
354 boost::shared_ptr<Region> r ((*i)->region());
356 distance = get_nudge_distance (r->position(), next_distance);
359 distance = next_distance;
362 XMLNode &before = r->playlist()->get_state();
364 if (r->position() > distance) {
365 r->set_position (r->position() - distance, this);
367 r->set_position (0, this);
369 XMLNode &after = r->playlist()->get_state();
370 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
373 commit_reversible_command ();
377 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
379 if (playhead_cursor->current_frame > distance) {
380 session->request_locate (playhead_cursor->current_frame - distance);
382 session->goto_start();
388 Editor::nudge_forward_capture_offset ()
392 if (!session) return;
394 if (!selection->regions.empty()) {
396 begin_reversible_command (_("nudge forward"));
398 distance = session->worst_output_latency();
400 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
401 boost::shared_ptr<Region> r ((*i)->region());
403 XMLNode &before = r->playlist()->get_state();
404 r->set_position (r->position() + distance, this);
405 XMLNode &after = r->playlist()->get_state();
406 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
409 commit_reversible_command ();
415 Editor::nudge_backward_capture_offset ()
419 if (!session) return;
421 if (!selection->regions.empty()) {
423 begin_reversible_command (_("nudge forward"));
425 distance = session->worst_output_latency();
427 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
428 boost::shared_ptr<Region> r ((*i)->region());
430 XMLNode &before = r->playlist()->get_state();
432 if (r->position() > distance) {
433 r->set_position (r->position() - distance, this);
435 r->set_position (0, this);
437 XMLNode &after = r->playlist()->get_state();
438 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
441 commit_reversible_command ();
448 Editor::move_to_start ()
450 session->goto_start ();
454 Editor::move_to_end ()
457 session->request_locate (session->current_end_frame());
461 Editor::build_region_boundary_cache ()
464 vector<RegionPoint> interesting_points;
465 boost::shared_ptr<Region> r;
466 TrackViewList tracks;
469 region_boundary_cache.clear ();
476 case SnapToRegionStart:
477 interesting_points.push_back (Start);
479 case SnapToRegionEnd:
480 interesting_points.push_back (End);
482 case SnapToRegionSync:
483 interesting_points.push_back (SyncPoint);
485 case SnapToRegionBoundary:
486 interesting_points.push_back (Start);
487 interesting_points.push_back (End);
490 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
495 TimeAxisView *ontrack = 0;
498 if (!selection->tracks.empty()) {
499 tlist = selection->tracks;
504 while (pos < session->current_end_frame() && !at_end) {
507 nframes_t lpos = max_frames;
509 for (vector<RegionPoint>::iterator p = interesting_points.begin(); p != interesting_points.end(); ++p) {
511 if ((r = find_next_region (pos, *p, 1, tlist, &ontrack)) == 0) {
513 /* move to next point type */
520 rpos = r->first_frame();
523 rpos = r->last_frame();
526 rpos = r->adjust_to_sync (r->first_frame());
533 AudioTimeAxisView *atav;
535 if (ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
536 if (atav->get_diskstream() != 0) {
537 speed = atav->get_diskstream()->speed();
541 rpos = track_frame_to_session_frame (rpos, speed);
547 /* prevent duplicates, but we don't use set<> because we want to be able
551 vector<nframes_t>::iterator ri;
553 for (ri = region_boundary_cache.begin(); ri != region_boundary_cache.end(); ++ri) {
559 if (ri == region_boundary_cache.end()) {
560 region_boundary_cache.push_back (rpos);
567 /* finally sort to be sure that the order is correct */
569 sort (region_boundary_cache.begin(), region_boundary_cache.end());
572 boost::shared_ptr<Region>
573 Editor::find_next_region (nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
575 TrackViewList::iterator i;
576 nframes_t closest = max_frames;
577 boost::shared_ptr<Region> ret;
581 nframes_t track_frame;
582 AudioTimeAxisView *atav;
584 for (i = tracks.begin(); i != tracks.end(); ++i) {
587 boost::shared_ptr<Region> r;
590 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
591 if (atav->get_diskstream()!=0)
592 track_speed = atav->get_diskstream()->speed();
595 track_frame = session_frame_to_track_frame(frame, track_speed);
597 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
603 rpos = r->first_frame ();
607 rpos = r->last_frame ();
611 rpos = r->adjust_to_sync (r->first_frame());
614 // rpos is a "track frame", converting it to "session frame"
615 rpos = track_frame_to_session_frame(rpos, track_speed);
618 distance = rpos - frame;
620 distance = frame - rpos;
623 if (distance < closest) {
635 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
637 boost::shared_ptr<Region> r;
638 nframes_t pos = cursor->current_frame;
644 TimeAxisView *ontrack = 0;
646 // so we don't find the current region again..
650 if (!selection->tracks.empty()) {
652 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
654 } else if (clicked_trackview) {
657 t.push_back (clicked_trackview);
659 r = find_next_region (pos, point, dir, t, &ontrack);
663 r = find_next_region (pos, point, dir, track_views, &ontrack);
672 pos = r->first_frame ();
676 pos = r->last_frame ();
680 pos = r->adjust_to_sync (r->first_frame());
685 AudioTimeAxisView *atav;
687 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
688 if (atav->get_diskstream() != 0) {
689 speed = atav->get_diskstream()->speed();
693 pos = track_frame_to_session_frame(pos, speed);
695 if (cursor == playhead_cursor) {
696 session->request_locate (pos);
698 cursor->set_position (pos);
703 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
705 cursor_to_region_point (cursor, point, 1);
709 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
711 cursor_to_region_point (cursor, point, -1);
715 Editor::cursor_to_selection_start (Cursor *cursor)
718 switch (mouse_mode) {
720 if (!selection->regions.empty()) {
721 pos = selection->regions.start();
726 if (!selection->time.empty()) {
727 pos = selection->time.start ();
735 if (cursor == playhead_cursor) {
736 session->request_locate (pos);
738 cursor->set_position (pos);
743 Editor::cursor_to_selection_end (Cursor *cursor)
747 switch (mouse_mode) {
749 if (!selection->regions.empty()) {
750 pos = selection->regions.end_frame();
755 if (!selection->time.empty()) {
756 pos = selection->time.end_frame ();
764 if (cursor == playhead_cursor) {
765 session->request_locate (pos);
767 cursor->set_position (pos);
772 Editor::scroll_playhead (bool forward)
774 nframes_t pos = playhead_cursor->current_frame;
775 nframes_t delta = (nframes_t) floor (current_page_frames() / 0.8);
778 if (pos == max_frames) {
782 if (pos < max_frames - delta) {
801 session->request_locate (pos);
805 Editor::playhead_backward ()
812 if (get_prefix (prefix, was_floating)) {
816 cnt = (nframes_t) floor (prefix * session->frame_rate ());
818 cnt = (nframes_t) prefix;
822 pos = playhead_cursor->current_frame;
824 if ((nframes_t) pos < cnt) {
830 /* XXX this is completely insane. with the current buffering
831 design, we'll force a complete track buffer flush and
832 reload, just to move 1 sample !!!
835 session->request_locate (pos);
839 Editor::playhead_forward ()
846 if (get_prefix (prefix, was_floating)) {
850 cnt = (nframes_t) floor (prefix * session->frame_rate ());
852 cnt = (nframes_t) floor (prefix);
856 pos = playhead_cursor->current_frame;
858 /* XXX this is completely insane. with the current buffering
859 design, we'll force a complete track buffer flush and
860 reload, just to move 1 sample !!!
863 session->request_locate (pos+cnt);
867 Editor::cursor_align (bool playhead_to_edit)
869 if (playhead_to_edit) {
871 session->request_locate (edit_cursor->current_frame);
874 edit_cursor->set_position (playhead_cursor->current_frame);
879 Editor::edit_cursor_backward ()
886 if (get_prefix (prefix, was_floating)) {
890 cnt = (nframes_t) floor (prefix * session->frame_rate ());
892 cnt = (nframes_t) prefix;
896 pos = edit_cursor->current_frame;
898 if ((nframes_t) pos < cnt) {
904 edit_cursor->set_position (pos);
908 Editor::edit_cursor_forward ()
915 if (get_prefix (prefix, was_floating)) {
919 cnt = (nframes_t) floor (prefix * session->frame_rate ());
921 cnt = (nframes_t) floor (prefix);
925 pos = edit_cursor->current_frame;
926 edit_cursor->set_position (pos+cnt);
930 Editor::goto_frame ()
936 if (get_prefix (prefix, was_floating)) {
941 frame = (nframes_t) floor (prefix * session->frame_rate());
943 frame = (nframes_t) floor (prefix);
946 session->request_locate (frame);
950 Editor::scroll_backward (float pages)
953 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
958 if (get_prefix (prefix, was_floating)) {
959 cnt = (nframes_t) floor (pages * one_page);
962 cnt = (nframes_t) floor (prefix * session->frame_rate());
964 cnt = (nframes_t) floor (prefix * one_page);
968 if (leftmost_frame < cnt) {
971 frame = leftmost_frame - cnt;
974 reset_x_origin (frame);
978 Editor::scroll_forward (float pages)
981 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
986 if (get_prefix (prefix, was_floating)) {
987 cnt = (nframes_t) floor (pages * one_page);
990 cnt = (nframes_t) floor (prefix * session->frame_rate());
992 cnt = (nframes_t) floor (prefix * one_page);
996 if (max_frames - cnt < leftmost_frame) {
997 frame = max_frames - cnt;
999 frame = leftmost_frame + cnt;
1002 reset_x_origin (frame);
1006 Editor::scroll_tracks_down ()
1012 if (get_prefix (prefix, was_floating)) {
1015 cnt = (int) floor (prefix);
1018 double vert_value = vertical_adjustment.get_value() + (cnt *
1019 vertical_adjustment.get_page_size());
1020 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
1021 vert_value = vertical_adjustment.get_upper() - canvas_height;
1023 vertical_adjustment.set_value (vert_value);
1027 Editor::scroll_tracks_up ()
1033 if (get_prefix (prefix, was_floating)) {
1036 cnt = (int) floor (prefix);
1039 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1043 Editor::scroll_tracks_down_line ()
1046 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1047 double vert_value = adj->get_value() + 20;
1049 if (vert_value>adj->get_upper() - canvas_height) {
1050 vert_value = adj->get_upper() - canvas_height;
1052 adj->set_value (vert_value);
1056 Editor::scroll_tracks_up_line ()
1058 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1059 adj->set_value (adj->get_value() - 20);
1065 Editor::temporal_zoom_step (bool coarser)
1067 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1071 nfpu = frames_per_unit;
1076 nfpu = max(1.0,(nfpu/1.61803399));
1079 temporal_zoom (nfpu);
1083 Editor::temporal_zoom (gdouble fpu)
1085 if (!session) return;
1087 nframes_t current_page = current_page_frames();
1088 nframes_t current_leftmost = leftmost_frame;
1089 nframes_t current_rightmost;
1090 nframes_t current_center;
1092 nframes_t leftmost_after_zoom = 0;
1097 new_page = (nframes_t) floor (canvas_width * nfpu);
1099 switch (zoom_focus) {
1101 leftmost_after_zoom = current_leftmost;
1104 case ZoomFocusRight:
1105 current_rightmost = leftmost_frame + current_page;
1106 if (current_rightmost > new_page) {
1107 leftmost_after_zoom = current_rightmost - new_page;
1109 leftmost_after_zoom = 0;
1113 case ZoomFocusCenter:
1114 current_center = current_leftmost + (current_page/2);
1115 if (current_center > (new_page/2)) {
1116 leftmost_after_zoom = current_center - (new_page / 2);
1118 leftmost_after_zoom = 0;
1122 case ZoomFocusPlayhead:
1123 /* try to keep the playhead in the center */
1124 if (playhead_cursor->current_frame > new_page/2) {
1125 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1127 leftmost_after_zoom = 0;
1132 /* try to keep the edit cursor in the center */
1133 if (edit_cursor->current_frame > new_page/2) {
1134 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1136 leftmost_after_zoom = 0;
1142 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1144 // begin_reversible_command (_("zoom"));
1145 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1146 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1147 // commit_reversible_command ();
1149 reposition_and_zoom (leftmost_after_zoom, nfpu);
1153 Editor::temporal_zoom_selection ()
1155 if (!selection) return;
1157 if (selection->time.empty()) {
1161 nframes_t start = selection->time[clicked_selection].start;
1162 nframes_t end = selection->time[clicked_selection].end;
1164 temporal_zoom_by_frame (start, end, "zoom to selection");
1168 Editor::temporal_zoom_session ()
1170 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1173 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1178 Editor::temporal_zoom_by_frame (nframes_t start, nframes_t end, const string & op)
1180 if (!session) return;
1182 if ((start == 0 && end == 0) || end < start) {
1186 nframes_t range = end - start;
1188 double new_fpu = (double)range / (double)canvas_width;
1191 // while (p2 < new_fpu) {
1196 nframes_t new_page = (nframes_t) floor (canvas_width * new_fpu);
1197 nframes_t middle = (nframes_t) floor( (double)start + ((double)range / 2.0f ));
1198 nframes_t new_leftmost = (nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1200 if (new_leftmost > middle) new_leftmost = 0;
1202 // begin_reversible_command (op);
1203 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1204 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1205 // commit_reversible_command ();
1207 reposition_and_zoom (new_leftmost, new_fpu);
1211 Editor::temporal_zoom_to_frame (bool coarser, nframes_t frame)
1213 if (!session) return;
1215 double range_before = frame - leftmost_frame;
1218 new_fpu = frames_per_unit;
1221 new_fpu *= 1.61803399;
1222 range_before *= 1.61803399;
1224 new_fpu = max(1.0,(new_fpu/1.61803399));
1225 range_before /= 1.61803399;
1228 if (new_fpu == frames_per_unit) return;
1230 nframes_t new_leftmost = frame - (nframes_t)range_before;
1232 if (new_leftmost > frame) new_leftmost = 0;
1234 // begin_reversible_command (_("zoom to frame"));
1235 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1236 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1237 // commit_reversible_command ();
1239 reposition_and_zoom (new_leftmost, new_fpu);
1243 Editor::add_location_from_selection ()
1247 if (selection->time.empty()) {
1251 if (session == 0 || clicked_trackview == 0) {
1255 nframes_t start = selection->time[clicked_selection].start;
1256 nframes_t end = selection->time[clicked_selection].end;
1258 session->locations()->next_available_name(rangename,"selection");
1259 Location *location = new Location (start, end, rangename, Location::IsRangeMarker);
1261 session->begin_reversible_command (_("add marker"));
1262 XMLNode &before = session->locations()->get_state();
1263 session->locations()->add (location, true);
1264 XMLNode &after = session->locations()->get_state();
1265 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1266 session->commit_reversible_command ();
1270 Editor::add_location_from_playhead_cursor ()
1274 nframes_t where = session->audible_frame();
1276 session->locations()->next_available_name(markername,"mark");
1277 Location *location = new Location (where, where, markername, Location::IsMark);
1278 session->begin_reversible_command (_("add marker"));
1279 XMLNode &before = session->locations()->get_state();
1280 session->locations()->add (location, true);
1281 XMLNode &after = session->locations()->get_state();
1282 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1283 session->commit_reversible_command ();
1287 Editor::add_location_from_audio_region ()
1289 if (selection->regions.empty()) {
1293 RegionView* rv = *(selection->regions.begin());
1294 boost::shared_ptr<Region> region = rv->region();
1296 Location *location = new Location (region->position(), region->last_frame(), region->name(), Location::IsRangeMarker);
1297 session->begin_reversible_command (_("add marker"));
1298 XMLNode &before = session->locations()->get_state();
1299 session->locations()->add (location, true);
1300 XMLNode &after = session->locations()->get_state();
1301 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1302 session->commit_reversible_command ();
1306 Editor::amplitude_zoom_step (bool in)
1320 #ifdef FIX_FOR_CANVAS
1321 /* XXX DO SOMETHING */
1330 Editor::delete_sample_forward ()
1335 Editor::delete_sample_backward ()
1340 Editor::delete_screen ()
1347 Editor::search_backwards ()
1353 Editor::search_forwards ()
1361 Editor::jump_forward_to_mark ()
1367 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1370 session->request_locate (location->start(), session->transport_rolling());
1372 session->request_locate (session->current_end_frame());
1377 Editor::jump_backward_to_mark ()
1383 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1386 session->request_locate (location->start(), session->transport_rolling());
1388 session->goto_start ();
1400 if (get_prefix (prefix, was_floating)) {
1401 pos = session->audible_frame ();
1404 pos = (nframes_t) floor (prefix * session->frame_rate ());
1406 pos = (nframes_t) floor (prefix);
1410 session->locations()->next_available_name(markername,"mark");
1411 session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true);
1415 Editor::clear_markers ()
1418 session->begin_reversible_command (_("clear markers"));
1419 XMLNode &before = session->locations()->get_state();
1420 session->locations()->clear_markers ();
1421 XMLNode &after = session->locations()->get_state();
1422 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1423 session->commit_reversible_command ();
1428 Editor::clear_ranges ()
1431 session->begin_reversible_command (_("clear ranges"));
1432 XMLNode &before = session->locations()->get_state();
1434 Location * looploc = session->locations()->auto_loop_location();
1435 Location * punchloc = session->locations()->auto_punch_location();
1437 session->locations()->clear_ranges ();
1439 if (looploc) session->locations()->add (looploc);
1440 if (punchloc) session->locations()->add (punchloc);
1442 XMLNode &after = session->locations()->get_state();
1443 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1444 session->commit_reversible_command ();
1449 Editor::clear_locations ()
1451 session->begin_reversible_command (_("clear locations"));
1452 XMLNode &before = session->locations()->get_state();
1453 session->locations()->clear ();
1454 XMLNode &after = session->locations()->get_state();
1455 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1456 session->commit_reversible_command ();
1457 session->locations()->clear ();
1461 Editor::unhide_markers ()
1463 for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1464 Location *l = (*i).first;
1465 if (l->is_hidden() && l->is_mark()) {
1466 l->set_hidden(false, this);
1472 Editor::unhide_ranges ()
1474 for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1475 Location *l = (*i).first;
1476 if (l->is_hidden() && l->is_range_marker()) {
1477 l->set_hidden(false, this);
1482 /* INSERT/REPLACE */
1485 Editor::insert_region_list_drag (boost::shared_ptr<AudioRegion> region, int x, int y)
1491 AudioTimeAxisView *atv = 0;
1492 boost::shared_ptr<Playlist> playlist;
1494 track_canvas.window_to_world (x, y, wx, wy);
1495 wx += horizontal_adjustment.get_value();
1496 wy += vertical_adjustment.get_value();
1499 event.type = GDK_BUTTON_RELEASE;
1500 event.button.x = wx;
1501 event.button.y = wy;
1503 where = event_frame (&event, &cx, &cy);
1505 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1506 /* clearly outside canvas area */
1510 if ((tv = trackview_by_y_position (cy)) == 0) {
1514 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1518 if ((playlist = atv->playlist()) == 0) {
1524 begin_reversible_command (_("insert dragged region"));
1525 XMLNode &before = playlist->get_state();
1526 playlist->add_region (RegionFactory::create (region), where, 1.0);
1527 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1528 commit_reversible_command ();
1532 Editor::insert_region_list_selection (float times)
1534 RouteTimeAxisView *tv = 0;
1535 boost::shared_ptr<Playlist> playlist;
1537 if (clicked_audio_trackview != 0) {
1538 tv = clicked_audio_trackview;
1539 } else if (!selection->tracks.empty()) {
1540 if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
1547 if ((playlist = tv->playlist()) == 0) {
1551 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1553 if (selected->count_selected_rows() != 1) {
1557 TreeView::Selection::ListHandle_Path rows = selected->get_selected_rows ();
1559 /* only one row selected, so rows.begin() is it */
1563 if ((iter = region_list_model->get_iter (*rows.begin()))) {
1565 boost::shared_ptr<Region> region = (*iter)[region_list_columns.region];
1567 begin_reversible_command (_("insert region"));
1568 XMLNode &before = playlist->get_state();
1569 playlist->add_region ((RegionFactory::create (region)), edit_cursor->current_frame, times);
1570 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1571 commit_reversible_command ();
1575 /* BUILT-IN EFFECTS */
1578 Editor::reverse_selection ()
1583 /* GAIN ENVELOPE EDITING */
1586 Editor::edit_envelope ()
1593 Editor::transition_to_rolling (bool fwd)
1599 switch (Config->get_slave_source()) {
1604 /* transport controlled by the master */
1608 if (session->is_auditioning()) {
1609 session->cancel_audition ();
1613 session->request_transport_speed (fwd ? 1.0f : -1.0f);
1617 Editor::toggle_playback (bool with_abort)
1623 switch (Config->get_slave_source()) {
1628 /* transport controlled by the master */
1632 if (session->is_auditioning()) {
1633 session->cancel_audition ();
1637 if (session->transport_rolling()) {
1638 session->request_stop (with_abort);
1639 if (session->get_play_loop()) {
1640 session->request_play_loop (false);
1643 session->request_transport_speed (1.0f);
1648 Editor::play_from_start ()
1650 session->request_locate (session->current_start_frame(), true);
1654 Editor::play_from_edit_cursor ()
1656 session->request_locate (edit_cursor->current_frame, true);
1660 Editor::play_selection ()
1662 if (selection->time.empty()) {
1666 session->request_play_range (true);
1670 Editor::play_selected_region ()
1672 if (!selection->regions.empty()) {
1673 RegionView *rv = *(selection->regions.begin());
1675 session->request_bounded_roll (rv->region()->position(), rv->region()->last_frame());
1680 Editor::loop_selected_region ()
1682 if (!selection->regions.empty()) {
1683 RegionView *rv = *(selection->regions.begin());
1686 if ((tll = transport_loop_location()) != 0) {
1688 tll->set (rv->region()->position(), rv->region()->last_frame());
1690 // enable looping, reposition and start rolling
1692 session->request_play_loop (true);
1693 session->request_locate (tll->start(), false);
1694 session->request_transport_speed (1.0f);
1700 Editor::play_location (Location& location)
1702 if (location.start() <= location.end()) {
1706 session->request_bounded_roll (location.start(), location.end());
1710 Editor::loop_location (Location& location)
1712 if (location.start() <= location.end()) {
1718 if ((tll = transport_loop_location()) != 0) {
1719 tll->set (location.start(), location.end());
1721 // enable looping, reposition and start rolling
1722 session->request_play_loop (true);
1723 session->request_locate (tll->start(), true);
1728 Editor::raise_region ()
1730 selection->foreach_region (&Region::raise);
1734 Editor::raise_region_to_top ()
1736 selection->foreach_region (&Region::raise_to_top);
1740 Editor::lower_region ()
1742 selection->foreach_region (&Region::lower);
1746 Editor::lower_region_to_bottom ()
1748 selection->foreach_region (&Region::lower_to_bottom);
1752 Editor::edit_region ()
1754 if (clicked_regionview == 0) {
1758 clicked_regionview->show_region_editor ();
1762 Editor::rename_region ()
1766 Button ok_button (_("OK"));
1767 Button cancel_button (_("Cancel"));
1769 if (selection->regions.empty()) {
1773 WindowTitle title(Glib::get_application_name());
1774 title += _("Rename Region");
1776 dialog.set_title (title.get_string());
1777 dialog.set_name ("RegionRenameWindow");
1778 dialog.set_size_request (300, -1);
1779 dialog.set_position (Gtk::WIN_POS_MOUSE);
1780 dialog.set_modal (true);
1782 dialog.get_vbox()->set_border_width (10);
1783 dialog.get_vbox()->pack_start (entry);
1784 dialog.get_action_area()->pack_start (ok_button);
1785 dialog.get_action_area()->pack_start (cancel_button);
1787 entry.set_name ("RegionNameDisplay");
1788 ok_button.set_name ("EditorGTKButton");
1789 cancel_button.set_name ("EditorGTKButton");
1791 region_renamed = false;
1793 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1794 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1795 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
1802 if (region_renamed) {
1803 (*selection->regions.begin())->region()->set_name (entry.get_text());
1804 redisplay_regions ();
1809 Editor::rename_region_finished (bool status)
1812 region_renamed = status;
1817 Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Route& route)
1819 if (session->is_auditioning()) {
1820 session->cancel_audition ();
1823 // note: some potential for creativity here, because region doesn't
1824 // have to belong to the playlist that Route is handling
1826 // bool was_soloed = route.soloed();
1828 route.set_solo (true, this);
1830 session->request_bounded_roll (region->position(), region->position() + region->length());
1832 /* XXX how to unset the solo state ? */
1836 Editor::audition_selected_region ()
1838 if (!selection->regions.empty()) {
1839 RegionView* rv = *(selection->regions.begin());
1840 session->audition_region (rv->region());
1845 Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
1847 session->audition_region (region);
1851 Editor::build_interthread_progress_window ()
1853 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
1855 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
1857 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
1858 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
1860 // GTK2FIX: this button needs a modifiable label
1862 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1863 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
1865 interthread_cancel_button.add (interthread_cancel_label);
1867 interthread_progress_window->set_default_size (200, 100);
1871 Editor::interthread_cancel_clicked ()
1873 if (current_interthread_info) {
1874 current_interthread_info->cancel = true;
1879 Editor::region_from_selection ()
1881 if (clicked_trackview == 0) {
1885 if (selection->time.empty()) {
1889 nframes_t start = selection->time[clicked_selection].start;
1890 nframes_t end = selection->time[clicked_selection].end;
1892 nframes_t selection_cnt = end - start + 1;
1894 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1895 boost::shared_ptr<AudioRegion> current;
1896 boost::shared_ptr<Region> current_r;
1897 boost::shared_ptr<Playlist> pl;
1899 nframes_t internal_start;
1902 if ((pl = (*i)->playlist()) == 0) {
1906 if ((current_r = pl->top_region_at (start)) == 0) {
1910 current = boost::dynamic_pointer_cast<AudioRegion> (current_r);
1911 // FIXME: audio only
1913 internal_start = start - current->position();
1914 session->region_name (new_name, current->name(), true);
1915 boost::shared_ptr<Region> region (RegionFactory::create (current, internal_start, selection_cnt, new_name));
1921 Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& new_regions)
1923 if (selection->time.empty() || selection->tracks.empty()) {
1927 nframes_t start = selection->time[clicked_selection].start;
1928 nframes_t end = selection->time[clicked_selection].end;
1930 sort_track_selection ();
1932 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1934 boost::shared_ptr<AudioRegion> current;
1935 boost::shared_ptr<Region> current_r;
1936 boost::shared_ptr<Playlist> playlist;
1937 nframes_t internal_start;
1940 if ((playlist = (*i)->playlist()) == 0) {
1944 if ((current_r = playlist->top_region_at(start)) == 0) {
1948 if ((current = boost::dynamic_pointer_cast<AudioRegion>(current_r)) == 0) {
1952 internal_start = start - current->position();
1953 session->region_name (new_name, current->name(), true);
1955 new_regions.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (current, internal_start, end - start + 1, new_name)));
1960 Editor::split_multichannel_region ()
1962 if (selection->regions.empty()) {
1966 vector<boost::shared_ptr<AudioRegion> > v;
1968 for (list<RegionView*>::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
1970 AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*x);
1972 if (!arv || arv->audio_region()->n_channels() < 2) {
1976 (arv)->audio_region()->separate_by_channel (*session, v);
1981 Editor::new_region_from_selection ()
1983 region_from_selection ();
1984 cancel_selection ();
1988 Editor::separate_region_from_selection ()
1990 bool doing_undo = false;
1992 if (selection->time.empty()) {
1996 boost::shared_ptr<Playlist> playlist;
1998 sort_track_selection ();
2000 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2002 AudioTimeAxisView* atv;
2004 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2006 if (atv->is_audio_track()) {
2008 /* no edits to destructive tracks */
2010 if (atv->audio_track()->audio_diskstream()->destructive()) {
2014 if ((playlist = atv->playlist()) != 0) {
2016 begin_reversible_command (_("separate"));
2021 before = &(playlist->get_state());
2023 /* XXX need to consider musical time selections here at some point */
2025 double speed = atv->get_diskstream()->speed();
2027 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2028 playlist->partition ((nframes_t)((*t).start * speed), (nframes_t)((*t).end * speed), true);
2032 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2038 if (doing_undo) commit_reversible_command ();
2042 Editor::separate_regions_using_location (Location& loc)
2044 bool doing_undo = false;
2046 if (loc.is_mark()) {
2050 boost::shared_ptr<Playlist> playlist;
2052 /* XXX i'm unsure as to whether this should operate on selected tracks only
2053 or the entire enchillada. uncomment the below line to correct the behaviour
2054 (currently set for all tracks)
2057 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2058 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2060 AudioTimeAxisView* atv;
2062 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2064 if (atv->is_audio_track()) {
2066 /* no edits to destructive tracks */
2068 if (atv->audio_track()->audio_diskstream()->destructive()) {
2072 if ((playlist = atv->playlist()) != 0) {
2075 begin_reversible_command (_("separate"));
2079 before = &(playlist->get_state());
2082 /* XXX need to consider musical time selections here at some point */
2084 double speed = atv->get_diskstream()->speed();
2087 playlist->partition ((nframes_t)(loc.start() * speed), (nframes_t)(loc.end() * speed), true);
2089 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2095 if (doing_undo) commit_reversible_command ();
2099 Editor::crop_region_to_selection ()
2101 if (selection->time.empty() || selection->tracks.empty()) {
2105 vector<boost::shared_ptr<Playlist> > playlists;
2106 boost::shared_ptr<Playlist> playlist;
2108 sort_track_selection ();
2110 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2112 AudioTimeAxisView* atv;
2114 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2116 if (atv->is_audio_track()) {
2118 /* no edits to destructive tracks */
2120 if (atv->audio_track()->audio_diskstream()->destructive()) {
2124 if ((playlist = atv->playlist()) != 0) {
2125 playlists.push_back (playlist);
2131 if (playlists.empty()) {
2139 begin_reversible_command (_("trim to selection"));
2141 for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2143 boost::shared_ptr<Region> region;
2145 start = selection->time.start();
2147 if ((region = (*i)->top_region_at(start)) == 0) {
2151 /* now adjust lengths to that we do the right thing
2152 if the selection extends beyond the region
2155 start = max (start, region->position());
2156 if (max_frames - start < region->length()) {
2157 end = start + region->length() - 1;
2161 end = min (selection->time.end_frame(), end);
2162 cnt = end - start + 1;
2164 XMLNode &before = (*i)->get_state();
2165 region->trim_to (start, cnt, this);
2166 XMLNode &after = (*i)->get_state();
2167 session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
2170 commit_reversible_command ();
2174 Editor::region_fill_track ()
2178 if (!session || selection->regions.empty()) {
2182 end = session->current_end_frame ();
2184 begin_reversible_command (_("region fill"));
2186 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2188 boost::shared_ptr<Region> region ((*i)->region());
2191 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
2195 boost::shared_ptr<Playlist> pl = region->playlist();
2197 if (end <= region->last_frame()) {
2201 double times = (double) (end - region->last_frame()) / (double) region->length();
2207 XMLNode &before = pl->get_state();
2208 pl->add_region (RegionFactory::create (ar), ar->last_frame(), times);
2209 session->add_command (new MementoCommand<Playlist>(*pl, &before, &pl->get_state()));
2212 commit_reversible_command ();
2216 Editor::region_fill_selection ()
2218 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2222 if (selection->time.empty()) {
2227 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2229 if (selected->count_selected_rows() != 1) {
2233 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2234 boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
2236 nframes_t start = selection->time[clicked_selection].start;
2237 nframes_t end = selection->time[clicked_selection].end;
2239 boost::shared_ptr<Playlist> playlist;
2241 if (selection->tracks.empty()) {
2245 nframes_t selection_length = end - start;
2246 float times = (float)selection_length / region->length();
2248 begin_reversible_command (_("fill selection"));
2250 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2252 if ((playlist = (*i)->playlist()) == 0) {
2256 XMLNode &before = playlist->get_state();
2257 playlist->add_region (RegionFactory::create (region), start, times);
2258 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
2261 commit_reversible_command ();
2265 Editor::set_a_regions_sync_position (boost::shared_ptr<Region> region, nframes_t position)
2268 if (!region->covers (position)) {
2269 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2272 begin_reversible_command (_("set region sync position"));
2273 XMLNode &before = region->playlist()->get_state();
2274 region->set_sync_position (position);
2275 XMLNode &after = region->playlist()->get_state();
2276 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2277 commit_reversible_command ();
2281 Editor::set_region_sync_from_edit_cursor ()
2283 if (clicked_regionview == 0) {
2287 if (!clicked_regionview->region()->covers (edit_cursor->current_frame)) {
2288 error << _("Place the edit cursor at the desired sync point") << endmsg;
2292 boost::shared_ptr<Region> region (clicked_regionview->region());
2293 begin_reversible_command (_("set sync from edit cursor"));
2294 XMLNode &before = region->playlist()->get_state();
2295 region->set_sync_position (edit_cursor->current_frame);
2296 XMLNode &after = region->playlist()->get_state();
2297 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2298 commit_reversible_command ();
2302 Editor::remove_region_sync ()
2304 if (clicked_regionview) {
2305 boost::shared_ptr<Region> region (clicked_regionview->region());
2306 begin_reversible_command (_("remove sync"));
2307 XMLNode &before = region->playlist()->get_state();
2308 region->clear_sync_position ();
2309 XMLNode &after = region->playlist()->get_state();
2310 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2311 commit_reversible_command ();
2316 Editor::naturalize ()
2318 if (selection->regions.empty()) {
2321 begin_reversible_command (_("naturalize"));
2322 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2323 XMLNode &before = (*i)->region()->get_state();
2324 (*i)->region()->move_to_natural_position (this);
2325 XMLNode &after = (*i)->region()->get_state();
2326 session->add_command (new MementoCommand<Region>(*((*i)->region().get()), &before, &after));
2328 commit_reversible_command ();
2332 Editor::align (RegionPoint what)
2334 align_selection (what, edit_cursor->current_frame);
2338 Editor::align_relative (RegionPoint what)
2340 align_selection_relative (what, edit_cursor->current_frame);
2343 struct RegionSortByTime {
2344 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2345 return a->region()->position() < b->region()->position();
2350 Editor::align_selection_relative (RegionPoint point, nframes_t position)
2352 if (selection->regions.empty()) {
2360 list<RegionView*> sorted;
2361 selection->regions.by_position (sorted);
2362 boost::shared_ptr<Region> r ((*sorted.begin())->region());
2366 pos = r->first_frame ();
2370 pos = r->last_frame();
2374 pos = r->adjust_to_sync (r->first_frame());
2378 if (pos > position) {
2379 distance = pos - position;
2382 distance = position - pos;
2386 begin_reversible_command (_("align selection (relative)"));
2388 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2390 boost::shared_ptr<Region> region ((*i)->region());
2392 XMLNode &before = region->playlist()->get_state();
2395 region->set_position (region->position() + distance, this);
2397 region->set_position (region->position() - distance, this);
2400 XMLNode &after = region->playlist()->get_state();
2401 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2405 commit_reversible_command ();
2409 Editor::align_selection (RegionPoint point, nframes_t position)
2411 if (selection->regions.empty()) {
2415 begin_reversible_command (_("align selection"));
2417 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2418 align_region_internal ((*i)->region(), point, position);
2421 commit_reversible_command ();
2425 Editor::align_region (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2427 begin_reversible_command (_("align region"));
2428 align_region_internal (region, point, position);
2429 commit_reversible_command ();
2433 Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2435 XMLNode &before = region->playlist()->get_state();
2439 region->set_position (region->adjust_to_sync (position), this);
2443 if (position > region->length()) {
2444 region->set_position (position - region->length(), this);
2449 region->set_position (position, this);
2453 XMLNode &after = region->playlist()->get_state();
2454 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2458 Editor::trim_region_to_edit_cursor ()
2460 if (clicked_regionview == 0) {
2464 boost::shared_ptr<Region> region (clicked_regionview->region());
2467 AudioTimeAxisView *atav;
2469 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2470 if (atav->get_diskstream() != 0) {
2471 speed = atav->get_diskstream()->speed();
2475 begin_reversible_command (_("trim to edit"));
2476 XMLNode &before = region->playlist()->get_state();
2477 region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2478 XMLNode &after = region->playlist()->get_state();
2479 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2480 commit_reversible_command ();
2484 Editor::trim_region_from_edit_cursor ()
2486 if (clicked_regionview == 0) {
2490 boost::shared_ptr<Region> region (clicked_regionview->region());
2493 AudioTimeAxisView *atav;
2495 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2496 if (atav->get_diskstream() != 0) {
2497 speed = atav->get_diskstream()->speed();
2501 begin_reversible_command (_("trim to edit"));
2502 XMLNode &before = region->playlist()->get_state();
2503 region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2504 XMLNode &after = region->playlist()->get_state();
2505 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2506 commit_reversible_command ();
2510 Editor::unfreeze_route ()
2512 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2516 clicked_audio_trackview->audio_track()->unfreeze ();
2520 Editor::_freeze_thread (void* arg)
2522 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2523 return static_cast<Editor*>(arg)->freeze_thread ();
2527 Editor::freeze_thread ()
2529 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2534 Editor::freeze_progress_timeout (void *arg)
2536 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2537 return !(current_interthread_info->done || current_interthread_info->cancel);
2541 Editor::freeze_route ()
2543 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2547 InterThreadInfo itt;
2549 if (interthread_progress_window == 0) {
2550 build_interthread_progress_window ();
2553 WindowTitle title(Glib::get_application_name());
2554 title += _("Freeze");
2555 interthread_progress_window->set_title (title.get_string());
2556 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2557 interthread_progress_window->show_all ();
2558 interthread_progress_bar.set_fraction (0.0f);
2559 interthread_progress_label.set_text ("");
2560 interthread_cancel_label.set_text (_("Cancel Freeze"));
2561 current_interthread_info = &itt;
2563 interthread_progress_connection =
2564 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2568 itt.progress = 0.0f;
2570 pthread_attr_t attr;
2571 pthread_attr_init(&attr);
2572 pthread_attr_setstacksize(&attr, 500000);
2574 pthread_create (&itt.thread, &attr, _freeze_thread, this);
2576 pthread_attr_destroy(&attr);
2578 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2580 while (!itt.done && !itt.cancel) {
2581 gtk_main_iteration ();
2584 interthread_progress_connection.disconnect ();
2585 interthread_progress_window->hide_all ();
2586 current_interthread_info = 0;
2587 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2591 Editor::bounce_range_selection ()
2593 if (selection->time.empty()) {
2597 TrackSelection views = selection->tracks;
2599 nframes_t start = selection->time[clicked_selection].start;
2600 nframes_t end = selection->time[clicked_selection].end;
2601 nframes_t cnt = end - start + 1;
2603 begin_reversible_command (_("bounce range"));
2605 for (TrackViewList::iterator i = views.begin(); i != views.end(); ++i) {
2607 AudioTimeAxisView* atv;
2609 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2613 boost::shared_ptr<Playlist> playlist;
2615 if ((playlist = atv->playlist()) == 0) {
2619 InterThreadInfo itt;
2623 itt.progress = false;
2625 XMLNode &before = playlist->get_state();
2626 atv->audio_track()->bounce_range (start, cnt, itt);
2627 XMLNode &after = playlist->get_state();
2628 session->add_command (new MementoCommand<Playlist> (*playlist, &before, &after));
2631 commit_reversible_command ();
2647 Editor::cut_copy (CutCopyOp op)
2649 /* only cancel selection if cut/copy is successful.*/
2661 opname = _("clear");
2665 cut_buffer->clear ();
2667 switch (current_mouse_mode()) {
2669 if (!selection->regions.empty() || !selection->points.empty()) {
2671 begin_reversible_command (opname + _(" objects"));
2673 if (!selection->regions.empty()) {
2675 cut_copy_regions (op);
2678 selection->clear_regions ();
2682 if (!selection->points.empty()) {
2683 cut_copy_points (op);
2686 selection->clear_points ();
2690 commit_reversible_command ();
2695 if (!selection->time.empty()) {
2697 begin_reversible_command (opname + _(" range"));
2698 cut_copy_ranges (op);
2699 commit_reversible_command ();
2702 selection->clear_time ();
2714 Editor::cut_copy_points (CutCopyOp op)
2716 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2718 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2721 atv->cut_copy_clear_objects (selection->points, op);
2726 struct PlaylistState {
2727 boost::shared_ptr<Playlist> playlist;
2731 struct lt_playlist {
2732 bool operator () (const PlaylistState& a, const PlaylistState& b) {
2733 return a.playlist < b.playlist;
2737 struct PlaylistMapping {
2739 boost::shared_ptr<AudioPlaylist> pl;
2741 PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
2745 Editor::cut_copy_regions (CutCopyOp op)
2747 /* we can't use a std::map here because the ordering is important, and we can't trivially sort
2748 a map when we want ordered access to both elements. i think.
2751 vector<PlaylistMapping> pmap;
2753 nframes_t first_position = max_frames;
2755 set<PlaylistState, lt_playlist> freezelist;
2756 pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
2758 /* get ordering correct before we cut/copy */
2760 selection->regions.sort_by_position_and_track ();
2762 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
2764 first_position = min ((*x)->region()->position(), first_position);
2766 if (op == Cut || op == Clear) {
2767 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
2771 PlaylistState before;
2772 before.playlist = pl;
2773 before.before = &pl->get_state();
2775 insert_result = freezelist.insert (before);
2777 if (insert_result.second) {
2783 TimeAxisView* tv = &(*x)->get_trackview();
2784 vector<PlaylistMapping>::iterator z;
2786 for (z = pmap.begin(); z != pmap.end(); ++z) {
2787 if ((*z).tv == tv) {
2792 if (z == pmap.end()) {
2793 pmap.push_back (PlaylistMapping (tv));
2797 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
2799 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
2802 /* impossible, but this handles it for the future */
2806 TimeAxisView& tv = (*x)->get_trackview();
2807 boost::shared_ptr<AudioPlaylist> npl;
2808 RegionSelection::iterator tmp;
2813 vector<PlaylistMapping>::iterator z;
2815 for (z = pmap.begin(); z != pmap.end(); ++z) {
2816 if ((*z).tv == &tv) {
2821 assert (z != pmap.end());
2824 npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
2831 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
2832 boost::shared_ptr<Region> _xx;
2838 _xx = RegionFactory::create ((*x)->region());
2839 npl->add_region (_xx, (*x)->region()->position() - first_position);
2840 pl->remove_region (((*x)->region()));
2846 /* copy region before adding, so we're not putting same object into two different playlists */
2847 npl->add_region (RegionFactory::create ((*x)->region()), (*x)->region()->position() - first_position);
2851 pl->remove_region (((*x)->region()));
2858 list<boost::shared_ptr<Playlist> > foo;
2860 /* the pmap is in the same order as the tracks in which selected regions occured */
2862 for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2864 foo.push_back ((*i).pl);
2869 cut_buffer->set (foo);
2872 for (set<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2873 (*pl).playlist->thaw ();
2874 session->add_command (new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
2879 Editor::cut_copy_ranges (CutCopyOp op)
2881 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2882 (*i)->cut_copy_clear (*selection, op);
2887 Editor::paste (float times)
2889 paste_internal (edit_cursor->current_frame, times);
2893 Editor::mouse_paste ()
2898 track_canvas.get_pointer (x, y);
2899 track_canvas.window_to_world (x, y, wx, wy);
2900 wx += horizontal_adjustment.get_value();
2901 wy += vertical_adjustment.get_value();
2904 event.type = GDK_BUTTON_RELEASE;
2905 event.button.x = wx;
2906 event.button.y = wy;
2908 nframes_t where = event_frame (&event, 0, 0);
2910 paste_internal (where, 1);
2914 Editor::paste_internal (nframes_t position, float times)
2916 bool commit = false;
2918 if (cut_buffer->empty() || selection->tracks.empty()) {
2922 if (position == max_frames) {
2923 position = edit_cursor->current_frame;
2926 begin_reversible_command (_("paste"));
2928 TrackSelection::iterator i;
2931 /* get everything in the correct order */
2933 sort_track_selection ();
2935 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
2937 /* undo/redo is handled by individual tracks */
2939 if ((*i)->paste (position, times, *cut_buffer, nth)) {
2945 commit_reversible_command ();
2950 Editor::paste_named_selection (float times)
2952 TrackSelection::iterator t;
2954 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
2956 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
2960 TreeModel::iterator i = selected->get_selected();
2961 NamedSelection* ns = (*i)[named_selection_columns.selection];
2963 list<boost::shared_ptr<Playlist> >::iterator chunk;
2964 list<boost::shared_ptr<Playlist> >::iterator tmp;
2966 chunk = ns->playlists.begin();
2968 begin_reversible_command (_("paste chunk"));
2970 sort_track_selection ();
2972 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
2974 AudioTimeAxisView* atv;
2975 boost::shared_ptr<Playlist> pl;
2976 boost::shared_ptr<AudioPlaylist> apl;
2978 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
2982 if ((pl = atv->playlist()) == 0) {
2986 if ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) == 0) {
2993 XMLNode &before = apl->get_state();
2994 apl->paste (*chunk, edit_cursor->current_frame, times);
2995 session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
2997 if (tmp != ns->playlists.end()) {
3002 commit_reversible_command();
3006 Editor::duplicate_some_regions (RegionSelection& regions, float times)
3008 boost::shared_ptr<Playlist> playlist;
3009 RegionSelection sel = regions; // clear (below) will clear the argument list
3011 begin_reversible_command (_("duplicate region"));
3013 selection->clear_regions ();
3015 for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3017 boost::shared_ptr<Region> r ((*i)->region());
3019 TimeAxisView& tv = (*i)->get_time_axis_view();
3020 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3021 sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3023 playlist = (*i)->region()->playlist();
3024 XMLNode &before = playlist->get_state();
3025 playlist->duplicate (r, r->last_frame(), times);
3026 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
3030 if (latest_regionview) {
3031 selection->add (latest_regionview);
3036 commit_reversible_command ();
3040 Editor::duplicate_selection (float times)
3042 if (selection->time.empty() || selection->tracks.empty()) {
3046 boost::shared_ptr<Playlist> playlist;
3047 vector<boost::shared_ptr<AudioRegion> > new_regions;
3048 vector<boost::shared_ptr<AudioRegion> >::iterator ri;
3050 create_region_from_selection (new_regions);
3052 if (new_regions.empty()) {
3056 begin_reversible_command (_("duplicate selection"));
3058 ri = new_regions.begin();
3060 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3061 if ((playlist = (*i)->playlist()) == 0) {
3064 XMLNode &before = playlist->get_state();
3065 playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
3066 XMLNode &after = playlist->get_state();
3067 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3070 if (ri == new_regions.end()) {
3075 commit_reversible_command ();
3079 Editor::reset_point_selection ()
3081 /* reset all selected points to the relevant default value */
3083 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3085 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3088 atv->reset_objects (selection->points);
3094 Editor::center_playhead ()
3096 float page = canvas_width * frames_per_unit;
3098 center_screen_internal (playhead_cursor->current_frame, page);
3102 Editor::center_edit_cursor ()
3104 float page = canvas_width * frames_per_unit;
3106 center_screen_internal (edit_cursor->current_frame, page);
3110 Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
3112 begin_reversible_command (_("clear playlist"));
3113 XMLNode &before = playlist->get_state();
3115 XMLNode &after = playlist->get_state();
3116 session->add_command (new MementoCommand<Playlist>(*playlist.get(), &before, &after));
3117 commit_reversible_command ();
3121 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3123 boost::shared_ptr<Playlist> playlist;
3125 nframes_t next_distance;
3128 if (use_edit_cursor) {
3129 start = edit_cursor->current_frame;
3134 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3138 if (selection->tracks.empty()) {
3142 begin_reversible_command (_("nudge track"));
3144 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3146 if ((playlist = (*i)->playlist()) == 0) {
3150 XMLNode &before = playlist->get_state();
3151 playlist->nudge_after (start, distance, forwards);
3152 XMLNode &after = playlist->get_state();
3153 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3156 commit_reversible_command ();
3160 Editor::remove_last_capture ()
3162 vector<string> choices;
3169 if (Config->get_verify_remove_last_capture()) {
3170 prompt = _("Do you really want to destroy the last capture?"
3171 "\n(This is destructive and cannot be undone)");
3173 choices.push_back (_("No, do nothing."));
3174 choices.push_back (_("Yes, destroy it."));
3176 Gtkmm2ext::Choice prompter (prompt, choices);
3178 if (prompter.run () == 1) {
3179 session->remove_last_capture ();
3183 session->remove_last_capture();
3188 Editor::normalize_region ()
3194 if (selection->regions.empty()) {
3198 begin_reversible_command (_("normalize"));
3200 track_canvas.get_window()->set_cursor (*wait_cursor);
3203 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3204 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3207 XMLNode &before = arv->region()->get_state();
3208 arv->audio_region()->normalize_to (0.0f);
3209 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3212 commit_reversible_command ();
3213 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3218 Editor::denormalize_region ()
3224 if (selection->regions.empty()) {
3228 begin_reversible_command ("denormalize");
3230 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3231 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3234 XMLNode &before = arv->region()->get_state();
3235 arv->audio_region()->set_scale_amplitude (1.0f);
3236 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3239 commit_reversible_command ();
3244 Editor::reverse_region ()
3250 Reverse rev (*session);
3251 apply_filter (rev, _("reverse regions"));
3255 Editor::apply_filter (AudioFilter& filter, string command)
3257 if (selection->regions.empty()) {
3261 begin_reversible_command (command);
3263 track_canvas.get_window()->set_cursor (*wait_cursor);
3266 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
3267 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3271 boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
3273 RegionSelection::iterator tmp;
3278 if (arv->audio_region()->apply (filter) == 0) {
3280 XMLNode &before = playlist->get_state();
3281 playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
3282 XMLNode &after = playlist->get_state();
3283 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
3291 commit_reversible_command ();
3292 selection->regions.clear ();
3295 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3299 Editor::region_selection_op (void (Region::*pmf)(void))
3301 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3302 Region* region = (*i)->region().get();
3309 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3311 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3312 Region* region = (*i)->region().get();
3313 (region->*pmf)(arg);
3318 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3320 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3321 Region* region = (*i)->region().get();
3327 Editor::external_edit_region ()
3329 if (!clicked_regionview) {
3337 Editor::brush (nframes_t pos)
3339 RegionSelection sel;
3342 if (selection->regions.empty()) {
3343 /* XXX get selection from region list */
3345 sel = selection->regions;
3352 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3353 mouse_brush_insert_region ((*i), pos);
3358 Editor::reset_region_gain_envelopes ()
3360 if (!session || selection->regions.empty()) {
3364 session->begin_reversible_command (_("reset region gain"));
3366 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3367 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3369 AutomationList& alist (arv->audio_region()->envelope());
3370 XMLNode& before (alist.get_state());
3372 arv->audio_region()->set_default_envelope ();
3373 session->add_command (new MementoCommand<AutomationList>(arv->audio_region()->envelope(), &before, &alist.get_state()));
3377 session->commit_reversible_command ();
3381 Editor::toggle_gain_envelope_visibility ()
3383 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3384 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3386 bool x = region_envelope_visible_item->get_active();
3387 if (x != arv->envelope_visible()) {
3388 arv->set_envelope_visible (x);
3395 Editor::toggle_gain_envelope_active ()
3397 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3398 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3400 bool x = region_envelope_active_item->get_active();
3401 if (x != arv->audio_region()->envelope_active()) {
3402 arv->audio_region()->set_envelope_active (x);
3409 Editor::toggle_region_lock ()
3411 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3412 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3414 bool x = region_lock_item->get_active();
3415 if (x != arv->audio_region()->locked()) {
3416 arv->audio_region()->set_locked (x);
3423 Editor::toggle_region_mute ()
3425 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3426 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3428 bool x = region_mute_item->get_active();
3429 if (x != arv->audio_region()->muted()) {
3430 arv->audio_region()->set_muted (x);
3437 Editor::toggle_region_opaque ()
3439 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3440 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3442 bool x = region_opaque_item->get_active();
3443 if (x != arv->audio_region()->opaque()) {
3444 arv->audio_region()->set_opaque (x);
3451 Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
3453 begin_reversible_command (_("set fade in shape"));
3455 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3456 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3462 AutomationList& alist = tmp->audio_region()->fade_in();
3463 XMLNode &before = alist.get_state();
3465 tmp->audio_region()->set_fade_in_shape (shape);
3467 XMLNode &after = alist.get_state();
3468 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3471 commit_reversible_command ();
3475 Editor::set_fade_out_shape (AudioRegion::FadeShape shape)
3477 begin_reversible_command (_("set fade out shape"));
3479 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3480 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3486 AutomationList& alist = tmp->audio_region()->fade_out();
3487 XMLNode &before = alist.get_state();
3489 tmp->audio_region()->set_fade_out_shape (shape);
3491 XMLNode &after = alist.get_state();
3492 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3495 commit_reversible_command ();
3499 Editor::set_fade_in_active (bool yn)
3501 begin_reversible_command (_("set fade in active"));
3503 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3504 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3511 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3513 XMLNode &before = ar->get_state();
3515 ar->set_fade_in_active (yn);
3517 XMLNode &after = ar->get_state();
3518 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
3523 Editor::set_fade_out_active (bool yn)
3525 begin_reversible_command (_("set fade out active"));
3527 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3528 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3534 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3536 XMLNode &before = ar->get_state();
3538 ar->set_fade_out_active (yn);
3540 XMLNode &after = ar->get_state();
3541 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
3546 /** Update crossfade visibility after its configuration has been changed */
3548 Editor::update_xfade_visibility ()
3550 _xfade_visibility = Config->get_xfades_visible ();
3552 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3553 AudioTimeAxisView* v = dynamic_cast<AudioTimeAxisView*>(*i);
3555 if (_xfade_visibility) {
3556 v->show_all_xfades ();
3558 v->hide_all_xfades ();