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>
35 #include <ardour/audioengine.h>
36 #include <ardour/session.h>
37 #include <ardour/audioplaylist.h>
38 #include <ardour/audioregion.h>
39 #include <ardour/audio_diskstream.h>
40 #include <ardour/utils.h>
41 #include <ardour/location.h>
42 #include <ardour/named_selection.h>
43 #include <ardour/audio_track.h>
44 #include <ardour/audioplaylist.h>
45 #include <ardour/region_factory.h>
46 #include <ardour/playlist_factory.h>
47 #include <ardour/reverse.h>
49 #include "ardour_ui.h"
51 #include "time_axis_view.h"
52 #include "audio_time_axis.h"
53 #include "automation_time_axis.h"
54 #include "streamview.h"
55 #include "audio_region_view.h"
56 #include "rgb_macros.h"
57 #include "selection_templates.h"
58 #include "selection.h"
60 #include "gtk-custom-hruler.h"
61 #include "gui_thread.h"
66 using namespace ARDOUR;
70 using namespace Editing;
72 /***********************************************************************
74 ***********************************************************************/
77 Editor::undo (uint32_t n)
85 Editor::redo (uint32_t n)
93 Editor::ensure_cursor (nframes_t *pos)
95 *pos = edit_cursor->current_frame;
100 Editor::split_region ()
102 split_region_at (edit_cursor->current_frame);
106 Editor::split_region_at (nframes_t where)
108 split_regions_at (where, selection->regions);
112 Editor::split_regions_at (nframes_t where, RegionSelection& regions)
114 begin_reversible_command (_("split"));
117 for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
119 RegionSelection::iterator tmp;
124 boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
126 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
128 _new_regionviews_show_envelope = arv->envelope_visible();
131 XMLNode &before = pl->get_state();
132 pl->split_region ((*a)->region(), where);
133 XMLNode &after = pl->get_state();
134 session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
140 commit_reversible_command ();
141 _new_regionviews_show_envelope = false;
145 Editor::remove_clicked_region ()
147 if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
151 boost::shared_ptr<Playlist> playlist = clicked_audio_trackview->playlist();
153 begin_reversible_command (_("remove region"));
154 XMLNode &before = playlist->get_state();
155 playlist->remove_region (clicked_regionview->region());
156 XMLNode &after = playlist->get_state();
157 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
158 commit_reversible_command ();
162 Editor::destroy_clicked_region ()
164 uint32_t selected = selection->regions.size();
166 if (!session || !selected) {
170 vector<string> choices;
173 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
174 It cannot be undone\n\
175 Do you really want to destroy %1 ?"),
177 _("these regions") : _("this region")));
179 choices.push_back (_("No, do nothing."));
182 choices.push_back (_("Yes, destroy them."));
184 choices.push_back (_("Yes, destroy it."));
187 Gtkmm2ext::Choice prompter (prompt, choices);
189 if (prompter.run() == 0) { /* first choice */
194 list<boost::shared_ptr<Region> > r;
196 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
197 r.push_back ((*i)->region());
200 session->destroy_regions (r);
204 boost::shared_ptr<Region>
205 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
208 boost::shared_ptr<Region> region;
211 if (selection->time.start () == selection->time.end_frame ()) {
213 /* no current selection-> is there a selected regionview? */
215 if (selection->regions.empty()) {
221 if (!selection->regions.empty()) {
223 rv = *(selection->regions.begin());
224 (*tv) = &rv->get_time_axis_view();
225 region = rv->region();
227 } else if (!selection->tracks.empty()) {
229 (*tv) = selection->tracks.front();
231 RouteTimeAxisView* rtv;
233 if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
234 boost::shared_ptr<Playlist> pl;
236 if ((pl = rtv->playlist()) == 0) {
240 region = pl->top_region_at (start);
248 Editor::extend_selection_to_end_of_region (bool next)
251 boost::shared_ptr<Region> region;
254 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
258 if (region && selection->time.start () == selection->time.end_frame ()) {
259 start = region->position();
261 start = selection->time.start ();
264 /* Try to leave the selection with the same route if possible */
266 if ((tv = selection->time.track) == 0) {
270 begin_reversible_command (_("extend selection"));
271 selection->set (tv, start, region->position() + region->length());
272 commit_reversible_command ();
276 Editor::extend_selection_to_start_of_region (bool previous)
279 boost::shared_ptr<Region> region;
282 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
286 if (region && selection->time.start () == selection->time.end_frame ()) {
287 end = region->position() + region->length();
289 end = selection->time.end_frame ();
292 /* Try to leave the selection with the same route if possible */
294 if ((tv = selection->time.track) == 0) {
298 begin_reversible_command (_("extend selection"));
299 selection->set (tv, region->position(), end);
300 commit_reversible_command ();
305 Editor::nudge_forward (bool next)
308 nframes_t next_distance;
310 if (!session) return;
312 if (!selection->regions.empty()) {
314 begin_reversible_command (_("nudge forward"));
316 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
317 boost::shared_ptr<Region> r ((*i)->region());
319 distance = get_nudge_distance (r->position(), next_distance);
322 distance = next_distance;
325 XMLNode &before = r->playlist()->get_state();
326 r->set_position (r->position() + distance, this);
327 XMLNode &after = r->playlist()->get_state();
328 session->add_command (new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
331 commit_reversible_command ();
334 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
335 session->request_locate (playhead_cursor->current_frame + distance);
340 Editor::nudge_backward (bool next)
343 nframes_t next_distance;
345 if (!session) return;
347 if (!selection->regions.empty()) {
349 begin_reversible_command (_("nudge forward"));
351 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
352 boost::shared_ptr<Region> r ((*i)->region());
354 distance = get_nudge_distance (r->position(), next_distance);
357 distance = next_distance;
360 XMLNode &before = r->playlist()->get_state();
362 if (r->position() > distance) {
363 r->set_position (r->position() - distance, this);
365 r->set_position (0, this);
367 XMLNode &after = r->playlist()->get_state();
368 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
371 commit_reversible_command ();
375 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
377 if (playhead_cursor->current_frame > distance) {
378 session->request_locate (playhead_cursor->current_frame - distance);
380 session->goto_start();
386 Editor::nudge_forward_capture_offset ()
390 if (!session) return;
392 if (!selection->regions.empty()) {
394 begin_reversible_command (_("nudge forward"));
396 distance = session->worst_output_latency();
398 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
399 boost::shared_ptr<Region> r ((*i)->region());
401 XMLNode &before = r->playlist()->get_state();
402 r->set_position (r->position() + distance, this);
403 XMLNode &after = r->playlist()->get_state();
404 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
407 commit_reversible_command ();
413 Editor::nudge_backward_capture_offset ()
417 if (!session) return;
419 if (!selection->regions.empty()) {
421 begin_reversible_command (_("nudge forward"));
423 distance = session->worst_output_latency();
425 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
426 boost::shared_ptr<Region> r ((*i)->region());
428 XMLNode &before = r->playlist()->get_state();
430 if (r->position() > distance) {
431 r->set_position (r->position() - distance, this);
433 r->set_position (0, this);
435 XMLNode &after = r->playlist()->get_state();
436 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
439 commit_reversible_command ();
446 Editor::move_to_start ()
448 session->goto_start ();
452 Editor::move_to_end ()
455 session->request_locate (session->current_end_frame());
459 Editor::build_region_boundary_cache ()
463 boost::shared_ptr<Region> r;
464 TrackViewList tracks;
466 region_boundary_cache.clear ();
473 case SnapToRegionStart:
476 case SnapToRegionEnd:
479 case SnapToRegionSync:
482 case SnapToRegionBoundary:
486 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
491 TimeAxisView *ontrack = 0;
493 while (pos < session->current_end_frame()) {
495 if (!selection->tracks.empty()) {
497 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
501 } else if (clicked_trackview) {
504 t.push_back (clicked_trackview);
506 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
512 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
520 case SnapToRegionStart:
521 rpos = r->first_frame();
523 case SnapToRegionEnd:
524 rpos = r->last_frame();
526 case SnapToRegionSync:
527 rpos = r->adjust_to_sync (r->first_frame());
530 case SnapToRegionBoundary:
531 rpos = r->last_frame();
538 AudioTimeAxisView *atav;
540 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
541 if (atav->get_diskstream() != 0) {
542 speed = atav->get_diskstream()->speed();
546 rpos = track_frame_to_session_frame(rpos, speed);
548 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
549 if (snap_type == SnapToRegionBoundary) {
550 region_boundary_cache.push_back (r->first_frame());
552 region_boundary_cache.push_back (rpos);
559 boost::shared_ptr<Region>
560 Editor::find_next_region (nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
562 TrackViewList::iterator i;
563 nframes_t closest = max_frames;
564 boost::shared_ptr<Region> ret;
568 nframes_t track_frame;
569 AudioTimeAxisView *atav;
571 for (i = tracks.begin(); i != tracks.end(); ++i) {
574 boost::shared_ptr<Region> r;
577 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
578 if (atav->get_diskstream()!=0)
579 track_speed = atav->get_diskstream()->speed();
582 track_frame = session_frame_to_track_frame(frame, track_speed);
584 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
590 rpos = r->first_frame ();
594 rpos = r->last_frame ();
598 rpos = r->adjust_to_sync (r->first_frame());
601 // rpos is a "track frame", converting it to "session frame"
602 rpos = track_frame_to_session_frame(rpos, track_speed);
605 distance = rpos - frame;
607 distance = frame - rpos;
610 if (distance < closest) {
622 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
624 boost::shared_ptr<Region> r;
625 nframes_t pos = cursor->current_frame;
631 TimeAxisView *ontrack = 0;
633 // so we don't find the current region again..
637 if (!selection->tracks.empty()) {
639 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
641 } else if (clicked_trackview) {
644 t.push_back (clicked_trackview);
646 r = find_next_region (pos, point, dir, t, &ontrack);
650 r = find_next_region (pos, point, dir, track_views, &ontrack);
659 pos = r->first_frame ();
663 pos = r->last_frame ();
667 pos = r->adjust_to_sync (r->first_frame());
672 AudioTimeAxisView *atav;
674 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
675 if (atav->get_diskstream() != 0) {
676 speed = atav->get_diskstream()->speed();
680 pos = track_frame_to_session_frame(pos, speed);
682 if (cursor == playhead_cursor) {
683 session->request_locate (pos);
685 cursor->set_position (pos);
690 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
692 cursor_to_region_point (cursor, point, 1);
696 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
698 cursor_to_region_point (cursor, point, -1);
702 Editor::cursor_to_selection_start (Cursor *cursor)
705 switch (mouse_mode) {
707 if (!selection->regions.empty()) {
708 pos = selection->regions.start();
713 if (!selection->time.empty()) {
714 pos = selection->time.start ();
722 if (cursor == playhead_cursor) {
723 session->request_locate (pos);
725 cursor->set_position (pos);
730 Editor::cursor_to_selection_end (Cursor *cursor)
734 switch (mouse_mode) {
736 if (!selection->regions.empty()) {
737 pos = selection->regions.end_frame();
742 if (!selection->time.empty()) {
743 pos = selection->time.end_frame ();
751 if (cursor == playhead_cursor) {
752 session->request_locate (pos);
754 cursor->set_position (pos);
759 Editor::scroll_playhead (bool forward)
761 nframes_t pos = playhead_cursor->current_frame;
762 nframes_t delta = (nframes_t) floor (current_page_frames() / 0.8);
765 if (pos == max_frames) {
769 if (pos < max_frames - delta) {
788 session->request_locate (pos);
792 Editor::playhead_backward ()
799 if (get_prefix (prefix, was_floating)) {
803 cnt = (nframes_t) floor (prefix * session->frame_rate ());
805 cnt = (nframes_t) prefix;
809 pos = playhead_cursor->current_frame;
811 if ((nframes_t) pos < cnt) {
817 /* XXX this is completely insane. with the current buffering
818 design, we'll force a complete track buffer flush and
819 reload, just to move 1 sample !!!
822 session->request_locate (pos);
826 Editor::playhead_forward ()
833 if (get_prefix (prefix, was_floating)) {
837 cnt = (nframes_t) floor (prefix * session->frame_rate ());
839 cnt = (nframes_t) floor (prefix);
843 pos = playhead_cursor->current_frame;
845 /* XXX this is completely insane. with the current buffering
846 design, we'll force a complete track buffer flush and
847 reload, just to move 1 sample !!!
850 session->request_locate (pos+cnt);
854 Editor::cursor_align (bool playhead_to_edit)
856 if (playhead_to_edit) {
858 session->request_locate (edit_cursor->current_frame);
861 edit_cursor->set_position (playhead_cursor->current_frame);
866 Editor::edit_cursor_backward ()
873 if (get_prefix (prefix, was_floating)) {
877 cnt = (nframes_t) floor (prefix * session->frame_rate ());
879 cnt = (nframes_t) prefix;
883 pos = edit_cursor->current_frame;
885 if ((nframes_t) pos < cnt) {
891 edit_cursor->set_position (pos);
895 Editor::edit_cursor_forward ()
902 if (get_prefix (prefix, was_floating)) {
906 cnt = (nframes_t) floor (prefix * session->frame_rate ());
908 cnt = (nframes_t) floor (prefix);
912 pos = edit_cursor->current_frame;
913 edit_cursor->set_position (pos+cnt);
917 Editor::goto_frame ()
923 if (get_prefix (prefix, was_floating)) {
928 frame = (nframes_t) floor (prefix * session->frame_rate());
930 frame = (nframes_t) floor (prefix);
933 session->request_locate (frame);
937 Editor::scroll_backward (float pages)
940 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
945 if (get_prefix (prefix, was_floating)) {
946 cnt = (nframes_t) floor (pages * one_page);
949 cnt = (nframes_t) floor (prefix * session->frame_rate());
951 cnt = (nframes_t) floor (prefix * one_page);
955 if (leftmost_frame < cnt) {
958 frame = leftmost_frame - cnt;
961 reset_x_origin (frame);
965 Editor::scroll_forward (float pages)
968 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
973 if (get_prefix (prefix, was_floating)) {
974 cnt = (nframes_t) floor (pages * one_page);
977 cnt = (nframes_t) floor (prefix * session->frame_rate());
979 cnt = (nframes_t) floor (prefix * one_page);
983 if (max_frames - cnt < leftmost_frame) {
984 frame = max_frames - cnt;
986 frame = leftmost_frame + cnt;
989 reset_x_origin (frame);
993 Editor::scroll_tracks_down ()
999 if (get_prefix (prefix, was_floating)) {
1002 cnt = (int) floor (prefix);
1005 double vert_value = vertical_adjustment.get_value() + (cnt *
1006 vertical_adjustment.get_page_size());
1007 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
1008 vert_value = vertical_adjustment.get_upper() - canvas_height;
1010 vertical_adjustment.set_value (vert_value);
1014 Editor::scroll_tracks_up ()
1020 if (get_prefix (prefix, was_floating)) {
1023 cnt = (int) floor (prefix);
1026 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1030 Editor::scroll_tracks_down_line ()
1033 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1034 double vert_value = adj->get_value() + 20;
1036 if (vert_value>adj->get_upper() - canvas_height) {
1037 vert_value = adj->get_upper() - canvas_height;
1039 adj->set_value (vert_value);
1043 Editor::scroll_tracks_up_line ()
1045 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1046 adj->set_value (adj->get_value() - 20);
1052 Editor::temporal_zoom_step (bool coarser)
1054 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1058 nfpu = frames_per_unit;
1063 nfpu = max(1.0,(nfpu/1.61803399));
1066 temporal_zoom (nfpu);
1070 Editor::temporal_zoom (gdouble fpu)
1072 if (!session) return;
1074 nframes_t current_page = current_page_frames();
1075 nframes_t current_leftmost = leftmost_frame;
1076 nframes_t current_rightmost;
1077 nframes_t current_center;
1079 nframes_t leftmost_after_zoom = 0;
1084 new_page = (nframes_t) floor (canvas_width * nfpu);
1086 switch (zoom_focus) {
1088 leftmost_after_zoom = current_leftmost;
1091 case ZoomFocusRight:
1092 current_rightmost = leftmost_frame + current_page;
1093 if (current_rightmost > new_page) {
1094 leftmost_after_zoom = current_rightmost - new_page;
1096 leftmost_after_zoom = 0;
1100 case ZoomFocusCenter:
1101 current_center = current_leftmost + (current_page/2);
1102 if (current_center > (new_page/2)) {
1103 leftmost_after_zoom = current_center - (new_page / 2);
1105 leftmost_after_zoom = 0;
1109 case ZoomFocusPlayhead:
1110 /* try to keep the playhead in the center */
1111 if (playhead_cursor->current_frame > new_page/2) {
1112 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1114 leftmost_after_zoom = 0;
1119 /* try to keep the edit cursor in the center */
1120 if (edit_cursor->current_frame > new_page/2) {
1121 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1123 leftmost_after_zoom = 0;
1129 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1131 // begin_reversible_command (_("zoom"));
1132 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1133 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1134 // commit_reversible_command ();
1136 reposition_and_zoom (leftmost_after_zoom, nfpu);
1140 Editor::temporal_zoom_selection ()
1142 if (!selection) return;
1144 if (selection->time.empty()) {
1148 nframes_t start = selection->time[clicked_selection].start;
1149 nframes_t end = selection->time[clicked_selection].end;
1151 temporal_zoom_by_frame (start, end, "zoom to selection");
1155 Editor::temporal_zoom_session ()
1157 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1160 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1165 Editor::temporal_zoom_by_frame (nframes_t start, nframes_t end, const string & op)
1167 if (!session) return;
1169 if ((start == 0 && end == 0) || end < start) {
1173 nframes_t range = end - start;
1175 double new_fpu = (double)range / (double)canvas_width;
1178 // while (p2 < new_fpu) {
1183 nframes_t new_page = (nframes_t) floor (canvas_width * new_fpu);
1184 nframes_t middle = (nframes_t) floor( (double)start + ((double)range / 2.0f ));
1185 nframes_t new_leftmost = (nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1187 if (new_leftmost > middle) new_leftmost = 0;
1189 // begin_reversible_command (op);
1190 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1191 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1192 // commit_reversible_command ();
1194 reposition_and_zoom (new_leftmost, new_fpu);
1198 Editor::temporal_zoom_to_frame (bool coarser, nframes_t frame)
1200 if (!session) return;
1202 double range_before = frame - leftmost_frame;
1205 new_fpu = frames_per_unit;
1208 new_fpu *= 1.61803399;
1209 range_before *= 1.61803399;
1211 new_fpu = max(1.0,(new_fpu/1.61803399));
1212 range_before /= 1.61803399;
1215 if (new_fpu == frames_per_unit) return;
1217 nframes_t new_leftmost = frame - (nframes_t)range_before;
1219 if (new_leftmost > frame) new_leftmost = 0;
1221 // begin_reversible_command (_("zoom to frame"));
1222 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1223 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1224 // commit_reversible_command ();
1226 reposition_and_zoom (new_leftmost, new_fpu);
1230 Editor::add_location_from_selection ()
1234 if (selection->time.empty()) {
1238 if (session == 0 || clicked_trackview == 0) {
1242 nframes_t start = selection->time[clicked_selection].start;
1243 nframes_t end = selection->time[clicked_selection].end;
1245 session->locations()->next_available_name(rangename,"selection");
1246 Location *location = new Location (start, end, rangename, Location::IsRangeMarker);
1248 session->begin_reversible_command (_("add marker"));
1249 XMLNode &before = session->locations()->get_state();
1250 session->locations()->add (location, true);
1251 XMLNode &after = session->locations()->get_state();
1252 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1253 session->commit_reversible_command ();
1257 Editor::add_location_from_playhead_cursor ()
1261 nframes_t where = session->audible_frame();
1263 session->locations()->next_available_name(markername,"mark");
1264 Location *location = new Location (where, where, markername, Location::IsMark);
1265 session->begin_reversible_command (_("add marker"));
1266 XMLNode &before = session->locations()->get_state();
1267 session->locations()->add (location, true);
1268 XMLNode &after = session->locations()->get_state();
1269 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1270 session->commit_reversible_command ();
1274 Editor::add_location_from_audio_region ()
1276 if (selection->regions.empty()) {
1280 RegionView* rv = *(selection->regions.begin());
1281 boost::shared_ptr<Region> region = rv->region();
1283 Location *location = new Location (region->position(), region->last_frame(), region->name(), Location::IsRangeMarker);
1284 session->begin_reversible_command (_("add marker"));
1285 XMLNode &before = session->locations()->get_state();
1286 session->locations()->add (location, true);
1287 XMLNode &after = session->locations()->get_state();
1288 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1289 session->commit_reversible_command ();
1293 Editor::amplitude_zoom_step (bool in)
1307 #ifdef FIX_FOR_CANVAS
1308 /* XXX DO SOMETHING */
1317 Editor::delete_sample_forward ()
1322 Editor::delete_sample_backward ()
1327 Editor::delete_screen ()
1334 Editor::search_backwards ()
1340 Editor::search_forwards ()
1348 Editor::jump_forward_to_mark ()
1354 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1357 session->request_locate (location->start(), session->transport_rolling());
1359 session->request_locate (session->current_end_frame());
1364 Editor::jump_backward_to_mark ()
1370 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1373 session->request_locate (location->start(), session->transport_rolling());
1375 session->goto_start ();
1387 if (get_prefix (prefix, was_floating)) {
1388 pos = session->audible_frame ();
1391 pos = (nframes_t) floor (prefix * session->frame_rate ());
1393 pos = (nframes_t) floor (prefix);
1397 session->locations()->next_available_name(markername,"mark");
1398 session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true);
1402 Editor::clear_markers ()
1405 session->begin_reversible_command (_("clear markers"));
1406 XMLNode &before = session->locations()->get_state();
1407 session->locations()->clear_markers ();
1408 XMLNode &after = session->locations()->get_state();
1409 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1410 session->commit_reversible_command ();
1415 Editor::clear_ranges ()
1418 session->begin_reversible_command (_("clear ranges"));
1419 XMLNode &before = session->locations()->get_state();
1421 Location * looploc = session->locations()->auto_loop_location();
1422 Location * punchloc = session->locations()->auto_punch_location();
1424 session->locations()->clear_ranges ();
1426 if (looploc) session->locations()->add (looploc);
1427 if (punchloc) session->locations()->add (punchloc);
1429 XMLNode &after = session->locations()->get_state();
1430 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1431 session->commit_reversible_command ();
1436 Editor::clear_locations ()
1438 session->begin_reversible_command (_("clear locations"));
1439 XMLNode &before = session->locations()->get_state();
1440 session->locations()->clear ();
1441 XMLNode &after = session->locations()->get_state();
1442 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1443 session->commit_reversible_command ();
1444 session->locations()->clear ();
1448 Editor::unhide_markers ()
1450 for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1451 Location *l = (*i).first;
1452 if (l->is_hidden() && l->is_mark()) {
1453 l->set_hidden(false, this);
1459 Editor::unhide_ranges ()
1461 for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1462 Location *l = (*i).first;
1463 if (l->is_hidden() && l->is_range_marker()) {
1464 l->set_hidden(false, this);
1469 /* INSERT/REPLACE */
1472 Editor::insert_region_list_drag (boost::shared_ptr<AudioRegion> region, int x, int y)
1478 AudioTimeAxisView *atv = 0;
1479 boost::shared_ptr<Playlist> playlist;
1481 track_canvas.window_to_world (x, y, wx, wy);
1482 wx += horizontal_adjustment.get_value();
1483 wy += vertical_adjustment.get_value();
1486 event.type = GDK_BUTTON_RELEASE;
1487 event.button.x = wx;
1488 event.button.y = wy;
1490 where = event_frame (&event, &cx, &cy);
1492 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1493 /* clearly outside canvas area */
1497 if ((tv = trackview_by_y_position (cy)) == 0) {
1501 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1505 if ((playlist = atv->playlist()) == 0) {
1509 cerr << "drop target playlist, UC = " << playlist.use_count() << endl;
1513 begin_reversible_command (_("insert dragged region"));
1514 XMLNode &before = playlist->get_state();
1515 cerr << "pre add target playlist, UC = " << playlist.use_count() << endl;
1516 playlist->add_region (RegionFactory::create (region), where, 1.0);
1517 cerr << "post add target playlist, UC = " << playlist.use_count() << endl;
1518 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1519 commit_reversible_command ();
1521 cerr << "post drop target playlist, UC = " << playlist.use_count() << endl;
1525 Editor::insert_region_list_selection (float times)
1527 RouteTimeAxisView *tv = 0;
1528 boost::shared_ptr<Playlist> playlist;
1530 if (clicked_audio_trackview != 0) {
1531 tv = clicked_audio_trackview;
1532 } else if (!selection->tracks.empty()) {
1533 if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
1540 if ((playlist = tv->playlist()) == 0) {
1544 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1546 if (selected->count_selected_rows() != 1) {
1550 TreeView::Selection::ListHandle_Path rows = selected->get_selected_rows ();
1552 /* only one row selected, so rows.begin() is it */
1556 if ((iter = region_list_model->get_iter (*rows.begin()))) {
1558 boost::shared_ptr<Region> region = (*iter)[region_list_columns.region];
1560 begin_reversible_command (_("insert region"));
1561 XMLNode &before = playlist->get_state();
1562 playlist->add_region ((RegionFactory::create (region)), edit_cursor->current_frame, times);
1563 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1564 commit_reversible_command ();
1568 /* BUILT-IN EFFECTS */
1571 Editor::reverse_selection ()
1576 /* GAIN ENVELOPE EDITING */
1579 Editor::edit_envelope ()
1586 Editor::transition_to_rolling (bool fwd)
1592 switch (Config->get_slave_source()) {
1597 /* transport controlled by the master */
1601 if (session->is_auditioning()) {
1602 session->cancel_audition ();
1606 session->request_transport_speed (fwd ? 1.0f : -1.0f);
1610 Editor::toggle_playback (bool with_abort)
1616 switch (Config->get_slave_source()) {
1621 /* transport controlled by the master */
1625 if (session->is_auditioning()) {
1626 session->cancel_audition ();
1630 if (session->transport_rolling()) {
1631 session->request_stop (with_abort);
1632 if (session->get_play_loop()) {
1633 session->request_play_loop (false);
1636 session->request_transport_speed (1.0f);
1641 Editor::play_from_start ()
1643 session->request_locate (session->current_start_frame(), true);
1647 Editor::play_from_edit_cursor ()
1649 session->request_locate (edit_cursor->current_frame, true);
1653 Editor::play_selection ()
1655 if (selection->time.empty()) {
1659 session->request_play_range (true);
1663 Editor::play_selected_region ()
1665 if (!selection->regions.empty()) {
1666 RegionView *rv = *(selection->regions.begin());
1668 session->request_bounded_roll (rv->region()->position(), rv->region()->last_frame());
1673 Editor::loop_selected_region ()
1675 if (!selection->regions.empty()) {
1676 RegionView *rv = *(selection->regions.begin());
1679 if ((tll = transport_loop_location()) != 0) {
1681 tll->set (rv->region()->position(), rv->region()->last_frame());
1683 // enable looping, reposition and start rolling
1685 session->request_play_loop (true);
1686 session->request_locate (tll->start(), false);
1687 session->request_transport_speed (1.0f);
1693 Editor::play_location (Location& location)
1695 if (location.start() <= location.end()) {
1699 session->request_bounded_roll (location.start(), location.end());
1703 Editor::loop_location (Location& location)
1705 if (location.start() <= location.end()) {
1711 if ((tll = transport_loop_location()) != 0) {
1712 tll->set (location.start(), location.end());
1714 // enable looping, reposition and start rolling
1715 session->request_play_loop (true);
1716 session->request_locate (tll->start(), true);
1721 Editor::raise_region ()
1723 selection->foreach_region (&Region::raise);
1727 Editor::raise_region_to_top ()
1729 selection->foreach_region (&Region::raise_to_top);
1733 Editor::lower_region ()
1735 selection->foreach_region (&Region::lower);
1739 Editor::lower_region_to_bottom ()
1741 selection->foreach_region (&Region::lower_to_bottom);
1745 Editor::edit_region ()
1747 if (clicked_regionview == 0) {
1751 clicked_regionview->show_region_editor ();
1755 Editor::rename_region ()
1759 Button ok_button (_("OK"));
1760 Button cancel_button (_("Cancel"));
1762 if (selection->regions.empty()) {
1766 dialog.set_title (_("ardour: rename region"));
1767 dialog.set_name ("RegionRenameWindow");
1768 dialog.set_size_request (300, -1);
1769 dialog.set_position (Gtk::WIN_POS_MOUSE);
1770 dialog.set_modal (true);
1772 dialog.get_vbox()->set_border_width (10);
1773 dialog.get_vbox()->pack_start (entry);
1774 dialog.get_action_area()->pack_start (ok_button);
1775 dialog.get_action_area()->pack_start (cancel_button);
1777 entry.set_name ("RegionNameDisplay");
1778 ok_button.set_name ("EditorGTKButton");
1779 cancel_button.set_name ("EditorGTKButton");
1781 region_renamed = false;
1783 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1784 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1785 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
1792 if (region_renamed) {
1793 (*selection->regions.begin())->region()->set_name (entry.get_text());
1794 redisplay_regions ();
1799 Editor::rename_region_finished (bool status)
1802 region_renamed = status;
1807 Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Route& route)
1809 if (session->is_auditioning()) {
1810 session->cancel_audition ();
1813 // note: some potential for creativity here, because region doesn't
1814 // have to belong to the playlist that Route is handling
1816 // bool was_soloed = route.soloed();
1818 route.set_solo (true, this);
1820 session->request_bounded_roll (region->position(), region->position() + region->length());
1822 /* XXX how to unset the solo state ? */
1826 Editor::audition_selected_region ()
1828 if (!selection->regions.empty()) {
1829 RegionView* rv = *(selection->regions.begin());
1830 session->audition_region (rv->region());
1835 Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
1837 session->audition_region (region);
1841 Editor::build_interthread_progress_window ()
1843 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
1845 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
1847 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
1848 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
1850 // GTK2FIX: this button needs a modifiable label
1852 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1853 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
1855 interthread_cancel_button.add (interthread_cancel_label);
1857 interthread_progress_window->set_default_size (200, 100);
1861 Editor::interthread_cancel_clicked ()
1863 if (current_interthread_info) {
1864 current_interthread_info->cancel = true;
1869 Editor::region_from_selection ()
1871 if (clicked_trackview == 0) {
1875 if (selection->time.empty()) {
1879 nframes_t start = selection->time[clicked_selection].start;
1880 nframes_t end = selection->time[clicked_selection].end;
1882 nframes_t selection_cnt = end - start + 1;
1884 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1885 boost::shared_ptr<AudioRegion> current;
1886 boost::shared_ptr<Region> current_r;
1887 boost::shared_ptr<Playlist> pl;
1889 nframes_t internal_start;
1892 if ((pl = (*i)->playlist()) == 0) {
1896 if ((current_r = pl->top_region_at (start)) == 0) {
1900 current = boost::dynamic_pointer_cast<AudioRegion> (current_r);
1901 // FIXME: audio only
1903 internal_start = start - current->position();
1904 session->region_name (new_name, current->name(), true);
1905 boost::shared_ptr<Region> region (RegionFactory::create (current, internal_start, selection_cnt, new_name));
1911 Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& new_regions)
1913 if (selection->time.empty() || selection->tracks.empty()) {
1917 nframes_t start = selection->time[clicked_selection].start;
1918 nframes_t end = selection->time[clicked_selection].end;
1920 sort_track_selection ();
1922 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1924 boost::shared_ptr<AudioRegion> current;
1925 boost::shared_ptr<Region> current_r;
1926 boost::shared_ptr<Playlist> playlist;
1927 nframes_t internal_start;
1930 if ((playlist = (*i)->playlist()) == 0) {
1934 if ((current_r = playlist->top_region_at(start)) == 0) {
1938 if ((current = boost::dynamic_pointer_cast<AudioRegion>(current_r)) == 0) {
1942 internal_start = start - current->position();
1943 session->region_name (new_name, current->name(), true);
1945 new_regions.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (current, internal_start, end - start + 1, new_name)));
1950 Editor::split_multichannel_region ()
1952 if (selection->regions.empty()) {
1956 vector<boost::shared_ptr<AudioRegion> > v;
1958 for (list<RegionView*>::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
1960 AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*x);
1962 if (!arv || arv->audio_region()->n_channels() < 2) {
1966 (arv)->audio_region()->separate_by_channel (*session, v);
1971 Editor::new_region_from_selection ()
1973 region_from_selection ();
1974 cancel_selection ();
1978 Editor::separate_region_from_selection ()
1980 bool doing_undo = false;
1982 if (selection->time.empty()) {
1986 boost::shared_ptr<Playlist> playlist;
1988 sort_track_selection ();
1990 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1992 AudioTimeAxisView* atv;
1994 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
1996 if (atv->is_audio_track()) {
1998 if ((playlist = atv->playlist()) != 0) {
2000 begin_reversible_command (_("separate"));
2005 before = &(playlist->get_state());
2007 /* XXX need to consider musical time selections here at some point */
2009 double speed = atv->get_diskstream()->speed();
2011 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2012 playlist->partition ((nframes_t)((*t).start * speed), (nframes_t)((*t).end * speed), true);
2016 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2022 if (doing_undo) commit_reversible_command ();
2026 Editor::separate_regions_using_location (Location& loc)
2028 bool doing_undo = false;
2030 if (loc.is_mark()) {
2034 boost::shared_ptr<Playlist> playlist;
2036 /* XXX i'm unsure as to whether this should operate on selected tracks only
2037 or the entire enchillada. uncomment the below line to correct the behaviour
2038 (currently set for all tracks)
2041 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2042 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2044 AudioTimeAxisView* atv;
2046 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2048 if (atv->is_audio_track()) {
2050 if ((playlist = atv->playlist()) != 0) {
2053 begin_reversible_command (_("separate"));
2057 before = &(playlist->get_state());
2060 /* XXX need to consider musical time selections here at some point */
2062 double speed = atv->get_diskstream()->speed();
2065 playlist->partition ((nframes_t)(loc.start() * speed), (nframes_t)(loc.end() * speed), true);
2067 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2073 if (doing_undo) commit_reversible_command ();
2077 Editor::crop_region_to_selection ()
2079 if (selection->time.empty()) {
2083 vector<boost::shared_ptr<Playlist> > playlists;
2084 boost::shared_ptr<Playlist> playlist;
2086 if (clicked_trackview != 0) {
2088 if ((playlist = clicked_trackview->playlist()) == 0) {
2092 playlists.push_back (playlist);
2096 sort_track_selection ();
2098 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2100 AudioTimeAxisView* atv;
2102 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2104 if (atv->is_audio_track()) {
2106 if ((playlist = atv->playlist()) != 0) {
2107 playlists.push_back (playlist);
2114 if (!playlists.empty()) {
2120 begin_reversible_command (_("trim to selection"));
2122 for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2124 boost::shared_ptr<Region> region;
2126 start = selection->time.start();
2128 if ((region = (*i)->top_region_at(start)) == 0) {
2132 /* now adjust lengths to that we do the right thing
2133 if the selection extends beyond the region
2136 start = max (start, region->position());
2137 end = min (selection->time.end_frame(), start + region->length() - 1);
2138 cnt = end - start + 1;
2140 XMLNode &before = (*i)->get_state();
2141 region->trim_to (start, cnt, this);
2142 XMLNode &after = (*i)->get_state();
2143 session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
2146 commit_reversible_command ();
2151 Editor::region_fill_track ()
2155 if (!session || selection->regions.empty()) {
2159 end = session->current_end_frame ();
2161 begin_reversible_command (_("region fill"));
2163 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2165 boost::shared_ptr<Region> region ((*i)->region());
2168 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
2172 boost::shared_ptr<Playlist> pl = region->playlist();
2174 if (end <= region->last_frame()) {
2178 double times = (double) (end - region->last_frame()) / (double) region->length();
2184 XMLNode &before = pl->get_state();
2185 pl->add_region (RegionFactory::create (ar), ar->last_frame(), times);
2186 session->add_command (new MementoCommand<Playlist>(*pl, &before, &pl->get_state()));
2189 commit_reversible_command ();
2193 Editor::region_fill_selection ()
2195 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2199 if (selection->time.empty()) {
2204 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2206 if (selected->count_selected_rows() != 1) {
2210 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2211 boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
2213 nframes_t start = selection->time[clicked_selection].start;
2214 nframes_t end = selection->time[clicked_selection].end;
2216 boost::shared_ptr<Playlist> playlist;
2218 if (selection->tracks.empty()) {
2222 nframes_t selection_length = end - start;
2223 float times = (float)selection_length / region->length();
2225 begin_reversible_command (_("fill selection"));
2227 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2229 if ((playlist = (*i)->playlist()) == 0) {
2233 XMLNode &before = playlist->get_state();
2234 playlist->add_region (RegionFactory::create (region), start, times);
2235 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
2238 commit_reversible_command ();
2242 Editor::set_a_regions_sync_position (boost::shared_ptr<Region> region, nframes_t position)
2245 if (!region->covers (position)) {
2246 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2249 begin_reversible_command (_("set region sync position"));
2250 XMLNode &before = region->playlist()->get_state();
2251 region->set_sync_position (position);
2252 XMLNode &after = region->playlist()->get_state();
2253 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2254 commit_reversible_command ();
2258 Editor::set_region_sync_from_edit_cursor ()
2260 if (clicked_regionview == 0) {
2264 if (!clicked_regionview->region()->covers (edit_cursor->current_frame)) {
2265 error << _("Place the edit cursor at the desired sync point") << endmsg;
2269 boost::shared_ptr<Region> region (clicked_regionview->region());
2270 begin_reversible_command (_("set sync from edit cursor"));
2271 XMLNode &before = region->playlist()->get_state();
2272 region->set_sync_position (edit_cursor->current_frame);
2273 XMLNode &after = region->playlist()->get_state();
2274 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2275 commit_reversible_command ();
2279 Editor::remove_region_sync ()
2281 if (clicked_regionview) {
2282 boost::shared_ptr<Region> region (clicked_regionview->region());
2283 begin_reversible_command (_("remove sync"));
2284 XMLNode &before = region->playlist()->get_state();
2285 region->clear_sync_position ();
2286 XMLNode &after = region->playlist()->get_state();
2287 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2288 commit_reversible_command ();
2293 Editor::naturalize ()
2295 if (selection->regions.empty()) {
2298 begin_reversible_command (_("naturalize"));
2299 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2300 XMLNode &before = (*i)->region()->get_state();
2301 (*i)->region()->move_to_natural_position (this);
2302 XMLNode &after = (*i)->region()->get_state();
2303 session->add_command (new MementoCommand<Region>(*((*i)->region().get()), &before, &after));
2305 commit_reversible_command ();
2309 Editor::align (RegionPoint what)
2311 align_selection (what, edit_cursor->current_frame);
2315 Editor::align_relative (RegionPoint what)
2317 align_selection_relative (what, edit_cursor->current_frame);
2320 struct RegionSortByTime {
2321 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2322 return a->region()->position() < b->region()->position();
2327 Editor::align_selection_relative (RegionPoint point, nframes_t position)
2329 if (selection->regions.empty()) {
2337 list<RegionView*> sorted;
2338 selection->regions.by_position (sorted);
2339 boost::shared_ptr<Region> r ((*sorted.begin())->region());
2343 pos = r->first_frame ();
2347 pos = r->last_frame();
2351 pos = r->adjust_to_sync (r->first_frame());
2355 if (pos > position) {
2356 distance = pos - position;
2359 distance = position - pos;
2363 begin_reversible_command (_("align selection (relative)"));
2365 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2367 boost::shared_ptr<Region> region ((*i)->region());
2369 XMLNode &before = region->playlist()->get_state();
2372 region->set_position (region->position() + distance, this);
2374 region->set_position (region->position() - distance, this);
2377 XMLNode &after = region->playlist()->get_state();
2378 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2382 commit_reversible_command ();
2386 Editor::align_selection (RegionPoint point, nframes_t position)
2388 if (selection->regions.empty()) {
2392 begin_reversible_command (_("align selection"));
2394 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2395 align_region_internal ((*i)->region(), point, position);
2398 commit_reversible_command ();
2402 Editor::align_region (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2404 begin_reversible_command (_("align region"));
2405 align_region_internal (region, point, position);
2406 commit_reversible_command ();
2410 Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2412 XMLNode &before = region->playlist()->get_state();
2416 region->set_position (region->adjust_to_sync (position), this);
2420 if (position > region->length()) {
2421 region->set_position (position - region->length(), this);
2426 region->set_position (position, this);
2430 XMLNode &after = region->playlist()->get_state();
2431 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2435 Editor::trim_region_to_edit_cursor ()
2437 if (clicked_regionview == 0) {
2441 boost::shared_ptr<Region> region (clicked_regionview->region());
2444 AudioTimeAxisView *atav;
2446 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2447 if (atav->get_diskstream() != 0) {
2448 speed = atav->get_diskstream()->speed();
2452 begin_reversible_command (_("trim to edit"));
2453 XMLNode &before = region->playlist()->get_state();
2454 region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2455 XMLNode &after = region->playlist()->get_state();
2456 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2457 commit_reversible_command ();
2461 Editor::trim_region_from_edit_cursor ()
2463 if (clicked_regionview == 0) {
2467 boost::shared_ptr<Region> region (clicked_regionview->region());
2470 AudioTimeAxisView *atav;
2472 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2473 if (atav->get_diskstream() != 0) {
2474 speed = atav->get_diskstream()->speed();
2478 begin_reversible_command (_("trim to edit"));
2479 XMLNode &before = region->playlist()->get_state();
2480 region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2481 XMLNode &after = region->playlist()->get_state();
2482 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2483 commit_reversible_command ();
2487 Editor::unfreeze_route ()
2489 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2493 clicked_audio_trackview->audio_track()->unfreeze ();
2497 Editor::_freeze_thread (void* arg)
2499 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2500 return static_cast<Editor*>(arg)->freeze_thread ();
2504 Editor::freeze_thread ()
2506 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2511 Editor::freeze_progress_timeout (void *arg)
2513 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2514 return !(current_interthread_info->done || current_interthread_info->cancel);
2518 Editor::freeze_route ()
2520 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2524 InterThreadInfo itt;
2526 if (interthread_progress_window == 0) {
2527 build_interthread_progress_window ();
2530 interthread_progress_window->set_title (_("ardour: freeze"));
2531 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2532 interthread_progress_window->show_all ();
2533 interthread_progress_bar.set_fraction (0.0f);
2534 interthread_progress_label.set_text ("");
2535 interthread_cancel_label.set_text (_("Cancel Freeze"));
2536 current_interthread_info = &itt;
2538 interthread_progress_connection =
2539 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2543 itt.progress = 0.0f;
2545 pthread_attr_t attr;
2546 pthread_attr_init(&attr);
2547 pthread_attr_setstacksize(&attr, 500000);
2549 pthread_create (&itt.thread, &attr, _freeze_thread, this);
2551 pthread_attr_destroy(&attr);
2553 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2555 while (!itt.done && !itt.cancel) {
2556 gtk_main_iteration ();
2559 interthread_progress_connection.disconnect ();
2560 interthread_progress_window->hide_all ();
2561 current_interthread_info = 0;
2562 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2566 Editor::bounce_range_selection ()
2568 if (selection->time.empty()) {
2572 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2574 nframes_t start = selection->time[clicked_selection].start;
2575 nframes_t end = selection->time[clicked_selection].end;
2576 nframes_t cnt = end - start + 1;
2578 begin_reversible_command (_("bounce range"));
2580 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2582 AudioTimeAxisView* atv;
2584 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2588 boost::shared_ptr<Playlist> playlist;
2590 if ((playlist = atv->playlist()) == 0) {
2594 InterThreadInfo itt;
2598 itt.progress = false;
2600 XMLNode &before = playlist->get_state();
2601 atv->audio_track()->bounce_range (start, cnt, itt);
2602 XMLNode &after = playlist->get_state();
2603 session->add_command (new MementoCommand<Playlist> (*playlist, &before, &after));
2606 commit_reversible_command ();
2624 Editor::cut_copy (CutCopyOp op)
2626 /* only cancel selection if cut/copy is successful.*/
2638 opname = _("clear");
2642 cut_buffer->clear ();
2644 switch (current_mouse_mode()) {
2646 if (!selection->regions.empty() || !selection->points.empty()) {
2648 begin_reversible_command (opname + _(" objects"));
2650 if (!selection->regions.empty()) {
2652 cut_copy_regions (op);
2655 selection->clear_regions ();
2659 if (!selection->points.empty()) {
2660 cut_copy_points (op);
2663 selection->clear_points ();
2667 commit_reversible_command ();
2672 if (!selection->time.empty()) {
2674 begin_reversible_command (opname + _(" range"));
2675 cut_copy_ranges (op);
2676 commit_reversible_command ();
2679 selection->clear_time ();
2691 Editor::cut_copy_points (CutCopyOp op)
2693 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2695 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2698 atv->cut_copy_clear_objects (selection->points, op);
2703 struct PlaylistState {
2704 boost::shared_ptr<Playlist> playlist;
2708 struct lt_playlist {
2709 bool operator () (const PlaylistState& a, const PlaylistState& b) {
2710 return a.playlist < b.playlist;
2714 struct PlaylistMapping {
2716 boost::shared_ptr<AudioPlaylist> pl;
2718 PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
2722 Editor::cut_copy_regions (CutCopyOp op)
2724 /* we can't use a std::map here because the ordering is important, and we can't trivially sort
2725 a map when we want ordered access to both elements. i think.
2728 vector<PlaylistMapping> pmap;
2730 nframes_t first_position = max_frames;
2732 set<PlaylistState, lt_playlist> freezelist;
2733 pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
2735 /* get ordering correct before we cut/copy */
2737 selection->regions.sort_by_position_and_track ();
2739 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
2741 first_position = min ((*x)->region()->position(), first_position);
2743 if (op == Cut || op == Clear) {
2744 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
2748 PlaylistState before;
2749 before.playlist = pl;
2750 before.before = &pl->get_state();
2752 insert_result = freezelist.insert (before);
2754 if (insert_result.second) {
2760 TimeAxisView* tv = &(*x)->get_trackview();
2761 vector<PlaylistMapping>::iterator z;
2763 for (z = pmap.begin(); z != pmap.end(); ++z) {
2764 if ((*z).tv == tv) {
2769 if (z == pmap.end()) {
2770 pmap.push_back (PlaylistMapping (tv));
2774 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
2776 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
2779 /* impossible, but this handles it for the future */
2783 TimeAxisView& tv = (*x)->get_trackview();
2784 boost::shared_ptr<AudioPlaylist> npl;
2785 RegionSelection::iterator tmp;
2790 vector<PlaylistMapping>::iterator z;
2792 for (z = pmap.begin(); z != pmap.end(); ++z) {
2793 if ((*z).tv == &tv) {
2798 assert (z != pmap.end());
2801 npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
2808 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
2814 npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
2815 pl->remove_region (((*x)->region()));
2821 npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
2825 pl->remove_region (((*x)->region()));
2832 list<boost::shared_ptr<Playlist> > foo;
2834 /* the pmap is in the same order as the tracks in which selected regions occured */
2836 for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2838 foo.push_back ((*i).pl);
2842 cut_buffer->set (foo);
2845 for (set<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2846 (*pl).playlist->thaw ();
2847 session->add_command (new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
2852 Editor::cut_copy_ranges (CutCopyOp op)
2854 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2855 (*i)->cut_copy_clear (*selection, op);
2860 Editor::paste (float times)
2862 paste_internal (edit_cursor->current_frame, times);
2866 Editor::mouse_paste ()
2871 track_canvas.get_pointer (x, y);
2872 track_canvas.window_to_world (x, y, wx, wy);
2873 wx += horizontal_adjustment.get_value();
2874 wy += vertical_adjustment.get_value();
2877 event.type = GDK_BUTTON_RELEASE;
2878 event.button.x = wx;
2879 event.button.y = wy;
2881 nframes_t where = event_frame (&event, 0, 0);
2883 paste_internal (where, 1);
2887 Editor::paste_internal (nframes_t position, float times)
2889 bool commit = false;
2891 if (cut_buffer->empty() || selection->tracks.empty()) {
2895 if (position == max_frames) {
2896 position = edit_cursor->current_frame;
2899 begin_reversible_command (_("paste"));
2901 TrackSelection::iterator i;
2904 /* get everything in the correct order */
2906 sort_track_selection ();
2908 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
2910 /* undo/redo is handled by individual tracks */
2912 if ((*i)->paste (position, times, *cut_buffer, nth)) {
2918 commit_reversible_command ();
2923 Editor::paste_named_selection (float times)
2925 TrackSelection::iterator t;
2927 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
2929 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
2933 TreeModel::iterator i = selected->get_selected();
2934 NamedSelection* ns = (*i)[named_selection_columns.selection];
2936 list<boost::shared_ptr<Playlist> >::iterator chunk;
2937 list<boost::shared_ptr<Playlist> >::iterator tmp;
2939 chunk = ns->playlists.begin();
2941 begin_reversible_command (_("paste chunk"));
2943 sort_track_selection ();
2945 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
2947 AudioTimeAxisView* atv;
2948 boost::shared_ptr<Playlist> pl;
2949 boost::shared_ptr<AudioPlaylist> apl;
2951 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
2955 if ((pl = atv->playlist()) == 0) {
2959 if ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) == 0) {
2966 XMLNode &before = apl->get_state();
2967 apl->paste (*chunk, edit_cursor->current_frame, times);
2968 session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
2970 if (tmp != ns->playlists.end()) {
2975 commit_reversible_command();
2979 Editor::duplicate_some_regions (RegionSelection& regions, float times)
2981 boost::shared_ptr<Playlist> playlist;
2982 RegionSelection sel = regions; // clear (below) will clear the argument list
2984 begin_reversible_command (_("duplicate region"));
2986 selection->clear_regions ();
2988 for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
2990 boost::shared_ptr<Region> r ((*i)->region());
2992 TimeAxisView& tv = (*i)->get_time_axis_view();
2993 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
2994 sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
2996 playlist = (*i)->region()->playlist();
2997 XMLNode &before = playlist->get_state();
2998 playlist->duplicate (r, r->last_frame(), times);
2999 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
3003 if (latest_regionview) {
3004 selection->add (latest_regionview);
3009 commit_reversible_command ();
3013 Editor::duplicate_selection (float times)
3015 if (selection->time.empty() || selection->tracks.empty()) {
3019 boost::shared_ptr<Playlist> playlist;
3020 vector<boost::shared_ptr<AudioRegion> > new_regions;
3021 vector<boost::shared_ptr<AudioRegion> >::iterator ri;
3023 create_region_from_selection (new_regions);
3025 if (new_regions.empty()) {
3029 begin_reversible_command (_("duplicate selection"));
3031 ri = new_regions.begin();
3033 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3034 if ((playlist = (*i)->playlist()) == 0) {
3037 XMLNode &before = playlist->get_state();
3038 playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
3039 XMLNode &after = playlist->get_state();
3040 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3043 if (ri == new_regions.end()) {
3048 commit_reversible_command ();
3052 Editor::reset_point_selection ()
3054 /* reset all selected points to the relevant default value */
3056 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3058 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3061 atv->reset_objects (selection->points);
3067 Editor::center_playhead ()
3069 float page = canvas_width * frames_per_unit;
3071 center_screen_internal (playhead_cursor->current_frame, page);
3075 Editor::center_edit_cursor ()
3077 float page = canvas_width * frames_per_unit;
3079 center_screen_internal (edit_cursor->current_frame, page);
3083 Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
3085 begin_reversible_command (_("clear playlist"));
3086 XMLNode &before = playlist->get_state();
3088 XMLNode &after = playlist->get_state();
3089 session->add_command (new MementoCommand<Playlist>(*playlist.get(), &before, &after));
3090 commit_reversible_command ();
3094 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3096 boost::shared_ptr<Playlist> playlist;
3098 nframes_t next_distance;
3101 if (use_edit_cursor) {
3102 start = edit_cursor->current_frame;
3107 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3111 if (selection->tracks.empty()) {
3115 begin_reversible_command (_("nudge track"));
3117 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3119 if ((playlist = (*i)->playlist()) == 0) {
3123 XMLNode &before = playlist->get_state();
3124 playlist->nudge_after (start, distance, forwards);
3125 XMLNode &after = playlist->get_state();
3126 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3129 commit_reversible_command ();
3133 Editor::remove_last_capture ()
3135 vector<string> choices;
3142 if (Config->get_verify_remove_last_capture()) {
3143 prompt = _("Do you really want to destroy the last capture?"
3144 "\n(This is destructive and cannot be undone)");
3146 choices.push_back (_("No, do nothing."));
3147 choices.push_back (_("Yes, destroy it."));
3149 Gtkmm2ext::Choice prompter (prompt, choices);
3151 if (prompter.run () == 1) {
3152 session->remove_last_capture ();
3156 session->remove_last_capture();
3161 Editor::normalize_region ()
3167 if (selection->regions.empty()) {
3171 begin_reversible_command (_("normalize"));
3173 track_canvas.get_window()->set_cursor (*wait_cursor);
3176 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3177 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3180 XMLNode &before = arv->region()->get_state();
3181 arv->audio_region()->normalize_to (0.0f);
3182 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3185 commit_reversible_command ();
3186 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3191 Editor::denormalize_region ()
3197 if (selection->regions.empty()) {
3201 begin_reversible_command ("denormalize");
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()->set_scale_amplitude (1.0f);
3209 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3212 commit_reversible_command ();
3217 Editor::reverse_region ()
3223 Reverse rev (*session);
3224 apply_filter (rev, _("reverse regions"));
3228 Editor::apply_filter (AudioFilter& filter, string command)
3230 if (selection->regions.empty()) {
3234 begin_reversible_command (command);
3236 track_canvas.get_window()->set_cursor (*wait_cursor);
3239 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
3240 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3244 boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
3246 RegionSelection::iterator tmp;
3251 if (arv->audio_region()->apply (filter) == 0) {
3253 XMLNode &before = playlist->get_state();
3254 playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
3255 XMLNode &after = playlist->get_state();
3256 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
3264 commit_reversible_command ();
3265 selection->regions.clear ();
3268 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3272 Editor::region_selection_op (void (Region::*pmf)(void))
3274 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3275 Region* region = (*i)->region().get();
3282 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3284 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3285 Region* region = (*i)->region().get();
3286 (region->*pmf)(arg);
3291 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3293 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3294 Region* region = (*i)->region().get();
3300 Editor::external_edit_region ()
3302 if (!clicked_regionview) {
3310 Editor::brush (nframes_t pos)
3312 RegionSelection sel;
3315 if (selection->regions.empty()) {
3316 /* XXX get selection from region list */
3318 sel = selection->regions;
3325 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3326 mouse_brush_insert_region ((*i), pos);
3331 Editor::reset_region_gain_envelopes ()
3333 if (!session || selection->regions.empty()) {
3337 session->begin_reversible_command (_("reset region gain"));
3339 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3340 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3342 AutomationList& alist (arv->audio_region()->envelope());
3343 XMLNode& before (alist.get_state());
3345 arv->audio_region()->set_default_envelope ();
3346 session->add_command (new MementoCommand<AutomationList>(arv->audio_region()->envelope(), &before, &alist.get_state()));
3350 session->commit_reversible_command ();
3354 Editor::toggle_gain_envelope_visibility ()
3356 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3357 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3359 bool x = region_envelope_visible_item->get_active();
3360 if (x != arv->envelope_visible()) {
3361 arv->set_envelope_visible (x);
3368 Editor::toggle_gain_envelope_active ()
3370 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3371 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3373 bool x = region_envelope_active_item->get_active();
3374 if (x != arv->audio_region()->envelope_active()) {
3375 arv->audio_region()->set_envelope_active (x);
3382 Editor::toggle_region_lock ()
3384 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3385 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3387 bool x = region_lock_item->get_active();
3388 if (x != arv->audio_region()->locked()) {
3389 arv->audio_region()->set_locked (x);
3396 Editor::toggle_region_mute ()
3398 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3399 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3401 bool x = region_mute_item->get_active();
3402 if (x != arv->audio_region()->muted()) {
3403 arv->audio_region()->set_muted (x);
3410 Editor::toggle_region_opaque ()
3412 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3413 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3415 bool x = region_opaque_item->get_active();
3416 if (x != arv->audio_region()->opaque()) {
3417 arv->audio_region()->set_opaque (x);
3424 Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
3426 begin_reversible_command (_("set fade in shape"));
3428 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3429 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3435 AutomationList& alist = tmp->audio_region()->fade_in();
3436 XMLNode &before = alist.get_state();
3438 tmp->audio_region()->set_fade_in_shape (shape);
3440 XMLNode &after = alist.get_state();
3441 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3444 commit_reversible_command ();
3448 Editor::set_fade_out_shape (AudioRegion::FadeShape shape)
3450 begin_reversible_command (_("set fade out shape"));
3452 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3453 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3459 AutomationList& alist = tmp->audio_region()->fade_out();
3460 XMLNode &before = alist.get_state();
3462 tmp->audio_region()->set_fade_out_shape (shape);
3464 XMLNode &after = alist.get_state();
3465 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3468 commit_reversible_command ();
3472 Editor::set_fade_in_active (bool yn)
3474 begin_reversible_command (_("set fade in active"));
3476 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3477 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3484 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3486 XMLNode &before = ar->get_state();
3488 ar->set_fade_in_active (yn);
3490 XMLNode &after = ar->get_state();
3491 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
3496 Editor::set_fade_out_active (bool yn)
3498 begin_reversible_command (_("set fade out active"));
3500 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3501 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3507 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3509 XMLNode &before = ar->get_state();
3511 ar->set_fade_out_active (yn);
3513 XMLNode &after = ar->get_state();
3514 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));