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"));
118 // if splitting a single region, and snap-to is using
119 // region boundaries, don't pay attention to them
121 if (regions.size() == 1) {
123 case SnapToRegionStart:
124 case SnapToRegionSync:
125 case SnapToRegionEnd:
135 for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
137 RegionSelection::iterator tmp;
142 boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
144 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
146 _new_regionviews_show_envelope = arv->envelope_visible();
149 XMLNode &before = pl->get_state();
150 pl->split_region ((*a)->region(), where);
151 XMLNode &after = pl->get_state();
152 session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
158 commit_reversible_command ();
159 _new_regionviews_show_envelope = false;
163 Editor::remove_clicked_region ()
165 if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
169 boost::shared_ptr<Playlist> playlist = clicked_audio_trackview->playlist();
171 begin_reversible_command (_("remove region"));
172 XMLNode &before = playlist->get_state();
173 playlist->remove_region (clicked_regionview->region());
174 XMLNode &after = playlist->get_state();
175 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
176 commit_reversible_command ();
180 Editor::destroy_clicked_region ()
182 uint32_t selected = selection->regions.size();
184 if (!session || !selected) {
188 vector<string> choices;
191 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
192 It cannot be undone\n\
193 Do you really want to destroy %1 ?"),
195 _("these regions") : _("this region")));
197 choices.push_back (_("No, do nothing."));
200 choices.push_back (_("Yes, destroy them."));
202 choices.push_back (_("Yes, destroy it."));
205 Gtkmm2ext::Choice prompter (prompt, choices);
207 if (prompter.run() == 0) { /* first choice */
212 list<boost::shared_ptr<Region> > r;
214 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
215 r.push_back ((*i)->region());
218 session->destroy_regions (r);
222 boost::shared_ptr<Region>
223 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
226 boost::shared_ptr<Region> region;
229 if (selection->time.start () == selection->time.end_frame ()) {
231 /* no current selection-> is there a selected regionview? */
233 if (selection->regions.empty()) {
239 if (!selection->regions.empty()) {
241 rv = *(selection->regions.begin());
242 (*tv) = &rv->get_time_axis_view();
243 region = rv->region();
245 } else if (!selection->tracks.empty()) {
247 (*tv) = selection->tracks.front();
249 RouteTimeAxisView* rtv;
251 if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
252 boost::shared_ptr<Playlist> pl;
254 if ((pl = rtv->playlist()) == 0) {
258 region = pl->top_region_at (start);
266 Editor::extend_selection_to_end_of_region (bool next)
269 boost::shared_ptr<Region> region;
272 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
276 if (region && selection->time.start () == selection->time.end_frame ()) {
277 start = region->position();
279 start = selection->time.start ();
282 /* Try to leave the selection with the same route if possible */
284 if ((tv = selection->time.track) == 0) {
288 begin_reversible_command (_("extend selection"));
289 selection->set (tv, start, region->position() + region->length());
290 commit_reversible_command ();
294 Editor::extend_selection_to_start_of_region (bool previous)
297 boost::shared_ptr<Region> region;
300 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
304 if (region && selection->time.start () == selection->time.end_frame ()) {
305 end = region->position() + region->length();
307 end = selection->time.end_frame ();
310 /* Try to leave the selection with the same route if possible */
312 if ((tv = selection->time.track) == 0) {
316 begin_reversible_command (_("extend selection"));
317 selection->set (tv, region->position(), end);
318 commit_reversible_command ();
323 Editor::nudge_forward (bool next)
326 nframes_t next_distance;
328 if (!session) return;
330 if (!selection->regions.empty()) {
332 begin_reversible_command (_("nudge forward"));
334 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
335 boost::shared_ptr<Region> r ((*i)->region());
337 distance = get_nudge_distance (r->position(), next_distance);
340 distance = next_distance;
343 XMLNode &before = r->playlist()->get_state();
344 r->set_position (r->position() + distance, this);
345 XMLNode &after = r->playlist()->get_state();
346 session->add_command (new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
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)
361 nframes_t next_distance;
363 if (!session) return;
365 if (!selection->regions.empty()) {
367 begin_reversible_command (_("nudge forward"));
369 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
370 boost::shared_ptr<Region> r ((*i)->region());
372 distance = get_nudge_distance (r->position(), next_distance);
375 distance = next_distance;
378 XMLNode &before = r->playlist()->get_state();
380 if (r->position() > distance) {
381 r->set_position (r->position() - distance, this);
383 r->set_position (0, this);
385 XMLNode &after = r->playlist()->get_state();
386 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
389 commit_reversible_command ();
393 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
395 if (playhead_cursor->current_frame > distance) {
396 session->request_locate (playhead_cursor->current_frame - distance);
398 session->goto_start();
404 Editor::nudge_forward_capture_offset ()
408 if (!session) return;
410 if (!selection->regions.empty()) {
412 begin_reversible_command (_("nudge forward"));
414 distance = session->worst_output_latency();
416 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
417 boost::shared_ptr<Region> r ((*i)->region());
419 XMLNode &before = r->playlist()->get_state();
420 r->set_position (r->position() + distance, this);
421 XMLNode &after = r->playlist()->get_state();
422 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
425 commit_reversible_command ();
431 Editor::nudge_backward_capture_offset ()
435 if (!session) return;
437 if (!selection->regions.empty()) {
439 begin_reversible_command (_("nudge forward"));
441 distance = session->worst_output_latency();
443 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
444 boost::shared_ptr<Region> r ((*i)->region());
446 XMLNode &before = r->playlist()->get_state();
448 if (r->position() > distance) {
449 r->set_position (r->position() - distance, this);
451 r->set_position (0, this);
453 XMLNode &after = r->playlist()->get_state();
454 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
457 commit_reversible_command ();
464 Editor::move_to_start ()
466 session->goto_start ();
470 Editor::move_to_end ()
473 session->request_locate (session->current_end_frame());
477 Editor::build_region_boundary_cache ()
480 vector<RegionPoint> interesting_points;
481 boost::shared_ptr<Region> r;
482 TrackViewList tracks;
485 region_boundary_cache.clear ();
492 case SnapToRegionStart:
493 interesting_points.push_back (Start);
495 case SnapToRegionEnd:
496 interesting_points.push_back (End);
498 case SnapToRegionSync:
499 interesting_points.push_back (SyncPoint);
501 case SnapToRegionBoundary:
502 interesting_points.push_back (Start);
503 interesting_points.push_back (End);
506 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
511 TimeAxisView *ontrack = 0;
514 if (!selection->tracks.empty()) {
515 tlist = selection->tracks;
520 while (pos < session->current_end_frame() && !at_end) {
523 nframes_t lpos = max_frames;
525 for (vector<RegionPoint>::iterator p = interesting_points.begin(); p != interesting_points.end(); ++p) {
527 if ((r = find_next_region (pos, *p, 1, tlist, &ontrack)) == 0) {
529 /* move to next point type */
536 rpos = r->first_frame();
539 rpos = r->last_frame();
542 rpos = r->adjust_to_sync (r->first_frame());
549 AudioTimeAxisView *atav;
551 if (ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
552 if (atav->get_diskstream() != 0) {
553 speed = atav->get_diskstream()->speed();
557 rpos = track_frame_to_session_frame (rpos, speed);
563 /* prevent duplicates, but we don't use set<> because we want to be able
567 vector<nframes_t>::iterator ri;
569 for (ri = region_boundary_cache.begin(); ri != region_boundary_cache.end(); ++ri) {
575 if (ri == region_boundary_cache.end()) {
576 region_boundary_cache.push_back (rpos);
583 /* finally sort to be sure that the order is correct */
585 sort (region_boundary_cache.begin(), region_boundary_cache.end());
588 boost::shared_ptr<Region>
589 Editor::find_next_region (nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
591 TrackViewList::iterator i;
592 nframes_t closest = max_frames;
593 boost::shared_ptr<Region> ret;
597 nframes_t track_frame;
598 AudioTimeAxisView *atav;
600 for (i = tracks.begin(); i != tracks.end(); ++i) {
603 boost::shared_ptr<Region> r;
606 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
607 if (atav->get_diskstream()!=0)
608 track_speed = atav->get_diskstream()->speed();
611 track_frame = session_frame_to_track_frame(frame, track_speed);
613 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
619 rpos = r->first_frame ();
623 rpos = r->last_frame ();
627 rpos = r->adjust_to_sync (r->first_frame());
630 // rpos is a "track frame", converting it to "session frame"
631 rpos = track_frame_to_session_frame(rpos, track_speed);
634 distance = rpos - frame;
636 distance = frame - rpos;
639 if (distance < closest) {
651 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
653 boost::shared_ptr<Region> r;
654 nframes_t pos = cursor->current_frame;
660 TimeAxisView *ontrack = 0;
662 // so we don't find the current region again..
666 if (!selection->tracks.empty()) {
668 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
670 } else if (clicked_trackview) {
673 t.push_back (clicked_trackview);
675 r = find_next_region (pos, point, dir, t, &ontrack);
679 r = find_next_region (pos, point, dir, track_views, &ontrack);
688 pos = r->first_frame ();
692 pos = r->last_frame ();
696 pos = r->adjust_to_sync (r->first_frame());
701 AudioTimeAxisView *atav;
703 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
704 if (atav->get_diskstream() != 0) {
705 speed = atav->get_diskstream()->speed();
709 pos = track_frame_to_session_frame(pos, speed);
711 if (cursor == playhead_cursor) {
712 session->request_locate (pos);
714 cursor->set_position (pos);
719 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
721 cursor_to_region_point (cursor, point, 1);
725 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
727 cursor_to_region_point (cursor, point, -1);
731 Editor::cursor_to_selection_start (Cursor *cursor)
734 switch (mouse_mode) {
736 if (!selection->regions.empty()) {
737 pos = selection->regions.start();
742 if (!selection->time.empty()) {
743 pos = selection->time.start ();
751 if (cursor == playhead_cursor) {
752 session->request_locate (pos);
754 cursor->set_position (pos);
759 Editor::cursor_to_selection_end (Cursor *cursor)
763 switch (mouse_mode) {
765 if (!selection->regions.empty()) {
766 pos = selection->regions.end_frame();
771 if (!selection->time.empty()) {
772 pos = selection->time.end_frame ();
780 if (cursor == playhead_cursor) {
781 session->request_locate (pos);
783 cursor->set_position (pos);
788 Editor::scroll_playhead (bool forward)
790 nframes_t pos = playhead_cursor->current_frame;
791 nframes_t delta = (nframes_t) floor (current_page_frames() / 0.8);
794 if (pos == max_frames) {
798 if (pos < max_frames - delta) {
817 session->request_locate (pos);
821 Editor::playhead_backward ()
828 if (get_prefix (prefix, was_floating)) {
832 cnt = (nframes_t) floor (prefix * session->frame_rate ());
834 cnt = (nframes_t) prefix;
838 pos = playhead_cursor->current_frame;
840 if ((nframes_t) pos < cnt) {
846 /* XXX this is completely insane. with the current buffering
847 design, we'll force a complete track buffer flush and
848 reload, just to move 1 sample !!!
851 session->request_locate (pos);
855 Editor::playhead_forward ()
862 if (get_prefix (prefix, was_floating)) {
866 cnt = (nframes_t) floor (prefix * session->frame_rate ());
868 cnt = (nframes_t) floor (prefix);
872 pos = playhead_cursor->current_frame;
874 /* XXX this is completely insane. with the current buffering
875 design, we'll force a complete track buffer flush and
876 reload, just to move 1 sample !!!
879 session->request_locate (pos+cnt);
883 Editor::cursor_align (bool playhead_to_edit)
885 if (playhead_to_edit) {
887 session->request_locate (edit_cursor->current_frame);
890 edit_cursor->set_position (playhead_cursor->current_frame);
895 Editor::edit_cursor_backward ()
902 if (get_prefix (prefix, was_floating)) {
906 cnt = (nframes_t) floor (prefix * session->frame_rate ());
908 cnt = (nframes_t) prefix;
912 pos = edit_cursor->current_frame;
914 if ((nframes_t) pos < cnt) {
920 edit_cursor->set_position (pos);
924 Editor::edit_cursor_forward ()
931 if (get_prefix (prefix, was_floating)) {
935 cnt = (nframes_t) floor (prefix * session->frame_rate ());
937 cnt = (nframes_t) floor (prefix);
941 pos = edit_cursor->current_frame;
942 edit_cursor->set_position (pos+cnt);
946 Editor::goto_frame ()
952 if (get_prefix (prefix, was_floating)) {
957 frame = (nframes_t) floor (prefix * session->frame_rate());
959 frame = (nframes_t) floor (prefix);
962 session->request_locate (frame);
966 Editor::scroll_backward (float pages)
969 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
974 if (get_prefix (prefix, was_floating)) {
975 cnt = (nframes_t) floor (pages * one_page);
978 cnt = (nframes_t) floor (prefix * session->frame_rate());
980 cnt = (nframes_t) floor (prefix * one_page);
984 if (leftmost_frame < cnt) {
987 frame = leftmost_frame - cnt;
990 reset_x_origin (frame);
994 Editor::scroll_forward (float pages)
997 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
1002 if (get_prefix (prefix, was_floating)) {
1003 cnt = (nframes_t) floor (pages * one_page);
1006 cnt = (nframes_t) floor (prefix * session->frame_rate());
1008 cnt = (nframes_t) floor (prefix * one_page);
1012 if (max_frames - cnt < leftmost_frame) {
1013 frame = max_frames - cnt;
1015 frame = leftmost_frame + cnt;
1018 reset_x_origin (frame);
1022 Editor::scroll_tracks_down ()
1028 if (get_prefix (prefix, was_floating)) {
1031 cnt = (int) floor (prefix);
1034 double vert_value = vertical_adjustment.get_value() + (cnt *
1035 vertical_adjustment.get_page_size());
1036 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
1037 vert_value = vertical_adjustment.get_upper() - canvas_height;
1039 vertical_adjustment.set_value (vert_value);
1043 Editor::scroll_tracks_up ()
1049 if (get_prefix (prefix, was_floating)) {
1052 cnt = (int) floor (prefix);
1055 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1059 Editor::scroll_tracks_down_line ()
1062 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1063 double vert_value = adj->get_value() + 20;
1065 if (vert_value>adj->get_upper() - canvas_height) {
1066 vert_value = adj->get_upper() - canvas_height;
1068 adj->set_value (vert_value);
1072 Editor::scroll_tracks_up_line ()
1074 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1075 adj->set_value (adj->get_value() - 20);
1081 Editor::temporal_zoom_step (bool coarser)
1083 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1087 nfpu = frames_per_unit;
1092 nfpu = max(1.0,(nfpu/1.61803399));
1095 temporal_zoom (nfpu);
1099 Editor::temporal_zoom (gdouble fpu)
1101 if (!session) return;
1103 nframes_t current_page = current_page_frames();
1104 nframes_t current_leftmost = leftmost_frame;
1105 nframes_t current_rightmost;
1106 nframes_t current_center;
1108 nframes_t leftmost_after_zoom = 0;
1113 new_page = (nframes_t) floor (canvas_width * nfpu);
1115 switch (zoom_focus) {
1117 leftmost_after_zoom = current_leftmost;
1120 case ZoomFocusRight:
1121 current_rightmost = leftmost_frame + current_page;
1122 if (current_rightmost > new_page) {
1123 leftmost_after_zoom = current_rightmost - new_page;
1125 leftmost_after_zoom = 0;
1129 case ZoomFocusCenter:
1130 current_center = current_leftmost + (current_page/2);
1131 if (current_center > (new_page/2)) {
1132 leftmost_after_zoom = current_center - (new_page / 2);
1134 leftmost_after_zoom = 0;
1138 case ZoomFocusPlayhead:
1139 /* try to keep the playhead in the center */
1140 if (playhead_cursor->current_frame > new_page/2) {
1141 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1143 leftmost_after_zoom = 0;
1148 /* try to keep the edit cursor in the center */
1149 if (edit_cursor->current_frame > new_page/2) {
1150 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1152 leftmost_after_zoom = 0;
1158 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1160 // begin_reversible_command (_("zoom"));
1161 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1162 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1163 // commit_reversible_command ();
1165 reposition_and_zoom (leftmost_after_zoom, nfpu);
1169 Editor::temporal_zoom_selection ()
1171 if (!selection) return;
1173 if (selection->time.empty()) {
1177 nframes_t start = selection->time[clicked_selection].start;
1178 nframes_t end = selection->time[clicked_selection].end;
1180 temporal_zoom_by_frame (start, end, "zoom to selection");
1184 Editor::temporal_zoom_session ()
1186 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1189 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1194 Editor::temporal_zoom_by_frame (nframes_t start, nframes_t end, const string & op)
1196 if (!session) return;
1198 if ((start == 0 && end == 0) || end < start) {
1202 nframes_t range = end - start;
1204 double new_fpu = (double)range / (double)canvas_width;
1207 // while (p2 < new_fpu) {
1212 nframes_t new_page = (nframes_t) floor (canvas_width * new_fpu);
1213 nframes_t middle = (nframes_t) floor( (double)start + ((double)range / 2.0f ));
1214 nframes_t new_leftmost = (nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1216 if (new_leftmost > middle) new_leftmost = 0;
1218 // begin_reversible_command (op);
1219 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1220 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1221 // commit_reversible_command ();
1223 reposition_and_zoom (new_leftmost, new_fpu);
1227 Editor::temporal_zoom_to_frame (bool coarser, nframes_t frame)
1229 if (!session) return;
1231 double range_before = frame - leftmost_frame;
1234 new_fpu = frames_per_unit;
1237 new_fpu *= 1.61803399;
1238 range_before *= 1.61803399;
1240 new_fpu = max(1.0,(new_fpu/1.61803399));
1241 range_before /= 1.61803399;
1244 if (new_fpu == frames_per_unit) return;
1246 nframes_t new_leftmost = frame - (nframes_t)range_before;
1248 if (new_leftmost > frame) new_leftmost = 0;
1250 // begin_reversible_command (_("zoom to frame"));
1251 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1252 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1253 // commit_reversible_command ();
1255 reposition_and_zoom (new_leftmost, new_fpu);
1259 Editor::add_location_from_selection ()
1263 if (selection->time.empty()) {
1267 if (session == 0 || clicked_trackview == 0) {
1271 nframes_t start = selection->time[clicked_selection].start;
1272 nframes_t end = selection->time[clicked_selection].end;
1274 session->locations()->next_available_name(rangename,"selection");
1275 Location *location = new Location (start, end, rangename, Location::IsRangeMarker);
1277 session->begin_reversible_command (_("add marker"));
1278 XMLNode &before = session->locations()->get_state();
1279 session->locations()->add (location, true);
1280 XMLNode &after = session->locations()->get_state();
1281 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1282 session->commit_reversible_command ();
1286 Editor::add_location_from_playhead_cursor ()
1290 nframes_t where = session->audible_frame();
1292 session->locations()->next_available_name(markername,"mark");
1293 Location *location = new Location (where, where, markername, Location::IsMark);
1294 session->begin_reversible_command (_("add marker"));
1295 XMLNode &before = session->locations()->get_state();
1296 session->locations()->add (location, true);
1297 XMLNode &after = session->locations()->get_state();
1298 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1299 session->commit_reversible_command ();
1303 Editor::add_location_from_audio_region ()
1305 if (selection->regions.empty()) {
1309 RegionView* rv = *(selection->regions.begin());
1310 boost::shared_ptr<Region> region = rv->region();
1312 Location *location = new Location (region->position(), region->last_frame(), region->name(), Location::IsRangeMarker);
1313 session->begin_reversible_command (_("add marker"));
1314 XMLNode &before = session->locations()->get_state();
1315 session->locations()->add (location, true);
1316 XMLNode &after = session->locations()->get_state();
1317 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1318 session->commit_reversible_command ();
1322 Editor::amplitude_zoom_step (bool in)
1336 #ifdef FIX_FOR_CANVAS
1337 /* XXX DO SOMETHING */
1346 Editor::delete_sample_forward ()
1351 Editor::delete_sample_backward ()
1356 Editor::delete_screen ()
1363 Editor::search_backwards ()
1369 Editor::search_forwards ()
1377 Editor::jump_forward_to_mark ()
1383 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1386 session->request_locate (location->start(), session->transport_rolling());
1388 session->request_locate (session->current_end_frame());
1393 Editor::jump_backward_to_mark ()
1399 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1402 session->request_locate (location->start(), session->transport_rolling());
1404 session->goto_start ();
1416 if (get_prefix (prefix, was_floating)) {
1417 pos = session->audible_frame ();
1420 pos = (nframes_t) floor (prefix * session->frame_rate ());
1422 pos = (nframes_t) floor (prefix);
1426 session->locations()->next_available_name(markername,"mark");
1427 session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true);
1431 Editor::clear_markers ()
1434 session->begin_reversible_command (_("clear markers"));
1435 XMLNode &before = session->locations()->get_state();
1436 session->locations()->clear_markers ();
1437 XMLNode &after = session->locations()->get_state();
1438 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1439 session->commit_reversible_command ();
1444 Editor::clear_ranges ()
1447 session->begin_reversible_command (_("clear ranges"));
1448 XMLNode &before = session->locations()->get_state();
1450 Location * looploc = session->locations()->auto_loop_location();
1451 Location * punchloc = session->locations()->auto_punch_location();
1453 session->locations()->clear_ranges ();
1455 if (looploc) session->locations()->add (looploc);
1456 if (punchloc) session->locations()->add (punchloc);
1458 XMLNode &after = session->locations()->get_state();
1459 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1460 session->commit_reversible_command ();
1465 Editor::clear_locations ()
1467 session->begin_reversible_command (_("clear locations"));
1468 XMLNode &before = session->locations()->get_state();
1469 session->locations()->clear ();
1470 XMLNode &after = session->locations()->get_state();
1471 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1472 session->commit_reversible_command ();
1473 session->locations()->clear ();
1477 Editor::unhide_markers ()
1479 for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1480 Location *l = (*i).first;
1481 if (l->is_hidden() && l->is_mark()) {
1482 l->set_hidden(false, this);
1488 Editor::unhide_ranges ()
1490 for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1491 Location *l = (*i).first;
1492 if (l->is_hidden() && l->is_range_marker()) {
1493 l->set_hidden(false, this);
1498 /* INSERT/REPLACE */
1501 Editor::insert_region_list_drag (boost::shared_ptr<AudioRegion> region, int x, int y)
1507 AudioTimeAxisView *atv = 0;
1508 boost::shared_ptr<Playlist> playlist;
1510 track_canvas.window_to_world (x, y, wx, wy);
1511 wx += horizontal_adjustment.get_value();
1512 wy += vertical_adjustment.get_value();
1515 event.type = GDK_BUTTON_RELEASE;
1516 event.button.x = wx;
1517 event.button.y = wy;
1519 where = event_frame (&event, &cx, &cy);
1521 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1522 /* clearly outside canvas area */
1526 if ((tv = trackview_by_y_position (cy)) == 0) {
1530 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1534 if ((playlist = atv->playlist()) == 0) {
1540 begin_reversible_command (_("insert dragged region"));
1541 XMLNode &before = playlist->get_state();
1542 playlist->add_region (RegionFactory::create (region), where, 1.0);
1543 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1544 commit_reversible_command ();
1548 Editor::insert_region_list_selection (float times)
1550 RouteTimeAxisView *tv = 0;
1551 boost::shared_ptr<Playlist> playlist;
1553 if (clicked_audio_trackview != 0) {
1554 tv = clicked_audio_trackview;
1555 } else if (!selection->tracks.empty()) {
1556 if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
1563 if ((playlist = tv->playlist()) == 0) {
1567 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1569 if (selected->count_selected_rows() != 1) {
1573 TreeView::Selection::ListHandle_Path rows = selected->get_selected_rows ();
1575 /* only one row selected, so rows.begin() is it */
1579 if ((iter = region_list_model->get_iter (*rows.begin()))) {
1581 boost::shared_ptr<Region> region = (*iter)[region_list_columns.region];
1583 begin_reversible_command (_("insert region"));
1584 XMLNode &before = playlist->get_state();
1585 playlist->add_region ((RegionFactory::create (region)), edit_cursor->current_frame, times);
1586 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1587 commit_reversible_command ();
1591 /* BUILT-IN EFFECTS */
1594 Editor::reverse_selection ()
1599 /* GAIN ENVELOPE EDITING */
1602 Editor::edit_envelope ()
1609 Editor::transition_to_rolling (bool fwd)
1615 switch (Config->get_slave_source()) {
1620 /* transport controlled by the master */
1624 if (session->is_auditioning()) {
1625 session->cancel_audition ();
1629 session->request_transport_speed (fwd ? 1.0f : -1.0f);
1633 Editor::toggle_playback (bool with_abort)
1639 switch (Config->get_slave_source()) {
1644 /* transport controlled by the master */
1648 if (session->is_auditioning()) {
1649 session->cancel_audition ();
1653 if (session->transport_rolling()) {
1654 session->request_stop (with_abort);
1655 if (session->get_play_loop()) {
1656 session->request_play_loop (false);
1659 session->request_transport_speed (1.0f);
1664 Editor::play_from_start ()
1666 session->request_locate (session->current_start_frame(), true);
1670 Editor::play_from_edit_cursor ()
1672 session->request_locate (edit_cursor->current_frame, true);
1676 Editor::play_selection ()
1678 if (selection->time.empty()) {
1682 session->request_play_range (true);
1686 Editor::play_selected_region ()
1688 if (!selection->regions.empty()) {
1689 RegionView *rv = *(selection->regions.begin());
1691 session->request_bounded_roll (rv->region()->position(), rv->region()->last_frame());
1696 Editor::loop_selected_region ()
1698 if (!selection->regions.empty()) {
1699 RegionView *rv = *(selection->regions.begin());
1702 if ((tll = transport_loop_location()) != 0) {
1704 tll->set (rv->region()->position(), rv->region()->last_frame());
1706 // enable looping, reposition and start rolling
1708 session->request_play_loop (true);
1709 session->request_locate (tll->start(), false);
1710 session->request_transport_speed (1.0f);
1716 Editor::play_location (Location& location)
1718 if (location.start() <= location.end()) {
1722 session->request_bounded_roll (location.start(), location.end());
1726 Editor::loop_location (Location& location)
1728 if (location.start() <= location.end()) {
1734 if ((tll = transport_loop_location()) != 0) {
1735 tll->set (location.start(), location.end());
1737 // enable looping, reposition and start rolling
1738 session->request_play_loop (true);
1739 session->request_locate (tll->start(), true);
1744 Editor::raise_region ()
1746 selection->foreach_region (&Region::raise);
1750 Editor::raise_region_to_top ()
1752 selection->foreach_region (&Region::raise_to_top);
1756 Editor::lower_region ()
1758 selection->foreach_region (&Region::lower);
1762 Editor::lower_region_to_bottom ()
1764 selection->foreach_region (&Region::lower_to_bottom);
1768 Editor::edit_region ()
1770 if (clicked_regionview == 0) {
1774 clicked_regionview->show_region_editor ();
1778 Editor::rename_region ()
1782 Button ok_button (_("OK"));
1783 Button cancel_button (_("Cancel"));
1785 if (selection->regions.empty()) {
1789 WindowTitle title(Glib::get_application_name());
1790 title += _("Rename Region");
1792 dialog.set_title (title.get_string());
1793 dialog.set_name ("RegionRenameWindow");
1794 dialog.set_size_request (300, -1);
1795 dialog.set_position (Gtk::WIN_POS_MOUSE);
1796 dialog.set_modal (true);
1798 dialog.get_vbox()->set_border_width (10);
1799 dialog.get_vbox()->pack_start (entry);
1800 dialog.get_action_area()->pack_start (ok_button);
1801 dialog.get_action_area()->pack_start (cancel_button);
1803 entry.set_name ("RegionNameDisplay");
1804 ok_button.set_name ("EditorGTKButton");
1805 cancel_button.set_name ("EditorGTKButton");
1807 region_renamed = false;
1809 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1810 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1811 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
1818 if (region_renamed) {
1819 (*selection->regions.begin())->region()->set_name (entry.get_text());
1820 redisplay_regions ();
1825 Editor::rename_region_finished (bool status)
1828 region_renamed = status;
1833 Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Route& route)
1835 if (session->is_auditioning()) {
1836 session->cancel_audition ();
1839 // note: some potential for creativity here, because region doesn't
1840 // have to belong to the playlist that Route is handling
1842 // bool was_soloed = route.soloed();
1844 route.set_solo (true, this);
1846 session->request_bounded_roll (region->position(), region->position() + region->length());
1848 /* XXX how to unset the solo state ? */
1852 Editor::audition_selected_region ()
1854 if (!selection->regions.empty()) {
1855 RegionView* rv = *(selection->regions.begin());
1856 session->audition_region (rv->region());
1861 Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
1863 session->audition_region (region);
1867 Editor::build_interthread_progress_window ()
1869 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
1871 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
1873 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
1874 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
1876 // GTK2FIX: this button needs a modifiable label
1878 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1879 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
1881 interthread_cancel_button.add (interthread_cancel_label);
1883 interthread_progress_window->set_default_size (200, 100);
1887 Editor::interthread_cancel_clicked ()
1889 if (current_interthread_info) {
1890 current_interthread_info->cancel = true;
1895 Editor::region_from_selection ()
1897 if (clicked_trackview == 0) {
1901 if (selection->time.empty()) {
1905 nframes_t start = selection->time[clicked_selection].start;
1906 nframes_t end = selection->time[clicked_selection].end;
1908 nframes_t selection_cnt = end - start + 1;
1910 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1911 boost::shared_ptr<AudioRegion> current;
1912 boost::shared_ptr<Region> current_r;
1913 boost::shared_ptr<Playlist> pl;
1915 nframes_t internal_start;
1918 if ((pl = (*i)->playlist()) == 0) {
1922 if ((current_r = pl->top_region_at (start)) == 0) {
1926 current = boost::dynamic_pointer_cast<AudioRegion> (current_r);
1927 // FIXME: audio only
1929 internal_start = start - current->position();
1930 session->region_name (new_name, current->name(), true);
1931 boost::shared_ptr<Region> region (RegionFactory::create (current, internal_start, selection_cnt, new_name));
1937 Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& new_regions)
1939 if (selection->time.empty() || selection->tracks.empty()) {
1943 nframes_t start = selection->time[clicked_selection].start;
1944 nframes_t end = selection->time[clicked_selection].end;
1946 sort_track_selection ();
1948 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1950 boost::shared_ptr<AudioRegion> current;
1951 boost::shared_ptr<Region> current_r;
1952 boost::shared_ptr<Playlist> playlist;
1953 nframes_t internal_start;
1956 if ((playlist = (*i)->playlist()) == 0) {
1960 if ((current_r = playlist->top_region_at(start)) == 0) {
1964 if ((current = boost::dynamic_pointer_cast<AudioRegion>(current_r)) == 0) {
1968 internal_start = start - current->position();
1969 session->region_name (new_name, current->name(), true);
1971 new_regions.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (current, internal_start, end - start + 1, new_name)));
1976 Editor::split_multichannel_region ()
1978 if (selection->regions.empty()) {
1982 vector<boost::shared_ptr<AudioRegion> > v;
1984 for (list<RegionView*>::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
1986 AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*x);
1988 if (!arv || arv->audio_region()->n_channels() < 2) {
1992 (arv)->audio_region()->separate_by_channel (*session, v);
1997 Editor::new_region_from_selection ()
1999 region_from_selection ();
2000 cancel_selection ();
2004 Editor::separate_region_from_selection ()
2006 bool doing_undo = false;
2008 if (selection->time.empty()) {
2012 boost::shared_ptr<Playlist> playlist;
2014 sort_track_selection ();
2016 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2018 AudioTimeAxisView* atv;
2020 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2022 if (atv->is_audio_track()) {
2024 /* no edits to destructive tracks */
2026 if (atv->audio_track()->audio_diskstream()->destructive()) {
2030 if ((playlist = atv->playlist()) != 0) {
2032 begin_reversible_command (_("separate"));
2037 before = &(playlist->get_state());
2039 /* XXX need to consider musical time selections here at some point */
2041 double speed = atv->get_diskstream()->speed();
2043 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2044 playlist->partition ((nframes_t)((*t).start * speed), (nframes_t)((*t).end * speed), true);
2048 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2054 if (doing_undo) commit_reversible_command ();
2058 Editor::separate_regions_using_location (Location& loc)
2060 bool doing_undo = false;
2062 if (loc.is_mark()) {
2066 boost::shared_ptr<Playlist> playlist;
2068 /* XXX i'm unsure as to whether this should operate on selected tracks only
2069 or the entire enchillada. uncomment the below line to correct the behaviour
2070 (currently set for all tracks)
2073 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2074 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2076 AudioTimeAxisView* atv;
2078 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2080 if (atv->is_audio_track()) {
2082 /* no edits to destructive tracks */
2084 if (atv->audio_track()->audio_diskstream()->destructive()) {
2088 if ((playlist = atv->playlist()) != 0) {
2091 begin_reversible_command (_("separate"));
2095 before = &(playlist->get_state());
2098 /* XXX need to consider musical time selections here at some point */
2100 double speed = atv->get_diskstream()->speed();
2103 playlist->partition ((nframes_t)(loc.start() * speed), (nframes_t)(loc.end() * speed), true);
2105 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2111 if (doing_undo) commit_reversible_command ();
2115 Editor::crop_region_to_selection ()
2117 if (selection->time.empty() || selection->tracks.empty()) {
2121 vector<boost::shared_ptr<Playlist> > playlists;
2122 boost::shared_ptr<Playlist> playlist;
2124 sort_track_selection ();
2126 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2128 AudioTimeAxisView* atv;
2130 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2132 if (atv->is_audio_track()) {
2134 /* no edits to destructive tracks */
2136 if (atv->audio_track()->audio_diskstream()->destructive()) {
2140 if ((playlist = atv->playlist()) != 0) {
2141 playlists.push_back (playlist);
2147 if (playlists.empty()) {
2155 begin_reversible_command (_("trim to selection"));
2157 for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2159 boost::shared_ptr<Region> region;
2161 start = selection->time.start();
2163 if ((region = (*i)->top_region_at(start)) == 0) {
2167 /* now adjust lengths to that we do the right thing
2168 if the selection extends beyond the region
2171 start = max (start, region->position());
2172 if (max_frames - start < region->length()) {
2173 end = start + region->length() - 1;
2177 end = min (selection->time.end_frame(), end);
2178 cnt = end - start + 1;
2180 XMLNode &before = (*i)->get_state();
2181 region->trim_to (start, cnt, this);
2182 XMLNode &after = (*i)->get_state();
2183 session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
2186 commit_reversible_command ();
2190 Editor::region_fill_track ()
2194 if (!session || selection->regions.empty()) {
2198 end = session->current_end_frame ();
2200 begin_reversible_command (_("region fill"));
2202 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2204 boost::shared_ptr<Region> region ((*i)->region());
2207 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
2211 boost::shared_ptr<Playlist> pl = region->playlist();
2213 if (end <= region->last_frame()) {
2217 double times = (double) (end - region->last_frame()) / (double) region->length();
2223 XMLNode &before = pl->get_state();
2224 pl->add_region (RegionFactory::create (ar), ar->last_frame(), times);
2225 session->add_command (new MementoCommand<Playlist>(*pl, &before, &pl->get_state()));
2228 commit_reversible_command ();
2232 Editor::region_fill_selection ()
2234 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2238 if (selection->time.empty()) {
2243 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2245 if (selected->count_selected_rows() != 1) {
2249 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2250 boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
2252 nframes_t start = selection->time[clicked_selection].start;
2253 nframes_t end = selection->time[clicked_selection].end;
2255 boost::shared_ptr<Playlist> playlist;
2257 if (selection->tracks.empty()) {
2261 nframes_t selection_length = end - start;
2262 float times = (float)selection_length / region->length();
2264 begin_reversible_command (_("fill selection"));
2266 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2268 if ((playlist = (*i)->playlist()) == 0) {
2272 XMLNode &before = playlist->get_state();
2273 playlist->add_region (RegionFactory::create (region), start, times);
2274 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
2277 commit_reversible_command ();
2281 Editor::set_a_regions_sync_position (boost::shared_ptr<Region> region, nframes_t position)
2284 if (!region->covers (position)) {
2285 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2288 begin_reversible_command (_("set region sync position"));
2289 XMLNode &before = region->playlist()->get_state();
2290 region->set_sync_position (position);
2291 XMLNode &after = region->playlist()->get_state();
2292 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2293 commit_reversible_command ();
2297 Editor::set_region_sync_from_edit_cursor ()
2299 if (clicked_regionview == 0) {
2303 if (!clicked_regionview->region()->covers (edit_cursor->current_frame)) {
2304 error << _("Place the edit cursor at the desired sync point") << endmsg;
2308 boost::shared_ptr<Region> region (clicked_regionview->region());
2309 begin_reversible_command (_("set sync from edit cursor"));
2310 XMLNode &before = region->playlist()->get_state();
2311 region->set_sync_position (edit_cursor->current_frame);
2312 XMLNode &after = region->playlist()->get_state();
2313 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2314 commit_reversible_command ();
2318 Editor::remove_region_sync ()
2320 if (clicked_regionview) {
2321 boost::shared_ptr<Region> region (clicked_regionview->region());
2322 begin_reversible_command (_("remove sync"));
2323 XMLNode &before = region->playlist()->get_state();
2324 region->clear_sync_position ();
2325 XMLNode &after = region->playlist()->get_state();
2326 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2327 commit_reversible_command ();
2332 Editor::naturalize ()
2334 if (selection->regions.empty()) {
2337 begin_reversible_command (_("naturalize"));
2338 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2339 XMLNode &before = (*i)->region()->get_state();
2340 (*i)->region()->move_to_natural_position (this);
2341 XMLNode &after = (*i)->region()->get_state();
2342 session->add_command (new MementoCommand<Region>(*((*i)->region().get()), &before, &after));
2344 commit_reversible_command ();
2348 Editor::align (RegionPoint what)
2350 align_selection (what, edit_cursor->current_frame);
2354 Editor::align_relative (RegionPoint what)
2356 align_selection_relative (what, edit_cursor->current_frame);
2359 struct RegionSortByTime {
2360 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2361 return a->region()->position() < b->region()->position();
2366 Editor::align_selection_relative (RegionPoint point, nframes_t position)
2368 if (selection->regions.empty()) {
2376 list<RegionView*> sorted;
2377 selection->regions.by_position (sorted);
2378 boost::shared_ptr<Region> r ((*sorted.begin())->region());
2382 pos = r->first_frame ();
2386 pos = r->last_frame();
2390 pos = r->adjust_to_sync (r->first_frame());
2394 if (pos > position) {
2395 distance = pos - position;
2398 distance = position - pos;
2402 begin_reversible_command (_("align selection (relative)"));
2404 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2406 boost::shared_ptr<Region> region ((*i)->region());
2408 XMLNode &before = region->playlist()->get_state();
2411 region->set_position (region->position() + distance, this);
2413 region->set_position (region->position() - distance, this);
2416 XMLNode &after = region->playlist()->get_state();
2417 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2421 commit_reversible_command ();
2425 Editor::align_selection (RegionPoint point, nframes_t position)
2427 if (selection->regions.empty()) {
2431 begin_reversible_command (_("align selection"));
2433 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2434 align_region_internal ((*i)->region(), point, position);
2437 commit_reversible_command ();
2441 Editor::align_region (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2443 begin_reversible_command (_("align region"));
2444 align_region_internal (region, point, position);
2445 commit_reversible_command ();
2449 Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2451 XMLNode &before = region->playlist()->get_state();
2455 region->set_position (region->adjust_to_sync (position), this);
2459 if (position > region->length()) {
2460 region->set_position (position - region->length(), this);
2465 region->set_position (position, this);
2469 XMLNode &after = region->playlist()->get_state();
2470 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2474 Editor::trim_region_to_edit_cursor ()
2476 if (clicked_regionview == 0) {
2480 boost::shared_ptr<Region> region (clicked_regionview->region());
2483 AudioTimeAxisView *atav;
2485 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2486 if (atav->get_diskstream() != 0) {
2487 speed = atav->get_diskstream()->speed();
2491 begin_reversible_command (_("trim to edit"));
2492 XMLNode &before = region->playlist()->get_state();
2493 region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2494 XMLNode &after = region->playlist()->get_state();
2495 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2496 commit_reversible_command ();
2500 Editor::trim_region_from_edit_cursor ()
2502 if (clicked_regionview == 0) {
2506 boost::shared_ptr<Region> region (clicked_regionview->region());
2509 AudioTimeAxisView *atav;
2511 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2512 if (atav->get_diskstream() != 0) {
2513 speed = atav->get_diskstream()->speed();
2517 begin_reversible_command (_("trim to edit"));
2518 XMLNode &before = region->playlist()->get_state();
2519 region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2520 XMLNode &after = region->playlist()->get_state();
2521 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2522 commit_reversible_command ();
2526 Editor::unfreeze_route ()
2528 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2532 clicked_audio_trackview->audio_track()->unfreeze ();
2536 Editor::_freeze_thread (void* arg)
2538 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2539 return static_cast<Editor*>(arg)->freeze_thread ();
2543 Editor::freeze_thread ()
2545 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2550 Editor::freeze_progress_timeout (void *arg)
2552 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2553 return !(current_interthread_info->done || current_interthread_info->cancel);
2557 Editor::freeze_route ()
2559 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2563 InterThreadInfo itt;
2565 if (interthread_progress_window == 0) {
2566 build_interthread_progress_window ();
2569 WindowTitle title(Glib::get_application_name());
2570 title += _("Freeze");
2571 interthread_progress_window->set_title (title.get_string());
2572 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2573 interthread_progress_window->show_all ();
2574 interthread_progress_bar.set_fraction (0.0f);
2575 interthread_progress_label.set_text ("");
2576 interthread_cancel_label.set_text (_("Cancel Freeze"));
2577 current_interthread_info = &itt;
2579 interthread_progress_connection =
2580 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2584 itt.progress = 0.0f;
2586 pthread_attr_t attr;
2587 pthread_attr_init(&attr);
2588 pthread_attr_setstacksize(&attr, 500000);
2590 pthread_create (&itt.thread, &attr, _freeze_thread, this);
2592 pthread_attr_destroy(&attr);
2594 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2596 while (!itt.done && !itt.cancel) {
2597 gtk_main_iteration ();
2600 interthread_progress_connection.disconnect ();
2601 interthread_progress_window->hide_all ();
2602 current_interthread_info = 0;
2603 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2607 Editor::bounce_range_selection ()
2609 if (selection->time.empty()) {
2613 TrackSelection views = selection->tracks;
2615 nframes_t start = selection->time[clicked_selection].start;
2616 nframes_t end = selection->time[clicked_selection].end;
2617 nframes_t cnt = end - start + 1;
2619 begin_reversible_command (_("bounce range"));
2621 for (TrackViewList::iterator i = views.begin(); i != views.end(); ++i) {
2623 AudioTimeAxisView* atv;
2625 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2629 boost::shared_ptr<Playlist> playlist;
2631 if ((playlist = atv->playlist()) == 0) {
2635 InterThreadInfo itt;
2639 itt.progress = false;
2641 XMLNode &before = playlist->get_state();
2642 atv->audio_track()->bounce_range (start, cnt, itt);
2643 XMLNode &after = playlist->get_state();
2644 session->add_command (new MementoCommand<Playlist> (*playlist, &before, &after));
2647 commit_reversible_command ();
2663 Editor::cut_copy (CutCopyOp op)
2665 /* only cancel selection if cut/copy is successful.*/
2677 opname = _("clear");
2681 cut_buffer->clear ();
2683 switch (current_mouse_mode()) {
2685 if (!selection->regions.empty() || !selection->points.empty()) {
2687 begin_reversible_command (opname + _(" objects"));
2689 if (!selection->regions.empty()) {
2691 cut_copy_regions (op);
2694 selection->clear_regions ();
2698 if (!selection->points.empty()) {
2699 cut_copy_points (op);
2702 selection->clear_points ();
2706 commit_reversible_command ();
2711 if (!selection->time.empty()) {
2713 begin_reversible_command (opname + _(" range"));
2714 cut_copy_ranges (op);
2715 commit_reversible_command ();
2718 selection->clear_time ();
2730 Editor::cut_copy_points (CutCopyOp op)
2732 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2734 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2737 atv->cut_copy_clear_objects (selection->points, op);
2742 struct PlaylistState {
2743 boost::shared_ptr<Playlist> playlist;
2747 struct lt_playlist {
2748 bool operator () (const PlaylistState& a, const PlaylistState& b) {
2749 return a.playlist < b.playlist;
2753 struct PlaylistMapping {
2755 boost::shared_ptr<AudioPlaylist> pl;
2757 PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
2761 Editor::cut_copy_regions (CutCopyOp op)
2763 /* we can't use a std::map here because the ordering is important, and we can't trivially sort
2764 a map when we want ordered access to both elements. i think.
2767 vector<PlaylistMapping> pmap;
2769 nframes_t first_position = max_frames;
2771 set<PlaylistState, lt_playlist> freezelist;
2772 pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
2774 /* get ordering correct before we cut/copy */
2776 selection->regions.sort_by_position_and_track ();
2778 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
2780 first_position = min ((*x)->region()->position(), first_position);
2782 if (op == Cut || op == Clear) {
2783 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
2787 PlaylistState before;
2788 before.playlist = pl;
2789 before.before = &pl->get_state();
2791 insert_result = freezelist.insert (before);
2793 if (insert_result.second) {
2799 TimeAxisView* tv = &(*x)->get_trackview();
2800 vector<PlaylistMapping>::iterator z;
2802 for (z = pmap.begin(); z != pmap.end(); ++z) {
2803 if ((*z).tv == tv) {
2808 if (z == pmap.end()) {
2809 pmap.push_back (PlaylistMapping (tv));
2813 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
2815 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
2818 /* impossible, but this handles it for the future */
2822 TimeAxisView& tv = (*x)->get_trackview();
2823 boost::shared_ptr<AudioPlaylist> npl;
2824 RegionSelection::iterator tmp;
2829 vector<PlaylistMapping>::iterator z;
2831 for (z = pmap.begin(); z != pmap.end(); ++z) {
2832 if ((*z).tv == &tv) {
2837 assert (z != pmap.end());
2840 npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
2847 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
2848 boost::shared_ptr<Region> _xx;
2854 _xx = RegionFactory::create ((*x)->region());
2855 npl->add_region (_xx, (*x)->region()->position() - first_position);
2856 pl->remove_region (((*x)->region()));
2862 /* copy region before adding, so we're not putting same object into two different playlists */
2863 npl->add_region (RegionFactory::create ((*x)->region()), (*x)->region()->position() - first_position);
2867 pl->remove_region (((*x)->region()));
2874 list<boost::shared_ptr<Playlist> > foo;
2876 /* the pmap is in the same order as the tracks in which selected regions occured */
2878 for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2880 foo.push_back ((*i).pl);
2885 cut_buffer->set (foo);
2888 for (set<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2889 (*pl).playlist->thaw ();
2890 session->add_command (new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
2895 Editor::cut_copy_ranges (CutCopyOp op)
2897 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2898 (*i)->cut_copy_clear (*selection, op);
2903 Editor::paste (float times)
2905 paste_internal (edit_cursor->current_frame, times);
2909 Editor::mouse_paste ()
2914 track_canvas.get_pointer (x, y);
2915 track_canvas.window_to_world (x, y, wx, wy);
2916 wx += horizontal_adjustment.get_value();
2917 wy += vertical_adjustment.get_value();
2920 event.type = GDK_BUTTON_RELEASE;
2921 event.button.x = wx;
2922 event.button.y = wy;
2924 nframes_t where = event_frame (&event, 0, 0);
2926 paste_internal (where, 1);
2930 Editor::paste_internal (nframes_t position, float times)
2932 bool commit = false;
2934 if (cut_buffer->empty() || selection->tracks.empty()) {
2938 if (position == max_frames) {
2939 position = edit_cursor->current_frame;
2942 begin_reversible_command (_("paste"));
2944 TrackSelection::iterator i;
2947 /* get everything in the correct order */
2949 sort_track_selection ();
2951 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
2953 /* undo/redo is handled by individual tracks */
2955 if ((*i)->paste (position, times, *cut_buffer, nth)) {
2961 commit_reversible_command ();
2966 Editor::paste_named_selection (float times)
2968 TrackSelection::iterator t;
2970 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
2972 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
2976 TreeModel::iterator i = selected->get_selected();
2977 NamedSelection* ns = (*i)[named_selection_columns.selection];
2979 list<boost::shared_ptr<Playlist> >::iterator chunk;
2980 list<boost::shared_ptr<Playlist> >::iterator tmp;
2982 chunk = ns->playlists.begin();
2984 begin_reversible_command (_("paste chunk"));
2986 sort_track_selection ();
2988 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
2990 AudioTimeAxisView* atv;
2991 boost::shared_ptr<Playlist> pl;
2992 boost::shared_ptr<AudioPlaylist> apl;
2994 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
2998 if ((pl = atv->playlist()) == 0) {
3002 if ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) == 0) {
3009 XMLNode &before = apl->get_state();
3010 apl->paste (*chunk, edit_cursor->current_frame, times);
3011 session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
3013 if (tmp != ns->playlists.end()) {
3018 commit_reversible_command();
3022 Editor::duplicate_some_regions (RegionSelection& regions, float times)
3024 boost::shared_ptr<Playlist> playlist;
3025 RegionSelection sel = regions; // clear (below) will clear the argument list
3027 begin_reversible_command (_("duplicate region"));
3029 selection->clear_regions ();
3031 for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3033 boost::shared_ptr<Region> r ((*i)->region());
3035 TimeAxisView& tv = (*i)->get_time_axis_view();
3036 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3037 sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3039 playlist = (*i)->region()->playlist();
3040 XMLNode &before = playlist->get_state();
3041 playlist->duplicate (r, r->last_frame(), times);
3042 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
3046 if (latest_regionview) {
3047 selection->add (latest_regionview);
3052 commit_reversible_command ();
3056 Editor::duplicate_selection (float times)
3058 if (selection->time.empty() || selection->tracks.empty()) {
3062 boost::shared_ptr<Playlist> playlist;
3063 vector<boost::shared_ptr<AudioRegion> > new_regions;
3064 vector<boost::shared_ptr<AudioRegion> >::iterator ri;
3066 create_region_from_selection (new_regions);
3068 if (new_regions.empty()) {
3072 begin_reversible_command (_("duplicate selection"));
3074 ri = new_regions.begin();
3076 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3077 if ((playlist = (*i)->playlist()) == 0) {
3080 XMLNode &before = playlist->get_state();
3081 playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
3082 XMLNode &after = playlist->get_state();
3083 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3086 if (ri == new_regions.end()) {
3091 commit_reversible_command ();
3095 Editor::reset_point_selection ()
3097 /* reset all selected points to the relevant default value */
3099 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3101 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3104 atv->reset_objects (selection->points);
3110 Editor::center_playhead ()
3112 float page = canvas_width * frames_per_unit;
3114 center_screen_internal (playhead_cursor->current_frame, page);
3118 Editor::center_edit_cursor ()
3120 float page = canvas_width * frames_per_unit;
3122 center_screen_internal (edit_cursor->current_frame, page);
3126 Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
3128 begin_reversible_command (_("clear playlist"));
3129 XMLNode &before = playlist->get_state();
3131 XMLNode &after = playlist->get_state();
3132 session->add_command (new MementoCommand<Playlist>(*playlist.get(), &before, &after));
3133 commit_reversible_command ();
3137 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3139 boost::shared_ptr<Playlist> playlist;
3141 nframes_t next_distance;
3144 if (use_edit_cursor) {
3145 start = edit_cursor->current_frame;
3150 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3154 if (selection->tracks.empty()) {
3158 begin_reversible_command (_("nudge track"));
3160 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3162 if ((playlist = (*i)->playlist()) == 0) {
3166 XMLNode &before = playlist->get_state();
3167 playlist->nudge_after (start, distance, forwards);
3168 XMLNode &after = playlist->get_state();
3169 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3172 commit_reversible_command ();
3176 Editor::remove_last_capture ()
3178 vector<string> choices;
3185 if (Config->get_verify_remove_last_capture()) {
3186 prompt = _("Do you really want to destroy the last capture?"
3187 "\n(This is destructive and cannot be undone)");
3189 choices.push_back (_("No, do nothing."));
3190 choices.push_back (_("Yes, destroy it."));
3192 Gtkmm2ext::Choice prompter (prompt, choices);
3194 if (prompter.run () == 1) {
3195 session->remove_last_capture ();
3199 session->remove_last_capture();
3204 Editor::normalize_region ()
3210 if (selection->regions.empty()) {
3214 begin_reversible_command (_("normalize"));
3216 track_canvas.get_window()->set_cursor (*wait_cursor);
3219 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3220 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3223 XMLNode &before = arv->region()->get_state();
3224 arv->audio_region()->normalize_to (0.0f);
3225 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3228 commit_reversible_command ();
3229 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3234 Editor::denormalize_region ()
3240 if (selection->regions.empty()) {
3244 begin_reversible_command ("denormalize");
3246 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3247 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3250 XMLNode &before = arv->region()->get_state();
3251 arv->audio_region()->set_scale_amplitude (1.0f);
3252 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3255 commit_reversible_command ();
3260 Editor::reverse_region ()
3266 Reverse rev (*session);
3267 apply_filter (rev, _("reverse regions"));
3271 Editor::apply_filter (AudioFilter& filter, string command)
3273 if (selection->regions.empty()) {
3277 begin_reversible_command (command);
3279 track_canvas.get_window()->set_cursor (*wait_cursor);
3282 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
3283 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3287 boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
3289 RegionSelection::iterator tmp;
3294 if (arv->audio_region()->apply (filter) == 0) {
3296 XMLNode &before = playlist->get_state();
3297 playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
3298 XMLNode &after = playlist->get_state();
3299 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
3307 commit_reversible_command ();
3308 selection->regions.clear ();
3311 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3315 Editor::region_selection_op (void (Region::*pmf)(void))
3317 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3318 Region* region = (*i)->region().get();
3325 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3327 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3328 Region* region = (*i)->region().get();
3329 (region->*pmf)(arg);
3334 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3336 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3337 Region* region = (*i)->region().get();
3343 Editor::external_edit_region ()
3345 if (!clicked_regionview) {
3353 Editor::brush (nframes_t pos)
3355 RegionSelection sel;
3358 if (selection->regions.empty()) {
3359 /* XXX get selection from region list */
3361 sel = selection->regions;
3368 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3369 mouse_brush_insert_region ((*i), pos);
3374 Editor::reset_region_gain_envelopes ()
3376 if (!session || selection->regions.empty()) {
3380 session->begin_reversible_command (_("reset region gain"));
3382 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3383 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3385 AutomationList& alist (arv->audio_region()->envelope());
3386 XMLNode& before (alist.get_state());
3388 arv->audio_region()->set_default_envelope ();
3389 session->add_command (new MementoCommand<AutomationList>(arv->audio_region()->envelope(), &before, &alist.get_state()));
3393 session->commit_reversible_command ();
3397 Editor::toggle_gain_envelope_visibility ()
3399 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3400 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3402 bool x = region_envelope_visible_item->get_active();
3403 if (x != arv->envelope_visible()) {
3404 arv->set_envelope_visible (x);
3411 Editor::toggle_gain_envelope_active ()
3413 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3414 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3416 bool x = region_envelope_active_item->get_active();
3417 if (x != arv->audio_region()->envelope_active()) {
3418 arv->audio_region()->set_envelope_active (x);
3425 Editor::toggle_region_lock ()
3427 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3428 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3430 bool x = region_lock_item->get_active();
3431 if (x != arv->audio_region()->locked()) {
3432 arv->audio_region()->set_locked (x);
3439 Editor::toggle_region_mute ()
3441 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3442 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3444 bool x = region_mute_item->get_active();
3445 if (x != arv->audio_region()->muted()) {
3446 arv->audio_region()->set_muted (x);
3453 Editor::toggle_region_opaque ()
3455 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3456 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3458 bool x = region_opaque_item->get_active();
3459 if (x != arv->audio_region()->opaque()) {
3460 arv->audio_region()->set_opaque (x);
3467 Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
3469 begin_reversible_command (_("set fade in shape"));
3471 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3472 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3478 AutomationList& alist = tmp->audio_region()->fade_in();
3479 XMLNode &before = alist.get_state();
3481 tmp->audio_region()->set_fade_in_shape (shape);
3483 XMLNode &after = alist.get_state();
3484 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3487 commit_reversible_command ();
3491 Editor::set_fade_out_shape (AudioRegion::FadeShape shape)
3493 begin_reversible_command (_("set fade out shape"));
3495 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3496 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3502 AutomationList& alist = tmp->audio_region()->fade_out();
3503 XMLNode &before = alist.get_state();
3505 tmp->audio_region()->set_fade_out_shape (shape);
3507 XMLNode &after = alist.get_state();
3508 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3511 commit_reversible_command ();
3515 Editor::set_fade_in_active (bool yn)
3517 begin_reversible_command (_("set fade in active"));
3519 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3520 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3527 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3529 XMLNode &before = ar->get_state();
3531 ar->set_fade_in_active (yn);
3533 XMLNode &after = ar->get_state();
3534 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
3539 Editor::set_fade_out_active (bool yn)
3541 begin_reversible_command (_("set fade out active"));
3543 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3544 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3550 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3552 XMLNode &before = ar->get_state();
3554 ar->set_fade_out_active (yn);
3556 XMLNode &after = ar->get_state();
3557 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
3562 /** Update crossfade visibility after its configuration has been changed */
3564 Editor::update_xfade_visibility ()
3566 _xfade_visibility = Config->get_xfades_visible ();
3568 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3569 AudioTimeAxisView* v = dynamic_cast<AudioTimeAxisView*>(*i);
3571 if (_xfade_visibility) {
3572 v->show_all_xfades ();
3574 v->hide_all_xfades ();