2 Copyright (C) 2000-2004 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include <pbd/error.h>
28 #include <pbd/basename.h>
29 #include <pbd/pthread_utils.h>
30 #include <pbd/memento_command.h>
32 #include <gtkmm2ext/utils.h>
33 #include <gtkmm2ext/choice.h>
34 #include <gtkmm2ext/window_title.h>
36 #include <ardour/audioengine.h>
37 #include <ardour/session.h>
38 #include <ardour/audioplaylist.h>
39 #include <ardour/audioregion.h>
40 #include <ardour/audio_diskstream.h>
41 #include <ardour/utils.h>
42 #include <ardour/location.h>
43 #include <ardour/named_selection.h>
44 #include <ardour/audio_track.h>
45 #include <ardour/audioplaylist.h>
46 #include <ardour/region_factory.h>
47 #include <ardour/playlist_factory.h>
48 #include <ardour/reverse.h>
50 #include "ardour_ui.h"
52 #include "time_axis_view.h"
53 #include "audio_time_axis.h"
54 #include "automation_time_axis.h"
55 #include "streamview.h"
56 #include "audio_region_view.h"
57 #include "rgb_macros.h"
58 #include "selection_templates.h"
59 #include "selection.h"
61 #include "gtk-custom-hruler.h"
62 #include "gui_thread.h"
67 using namespace ARDOUR;
71 using namespace Gtkmm2ext;
72 using namespace Editing;
74 /***********************************************************************
76 ***********************************************************************/
79 Editor::undo (uint32_t n)
87 Editor::redo (uint32_t n)
95 Editor::ensure_cursor (nframes_t *pos)
97 *pos = edit_cursor->current_frame;
102 Editor::split_region ()
104 split_region_at (edit_cursor->current_frame);
108 Editor::split_region_at (nframes_t where)
110 split_regions_at (where, selection->regions);
114 Editor::split_regions_at (nframes_t where, RegionSelection& regions)
116 begin_reversible_command (_("split"));
119 for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
121 RegionSelection::iterator tmp;
126 boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
128 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
130 _new_regionviews_show_envelope = arv->envelope_visible();
133 XMLNode &before = pl->get_state();
134 pl->split_region ((*a)->region(), where);
135 XMLNode &after = pl->get_state();
136 session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
142 commit_reversible_command ();
143 _new_regionviews_show_envelope = false;
147 Editor::remove_clicked_region ()
149 if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
153 boost::shared_ptr<Playlist> playlist = clicked_audio_trackview->playlist();
155 begin_reversible_command (_("remove region"));
156 XMLNode &before = playlist->get_state();
157 playlist->remove_region (clicked_regionview->region());
158 XMLNode &after = playlist->get_state();
159 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
160 commit_reversible_command ();
164 Editor::destroy_clicked_region ()
166 uint32_t selected = selection->regions.size();
168 if (!session || !selected) {
172 vector<string> choices;
175 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
176 It cannot be undone\n\
177 Do you really want to destroy %1 ?"),
179 _("these regions") : _("this region")));
181 choices.push_back (_("No, do nothing."));
184 choices.push_back (_("Yes, destroy them."));
186 choices.push_back (_("Yes, destroy it."));
189 Gtkmm2ext::Choice prompter (prompt, choices);
191 if (prompter.run() == 0) { /* first choice */
196 list<boost::shared_ptr<Region> > r;
198 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
199 r.push_back ((*i)->region());
202 session->destroy_regions (r);
206 boost::shared_ptr<Region>
207 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
210 boost::shared_ptr<Region> region;
213 if (selection->time.start () == selection->time.end_frame ()) {
215 /* no current selection-> is there a selected regionview? */
217 if (selection->regions.empty()) {
223 if (!selection->regions.empty()) {
225 rv = *(selection->regions.begin());
226 (*tv) = &rv->get_time_axis_view();
227 region = rv->region();
229 } else if (!selection->tracks.empty()) {
231 (*tv) = selection->tracks.front();
233 RouteTimeAxisView* rtv;
235 if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
236 boost::shared_ptr<Playlist> pl;
238 if ((pl = rtv->playlist()) == 0) {
242 region = pl->top_region_at (start);
250 Editor::extend_selection_to_end_of_region (bool next)
253 boost::shared_ptr<Region> region;
256 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
260 if (region && selection->time.start () == selection->time.end_frame ()) {
261 start = region->position();
263 start = selection->time.start ();
266 /* Try to leave the selection with the same route if possible */
268 if ((tv = selection->time.track) == 0) {
272 begin_reversible_command (_("extend selection"));
273 selection->set (tv, start, region->position() + region->length());
274 commit_reversible_command ();
278 Editor::extend_selection_to_start_of_region (bool previous)
281 boost::shared_ptr<Region> region;
284 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
288 if (region && selection->time.start () == selection->time.end_frame ()) {
289 end = region->position() + region->length();
291 end = selection->time.end_frame ();
294 /* Try to leave the selection with the same route if possible */
296 if ((tv = selection->time.track) == 0) {
300 begin_reversible_command (_("extend selection"));
301 selection->set (tv, region->position(), end);
302 commit_reversible_command ();
307 Editor::nudge_forward (bool next)
310 nframes_t next_distance;
312 if (!session) return;
314 if (!selection->regions.empty()) {
316 begin_reversible_command (_("nudge forward"));
318 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
319 boost::shared_ptr<Region> r ((*i)->region());
321 distance = get_nudge_distance (r->position(), next_distance);
324 distance = next_distance;
327 XMLNode &before = r->playlist()->get_state();
328 r->set_position (r->position() + distance, this);
329 XMLNode &after = r->playlist()->get_state();
330 session->add_command (new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
333 commit_reversible_command ();
336 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
337 session->request_locate (playhead_cursor->current_frame + distance);
342 Editor::nudge_backward (bool next)
345 nframes_t next_distance;
347 if (!session) return;
349 if (!selection->regions.empty()) {
351 begin_reversible_command (_("nudge forward"));
353 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
354 boost::shared_ptr<Region> r ((*i)->region());
356 distance = get_nudge_distance (r->position(), next_distance);
359 distance = next_distance;
362 XMLNode &before = r->playlist()->get_state();
364 if (r->position() > distance) {
365 r->set_position (r->position() - distance, this);
367 r->set_position (0, this);
369 XMLNode &after = r->playlist()->get_state();
370 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
373 commit_reversible_command ();
377 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
379 if (playhead_cursor->current_frame > distance) {
380 session->request_locate (playhead_cursor->current_frame - distance);
382 session->goto_start();
388 Editor::nudge_forward_capture_offset ()
392 if (!session) return;
394 if (!selection->regions.empty()) {
396 begin_reversible_command (_("nudge forward"));
398 distance = session->worst_output_latency();
400 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
401 boost::shared_ptr<Region> r ((*i)->region());
403 XMLNode &before = r->playlist()->get_state();
404 r->set_position (r->position() + distance, this);
405 XMLNode &after = r->playlist()->get_state();
406 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
409 commit_reversible_command ();
415 Editor::nudge_backward_capture_offset ()
419 if (!session) return;
421 if (!selection->regions.empty()) {
423 begin_reversible_command (_("nudge forward"));
425 distance = session->worst_output_latency();
427 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
428 boost::shared_ptr<Region> r ((*i)->region());
430 XMLNode &before = r->playlist()->get_state();
432 if (r->position() > distance) {
433 r->set_position (r->position() - distance, this);
435 r->set_position (0, this);
437 XMLNode &after = r->playlist()->get_state();
438 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
441 commit_reversible_command ();
448 Editor::move_to_start ()
450 session->goto_start ();
454 Editor::move_to_end ()
457 session->request_locate (session->current_end_frame());
461 Editor::build_region_boundary_cache ()
465 boost::shared_ptr<Region> r;
466 TrackViewList tracks;
468 region_boundary_cache.clear ();
475 case SnapToRegionStart:
478 case SnapToRegionEnd:
481 case SnapToRegionSync:
484 case SnapToRegionBoundary:
488 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
493 TimeAxisView *ontrack = 0;
495 while (pos < session->current_end_frame()) {
497 if (!selection->tracks.empty()) {
499 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
503 } else if (clicked_trackview) {
506 t.push_back (clicked_trackview);
508 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
514 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
522 case SnapToRegionStart:
523 rpos = r->first_frame();
525 case SnapToRegionEnd:
526 rpos = r->last_frame();
528 case SnapToRegionSync:
529 rpos = r->adjust_to_sync (r->first_frame());
532 case SnapToRegionBoundary:
533 rpos = r->last_frame();
540 AudioTimeAxisView *atav;
542 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
543 if (atav->get_diskstream() != 0) {
544 speed = atav->get_diskstream()->speed();
548 rpos = track_frame_to_session_frame(rpos, speed);
550 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
551 if (snap_type == SnapToRegionBoundary) {
552 region_boundary_cache.push_back (r->first_frame());
554 region_boundary_cache.push_back (rpos);
561 boost::shared_ptr<Region>
562 Editor::find_next_region (nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
564 TrackViewList::iterator i;
565 nframes_t closest = max_frames;
566 boost::shared_ptr<Region> ret;
570 nframes_t track_frame;
571 AudioTimeAxisView *atav;
573 for (i = tracks.begin(); i != tracks.end(); ++i) {
576 boost::shared_ptr<Region> r;
579 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
580 if (atav->get_diskstream()!=0)
581 track_speed = atav->get_diskstream()->speed();
584 track_frame = session_frame_to_track_frame(frame, track_speed);
586 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
592 rpos = r->first_frame ();
596 rpos = r->last_frame ();
600 rpos = r->adjust_to_sync (r->first_frame());
603 // rpos is a "track frame", converting it to "session frame"
604 rpos = track_frame_to_session_frame(rpos, track_speed);
607 distance = rpos - frame;
609 distance = frame - rpos;
612 if (distance < closest) {
624 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
626 boost::shared_ptr<Region> r;
627 nframes_t pos = cursor->current_frame;
633 TimeAxisView *ontrack = 0;
635 // so we don't find the current region again..
639 if (!selection->tracks.empty()) {
641 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
643 } else if (clicked_trackview) {
646 t.push_back (clicked_trackview);
648 r = find_next_region (pos, point, dir, t, &ontrack);
652 r = find_next_region (pos, point, dir, track_views, &ontrack);
661 pos = r->first_frame ();
665 pos = r->last_frame ();
669 pos = r->adjust_to_sync (r->first_frame());
674 AudioTimeAxisView *atav;
676 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
677 if (atav->get_diskstream() != 0) {
678 speed = atav->get_diskstream()->speed();
682 pos = track_frame_to_session_frame(pos, speed);
684 if (cursor == playhead_cursor) {
685 session->request_locate (pos);
687 cursor->set_position (pos);
692 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
694 cursor_to_region_point (cursor, point, 1);
698 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
700 cursor_to_region_point (cursor, point, -1);
704 Editor::cursor_to_selection_start (Cursor *cursor)
707 switch (mouse_mode) {
709 if (!selection->regions.empty()) {
710 pos = selection->regions.start();
715 if (!selection->time.empty()) {
716 pos = selection->time.start ();
724 if (cursor == playhead_cursor) {
725 session->request_locate (pos);
727 cursor->set_position (pos);
732 Editor::cursor_to_selection_end (Cursor *cursor)
736 switch (mouse_mode) {
738 if (!selection->regions.empty()) {
739 pos = selection->regions.end_frame();
744 if (!selection->time.empty()) {
745 pos = selection->time.end_frame ();
753 if (cursor == playhead_cursor) {
754 session->request_locate (pos);
756 cursor->set_position (pos);
761 Editor::scroll_playhead (bool forward)
763 nframes_t pos = playhead_cursor->current_frame;
764 nframes_t delta = (nframes_t) floor (current_page_frames() / 0.8);
767 if (pos == max_frames) {
771 if (pos < max_frames - delta) {
790 session->request_locate (pos);
794 Editor::playhead_backward ()
801 if (get_prefix (prefix, was_floating)) {
805 cnt = (nframes_t) floor (prefix * session->frame_rate ());
807 cnt = (nframes_t) prefix;
811 pos = playhead_cursor->current_frame;
813 if ((nframes_t) pos < cnt) {
819 /* XXX this is completely insane. with the current buffering
820 design, we'll force a complete track buffer flush and
821 reload, just to move 1 sample !!!
824 session->request_locate (pos);
828 Editor::playhead_forward ()
835 if (get_prefix (prefix, was_floating)) {
839 cnt = (nframes_t) floor (prefix * session->frame_rate ());
841 cnt = (nframes_t) floor (prefix);
845 pos = playhead_cursor->current_frame;
847 /* XXX this is completely insane. with the current buffering
848 design, we'll force a complete track buffer flush and
849 reload, just to move 1 sample !!!
852 session->request_locate (pos+cnt);
856 Editor::cursor_align (bool playhead_to_edit)
858 if (playhead_to_edit) {
860 session->request_locate (edit_cursor->current_frame);
863 edit_cursor->set_position (playhead_cursor->current_frame);
868 Editor::edit_cursor_backward ()
875 if (get_prefix (prefix, was_floating)) {
879 cnt = (nframes_t) floor (prefix * session->frame_rate ());
881 cnt = (nframes_t) prefix;
885 pos = edit_cursor->current_frame;
887 if ((nframes_t) pos < cnt) {
893 edit_cursor->set_position (pos);
897 Editor::edit_cursor_forward ()
904 if (get_prefix (prefix, was_floating)) {
908 cnt = (nframes_t) floor (prefix * session->frame_rate ());
910 cnt = (nframes_t) floor (prefix);
914 pos = edit_cursor->current_frame;
915 edit_cursor->set_position (pos+cnt);
919 Editor::goto_frame ()
925 if (get_prefix (prefix, was_floating)) {
930 frame = (nframes_t) floor (prefix * session->frame_rate());
932 frame = (nframes_t) floor (prefix);
935 session->request_locate (frame);
939 Editor::scroll_backward (float pages)
942 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
947 if (get_prefix (prefix, was_floating)) {
948 cnt = (nframes_t) floor (pages * one_page);
951 cnt = (nframes_t) floor (prefix * session->frame_rate());
953 cnt = (nframes_t) floor (prefix * one_page);
957 if (leftmost_frame < cnt) {
960 frame = leftmost_frame - cnt;
963 reset_x_origin (frame);
967 Editor::scroll_forward (float pages)
970 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
975 if (get_prefix (prefix, was_floating)) {
976 cnt = (nframes_t) floor (pages * one_page);
979 cnt = (nframes_t) floor (prefix * session->frame_rate());
981 cnt = (nframes_t) floor (prefix * one_page);
985 if (max_frames - cnt < leftmost_frame) {
986 frame = max_frames - cnt;
988 frame = leftmost_frame + cnt;
991 reset_x_origin (frame);
995 Editor::scroll_tracks_down ()
1001 if (get_prefix (prefix, was_floating)) {
1004 cnt = (int) floor (prefix);
1007 double vert_value = vertical_adjustment.get_value() + (cnt *
1008 vertical_adjustment.get_page_size());
1009 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
1010 vert_value = vertical_adjustment.get_upper() - canvas_height;
1012 vertical_adjustment.set_value (vert_value);
1016 Editor::scroll_tracks_up ()
1022 if (get_prefix (prefix, was_floating)) {
1025 cnt = (int) floor (prefix);
1028 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1032 Editor::scroll_tracks_down_line ()
1035 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1036 double vert_value = adj->get_value() + 20;
1038 if (vert_value>adj->get_upper() - canvas_height) {
1039 vert_value = adj->get_upper() - canvas_height;
1041 adj->set_value (vert_value);
1045 Editor::scroll_tracks_up_line ()
1047 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1048 adj->set_value (adj->get_value() - 20);
1054 Editor::temporal_zoom_step (bool coarser)
1056 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1060 nfpu = frames_per_unit;
1065 nfpu = max(1.0,(nfpu/1.61803399));
1068 temporal_zoom (nfpu);
1072 Editor::temporal_zoom (gdouble fpu)
1074 if (!session) return;
1076 nframes_t current_page = current_page_frames();
1077 nframes_t current_leftmost = leftmost_frame;
1078 nframes_t current_rightmost;
1079 nframes_t current_center;
1081 nframes_t leftmost_after_zoom = 0;
1086 new_page = (nframes_t) floor (canvas_width * nfpu);
1088 switch (zoom_focus) {
1090 leftmost_after_zoom = current_leftmost;
1093 case ZoomFocusRight:
1094 current_rightmost = leftmost_frame + current_page;
1095 if (current_rightmost > new_page) {
1096 leftmost_after_zoom = current_rightmost - new_page;
1098 leftmost_after_zoom = 0;
1102 case ZoomFocusCenter:
1103 current_center = current_leftmost + (current_page/2);
1104 if (current_center > (new_page/2)) {
1105 leftmost_after_zoom = current_center - (new_page / 2);
1107 leftmost_after_zoom = 0;
1111 case ZoomFocusPlayhead:
1112 /* try to keep the playhead in the center */
1113 if (playhead_cursor->current_frame > new_page/2) {
1114 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1116 leftmost_after_zoom = 0;
1121 /* try to keep the edit cursor in the center */
1122 if (edit_cursor->current_frame > new_page/2) {
1123 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1125 leftmost_after_zoom = 0;
1131 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1133 // begin_reversible_command (_("zoom"));
1134 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1135 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1136 // commit_reversible_command ();
1138 reposition_and_zoom (leftmost_after_zoom, nfpu);
1142 Editor::temporal_zoom_selection ()
1144 if (!selection) return;
1146 if (selection->time.empty()) {
1150 nframes_t start = selection->time[clicked_selection].start;
1151 nframes_t end = selection->time[clicked_selection].end;
1153 temporal_zoom_by_frame (start, end, "zoom to selection");
1157 Editor::temporal_zoom_session ()
1159 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1162 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1167 Editor::temporal_zoom_by_frame (nframes_t start, nframes_t end, const string & op)
1169 if (!session) return;
1171 if ((start == 0 && end == 0) || end < start) {
1175 nframes_t range = end - start;
1177 double new_fpu = (double)range / (double)canvas_width;
1180 // while (p2 < new_fpu) {
1185 nframes_t new_page = (nframes_t) floor (canvas_width * new_fpu);
1186 nframes_t middle = (nframes_t) floor( (double)start + ((double)range / 2.0f ));
1187 nframes_t new_leftmost = (nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1189 if (new_leftmost > middle) new_leftmost = 0;
1191 // begin_reversible_command (op);
1192 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1193 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1194 // commit_reversible_command ();
1196 reposition_and_zoom (new_leftmost, new_fpu);
1200 Editor::temporal_zoom_to_frame (bool coarser, nframes_t frame)
1202 if (!session) return;
1204 double range_before = frame - leftmost_frame;
1207 new_fpu = frames_per_unit;
1210 new_fpu *= 1.61803399;
1211 range_before *= 1.61803399;
1213 new_fpu = max(1.0,(new_fpu/1.61803399));
1214 range_before /= 1.61803399;
1217 if (new_fpu == frames_per_unit) return;
1219 nframes_t new_leftmost = frame - (nframes_t)range_before;
1221 if (new_leftmost > frame) new_leftmost = 0;
1223 // begin_reversible_command (_("zoom to frame"));
1224 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1225 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1226 // commit_reversible_command ();
1228 reposition_and_zoom (new_leftmost, new_fpu);
1232 Editor::add_location_from_selection ()
1236 if (selection->time.empty()) {
1240 if (session == 0 || clicked_trackview == 0) {
1244 nframes_t start = selection->time[clicked_selection].start;
1245 nframes_t end = selection->time[clicked_selection].end;
1247 session->locations()->next_available_name(rangename,"selection");
1248 Location *location = new Location (start, end, rangename, Location::IsRangeMarker);
1250 session->begin_reversible_command (_("add marker"));
1251 XMLNode &before = session->locations()->get_state();
1252 session->locations()->add (location, true);
1253 XMLNode &after = session->locations()->get_state();
1254 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1255 session->commit_reversible_command ();
1259 Editor::add_location_from_playhead_cursor ()
1263 nframes_t where = session->audible_frame();
1265 session->locations()->next_available_name(markername,"mark");
1266 Location *location = new Location (where, where, markername, Location::IsMark);
1267 session->begin_reversible_command (_("add marker"));
1268 XMLNode &before = session->locations()->get_state();
1269 session->locations()->add (location, true);
1270 XMLNode &after = session->locations()->get_state();
1271 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1272 session->commit_reversible_command ();
1276 Editor::add_location_from_audio_region ()
1278 if (selection->regions.empty()) {
1282 RegionView* rv = *(selection->regions.begin());
1283 boost::shared_ptr<Region> region = rv->region();
1285 Location *location = new Location (region->position(), region->last_frame(), region->name(), Location::IsRangeMarker);
1286 session->begin_reversible_command (_("add marker"));
1287 XMLNode &before = session->locations()->get_state();
1288 session->locations()->add (location, true);
1289 XMLNode &after = session->locations()->get_state();
1290 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1291 session->commit_reversible_command ();
1295 Editor::amplitude_zoom_step (bool in)
1309 #ifdef FIX_FOR_CANVAS
1310 /* XXX DO SOMETHING */
1319 Editor::delete_sample_forward ()
1324 Editor::delete_sample_backward ()
1329 Editor::delete_screen ()
1336 Editor::search_backwards ()
1342 Editor::search_forwards ()
1350 Editor::jump_forward_to_mark ()
1356 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1359 session->request_locate (location->start(), session->transport_rolling());
1361 session->request_locate (session->current_end_frame());
1366 Editor::jump_backward_to_mark ()
1372 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1375 session->request_locate (location->start(), session->transport_rolling());
1377 session->goto_start ();
1389 if (get_prefix (prefix, was_floating)) {
1390 pos = session->audible_frame ();
1393 pos = (nframes_t) floor (prefix * session->frame_rate ());
1395 pos = (nframes_t) floor (prefix);
1399 session->locations()->next_available_name(markername,"mark");
1400 session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true);
1404 Editor::clear_markers ()
1407 session->begin_reversible_command (_("clear markers"));
1408 XMLNode &before = session->locations()->get_state();
1409 session->locations()->clear_markers ();
1410 XMLNode &after = session->locations()->get_state();
1411 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1412 session->commit_reversible_command ();
1417 Editor::clear_ranges ()
1420 session->begin_reversible_command (_("clear ranges"));
1421 XMLNode &before = session->locations()->get_state();
1423 Location * looploc = session->locations()->auto_loop_location();
1424 Location * punchloc = session->locations()->auto_punch_location();
1426 session->locations()->clear_ranges ();
1428 if (looploc) session->locations()->add (looploc);
1429 if (punchloc) session->locations()->add (punchloc);
1431 XMLNode &after = session->locations()->get_state();
1432 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1433 session->commit_reversible_command ();
1438 Editor::clear_locations ()
1440 session->begin_reversible_command (_("clear locations"));
1441 XMLNode &before = session->locations()->get_state();
1442 session->locations()->clear ();
1443 XMLNode &after = session->locations()->get_state();
1444 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1445 session->commit_reversible_command ();
1446 session->locations()->clear ();
1450 Editor::unhide_markers ()
1452 for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1453 Location *l = (*i).first;
1454 if (l->is_hidden() && l->is_mark()) {
1455 l->set_hidden(false, this);
1461 Editor::unhide_ranges ()
1463 for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1464 Location *l = (*i).first;
1465 if (l->is_hidden() && l->is_range_marker()) {
1466 l->set_hidden(false, this);
1471 /* INSERT/REPLACE */
1474 Editor::insert_region_list_drag (boost::shared_ptr<AudioRegion> region, int x, int y)
1480 AudioTimeAxisView *atv = 0;
1481 boost::shared_ptr<Playlist> playlist;
1483 track_canvas.window_to_world (x, y, wx, wy);
1484 wx += horizontal_adjustment.get_value();
1485 wy += vertical_adjustment.get_value();
1488 event.type = GDK_BUTTON_RELEASE;
1489 event.button.x = wx;
1490 event.button.y = wy;
1492 where = event_frame (&event, &cx, &cy);
1494 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1495 /* clearly outside canvas area */
1499 if ((tv = trackview_by_y_position (cy)) == 0) {
1503 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1507 if ((playlist = atv->playlist()) == 0) {
1511 cerr << "drop target playlist, UC = " << playlist.use_count() << endl;
1515 begin_reversible_command (_("insert dragged region"));
1516 XMLNode &before = playlist->get_state();
1517 cerr << "pre add target playlist, UC = " << playlist.use_count() << endl;
1518 playlist->add_region (RegionFactory::create (region), where, 1.0);
1519 cerr << "post add target playlist, UC = " << playlist.use_count() << endl;
1520 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1521 commit_reversible_command ();
1523 cerr << "post drop target playlist, UC = " << playlist.use_count() << endl;
1527 Editor::insert_region_list_selection (float times)
1529 RouteTimeAxisView *tv = 0;
1530 boost::shared_ptr<Playlist> playlist;
1532 if (clicked_audio_trackview != 0) {
1533 tv = clicked_audio_trackview;
1534 } else if (!selection->tracks.empty()) {
1535 if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
1542 if ((playlist = tv->playlist()) == 0) {
1546 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1548 if (selected->count_selected_rows() != 1) {
1552 TreeView::Selection::ListHandle_Path rows = selected->get_selected_rows ();
1554 /* only one row selected, so rows.begin() is it */
1558 if ((iter = region_list_model->get_iter (*rows.begin()))) {
1560 boost::shared_ptr<Region> region = (*iter)[region_list_columns.region];
1562 begin_reversible_command (_("insert region"));
1563 XMLNode &before = playlist->get_state();
1564 playlist->add_region ((RegionFactory::create (region)), edit_cursor->current_frame, times);
1565 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1566 commit_reversible_command ();
1570 /* BUILT-IN EFFECTS */
1573 Editor::reverse_selection ()
1578 /* GAIN ENVELOPE EDITING */
1581 Editor::edit_envelope ()
1588 Editor::transition_to_rolling (bool fwd)
1594 switch (Config->get_slave_source()) {
1599 /* transport controlled by the master */
1603 if (session->is_auditioning()) {
1604 session->cancel_audition ();
1608 session->request_transport_speed (fwd ? 1.0f : -1.0f);
1612 Editor::toggle_playback (bool with_abort)
1618 switch (Config->get_slave_source()) {
1623 /* transport controlled by the master */
1627 if (session->is_auditioning()) {
1628 session->cancel_audition ();
1632 if (session->transport_rolling()) {
1633 session->request_stop (with_abort);
1634 if (session->get_play_loop()) {
1635 session->request_play_loop (false);
1638 session->request_transport_speed (1.0f);
1643 Editor::play_from_start ()
1645 session->request_locate (session->current_start_frame(), true);
1649 Editor::play_from_edit_cursor ()
1651 session->request_locate (edit_cursor->current_frame, true);
1655 Editor::play_selection ()
1657 if (selection->time.empty()) {
1661 session->request_play_range (true);
1665 Editor::play_selected_region ()
1667 if (!selection->regions.empty()) {
1668 RegionView *rv = *(selection->regions.begin());
1670 session->request_bounded_roll (rv->region()->position(), rv->region()->last_frame());
1675 Editor::loop_selected_region ()
1677 if (!selection->regions.empty()) {
1678 RegionView *rv = *(selection->regions.begin());
1681 if ((tll = transport_loop_location()) != 0) {
1683 tll->set (rv->region()->position(), rv->region()->last_frame());
1685 // enable looping, reposition and start rolling
1687 session->request_play_loop (true);
1688 session->request_locate (tll->start(), false);
1689 session->request_transport_speed (1.0f);
1695 Editor::play_location (Location& location)
1697 if (location.start() <= location.end()) {
1701 session->request_bounded_roll (location.start(), location.end());
1705 Editor::loop_location (Location& location)
1707 if (location.start() <= location.end()) {
1713 if ((tll = transport_loop_location()) != 0) {
1714 tll->set (location.start(), location.end());
1716 // enable looping, reposition and start rolling
1717 session->request_play_loop (true);
1718 session->request_locate (tll->start(), true);
1723 Editor::raise_region ()
1725 selection->foreach_region (&Region::raise);
1729 Editor::raise_region_to_top ()
1731 selection->foreach_region (&Region::raise_to_top);
1735 Editor::lower_region ()
1737 selection->foreach_region (&Region::lower);
1741 Editor::lower_region_to_bottom ()
1743 selection->foreach_region (&Region::lower_to_bottom);
1747 Editor::edit_region ()
1749 if (clicked_regionview == 0) {
1753 clicked_regionview->show_region_editor ();
1757 Editor::rename_region ()
1761 Button ok_button (_("OK"));
1762 Button cancel_button (_("Cancel"));
1764 if (selection->regions.empty()) {
1768 WindowTitle title(Glib::get_application_name());
1769 title += _("Rename Region");
1771 dialog.set_title (title.get_string());
1772 dialog.set_name ("RegionRenameWindow");
1773 dialog.set_size_request (300, -1);
1774 dialog.set_position (Gtk::WIN_POS_MOUSE);
1775 dialog.set_modal (true);
1777 dialog.get_vbox()->set_border_width (10);
1778 dialog.get_vbox()->pack_start (entry);
1779 dialog.get_action_area()->pack_start (ok_button);
1780 dialog.get_action_area()->pack_start (cancel_button);
1782 entry.set_name ("RegionNameDisplay");
1783 ok_button.set_name ("EditorGTKButton");
1784 cancel_button.set_name ("EditorGTKButton");
1786 region_renamed = false;
1788 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1789 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1790 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
1797 if (region_renamed) {
1798 (*selection->regions.begin())->region()->set_name (entry.get_text());
1799 redisplay_regions ();
1804 Editor::rename_region_finished (bool status)
1807 region_renamed = status;
1812 Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Route& route)
1814 if (session->is_auditioning()) {
1815 session->cancel_audition ();
1818 // note: some potential for creativity here, because region doesn't
1819 // have to belong to the playlist that Route is handling
1821 // bool was_soloed = route.soloed();
1823 route.set_solo (true, this);
1825 session->request_bounded_roll (region->position(), region->position() + region->length());
1827 /* XXX how to unset the solo state ? */
1831 Editor::audition_selected_region ()
1833 if (!selection->regions.empty()) {
1834 RegionView* rv = *(selection->regions.begin());
1835 session->audition_region (rv->region());
1840 Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
1842 session->audition_region (region);
1846 Editor::build_interthread_progress_window ()
1848 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
1850 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
1852 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
1853 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
1855 // GTK2FIX: this button needs a modifiable label
1857 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1858 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
1860 interthread_cancel_button.add (interthread_cancel_label);
1862 interthread_progress_window->set_default_size (200, 100);
1866 Editor::interthread_cancel_clicked ()
1868 if (current_interthread_info) {
1869 current_interthread_info->cancel = true;
1874 Editor::region_from_selection ()
1876 if (clicked_trackview == 0) {
1880 if (selection->time.empty()) {
1884 nframes_t start = selection->time[clicked_selection].start;
1885 nframes_t end = selection->time[clicked_selection].end;
1887 nframes_t selection_cnt = end - start + 1;
1889 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1890 boost::shared_ptr<AudioRegion> current;
1891 boost::shared_ptr<Region> current_r;
1892 boost::shared_ptr<Playlist> pl;
1894 nframes_t internal_start;
1897 if ((pl = (*i)->playlist()) == 0) {
1901 if ((current_r = pl->top_region_at (start)) == 0) {
1905 current = boost::dynamic_pointer_cast<AudioRegion> (current_r);
1906 // FIXME: audio only
1908 internal_start = start - current->position();
1909 session->region_name (new_name, current->name(), true);
1910 boost::shared_ptr<Region> region (RegionFactory::create (current, internal_start, selection_cnt, new_name));
1916 Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& new_regions)
1918 if (selection->time.empty() || selection->tracks.empty()) {
1922 nframes_t start = selection->time[clicked_selection].start;
1923 nframes_t end = selection->time[clicked_selection].end;
1925 sort_track_selection ();
1927 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1929 boost::shared_ptr<AudioRegion> current;
1930 boost::shared_ptr<Region> current_r;
1931 boost::shared_ptr<Playlist> playlist;
1932 nframes_t internal_start;
1935 if ((playlist = (*i)->playlist()) == 0) {
1939 if ((current_r = playlist->top_region_at(start)) == 0) {
1943 if ((current = boost::dynamic_pointer_cast<AudioRegion>(current_r)) == 0) {
1947 internal_start = start - current->position();
1948 session->region_name (new_name, current->name(), true);
1950 new_regions.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (current, internal_start, end - start + 1, new_name)));
1955 Editor::split_multichannel_region ()
1957 if (selection->regions.empty()) {
1961 vector<boost::shared_ptr<AudioRegion> > v;
1963 for (list<RegionView*>::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
1965 AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*x);
1967 if (!arv || arv->audio_region()->n_channels() < 2) {
1971 (arv)->audio_region()->separate_by_channel (*session, v);
1976 Editor::new_region_from_selection ()
1978 region_from_selection ();
1979 cancel_selection ();
1983 Editor::separate_region_from_selection ()
1985 bool doing_undo = false;
1987 if (selection->time.empty()) {
1991 boost::shared_ptr<Playlist> playlist;
1993 sort_track_selection ();
1995 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1997 AudioTimeAxisView* atv;
1999 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2001 if (atv->is_audio_track()) {
2003 if ((playlist = atv->playlist()) != 0) {
2005 begin_reversible_command (_("separate"));
2010 before = &(playlist->get_state());
2012 /* XXX need to consider musical time selections here at some point */
2014 double speed = atv->get_diskstream()->speed();
2016 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2017 playlist->partition ((nframes_t)((*t).start * speed), (nframes_t)((*t).end * speed), true);
2021 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2027 if (doing_undo) commit_reversible_command ();
2031 Editor::separate_regions_using_location (Location& loc)
2033 bool doing_undo = false;
2035 if (loc.is_mark()) {
2039 boost::shared_ptr<Playlist> playlist;
2041 /* XXX i'm unsure as to whether this should operate on selected tracks only
2042 or the entire enchillada. uncomment the below line to correct the behaviour
2043 (currently set for all tracks)
2046 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2047 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2049 AudioTimeAxisView* atv;
2051 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2053 if (atv->is_audio_track()) {
2055 if ((playlist = atv->playlist()) != 0) {
2058 begin_reversible_command (_("separate"));
2062 before = &(playlist->get_state());
2065 /* XXX need to consider musical time selections here at some point */
2067 double speed = atv->get_diskstream()->speed();
2070 playlist->partition ((nframes_t)(loc.start() * speed), (nframes_t)(loc.end() * speed), true);
2072 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2078 if (doing_undo) commit_reversible_command ();
2082 Editor::crop_region_to_selection ()
2084 if (selection->time.empty()) {
2088 vector<boost::shared_ptr<Playlist> > playlists;
2089 boost::shared_ptr<Playlist> playlist;
2091 if (clicked_trackview != 0) {
2093 if ((playlist = clicked_trackview->playlist()) == 0) {
2097 playlists.push_back (playlist);
2101 sort_track_selection ();
2103 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2105 AudioTimeAxisView* atv;
2107 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2109 if (atv->is_audio_track()) {
2111 if ((playlist = atv->playlist()) != 0) {
2112 playlists.push_back (playlist);
2119 if (!playlists.empty()) {
2125 begin_reversible_command (_("trim to selection"));
2127 for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2129 boost::shared_ptr<Region> region;
2131 start = selection->time.start();
2133 if ((region = (*i)->top_region_at(start)) == 0) {
2137 /* now adjust lengths to that we do the right thing
2138 if the selection extends beyond the region
2141 start = max (start, region->position());
2142 end = min (selection->time.end_frame(), start + region->length() - 1);
2143 cnt = end - start + 1;
2145 XMLNode &before = (*i)->get_state();
2146 region->trim_to (start, cnt, this);
2147 XMLNode &after = (*i)->get_state();
2148 session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
2151 commit_reversible_command ();
2156 Editor::region_fill_track ()
2160 if (!session || selection->regions.empty()) {
2164 end = session->current_end_frame ();
2166 begin_reversible_command (_("region fill"));
2168 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2170 boost::shared_ptr<Region> region ((*i)->region());
2173 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
2177 boost::shared_ptr<Playlist> pl = region->playlist();
2179 if (end <= region->last_frame()) {
2183 double times = (double) (end - region->last_frame()) / (double) region->length();
2189 XMLNode &before = pl->get_state();
2190 pl->add_region (RegionFactory::create (ar), ar->last_frame(), times);
2191 session->add_command (new MementoCommand<Playlist>(*pl, &before, &pl->get_state()));
2194 commit_reversible_command ();
2198 Editor::region_fill_selection ()
2200 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2204 if (selection->time.empty()) {
2209 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2211 if (selected->count_selected_rows() != 1) {
2215 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2216 boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
2218 nframes_t start = selection->time[clicked_selection].start;
2219 nframes_t end = selection->time[clicked_selection].end;
2221 boost::shared_ptr<Playlist> playlist;
2223 if (selection->tracks.empty()) {
2227 nframes_t selection_length = end - start;
2228 float times = (float)selection_length / region->length();
2230 begin_reversible_command (_("fill selection"));
2232 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2234 if ((playlist = (*i)->playlist()) == 0) {
2238 XMLNode &before = playlist->get_state();
2239 playlist->add_region (RegionFactory::create (region), start, times);
2240 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
2243 commit_reversible_command ();
2247 Editor::set_a_regions_sync_position (boost::shared_ptr<Region> region, nframes_t position)
2250 if (!region->covers (position)) {
2251 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2254 begin_reversible_command (_("set region sync position"));
2255 XMLNode &before = region->playlist()->get_state();
2256 region->set_sync_position (position);
2257 XMLNode &after = region->playlist()->get_state();
2258 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2259 commit_reversible_command ();
2263 Editor::set_region_sync_from_edit_cursor ()
2265 if (clicked_regionview == 0) {
2269 if (!clicked_regionview->region()->covers (edit_cursor->current_frame)) {
2270 error << _("Place the edit cursor at the desired sync point") << endmsg;
2274 boost::shared_ptr<Region> region (clicked_regionview->region());
2275 begin_reversible_command (_("set sync from edit cursor"));
2276 XMLNode &before = region->playlist()->get_state();
2277 region->set_sync_position (edit_cursor->current_frame);
2278 XMLNode &after = region->playlist()->get_state();
2279 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2280 commit_reversible_command ();
2284 Editor::remove_region_sync ()
2286 if (clicked_regionview) {
2287 boost::shared_ptr<Region> region (clicked_regionview->region());
2288 begin_reversible_command (_("remove sync"));
2289 XMLNode &before = region->playlist()->get_state();
2290 region->clear_sync_position ();
2291 XMLNode &after = region->playlist()->get_state();
2292 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2293 commit_reversible_command ();
2298 Editor::naturalize ()
2300 if (selection->regions.empty()) {
2303 begin_reversible_command (_("naturalize"));
2304 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2305 XMLNode &before = (*i)->region()->get_state();
2306 (*i)->region()->move_to_natural_position (this);
2307 XMLNode &after = (*i)->region()->get_state();
2308 session->add_command (new MementoCommand<Region>(*((*i)->region().get()), &before, &after));
2310 commit_reversible_command ();
2314 Editor::align (RegionPoint what)
2316 align_selection (what, edit_cursor->current_frame);
2320 Editor::align_relative (RegionPoint what)
2322 align_selection_relative (what, edit_cursor->current_frame);
2325 struct RegionSortByTime {
2326 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2327 return a->region()->position() < b->region()->position();
2332 Editor::align_selection_relative (RegionPoint point, nframes_t position)
2334 if (selection->regions.empty()) {
2342 list<RegionView*> sorted;
2343 selection->regions.by_position (sorted);
2344 boost::shared_ptr<Region> r ((*sorted.begin())->region());
2348 pos = r->first_frame ();
2352 pos = r->last_frame();
2356 pos = r->adjust_to_sync (r->first_frame());
2360 if (pos > position) {
2361 distance = pos - position;
2364 distance = position - pos;
2368 begin_reversible_command (_("align selection (relative)"));
2370 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2372 boost::shared_ptr<Region> region ((*i)->region());
2374 XMLNode &before = region->playlist()->get_state();
2377 region->set_position (region->position() + distance, this);
2379 region->set_position (region->position() - distance, this);
2382 XMLNode &after = region->playlist()->get_state();
2383 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2387 commit_reversible_command ();
2391 Editor::align_selection (RegionPoint point, nframes_t position)
2393 if (selection->regions.empty()) {
2397 begin_reversible_command (_("align selection"));
2399 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2400 align_region_internal ((*i)->region(), point, position);
2403 commit_reversible_command ();
2407 Editor::align_region (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2409 begin_reversible_command (_("align region"));
2410 align_region_internal (region, point, position);
2411 commit_reversible_command ();
2415 Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2417 XMLNode &before = region->playlist()->get_state();
2421 region->set_position (region->adjust_to_sync (position), this);
2425 if (position > region->length()) {
2426 region->set_position (position - region->length(), this);
2431 region->set_position (position, this);
2435 XMLNode &after = region->playlist()->get_state();
2436 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2440 Editor::trim_region_to_edit_cursor ()
2442 if (clicked_regionview == 0) {
2446 boost::shared_ptr<Region> region (clicked_regionview->region());
2449 AudioTimeAxisView *atav;
2451 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2452 if (atav->get_diskstream() != 0) {
2453 speed = atav->get_diskstream()->speed();
2457 begin_reversible_command (_("trim to edit"));
2458 XMLNode &before = region->playlist()->get_state();
2459 region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2460 XMLNode &after = region->playlist()->get_state();
2461 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2462 commit_reversible_command ();
2466 Editor::trim_region_from_edit_cursor ()
2468 if (clicked_regionview == 0) {
2472 boost::shared_ptr<Region> region (clicked_regionview->region());
2475 AudioTimeAxisView *atav;
2477 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2478 if (atav->get_diskstream() != 0) {
2479 speed = atav->get_diskstream()->speed();
2483 begin_reversible_command (_("trim to edit"));
2484 XMLNode &before = region->playlist()->get_state();
2485 region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2486 XMLNode &after = region->playlist()->get_state();
2487 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2488 commit_reversible_command ();
2492 Editor::unfreeze_route ()
2494 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2498 clicked_audio_trackview->audio_track()->unfreeze ();
2502 Editor::_freeze_thread (void* arg)
2504 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2505 return static_cast<Editor*>(arg)->freeze_thread ();
2509 Editor::freeze_thread ()
2511 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2516 Editor::freeze_progress_timeout (void *arg)
2518 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2519 return !(current_interthread_info->done || current_interthread_info->cancel);
2523 Editor::freeze_route ()
2525 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2529 InterThreadInfo itt;
2531 if (interthread_progress_window == 0) {
2532 build_interthread_progress_window ();
2535 WindowTitle title(Glib::get_application_name());
2536 title += _("Freeze");
2537 interthread_progress_window->set_title (title.get_string());
2538 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2539 interthread_progress_window->show_all ();
2540 interthread_progress_bar.set_fraction (0.0f);
2541 interthread_progress_label.set_text ("");
2542 interthread_cancel_label.set_text (_("Cancel Freeze"));
2543 current_interthread_info = &itt;
2545 interthread_progress_connection =
2546 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2550 itt.progress = 0.0f;
2552 pthread_attr_t attr;
2553 pthread_attr_init(&attr);
2554 pthread_attr_setstacksize(&attr, 500000);
2556 pthread_create (&itt.thread, &attr, _freeze_thread, this);
2558 pthread_attr_destroy(&attr);
2560 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2562 while (!itt.done && !itt.cancel) {
2563 gtk_main_iteration ();
2566 interthread_progress_connection.disconnect ();
2567 interthread_progress_window->hide_all ();
2568 current_interthread_info = 0;
2569 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2573 Editor::bounce_range_selection ()
2575 if (selection->time.empty()) {
2579 TrackSelection views = selection->tracks;
2581 nframes_t start = selection->time[clicked_selection].start;
2582 nframes_t end = selection->time[clicked_selection].end;
2583 nframes_t cnt = end - start + 1;
2585 begin_reversible_command (_("bounce range"));
2587 for (TrackViewList::iterator i = views.begin(); i != views.end(); ++i) {
2589 AudioTimeAxisView* atv;
2591 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2595 boost::shared_ptr<Playlist> playlist;
2597 if ((playlist = atv->playlist()) == 0) {
2601 InterThreadInfo itt;
2605 itt.progress = false;
2607 XMLNode &before = playlist->get_state();
2608 atv->audio_track()->bounce_range (start, cnt, itt);
2609 XMLNode &after = playlist->get_state();
2610 session->add_command (new MementoCommand<Playlist> (*playlist, &before, &after));
2613 commit_reversible_command ();
2629 Editor::cut_copy (CutCopyOp op)
2631 /* only cancel selection if cut/copy is successful.*/
2643 opname = _("clear");
2647 cut_buffer->clear ();
2649 switch (current_mouse_mode()) {
2651 if (!selection->regions.empty() || !selection->points.empty()) {
2653 begin_reversible_command (opname + _(" objects"));
2655 if (!selection->regions.empty()) {
2657 cut_copy_regions (op);
2660 selection->clear_regions ();
2664 if (!selection->points.empty()) {
2665 cut_copy_points (op);
2668 selection->clear_points ();
2672 commit_reversible_command ();
2677 if (!selection->time.empty()) {
2679 begin_reversible_command (opname + _(" range"));
2680 cut_copy_ranges (op);
2681 commit_reversible_command ();
2684 selection->clear_time ();
2696 Editor::cut_copy_points (CutCopyOp op)
2698 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2700 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2703 atv->cut_copy_clear_objects (selection->points, op);
2708 struct PlaylistState {
2709 boost::shared_ptr<Playlist> playlist;
2713 struct lt_playlist {
2714 bool operator () (const PlaylistState& a, const PlaylistState& b) {
2715 return a.playlist < b.playlist;
2719 struct PlaylistMapping {
2721 boost::shared_ptr<AudioPlaylist> pl;
2723 PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
2727 Editor::cut_copy_regions (CutCopyOp op)
2729 /* we can't use a std::map here because the ordering is important, and we can't trivially sort
2730 a map when we want ordered access to both elements. i think.
2733 vector<PlaylistMapping> pmap;
2735 nframes_t first_position = max_frames;
2737 set<PlaylistState, lt_playlist> freezelist;
2738 pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
2740 /* get ordering correct before we cut/copy */
2742 selection->regions.sort_by_position_and_track ();
2744 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
2746 first_position = min ((*x)->region()->position(), first_position);
2748 if (op == Cut || op == Clear) {
2749 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
2753 PlaylistState before;
2754 before.playlist = pl;
2755 before.before = &pl->get_state();
2757 insert_result = freezelist.insert (before);
2759 if (insert_result.second) {
2765 TimeAxisView* tv = &(*x)->get_trackview();
2766 vector<PlaylistMapping>::iterator z;
2768 for (z = pmap.begin(); z != pmap.end(); ++z) {
2769 if ((*z).tv == tv) {
2774 if (z == pmap.end()) {
2775 pmap.push_back (PlaylistMapping (tv));
2779 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
2781 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
2784 /* impossible, but this handles it for the future */
2788 TimeAxisView& tv = (*x)->get_trackview();
2789 boost::shared_ptr<AudioPlaylist> npl;
2790 RegionSelection::iterator tmp;
2795 vector<PlaylistMapping>::iterator z;
2797 for (z = pmap.begin(); z != pmap.end(); ++z) {
2798 if ((*z).tv == &tv) {
2803 assert (z != pmap.end());
2806 npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
2813 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
2814 boost::shared_ptr<Region> _xx;
2820 _xx = RegionFactory::create ((*x)->region());
2821 npl->add_region (_xx, (*x)->region()->position() - first_position);
2822 pl->remove_region (((*x)->region()));
2828 npl->add_region ((*x)->region(), (*x)->region()->position() - first_position);
2832 pl->remove_region (((*x)->region()));
2839 list<boost::shared_ptr<Playlist> > foo;
2841 /* the pmap is in the same order as the tracks in which selected regions occured */
2843 for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2845 foo.push_back ((*i).pl);
2850 cut_buffer->set (foo);
2853 for (set<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2854 (*pl).playlist->thaw ();
2855 session->add_command (new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
2860 Editor::cut_copy_ranges (CutCopyOp op)
2862 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2863 (*i)->cut_copy_clear (*selection, op);
2868 Editor::paste (float times)
2870 paste_internal (edit_cursor->current_frame, times);
2874 Editor::mouse_paste ()
2879 track_canvas.get_pointer (x, y);
2880 track_canvas.window_to_world (x, y, wx, wy);
2881 wx += horizontal_adjustment.get_value();
2882 wy += vertical_adjustment.get_value();
2885 event.type = GDK_BUTTON_RELEASE;
2886 event.button.x = wx;
2887 event.button.y = wy;
2889 nframes_t where = event_frame (&event, 0, 0);
2891 paste_internal (where, 1);
2895 Editor::paste_internal (nframes_t position, float times)
2897 bool commit = false;
2899 if (cut_buffer->empty() || selection->tracks.empty()) {
2903 if (position == max_frames) {
2904 position = edit_cursor->current_frame;
2907 begin_reversible_command (_("paste"));
2909 TrackSelection::iterator i;
2912 /* get everything in the correct order */
2914 sort_track_selection ();
2916 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
2918 /* undo/redo is handled by individual tracks */
2920 if ((*i)->paste (position, times, *cut_buffer, nth)) {
2926 commit_reversible_command ();
2931 Editor::paste_named_selection (float times)
2933 TrackSelection::iterator t;
2935 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
2937 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
2941 TreeModel::iterator i = selected->get_selected();
2942 NamedSelection* ns = (*i)[named_selection_columns.selection];
2944 list<boost::shared_ptr<Playlist> >::iterator chunk;
2945 list<boost::shared_ptr<Playlist> >::iterator tmp;
2947 chunk = ns->playlists.begin();
2949 begin_reversible_command (_("paste chunk"));
2951 sort_track_selection ();
2953 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
2955 AudioTimeAxisView* atv;
2956 boost::shared_ptr<Playlist> pl;
2957 boost::shared_ptr<AudioPlaylist> apl;
2959 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
2963 if ((pl = atv->playlist()) == 0) {
2967 if ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) == 0) {
2974 XMLNode &before = apl->get_state();
2975 apl->paste (*chunk, edit_cursor->current_frame, times);
2976 session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
2978 if (tmp != ns->playlists.end()) {
2983 commit_reversible_command();
2987 Editor::duplicate_some_regions (RegionSelection& regions, float times)
2989 boost::shared_ptr<Playlist> playlist;
2990 RegionSelection sel = regions; // clear (below) will clear the argument list
2992 begin_reversible_command (_("duplicate region"));
2994 selection->clear_regions ();
2996 for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
2998 boost::shared_ptr<Region> r ((*i)->region());
3000 TimeAxisView& tv = (*i)->get_time_axis_view();
3001 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3002 sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3004 playlist = (*i)->region()->playlist();
3005 XMLNode &before = playlist->get_state();
3006 playlist->duplicate (r, r->last_frame(), times);
3007 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
3011 if (latest_regionview) {
3012 selection->add (latest_regionview);
3017 commit_reversible_command ();
3021 Editor::duplicate_selection (float times)
3023 if (selection->time.empty() || selection->tracks.empty()) {
3027 boost::shared_ptr<Playlist> playlist;
3028 vector<boost::shared_ptr<AudioRegion> > new_regions;
3029 vector<boost::shared_ptr<AudioRegion> >::iterator ri;
3031 create_region_from_selection (new_regions);
3033 if (new_regions.empty()) {
3037 begin_reversible_command (_("duplicate selection"));
3039 ri = new_regions.begin();
3041 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3042 if ((playlist = (*i)->playlist()) == 0) {
3045 XMLNode &before = playlist->get_state();
3046 playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
3047 XMLNode &after = playlist->get_state();
3048 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3051 if (ri == new_regions.end()) {
3056 commit_reversible_command ();
3060 Editor::reset_point_selection ()
3062 /* reset all selected points to the relevant default value */
3064 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3066 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3069 atv->reset_objects (selection->points);
3075 Editor::center_playhead ()
3077 float page = canvas_width * frames_per_unit;
3079 center_screen_internal (playhead_cursor->current_frame, page);
3083 Editor::center_edit_cursor ()
3085 float page = canvas_width * frames_per_unit;
3087 center_screen_internal (edit_cursor->current_frame, page);
3091 Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
3093 begin_reversible_command (_("clear playlist"));
3094 XMLNode &before = playlist->get_state();
3096 XMLNode &after = playlist->get_state();
3097 session->add_command (new MementoCommand<Playlist>(*playlist.get(), &before, &after));
3098 commit_reversible_command ();
3102 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3104 boost::shared_ptr<Playlist> playlist;
3106 nframes_t next_distance;
3109 if (use_edit_cursor) {
3110 start = edit_cursor->current_frame;
3115 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3119 if (selection->tracks.empty()) {
3123 begin_reversible_command (_("nudge track"));
3125 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3127 if ((playlist = (*i)->playlist()) == 0) {
3131 XMLNode &before = playlist->get_state();
3132 playlist->nudge_after (start, distance, forwards);
3133 XMLNode &after = playlist->get_state();
3134 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3137 commit_reversible_command ();
3141 Editor::remove_last_capture ()
3143 vector<string> choices;
3150 if (Config->get_verify_remove_last_capture()) {
3151 prompt = _("Do you really want to destroy the last capture?"
3152 "\n(This is destructive and cannot be undone)");
3154 choices.push_back (_("No, do nothing."));
3155 choices.push_back (_("Yes, destroy it."));
3157 Gtkmm2ext::Choice prompter (prompt, choices);
3159 if (prompter.run () == 1) {
3160 session->remove_last_capture ();
3164 session->remove_last_capture();
3169 Editor::normalize_region ()
3175 if (selection->regions.empty()) {
3179 begin_reversible_command (_("normalize"));
3181 track_canvas.get_window()->set_cursor (*wait_cursor);
3184 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3185 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3188 XMLNode &before = arv->region()->get_state();
3189 arv->audio_region()->normalize_to (0.0f);
3190 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3193 commit_reversible_command ();
3194 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3199 Editor::denormalize_region ()
3205 if (selection->regions.empty()) {
3209 begin_reversible_command ("denormalize");
3211 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3212 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3215 XMLNode &before = arv->region()->get_state();
3216 arv->audio_region()->set_scale_amplitude (1.0f);
3217 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3220 commit_reversible_command ();
3225 Editor::reverse_region ()
3231 Reverse rev (*session);
3232 apply_filter (rev, _("reverse regions"));
3236 Editor::apply_filter (AudioFilter& filter, string command)
3238 if (selection->regions.empty()) {
3242 begin_reversible_command (command);
3244 track_canvas.get_window()->set_cursor (*wait_cursor);
3247 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
3248 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3252 boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
3254 RegionSelection::iterator tmp;
3259 if (arv->audio_region()->apply (filter) == 0) {
3261 XMLNode &before = playlist->get_state();
3262 playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
3263 XMLNode &after = playlist->get_state();
3264 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
3272 commit_reversible_command ();
3273 selection->regions.clear ();
3276 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3280 Editor::region_selection_op (void (Region::*pmf)(void))
3282 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3283 Region* region = (*i)->region().get();
3290 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3292 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3293 Region* region = (*i)->region().get();
3294 (region->*pmf)(arg);
3299 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3301 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3302 Region* region = (*i)->region().get();
3308 Editor::external_edit_region ()
3310 if (!clicked_regionview) {
3318 Editor::brush (nframes_t pos)
3320 RegionSelection sel;
3323 if (selection->regions.empty()) {
3324 /* XXX get selection from region list */
3326 sel = selection->regions;
3333 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3334 mouse_brush_insert_region ((*i), pos);
3339 Editor::reset_region_gain_envelopes ()
3341 if (!session || selection->regions.empty()) {
3345 session->begin_reversible_command (_("reset region gain"));
3347 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3348 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3350 AutomationList& alist (arv->audio_region()->envelope());
3351 XMLNode& before (alist.get_state());
3353 arv->audio_region()->set_default_envelope ();
3354 session->add_command (new MementoCommand<AutomationList>(arv->audio_region()->envelope(), &before, &alist.get_state()));
3358 session->commit_reversible_command ();
3362 Editor::toggle_gain_envelope_visibility ()
3364 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3365 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3367 bool x = region_envelope_visible_item->get_active();
3368 if (x != arv->envelope_visible()) {
3369 arv->set_envelope_visible (x);
3376 Editor::toggle_gain_envelope_active ()
3378 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3379 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3381 bool x = region_envelope_active_item->get_active();
3382 if (x != arv->audio_region()->envelope_active()) {
3383 arv->audio_region()->set_envelope_active (x);
3390 Editor::toggle_region_lock ()
3392 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3393 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3395 bool x = region_lock_item->get_active();
3396 if (x != arv->audio_region()->locked()) {
3397 arv->audio_region()->set_locked (x);
3404 Editor::toggle_region_mute ()
3406 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3407 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3409 bool x = region_mute_item->get_active();
3410 if (x != arv->audio_region()->muted()) {
3411 arv->audio_region()->set_muted (x);
3418 Editor::toggle_region_opaque ()
3420 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3421 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3423 bool x = region_opaque_item->get_active();
3424 if (x != arv->audio_region()->opaque()) {
3425 arv->audio_region()->set_opaque (x);
3432 Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
3434 begin_reversible_command (_("set fade in shape"));
3436 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3437 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3443 AutomationList& alist = tmp->audio_region()->fade_in();
3444 XMLNode &before = alist.get_state();
3446 tmp->audio_region()->set_fade_in_shape (shape);
3448 XMLNode &after = alist.get_state();
3449 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3452 commit_reversible_command ();
3456 Editor::set_fade_out_shape (AudioRegion::FadeShape shape)
3458 begin_reversible_command (_("set fade out shape"));
3460 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3461 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3467 AutomationList& alist = tmp->audio_region()->fade_out();
3468 XMLNode &before = alist.get_state();
3470 tmp->audio_region()->set_fade_out_shape (shape);
3472 XMLNode &after = alist.get_state();
3473 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3476 commit_reversible_command ();
3480 Editor::set_fade_in_active (bool yn)
3482 begin_reversible_command (_("set fade in active"));
3484 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3485 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3492 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3494 XMLNode &before = ar->get_state();
3496 ar->set_fade_in_active (yn);
3498 XMLNode &after = ar->get_state();
3499 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
3504 Editor::set_fade_out_active (bool yn)
3506 begin_reversible_command (_("set fade out active"));
3508 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3509 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3515 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3517 XMLNode &before = ar->get_state();
3519 ar->set_fade_out_active (yn);
3521 XMLNode &after = ar->get_state();
3522 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));