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_routeview == 0 || clicked_regionview == 0) {
151 boost::shared_ptr<Playlist> playlist = clicked_routeview->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_axisview) {
504 t.push_back (clicked_axisview);
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_axisview) {
644 t.push_back (clicked_axisview);
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_axisview == 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<Region> 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_routeview != 0) {
1531 tv = clicked_routeview;
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_axisview == 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 assert(current); // FIXME
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 ()
1982 bool doing_undo = false;
1984 if (selection->time.empty()) {
1988 boost::shared_ptr<Playlist> playlist;
1990 sort_track_selection ();
1992 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1994 AudioTimeAxisView* atv;
1996 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
1998 if (atv->is_audio_track()) {
2000 if ((playlist = atv->playlist()) != 0) {
2002 begin_reversible_command (_("separate"));
2007 before = &(playlist->get_state());
2009 /* XXX need to consider musical time selections here at some point */
2011 double speed = atv->get_diskstream()->speed();
2013 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2014 playlist->partition ((nframes_t)((*t).start * speed), (nframes_t)((*t).end * speed), true);
2018 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2024 if (doing_undo) commit_reversible_command ();
2028 Editor::separate_regions_using_location (Location& loc)
2032 bool doing_undo = false;
2034 if (loc.is_mark()) {
2038 boost::shared_ptr<Playlist> playlist;
2040 /* XXX i'm unsure as to whether this should operate on selected tracks only
2041 or the entire enchillada. uncomment the below line to correct the behaviour
2042 (currently set for all tracks)
2045 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2046 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2048 AudioTimeAxisView* atv;
2050 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2052 if (atv->is_audio_track()) {
2054 if ((playlist = atv->playlist()) != 0) {
2057 begin_reversible_command (_("separate"));
2061 before = &(playlist->get_state());
2064 /* XXX need to consider musical time selections here at some point */
2066 double speed = atv->get_diskstream()->speed();
2069 playlist->partition ((nframes_t)(loc.start() * speed), (nframes_t)(loc.end() * speed), true);
2071 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2077 if (doing_undo) commit_reversible_command ();
2081 Editor::crop_region_to_selection ()
2083 if (selection->time.empty()) {
2087 vector<boost::shared_ptr<Playlist> > playlists;
2088 boost::shared_ptr<Playlist> playlist;
2090 if (clicked_axisview != 0) {
2092 if ((playlist = clicked_axisview->playlist()) == 0) {
2096 playlists.push_back (playlist);
2100 sort_track_selection ();
2102 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2104 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*i);
2106 if (rtv && rtv->is_track()) {
2108 if ((playlist = rtv->playlist()) != 0) {
2109 playlists.push_back (playlist);
2115 if (!playlists.empty()) {
2121 begin_reversible_command (_("trim to selection"));
2123 for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2125 boost::shared_ptr<Region> region;
2127 start = selection->time.start();
2129 if ((region = (*i)->top_region_at(start)) == 0) {
2133 /* now adjust lengths to that we do the right thing
2134 if the selection extends beyond the region
2137 start = max (start, region->position());
2138 end = min (selection->time.end_frame(), start + region->length() - 1);
2139 cnt = end - start + 1;
2141 XMLNode &before = (*i)->get_state();
2142 region->trim_to (start, cnt, this);
2143 XMLNode &after = (*i)->get_state();
2144 session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
2147 commit_reversible_command ();
2152 Editor::region_fill_track ()
2156 if (!session || selection->regions.empty()) {
2160 end = session->current_end_frame ();
2162 begin_reversible_command (_("region fill"));
2164 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2166 boost::shared_ptr<Region> region ((*i)->region());
2169 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_routeview == 0 || !clicked_routeview->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 RegionView* a, const RegionView* 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_axisview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_axisview)) != 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_axisview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_axisview)) != 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_routeview == 0 || !clicked_routeview->is_track()) {
2493 clicked_routeview->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_routeview->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_routeview == 0 || !clicked_routeview->is_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 TrackSelection views = selection->tracks;
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 ();
2622 Editor::cut_copy (CutCopyOp op)
2624 /* only cancel selection if cut/copy is successful.*/
2636 opname = _("clear");
2640 cut_buffer->clear ();
2642 switch (current_mouse_mode()) {
2644 if (!selection->regions.empty() || !selection->points.empty()) {
2646 begin_reversible_command (opname + _(" objects"));
2648 if (!selection->regions.empty()) {
2650 cut_copy_regions (op);
2653 selection->clear_regions ();
2657 if (!selection->points.empty()) {
2658 cut_copy_points (op);
2661 selection->clear_points ();
2665 commit_reversible_command ();
2670 if (!selection->time.empty()) {
2672 begin_reversible_command (opname + _(" range"));
2673 cut_copy_ranges (op);
2674 commit_reversible_command ();
2677 selection->clear_time ();
2689 Editor::cut_copy_points (CutCopyOp op)
2691 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2693 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2696 atv->cut_copy_clear_objects (selection->points, op);
2701 struct PlaylistState {
2702 boost::shared_ptr<Playlist> playlist;
2706 struct lt_playlist {
2707 bool operator () (const PlaylistState& a, const PlaylistState& b) {
2708 return a.playlist < b.playlist;
2712 struct PlaylistMapping {
2714 boost::shared_ptr<Playlist> pl;
2716 PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
2720 Editor::cut_copy_regions (CutCopyOp op)
2722 /* we can't use a std::map here because the ordering is important, and we can't trivially sort
2723 a map when we want ordered access to both elements. i think.
2726 vector<PlaylistMapping> pmap;
2728 nframes_t first_position = max_frames;
2730 set<PlaylistState, lt_playlist> freezelist;
2731 pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
2733 /* get ordering correct before we cut/copy */
2735 selection->regions.sort_by_position_and_track ();
2737 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
2739 first_position = min ((*x)->region()->position(), first_position);
2741 if (op == Cut || op == Clear) {
2742 boost::shared_ptr<Playlist> pl = (*x)->region()->playlist();
2746 PlaylistState before;
2747 before.playlist = pl;
2748 before.before = &pl->get_state();
2750 insert_result = freezelist.insert (before);
2752 if (insert_result.second) {
2758 TimeAxisView* tv = &(*x)->get_trackview();
2759 vector<PlaylistMapping>::iterator z;
2761 for (z = pmap.begin(); z != pmap.end(); ++z) {
2762 if ((*z).tv == tv) {
2767 if (z == pmap.end()) {
2768 pmap.push_back (PlaylistMapping (tv));
2772 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
2774 boost::shared_ptr<Playlist> pl = (*x)->region()->playlist();
2777 /* impossible, but this handles it for the future */
2781 TimeAxisView& tv = (*x)->get_trackview();
2782 boost::shared_ptr<Playlist> npl;
2783 RegionSelection::iterator tmp;
2788 vector<PlaylistMapping>::iterator z;
2790 for (z = pmap.begin(); z != pmap.end(); ++z) {
2791 if ((*z).tv == &tv) {
2796 assert (z != pmap.end());
2799 npl = PlaylistFactory::create (pl->data_type(), *session, "cutlist", true);
2806 boost::shared_ptr<Region> r = (*x)->region();
2812 npl->add_region (RegionFactory::create (r), r->position() - first_position);
2813 pl->remove_region (r);
2819 npl->add_region (RegionFactory::create (r), r->position() - first_position);
2823 pl->remove_region (r);
2830 list<boost::shared_ptr<Playlist> > foo;
2832 /* the pmap is in the same order as the tracks in which selected regions occured */
2834 for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2836 foo.push_back ((*i).pl);
2840 cut_buffer->set (foo);
2843 for (set<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2844 (*pl).playlist->thaw ();
2845 session->add_command (new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
2850 Editor::cut_copy_ranges (CutCopyOp op)
2852 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2853 (*i)->cut_copy_clear (*selection, op);
2858 Editor::paste (float times)
2860 paste_internal (edit_cursor->current_frame, times);
2864 Editor::mouse_paste ()
2869 track_canvas.get_pointer (x, y);
2870 track_canvas.window_to_world (x, y, wx, wy);
2871 wx += horizontal_adjustment.get_value();
2872 wy += vertical_adjustment.get_value();
2875 event.type = GDK_BUTTON_RELEASE;
2876 event.button.x = wx;
2877 event.button.y = wy;
2879 nframes_t where = event_frame (&event, 0, 0);
2881 paste_internal (where, 1);
2885 Editor::paste_internal (nframes_t position, float times)
2887 bool commit = false;
2889 if (cut_buffer->empty() || selection->tracks.empty()) {
2893 if (position == max_frames) {
2894 position = edit_cursor->current_frame;
2897 begin_reversible_command (_("paste"));
2899 TrackSelection::iterator i;
2902 /* get everything in the correct order */
2904 sort_track_selection ();
2906 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
2908 /* undo/redo is handled by individual tracks */
2910 if ((*i)->paste (position, times, *cut_buffer, nth)) {
2916 commit_reversible_command ();
2921 Editor::paste_named_selection (float times)
2923 TrackSelection::iterator t;
2925 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
2927 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
2931 TreeModel::iterator i = selected->get_selected();
2932 NamedSelection* ns = (*i)[named_selection_columns.selection];
2934 list<boost::shared_ptr<Playlist> >::iterator chunk;
2935 list<boost::shared_ptr<Playlist> >::iterator tmp;
2937 chunk = ns->playlists.begin();
2939 begin_reversible_command (_("paste chunk"));
2941 sort_track_selection ();
2943 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
2945 AudioTimeAxisView* atv;
2946 boost::shared_ptr<Playlist> pl;
2947 boost::shared_ptr<AudioPlaylist> apl;
2949 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
2953 if ((pl = atv->playlist()) == 0) {
2957 if ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) == 0) {
2964 XMLNode &before = apl->get_state();
2965 apl->paste (*chunk, edit_cursor->current_frame, times);
2966 session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
2968 if (tmp != ns->playlists.end()) {
2973 commit_reversible_command();
2977 Editor::duplicate_some_regions (RegionSelection& regions, float times)
2979 boost::shared_ptr<Playlist> playlist;
2980 RegionSelection sel = regions; // clear (below) will clear the argument list
2982 begin_reversible_command (_("duplicate region"));
2984 selection->clear_regions ();
2986 for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
2988 boost::shared_ptr<Region> r ((*i)->region());
2990 TimeAxisView& tv = (*i)->get_time_axis_view();
2991 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
2992 sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
2994 playlist = (*i)->region()->playlist();
2995 XMLNode &before = playlist->get_state();
2996 playlist->duplicate (r, r->last_frame(), times);
2997 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
3001 if (latest_regionview) {
3002 selection->add (latest_regionview);
3007 commit_reversible_command ();
3011 Editor::duplicate_selection (float times)
3013 if (selection->time.empty() || selection->tracks.empty()) {
3017 boost::shared_ptr<Playlist> playlist;
3018 vector<boost::shared_ptr<AudioRegion> > new_regions;
3019 vector<boost::shared_ptr<AudioRegion> >::iterator ri;
3021 create_region_from_selection (new_regions);
3023 if (new_regions.empty()) {
3027 begin_reversible_command (_("duplicate selection"));
3029 ri = new_regions.begin();
3031 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3032 if ((playlist = (*i)->playlist()) == 0) {
3035 XMLNode &before = playlist->get_state();
3036 playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
3037 XMLNode &after = playlist->get_state();
3038 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3041 if (ri == new_regions.end()) {
3046 commit_reversible_command ();
3050 Editor::reset_point_selection ()
3052 /* reset all selected points to the relevant default value */
3054 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3056 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3059 atv->reset_objects (selection->points);
3065 Editor::center_playhead ()
3067 float page = canvas_width * frames_per_unit;
3069 center_screen_internal (playhead_cursor->current_frame, page);
3073 Editor::center_edit_cursor ()
3075 float page = canvas_width * frames_per_unit;
3077 center_screen_internal (edit_cursor->current_frame, page);
3081 Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
3083 begin_reversible_command (_("clear playlist"));
3084 XMLNode &before = playlist->get_state();
3086 XMLNode &after = playlist->get_state();
3087 session->add_command (new MementoCommand<Playlist>(*playlist.get(), &before, &after));
3088 commit_reversible_command ();
3092 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3094 boost::shared_ptr<Playlist> playlist;
3096 nframes_t next_distance;
3099 if (use_edit_cursor) {
3100 start = edit_cursor->current_frame;
3105 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3109 if (selection->tracks.empty()) {
3113 begin_reversible_command (_("nudge track"));
3115 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3117 if ((playlist = (*i)->playlist()) == 0) {
3121 XMLNode &before = playlist->get_state();
3122 playlist->nudge_after (start, distance, forwards);
3123 XMLNode &after = playlist->get_state();
3124 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3127 commit_reversible_command ();
3131 Editor::remove_last_capture ()
3133 vector<string> choices;
3140 if (Config->get_verify_remove_last_capture()) {
3141 prompt = _("Do you really want to destroy the last capture?"
3142 "\n(This is destructive and cannot be undone)");
3144 choices.push_back (_("No, do nothing."));
3145 choices.push_back (_("Yes, destroy it."));
3147 Gtkmm2ext::Choice prompter (prompt, choices);
3149 if (prompter.run () == 1) {
3150 session->remove_last_capture ();
3154 session->remove_last_capture();
3159 Editor::normalize_region ()
3165 if (selection->regions.empty()) {
3169 begin_reversible_command (_("normalize"));
3171 track_canvas.get_window()->set_cursor (*wait_cursor);
3174 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3175 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3178 XMLNode &before = arv->region()->get_state();
3179 arv->audio_region()->normalize_to (0.0f);
3180 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3183 commit_reversible_command ();
3184 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3189 Editor::denormalize_region ()
3195 if (selection->regions.empty()) {
3199 begin_reversible_command ("denormalize");
3201 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3202 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3205 XMLNode &before = arv->region()->get_state();
3206 arv->audio_region()->set_scale_amplitude (1.0f);
3207 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3210 commit_reversible_command ();
3215 Editor::reverse_region ()
3221 Reverse rev (*session);
3222 apply_filter (rev, _("reverse regions"));
3226 Editor::apply_filter (AudioFilter& filter, string command)
3228 if (selection->regions.empty()) {
3232 begin_reversible_command (command);
3234 track_canvas.get_window()->set_cursor (*wait_cursor);
3237 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
3238 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3242 boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
3244 RegionSelection::iterator tmp;
3249 if (arv->audio_region()->apply (filter) == 0) {
3251 XMLNode &before = playlist->get_state();
3252 playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
3253 XMLNode &after = playlist->get_state();
3254 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
3262 commit_reversible_command ();
3263 selection->regions.clear ();
3266 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3270 Editor::region_selection_op (void (Region::*pmf)(void))
3272 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3273 Region* region = (*i)->region().get();
3280 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3282 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3283 Region* region = (*i)->region().get();
3284 (region->*pmf)(arg);
3289 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3291 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3292 Region* region = (*i)->region().get();
3298 Editor::external_edit_region ()
3300 if (!clicked_regionview) {
3308 Editor::brush (nframes_t pos)
3310 RegionSelection sel;
3313 if (selection->regions.empty()) {
3314 /* XXX get selection from region list */
3316 sel = selection->regions;
3323 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3324 mouse_brush_insert_region ((*i), pos);
3329 Editor::reset_region_gain_envelopes ()
3331 if (!session || selection->regions.empty()) {
3335 session->begin_reversible_command (_("reset region gain"));
3337 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3338 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3340 AutomationList& alist (arv->audio_region()->envelope());
3341 XMLNode& before (alist.get_state());
3343 arv->audio_region()->set_default_envelope ();
3344 session->add_command (new MementoCommand<AutomationList>(arv->audio_region()->envelope(), &before, &alist.get_state()));
3348 session->commit_reversible_command ();
3352 Editor::toggle_gain_envelope_visibility ()
3354 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3355 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3357 bool x = region_envelope_visible_item->get_active();
3358 if (x != arv->envelope_visible()) {
3359 arv->set_envelope_visible (x);
3366 Editor::toggle_gain_envelope_active ()
3368 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3369 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3371 bool x = region_envelope_active_item->get_active();
3372 if (x != arv->audio_region()->envelope_active()) {
3373 arv->audio_region()->set_envelope_active (x);
3380 Editor::toggle_region_lock ()
3382 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3383 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3385 bool x = region_lock_item->get_active();
3386 if (x != arv->audio_region()->locked()) {
3387 arv->audio_region()->set_locked (x);
3394 Editor::toggle_region_mute ()
3396 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3397 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3399 bool x = region_mute_item->get_active();
3400 if (x != arv->audio_region()->muted()) {
3401 arv->audio_region()->set_muted (x);
3408 Editor::toggle_region_opaque ()
3410 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3411 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3413 bool x = region_opaque_item->get_active();
3414 if (x != arv->audio_region()->opaque()) {
3415 arv->audio_region()->set_opaque (x);
3422 Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
3424 begin_reversible_command (_("set fade in shape"));
3426 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3427 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3433 AutomationList& alist = tmp->audio_region()->fade_in();
3434 XMLNode &before = alist.get_state();
3436 tmp->audio_region()->set_fade_in_shape (shape);
3438 XMLNode &after = alist.get_state();
3439 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3442 commit_reversible_command ();
3446 Editor::set_fade_out_shape (AudioRegion::FadeShape shape)
3448 begin_reversible_command (_("set fade out shape"));
3450 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3451 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3457 AutomationList& alist = tmp->audio_region()->fade_out();
3458 XMLNode &before = alist.get_state();
3460 tmp->audio_region()->set_fade_out_shape (shape);
3462 XMLNode &after = alist.get_state();
3463 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3466 commit_reversible_command ();
3470 Editor::set_fade_in_active (bool yn)
3472 begin_reversible_command (_("set fade in active"));
3474 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3475 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3482 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3484 XMLNode &before = ar->get_state();
3486 ar->set_fade_in_active (yn);
3488 XMLNode &after = ar->get_state();
3489 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
3494 Editor::set_fade_out_active (bool yn)
3496 begin_reversible_command (_("set fade out active"));
3498 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3499 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3505 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3507 XMLNode &before = ar->get_state();
3509 ar->set_fade_out_active (yn);
3511 XMLNode &after = ar->get_state();
3512 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));