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) {
1513 begin_reversible_command (_("insert dragged region"));
1514 XMLNode &before = playlist->get_state();
1515 playlist->add_region (RegionFactory::create (region), where, 1.0);
1516 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1517 commit_reversible_command ();
1521 Editor::insert_region_list_selection (float times)
1523 RouteTimeAxisView *tv = 0;
1524 boost::shared_ptr<Playlist> playlist;
1526 if (clicked_audio_trackview != 0) {
1527 tv = clicked_audio_trackview;
1528 } else if (!selection->tracks.empty()) {
1529 if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
1536 if ((playlist = tv->playlist()) == 0) {
1540 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1542 if (selected->count_selected_rows() != 1) {
1546 TreeView::Selection::ListHandle_Path rows = selected->get_selected_rows ();
1548 /* only one row selected, so rows.begin() is it */
1552 if ((iter = region_list_model->get_iter (*rows.begin()))) {
1554 boost::shared_ptr<Region> region = (*iter)[region_list_columns.region];
1556 begin_reversible_command (_("insert region"));
1557 XMLNode &before = playlist->get_state();
1558 playlist->add_region ((RegionFactory::create (region)), edit_cursor->current_frame, times);
1559 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1560 commit_reversible_command ();
1564 /* BUILT-IN EFFECTS */
1567 Editor::reverse_selection ()
1572 /* GAIN ENVELOPE EDITING */
1575 Editor::edit_envelope ()
1582 Editor::transition_to_rolling (bool fwd)
1588 switch (Config->get_slave_source()) {
1593 /* transport controlled by the master */
1597 if (session->is_auditioning()) {
1598 session->cancel_audition ();
1602 session->request_transport_speed (fwd ? 1.0f : -1.0f);
1606 Editor::toggle_playback (bool with_abort)
1612 switch (Config->get_slave_source()) {
1617 /* transport controlled by the master */
1621 if (session->is_auditioning()) {
1622 session->cancel_audition ();
1626 if (session->transport_rolling()) {
1627 session->request_stop (with_abort);
1628 if (session->get_play_loop()) {
1629 session->request_play_loop (false);
1632 session->request_transport_speed (1.0f);
1637 Editor::play_from_start ()
1639 session->request_locate (session->current_start_frame(), true);
1643 Editor::play_from_edit_cursor ()
1645 session->request_locate (edit_cursor->current_frame, true);
1649 Editor::play_selection ()
1651 if (selection->time.empty()) {
1655 session->request_play_range (true);
1659 Editor::play_selected_region ()
1661 if (!selection->regions.empty()) {
1662 RegionView *rv = *(selection->regions.begin());
1664 session->request_bounded_roll (rv->region()->position(), rv->region()->last_frame());
1669 Editor::loop_selected_region ()
1671 if (!selection->regions.empty()) {
1672 RegionView *rv = *(selection->regions.begin());
1675 if ((tll = transport_loop_location()) != 0) {
1677 tll->set (rv->region()->position(), rv->region()->last_frame());
1679 // enable looping, reposition and start rolling
1681 session->request_play_loop (true);
1682 session->request_locate (tll->start(), false);
1683 session->request_transport_speed (1.0f);
1689 Editor::play_location (Location& location)
1691 if (location.start() <= location.end()) {
1695 session->request_bounded_roll (location.start(), location.end());
1699 Editor::loop_location (Location& location)
1701 if (location.start() <= location.end()) {
1707 if ((tll = transport_loop_location()) != 0) {
1708 tll->set (location.start(), location.end());
1710 // enable looping, reposition and start rolling
1711 session->request_play_loop (true);
1712 session->request_locate (tll->start(), true);
1717 Editor::raise_region ()
1719 selection->foreach_region (&Region::raise);
1723 Editor::raise_region_to_top ()
1725 selection->foreach_region (&Region::raise_to_top);
1729 Editor::lower_region ()
1731 selection->foreach_region (&Region::lower);
1735 Editor::lower_region_to_bottom ()
1737 selection->foreach_region (&Region::lower_to_bottom);
1741 Editor::edit_region ()
1743 if (clicked_regionview == 0) {
1747 clicked_regionview->show_region_editor ();
1751 Editor::rename_region ()
1755 Button ok_button (_("OK"));
1756 Button cancel_button (_("Cancel"));
1758 if (selection->regions.empty()) {
1762 WindowTitle title(Glib::get_application_name());
1763 title += _("Rename Region");
1765 dialog.set_title (title.get_string());
1766 dialog.set_name ("RegionRenameWindow");
1767 dialog.set_size_request (300, -1);
1768 dialog.set_position (Gtk::WIN_POS_MOUSE);
1769 dialog.set_modal (true);
1771 dialog.get_vbox()->set_border_width (10);
1772 dialog.get_vbox()->pack_start (entry);
1773 dialog.get_action_area()->pack_start (ok_button);
1774 dialog.get_action_area()->pack_start (cancel_button);
1776 entry.set_name ("RegionNameDisplay");
1777 ok_button.set_name ("EditorGTKButton");
1778 cancel_button.set_name ("EditorGTKButton");
1780 region_renamed = false;
1782 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1783 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1784 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
1791 if (region_renamed) {
1792 (*selection->regions.begin())->region()->set_name (entry.get_text());
1793 redisplay_regions ();
1798 Editor::rename_region_finished (bool status)
1801 region_renamed = status;
1806 Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Route& route)
1808 if (session->is_auditioning()) {
1809 session->cancel_audition ();
1812 // note: some potential for creativity here, because region doesn't
1813 // have to belong to the playlist that Route is handling
1815 // bool was_soloed = route.soloed();
1817 route.set_solo (true, this);
1819 session->request_bounded_roll (region->position(), region->position() + region->length());
1821 /* XXX how to unset the solo state ? */
1825 Editor::audition_selected_region ()
1827 if (!selection->regions.empty()) {
1828 RegionView* rv = *(selection->regions.begin());
1829 session->audition_region (rv->region());
1834 Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
1836 session->audition_region (region);
1840 Editor::build_interthread_progress_window ()
1842 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
1844 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
1846 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
1847 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
1849 // GTK2FIX: this button needs a modifiable label
1851 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1852 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
1854 interthread_cancel_button.add (interthread_cancel_label);
1856 interthread_progress_window->set_default_size (200, 100);
1860 Editor::interthread_cancel_clicked ()
1862 if (current_interthread_info) {
1863 current_interthread_info->cancel = true;
1868 Editor::region_from_selection ()
1870 if (clicked_trackview == 0) {
1874 if (selection->time.empty()) {
1878 nframes_t start = selection->time[clicked_selection].start;
1879 nframes_t end = selection->time[clicked_selection].end;
1881 nframes_t selection_cnt = end - start + 1;
1883 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1884 boost::shared_ptr<AudioRegion> current;
1885 boost::shared_ptr<Region> current_r;
1886 boost::shared_ptr<Playlist> pl;
1888 nframes_t internal_start;
1891 if ((pl = (*i)->playlist()) == 0) {
1895 if ((current_r = pl->top_region_at (start)) == 0) {
1899 current = boost::dynamic_pointer_cast<AudioRegion> (current_r);
1900 // FIXME: audio only
1902 internal_start = start - current->position();
1903 session->region_name (new_name, current->name(), true);
1904 boost::shared_ptr<Region> region (RegionFactory::create (current, internal_start, selection_cnt, new_name));
1910 Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& new_regions)
1912 if (selection->time.empty() || selection->tracks.empty()) {
1916 nframes_t start = selection->time[clicked_selection].start;
1917 nframes_t end = selection->time[clicked_selection].end;
1919 sort_track_selection ();
1921 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1923 boost::shared_ptr<AudioRegion> current;
1924 boost::shared_ptr<Region> current_r;
1925 boost::shared_ptr<Playlist> playlist;
1926 nframes_t internal_start;
1929 if ((playlist = (*i)->playlist()) == 0) {
1933 if ((current_r = playlist->top_region_at(start)) == 0) {
1937 if ((current = boost::dynamic_pointer_cast<AudioRegion>(current_r)) == 0) {
1941 internal_start = start - current->position();
1942 session->region_name (new_name, current->name(), true);
1944 new_regions.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (current, internal_start, end - start + 1, new_name)));
1949 Editor::split_multichannel_region ()
1951 if (selection->regions.empty()) {
1955 vector<boost::shared_ptr<AudioRegion> > v;
1957 for (list<RegionView*>::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
1959 AudioRegionView* arv = dynamic_cast<AudioRegionView*>(*x);
1961 if (!arv || arv->audio_region()->n_channels() < 2) {
1965 (arv)->audio_region()->separate_by_channel (*session, v);
1970 Editor::new_region_from_selection ()
1972 region_from_selection ();
1973 cancel_selection ();
1977 Editor::separate_region_from_selection ()
1979 bool doing_undo = false;
1981 if (selection->time.empty()) {
1985 boost::shared_ptr<Playlist> playlist;
1987 sort_track_selection ();
1989 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1991 AudioTimeAxisView* atv;
1993 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
1995 if (atv->is_audio_track()) {
1997 /* no edits to destructive tracks */
1999 if (atv->audio_track()->audio_diskstream()->destructive()) {
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 /* no edits to destructive tracks */
2057 if (atv->audio_track()->audio_diskstream()->destructive()) {
2061 if ((playlist = atv->playlist()) != 0) {
2064 begin_reversible_command (_("separate"));
2068 before = &(playlist->get_state());
2071 /* XXX need to consider musical time selections here at some point */
2073 double speed = atv->get_diskstream()->speed();
2076 playlist->partition ((nframes_t)(loc.start() * speed), (nframes_t)(loc.end() * speed), true);
2078 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2084 if (doing_undo) commit_reversible_command ();
2088 Editor::crop_region_to_selection ()
2090 if (selection->time.empty() || selection->tracks.empty()) {
2094 vector<boost::shared_ptr<Playlist> > playlists;
2095 boost::shared_ptr<Playlist> playlist;
2097 sort_track_selection ();
2099 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2101 AudioTimeAxisView* atv;
2103 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2105 if (atv->is_audio_track()) {
2107 /* no edits to destructive tracks */
2109 if (atv->audio_track()->audio_diskstream()->destructive()) {
2113 if ((playlist = atv->playlist()) != 0) {
2114 playlists.push_back (playlist);
2120 if (playlists.empty()) {
2128 begin_reversible_command (_("trim to selection"));
2130 for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2132 boost::shared_ptr<Region> region;
2134 start = selection->time.start();
2136 if ((region = (*i)->top_region_at(start)) == 0) {
2140 /* now adjust lengths to that we do the right thing
2141 if the selection extends beyond the region
2144 start = max (start, region->position());
2145 if (max_frames - start < region->length()) {
2146 end = start + region->length() - 1;
2150 end = min (selection->time.end_frame(), end);
2151 cnt = end - start + 1;
2153 XMLNode &before = (*i)->get_state();
2154 region->trim_to (start, cnt, this);
2155 XMLNode &after = (*i)->get_state();
2156 session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
2159 commit_reversible_command ();
2163 Editor::region_fill_track ()
2167 if (!session || selection->regions.empty()) {
2171 end = session->current_end_frame ();
2173 begin_reversible_command (_("region fill"));
2175 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2177 boost::shared_ptr<Region> region ((*i)->region());
2180 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
2184 boost::shared_ptr<Playlist> pl = region->playlist();
2186 if (end <= region->last_frame()) {
2190 double times = (double) (end - region->last_frame()) / (double) region->length();
2196 XMLNode &before = pl->get_state();
2197 pl->add_region (RegionFactory::create (ar), ar->last_frame(), times);
2198 session->add_command (new MementoCommand<Playlist>(*pl, &before, &pl->get_state()));
2201 commit_reversible_command ();
2205 Editor::region_fill_selection ()
2207 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2211 if (selection->time.empty()) {
2216 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2218 if (selected->count_selected_rows() != 1) {
2222 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2223 boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
2225 nframes_t start = selection->time[clicked_selection].start;
2226 nframes_t end = selection->time[clicked_selection].end;
2228 boost::shared_ptr<Playlist> playlist;
2230 if (selection->tracks.empty()) {
2234 nframes_t selection_length = end - start;
2235 float times = (float)selection_length / region->length();
2237 begin_reversible_command (_("fill selection"));
2239 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2241 if ((playlist = (*i)->playlist()) == 0) {
2245 XMLNode &before = playlist->get_state();
2246 playlist->add_region (RegionFactory::create (region), start, times);
2247 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
2250 commit_reversible_command ();
2254 Editor::set_a_regions_sync_position (boost::shared_ptr<Region> region, nframes_t position)
2257 if (!region->covers (position)) {
2258 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2261 begin_reversible_command (_("set region sync position"));
2262 XMLNode &before = region->playlist()->get_state();
2263 region->set_sync_position (position);
2264 XMLNode &after = region->playlist()->get_state();
2265 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2266 commit_reversible_command ();
2270 Editor::set_region_sync_from_edit_cursor ()
2272 if (clicked_regionview == 0) {
2276 if (!clicked_regionview->region()->covers (edit_cursor->current_frame)) {
2277 error << _("Place the edit cursor at the desired sync point") << endmsg;
2281 boost::shared_ptr<Region> region (clicked_regionview->region());
2282 begin_reversible_command (_("set sync from edit cursor"));
2283 XMLNode &before = region->playlist()->get_state();
2284 region->set_sync_position (edit_cursor->current_frame);
2285 XMLNode &after = region->playlist()->get_state();
2286 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2287 commit_reversible_command ();
2291 Editor::remove_region_sync ()
2293 if (clicked_regionview) {
2294 boost::shared_ptr<Region> region (clicked_regionview->region());
2295 begin_reversible_command (_("remove sync"));
2296 XMLNode &before = region->playlist()->get_state();
2297 region->clear_sync_position ();
2298 XMLNode &after = region->playlist()->get_state();
2299 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2300 commit_reversible_command ();
2305 Editor::naturalize ()
2307 if (selection->regions.empty()) {
2310 begin_reversible_command (_("naturalize"));
2311 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2312 XMLNode &before = (*i)->region()->get_state();
2313 (*i)->region()->move_to_natural_position (this);
2314 XMLNode &after = (*i)->region()->get_state();
2315 session->add_command (new MementoCommand<Region>(*((*i)->region().get()), &before, &after));
2317 commit_reversible_command ();
2321 Editor::align (RegionPoint what)
2323 align_selection (what, edit_cursor->current_frame);
2327 Editor::align_relative (RegionPoint what)
2329 align_selection_relative (what, edit_cursor->current_frame);
2332 struct RegionSortByTime {
2333 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2334 return a->region()->position() < b->region()->position();
2339 Editor::align_selection_relative (RegionPoint point, nframes_t position)
2341 if (selection->regions.empty()) {
2349 list<RegionView*> sorted;
2350 selection->regions.by_position (sorted);
2351 boost::shared_ptr<Region> r ((*sorted.begin())->region());
2355 pos = r->first_frame ();
2359 pos = r->last_frame();
2363 pos = r->adjust_to_sync (r->first_frame());
2367 if (pos > position) {
2368 distance = pos - position;
2371 distance = position - pos;
2375 begin_reversible_command (_("align selection (relative)"));
2377 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2379 boost::shared_ptr<Region> region ((*i)->region());
2381 XMLNode &before = region->playlist()->get_state();
2384 region->set_position (region->position() + distance, this);
2386 region->set_position (region->position() - distance, this);
2389 XMLNode &after = region->playlist()->get_state();
2390 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2394 commit_reversible_command ();
2398 Editor::align_selection (RegionPoint point, nframes_t position)
2400 if (selection->regions.empty()) {
2404 begin_reversible_command (_("align selection"));
2406 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2407 align_region_internal ((*i)->region(), point, position);
2410 commit_reversible_command ();
2414 Editor::align_region (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2416 begin_reversible_command (_("align region"));
2417 align_region_internal (region, point, position);
2418 commit_reversible_command ();
2422 Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2424 XMLNode &before = region->playlist()->get_state();
2428 region->set_position (region->adjust_to_sync (position), this);
2432 if (position > region->length()) {
2433 region->set_position (position - region->length(), this);
2438 region->set_position (position, this);
2442 XMLNode &after = region->playlist()->get_state();
2443 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2447 Editor::trim_region_to_edit_cursor ()
2449 if (clicked_regionview == 0) {
2453 boost::shared_ptr<Region> region (clicked_regionview->region());
2456 AudioTimeAxisView *atav;
2458 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2459 if (atav->get_diskstream() != 0) {
2460 speed = atav->get_diskstream()->speed();
2464 begin_reversible_command (_("trim to edit"));
2465 XMLNode &before = region->playlist()->get_state();
2466 region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2467 XMLNode &after = region->playlist()->get_state();
2468 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2469 commit_reversible_command ();
2473 Editor::trim_region_from_edit_cursor ()
2475 if (clicked_regionview == 0) {
2479 boost::shared_ptr<Region> region (clicked_regionview->region());
2482 AudioTimeAxisView *atav;
2484 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2485 if (atav->get_diskstream() != 0) {
2486 speed = atav->get_diskstream()->speed();
2490 begin_reversible_command (_("trim to edit"));
2491 XMLNode &before = region->playlist()->get_state();
2492 region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2493 XMLNode &after = region->playlist()->get_state();
2494 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2495 commit_reversible_command ();
2499 Editor::unfreeze_route ()
2501 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2505 clicked_audio_trackview->audio_track()->unfreeze ();
2509 Editor::_freeze_thread (void* arg)
2511 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2512 return static_cast<Editor*>(arg)->freeze_thread ();
2516 Editor::freeze_thread ()
2518 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2523 Editor::freeze_progress_timeout (void *arg)
2525 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2526 return !(current_interthread_info->done || current_interthread_info->cancel);
2530 Editor::freeze_route ()
2532 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2536 InterThreadInfo itt;
2538 if (interthread_progress_window == 0) {
2539 build_interthread_progress_window ();
2542 WindowTitle title(Glib::get_application_name());
2543 title += _("Freeze");
2544 interthread_progress_window->set_title (title.get_string());
2545 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2546 interthread_progress_window->show_all ();
2547 interthread_progress_bar.set_fraction (0.0f);
2548 interthread_progress_label.set_text ("");
2549 interthread_cancel_label.set_text (_("Cancel Freeze"));
2550 current_interthread_info = &itt;
2552 interthread_progress_connection =
2553 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2557 itt.progress = 0.0f;
2559 pthread_attr_t attr;
2560 pthread_attr_init(&attr);
2561 pthread_attr_setstacksize(&attr, 500000);
2563 pthread_create (&itt.thread, &attr, _freeze_thread, this);
2565 pthread_attr_destroy(&attr);
2567 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2569 while (!itt.done && !itt.cancel) {
2570 gtk_main_iteration ();
2573 interthread_progress_connection.disconnect ();
2574 interthread_progress_window->hide_all ();
2575 current_interthread_info = 0;
2576 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2580 Editor::bounce_range_selection ()
2582 if (selection->time.empty()) {
2586 TrackSelection views = selection->tracks;
2588 nframes_t start = selection->time[clicked_selection].start;
2589 nframes_t end = selection->time[clicked_selection].end;
2590 nframes_t cnt = end - start + 1;
2592 begin_reversible_command (_("bounce range"));
2594 for (TrackViewList::iterator i = views.begin(); i != views.end(); ++i) {
2596 AudioTimeAxisView* atv;
2598 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2602 boost::shared_ptr<Playlist> playlist;
2604 if ((playlist = atv->playlist()) == 0) {
2608 InterThreadInfo itt;
2612 itt.progress = false;
2614 XMLNode &before = playlist->get_state();
2615 atv->audio_track()->bounce_range (start, cnt, itt);
2616 XMLNode &after = playlist->get_state();
2617 session->add_command (new MementoCommand<Playlist> (*playlist, &before, &after));
2620 commit_reversible_command ();
2636 Editor::cut_copy (CutCopyOp op)
2638 /* only cancel selection if cut/copy is successful.*/
2650 opname = _("clear");
2654 cut_buffer->clear ();
2656 switch (current_mouse_mode()) {
2658 if (!selection->regions.empty() || !selection->points.empty()) {
2660 begin_reversible_command (opname + _(" objects"));
2662 if (!selection->regions.empty()) {
2664 cut_copy_regions (op);
2667 selection->clear_regions ();
2671 if (!selection->points.empty()) {
2672 cut_copy_points (op);
2675 selection->clear_points ();
2679 commit_reversible_command ();
2684 if (!selection->time.empty()) {
2686 begin_reversible_command (opname + _(" range"));
2687 cut_copy_ranges (op);
2688 commit_reversible_command ();
2691 selection->clear_time ();
2703 Editor::cut_copy_points (CutCopyOp op)
2705 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2707 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2710 atv->cut_copy_clear_objects (selection->points, op);
2715 struct PlaylistState {
2716 boost::shared_ptr<Playlist> playlist;
2720 struct lt_playlist {
2721 bool operator () (const PlaylistState& a, const PlaylistState& b) {
2722 return a.playlist < b.playlist;
2726 struct PlaylistMapping {
2728 boost::shared_ptr<AudioPlaylist> pl;
2730 PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
2734 Editor::cut_copy_regions (CutCopyOp op)
2736 /* we can't use a std::map here because the ordering is important, and we can't trivially sort
2737 a map when we want ordered access to both elements. i think.
2740 vector<PlaylistMapping> pmap;
2742 nframes_t first_position = max_frames;
2744 set<PlaylistState, lt_playlist> freezelist;
2745 pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
2747 /* get ordering correct before we cut/copy */
2749 selection->regions.sort_by_position_and_track ();
2751 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
2753 first_position = min ((*x)->region()->position(), first_position);
2755 if (op == Cut || op == Clear) {
2756 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
2760 PlaylistState before;
2761 before.playlist = pl;
2762 before.before = &pl->get_state();
2764 insert_result = freezelist.insert (before);
2766 if (insert_result.second) {
2772 TimeAxisView* tv = &(*x)->get_trackview();
2773 vector<PlaylistMapping>::iterator z;
2775 for (z = pmap.begin(); z != pmap.end(); ++z) {
2776 if ((*z).tv == tv) {
2781 if (z == pmap.end()) {
2782 pmap.push_back (PlaylistMapping (tv));
2786 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
2788 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
2791 /* impossible, but this handles it for the future */
2795 TimeAxisView& tv = (*x)->get_trackview();
2796 boost::shared_ptr<AudioPlaylist> npl;
2797 RegionSelection::iterator tmp;
2802 vector<PlaylistMapping>::iterator z;
2804 for (z = pmap.begin(); z != pmap.end(); ++z) {
2805 if ((*z).tv == &tv) {
2810 assert (z != pmap.end());
2813 npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
2820 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
2821 boost::shared_ptr<Region> _xx;
2827 _xx = RegionFactory::create ((*x)->region());
2828 npl->add_region (_xx, (*x)->region()->position() - first_position);
2829 pl->remove_region (((*x)->region()));
2835 /* copy region before adding, so we're not putting same object into two different playlists */
2836 npl->add_region (RegionFactory::create ((*x)->region()), (*x)->region()->position() - first_position);
2840 pl->remove_region (((*x)->region()));
2847 list<boost::shared_ptr<Playlist> > foo;
2849 /* the pmap is in the same order as the tracks in which selected regions occured */
2851 for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2853 foo.push_back ((*i).pl);
2858 cut_buffer->set (foo);
2861 for (set<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2862 (*pl).playlist->thaw ();
2863 session->add_command (new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
2868 Editor::cut_copy_ranges (CutCopyOp op)
2870 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2871 (*i)->cut_copy_clear (*selection, op);
2876 Editor::paste (float times)
2878 paste_internal (edit_cursor->current_frame, times);
2882 Editor::mouse_paste ()
2887 track_canvas.get_pointer (x, y);
2888 track_canvas.window_to_world (x, y, wx, wy);
2889 wx += horizontal_adjustment.get_value();
2890 wy += vertical_adjustment.get_value();
2893 event.type = GDK_BUTTON_RELEASE;
2894 event.button.x = wx;
2895 event.button.y = wy;
2897 nframes_t where = event_frame (&event, 0, 0);
2899 paste_internal (where, 1);
2903 Editor::paste_internal (nframes_t position, float times)
2905 bool commit = false;
2907 if (cut_buffer->empty() || selection->tracks.empty()) {
2911 if (position == max_frames) {
2912 position = edit_cursor->current_frame;
2915 begin_reversible_command (_("paste"));
2917 TrackSelection::iterator i;
2920 /* get everything in the correct order */
2922 sort_track_selection ();
2924 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
2926 /* undo/redo is handled by individual tracks */
2928 if ((*i)->paste (position, times, *cut_buffer, nth)) {
2934 commit_reversible_command ();
2939 Editor::paste_named_selection (float times)
2941 TrackSelection::iterator t;
2943 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
2945 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
2949 TreeModel::iterator i = selected->get_selected();
2950 NamedSelection* ns = (*i)[named_selection_columns.selection];
2952 list<boost::shared_ptr<Playlist> >::iterator chunk;
2953 list<boost::shared_ptr<Playlist> >::iterator tmp;
2955 chunk = ns->playlists.begin();
2957 begin_reversible_command (_("paste chunk"));
2959 sort_track_selection ();
2961 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
2963 AudioTimeAxisView* atv;
2964 boost::shared_ptr<Playlist> pl;
2965 boost::shared_ptr<AudioPlaylist> apl;
2967 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
2971 if ((pl = atv->playlist()) == 0) {
2975 if ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) == 0) {
2982 XMLNode &before = apl->get_state();
2983 apl->paste (*chunk, edit_cursor->current_frame, times);
2984 session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
2986 if (tmp != ns->playlists.end()) {
2991 commit_reversible_command();
2995 Editor::duplicate_some_regions (RegionSelection& regions, float times)
2997 boost::shared_ptr<Playlist> playlist;
2998 RegionSelection sel = regions; // clear (below) will clear the argument list
3000 begin_reversible_command (_("duplicate region"));
3002 selection->clear_regions ();
3004 for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3006 boost::shared_ptr<Region> r ((*i)->region());
3008 TimeAxisView& tv = (*i)->get_time_axis_view();
3009 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3010 sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3012 playlist = (*i)->region()->playlist();
3013 XMLNode &before = playlist->get_state();
3014 playlist->duplicate (r, r->last_frame(), times);
3015 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
3019 if (latest_regionview) {
3020 selection->add (latest_regionview);
3025 commit_reversible_command ();
3029 Editor::duplicate_selection (float times)
3031 if (selection->time.empty() || selection->tracks.empty()) {
3035 boost::shared_ptr<Playlist> playlist;
3036 vector<boost::shared_ptr<AudioRegion> > new_regions;
3037 vector<boost::shared_ptr<AudioRegion> >::iterator ri;
3039 create_region_from_selection (new_regions);
3041 if (new_regions.empty()) {
3045 begin_reversible_command (_("duplicate selection"));
3047 ri = new_regions.begin();
3049 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3050 if ((playlist = (*i)->playlist()) == 0) {
3053 XMLNode &before = playlist->get_state();
3054 playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
3055 XMLNode &after = playlist->get_state();
3056 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3059 if (ri == new_regions.end()) {
3064 commit_reversible_command ();
3068 Editor::reset_point_selection ()
3070 /* reset all selected points to the relevant default value */
3072 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3074 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3077 atv->reset_objects (selection->points);
3083 Editor::center_playhead ()
3085 float page = canvas_width * frames_per_unit;
3087 center_screen_internal (playhead_cursor->current_frame, page);
3091 Editor::center_edit_cursor ()
3093 float page = canvas_width * frames_per_unit;
3095 center_screen_internal (edit_cursor->current_frame, page);
3099 Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
3101 begin_reversible_command (_("clear playlist"));
3102 XMLNode &before = playlist->get_state();
3104 XMLNode &after = playlist->get_state();
3105 session->add_command (new MementoCommand<Playlist>(*playlist.get(), &before, &after));
3106 commit_reversible_command ();
3110 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3112 boost::shared_ptr<Playlist> playlist;
3114 nframes_t next_distance;
3117 if (use_edit_cursor) {
3118 start = edit_cursor->current_frame;
3123 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3127 if (selection->tracks.empty()) {
3131 begin_reversible_command (_("nudge track"));
3133 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3135 if ((playlist = (*i)->playlist()) == 0) {
3139 XMLNode &before = playlist->get_state();
3140 playlist->nudge_after (start, distance, forwards);
3141 XMLNode &after = playlist->get_state();
3142 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3145 commit_reversible_command ();
3149 Editor::remove_last_capture ()
3151 vector<string> choices;
3158 if (Config->get_verify_remove_last_capture()) {
3159 prompt = _("Do you really want to destroy the last capture?"
3160 "\n(This is destructive and cannot be undone)");
3162 choices.push_back (_("No, do nothing."));
3163 choices.push_back (_("Yes, destroy it."));
3165 Gtkmm2ext::Choice prompter (prompt, choices);
3167 if (prompter.run () == 1) {
3168 session->remove_last_capture ();
3172 session->remove_last_capture();
3177 Editor::normalize_region ()
3183 if (selection->regions.empty()) {
3187 begin_reversible_command (_("normalize"));
3189 track_canvas.get_window()->set_cursor (*wait_cursor);
3192 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3193 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3196 XMLNode &before = arv->region()->get_state();
3197 arv->audio_region()->normalize_to (0.0f);
3198 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3201 commit_reversible_command ();
3202 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3207 Editor::denormalize_region ()
3213 if (selection->regions.empty()) {
3217 begin_reversible_command ("denormalize");
3219 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3220 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3223 XMLNode &before = arv->region()->get_state();
3224 arv->audio_region()->set_scale_amplitude (1.0f);
3225 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3228 commit_reversible_command ();
3233 Editor::reverse_region ()
3239 Reverse rev (*session);
3240 apply_filter (rev, _("reverse regions"));
3244 Editor::apply_filter (AudioFilter& filter, string command)
3246 if (selection->regions.empty()) {
3250 begin_reversible_command (command);
3252 track_canvas.get_window()->set_cursor (*wait_cursor);
3255 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
3256 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3260 boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
3262 RegionSelection::iterator tmp;
3267 if (arv->audio_region()->apply (filter) == 0) {
3269 XMLNode &before = playlist->get_state();
3270 playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
3271 XMLNode &after = playlist->get_state();
3272 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
3280 commit_reversible_command ();
3281 selection->regions.clear ();
3284 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3288 Editor::region_selection_op (void (Region::*pmf)(void))
3290 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3291 Region* region = (*i)->region().get();
3298 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3300 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3301 Region* region = (*i)->region().get();
3302 (region->*pmf)(arg);
3307 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3309 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3310 Region* region = (*i)->region().get();
3316 Editor::external_edit_region ()
3318 if (!clicked_regionview) {
3326 Editor::brush (nframes_t pos)
3328 RegionSelection sel;
3331 if (selection->regions.empty()) {
3332 /* XXX get selection from region list */
3334 sel = selection->regions;
3341 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3342 mouse_brush_insert_region ((*i), pos);
3347 Editor::reset_region_gain_envelopes ()
3349 if (!session || selection->regions.empty()) {
3353 session->begin_reversible_command (_("reset region gain"));
3355 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3356 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3358 AutomationList& alist (arv->audio_region()->envelope());
3359 XMLNode& before (alist.get_state());
3361 arv->audio_region()->set_default_envelope ();
3362 session->add_command (new MementoCommand<AutomationList>(arv->audio_region()->envelope(), &before, &alist.get_state()));
3366 session->commit_reversible_command ();
3370 Editor::toggle_gain_envelope_visibility ()
3372 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3373 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3375 bool x = region_envelope_visible_item->get_active();
3376 if (x != arv->envelope_visible()) {
3377 arv->set_envelope_visible (x);
3384 Editor::toggle_gain_envelope_active ()
3386 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3387 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3389 bool x = region_envelope_active_item->get_active();
3390 if (x != arv->audio_region()->envelope_active()) {
3391 arv->audio_region()->set_envelope_active (x);
3398 Editor::toggle_region_lock ()
3400 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3401 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3403 bool x = region_lock_item->get_active();
3404 if (x != arv->audio_region()->locked()) {
3405 arv->audio_region()->set_locked (x);
3412 Editor::toggle_region_mute ()
3414 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3415 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3417 bool x = region_mute_item->get_active();
3418 if (x != arv->audio_region()->muted()) {
3419 arv->audio_region()->set_muted (x);
3426 Editor::toggle_region_opaque ()
3428 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3429 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3431 bool x = region_opaque_item->get_active();
3432 if (x != arv->audio_region()->opaque()) {
3433 arv->audio_region()->set_opaque (x);
3440 Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
3442 begin_reversible_command (_("set fade in shape"));
3444 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3445 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3451 AutomationList& alist = tmp->audio_region()->fade_in();
3452 XMLNode &before = alist.get_state();
3454 tmp->audio_region()->set_fade_in_shape (shape);
3456 XMLNode &after = alist.get_state();
3457 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3460 commit_reversible_command ();
3464 Editor::set_fade_out_shape (AudioRegion::FadeShape shape)
3466 begin_reversible_command (_("set fade out shape"));
3468 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3469 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3475 AutomationList& alist = tmp->audio_region()->fade_out();
3476 XMLNode &before = alist.get_state();
3478 tmp->audio_region()->set_fade_out_shape (shape);
3480 XMLNode &after = alist.get_state();
3481 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3484 commit_reversible_command ();
3488 Editor::set_fade_in_active (bool yn)
3490 begin_reversible_command (_("set fade in active"));
3492 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3493 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3500 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3502 XMLNode &before = ar->get_state();
3504 ar->set_fade_in_active (yn);
3506 XMLNode &after = ar->get_state();
3507 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
3512 Editor::set_fade_out_active (bool yn)
3514 begin_reversible_command (_("set fade out active"));
3516 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3517 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3523 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3525 XMLNode &before = ar->get_state();
3527 ar->set_fade_out_active (yn);
3529 XMLNode &after = ar->get_state();
3530 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));