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.
28 #include <pbd/error.h>
29 #include <pbd/basename.h>
30 #include <pbd/pthread_utils.h>
31 #include <pbd/memento_command.h>
33 #include <gtkmm2ext/utils.h>
34 #include <gtkmm2ext/choice.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 Editing;
73 /***********************************************************************
75 ***********************************************************************/
78 Editor::undo (uint32_t n)
86 Editor::redo (uint32_t n)
94 Editor::ensure_cursor (nframes_t *pos)
96 *pos = edit_cursor->current_frame;
101 Editor::split_region ()
103 split_region_at (edit_cursor->current_frame);
107 Editor::split_region_at (nframes_t where)
109 split_regions_at (where, selection->regions);
113 Editor::split_regions_at (nframes_t where, RegionSelection& regions)
115 begin_reversible_command (_("split"));
118 for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
120 RegionSelection::iterator tmp;
125 boost::shared_ptr<Playlist> pl = (*a)->region()->playlist();
127 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
129 _new_regionviews_show_envelope = arv->envelope_visible();
132 XMLNode &before = pl->get_state();
133 pl->split_region ((*a)->region(), where);
134 XMLNode &after = pl->get_state();
135 session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
141 commit_reversible_command ();
142 _new_regionviews_show_envelope = false;
146 Editor::remove_clicked_region ()
148 if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
152 boost::shared_ptr<Playlist> playlist = clicked_audio_trackview->playlist();
154 begin_reversible_command (_("remove region"));
155 XMLNode &before = playlist->get_state();
156 playlist->remove_region (clicked_regionview->region());
157 XMLNode &after = playlist->get_state();
158 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
159 commit_reversible_command ();
163 Editor::destroy_clicked_region ()
165 uint32_t selected = selection->regions.size();
167 if (!session || !selected) {
171 vector<string> choices;
174 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
175 It cannot be undone\n\
176 Do you really want to destroy %1 ?"),
178 _("these regions") : _("this region")));
180 choices.push_back (_("No, do nothing."));
183 choices.push_back (_("Yes, destroy them."));
185 choices.push_back (_("Yes, destroy it."));
188 Gtkmm2ext::Choice prompter (prompt, choices);
190 if (prompter.run() == 0) { /* first choice */
195 list<boost::shared_ptr<Region> > r;
197 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
198 r.push_back ((*i)->region());
201 session->destroy_regions (r);
205 boost::shared_ptr<Region>
206 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
209 boost::shared_ptr<Region> region;
212 if (selection->time.start () == selection->time.end_frame ()) {
214 /* no current selection-> is there a selected regionview? */
216 if (selection->regions.empty()) {
222 if (!selection->regions.empty()) {
224 rv = *(selection->regions.begin());
225 (*tv) = &rv->get_time_axis_view();
226 region = rv->region();
228 } else if (!selection->tracks.empty()) {
230 (*tv) = selection->tracks.front();
232 RouteTimeAxisView* rtv;
234 if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
235 boost::shared_ptr<Playlist> pl;
237 if ((pl = rtv->playlist()) == 0) {
241 region = pl->top_region_at (start);
249 Editor::extend_selection_to_end_of_region (bool next)
252 boost::shared_ptr<Region> region;
255 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
259 if (region && selection->time.start () == selection->time.end_frame ()) {
260 start = region->position();
262 start = selection->time.start ();
265 /* Try to leave the selection with the same route if possible */
267 if ((tv = selection->time.track) == 0) {
271 begin_reversible_command (_("extend selection"));
272 selection->set (tv, start, region->position() + region->length());
273 commit_reversible_command ();
277 Editor::extend_selection_to_start_of_region (bool previous)
280 boost::shared_ptr<Region> region;
283 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
287 if (region && selection->time.start () == selection->time.end_frame ()) {
288 end = region->position() + region->length();
290 end = selection->time.end_frame ();
293 /* Try to leave the selection with the same route if possible */
295 if ((tv = selection->time.track) == 0) {
299 begin_reversible_command (_("extend selection"));
300 selection->set (tv, region->position(), end);
301 commit_reversible_command ();
306 Editor::nudge_forward (bool next)
309 nframes_t next_distance;
311 if (!session) return;
313 if (!selection->regions.empty()) {
315 begin_reversible_command (_("nudge forward"));
317 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
318 boost::shared_ptr<Region> r ((*i)->region());
320 distance = get_nudge_distance (r->position(), next_distance);
323 distance = next_distance;
326 XMLNode &before = r->playlist()->get_state();
327 r->set_position (r->position() + distance, this);
328 XMLNode &after = r->playlist()->get_state();
329 session->add_command (new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
332 commit_reversible_command ();
335 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
336 session->request_locate (playhead_cursor->current_frame + distance);
341 Editor::nudge_backward (bool next)
344 nframes_t next_distance;
346 if (!session) return;
348 if (!selection->regions.empty()) {
350 begin_reversible_command (_("nudge forward"));
352 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
353 boost::shared_ptr<Region> r ((*i)->region());
355 distance = get_nudge_distance (r->position(), next_distance);
358 distance = next_distance;
361 XMLNode &before = r->playlist()->get_state();
363 if (r->position() > distance) {
364 r->set_position (r->position() - distance, this);
366 r->set_position (0, this);
368 XMLNode &after = r->playlist()->get_state();
369 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
372 commit_reversible_command ();
376 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
378 if (playhead_cursor->current_frame > distance) {
379 session->request_locate (playhead_cursor->current_frame - distance);
381 session->goto_start();
387 Editor::nudge_forward_capture_offset ()
391 if (!session) return;
393 if (!selection->regions.empty()) {
395 begin_reversible_command (_("nudge forward"));
397 distance = session->worst_output_latency();
399 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
400 boost::shared_ptr<Region> r ((*i)->region());
402 XMLNode &before = r->playlist()->get_state();
403 r->set_position (r->position() + distance, this);
404 XMLNode &after = r->playlist()->get_state();
405 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
408 commit_reversible_command ();
414 Editor::nudge_backward_capture_offset ()
418 if (!session) return;
420 if (!selection->regions.empty()) {
422 begin_reversible_command (_("nudge forward"));
424 distance = session->worst_output_latency();
426 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
427 boost::shared_ptr<Region> r ((*i)->region());
429 XMLNode &before = r->playlist()->get_state();
431 if (r->position() > distance) {
432 r->set_position (r->position() - distance, this);
434 r->set_position (0, this);
436 XMLNode &after = r->playlist()->get_state();
437 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
440 commit_reversible_command ();
447 Editor::move_to_start ()
449 session->goto_start ();
453 Editor::move_to_end ()
456 session->request_locate (session->current_end_frame());
460 Editor::build_region_boundary_cache ()
464 boost::shared_ptr<Region> r;
465 TrackViewList tracks;
467 region_boundary_cache.clear ();
474 case SnapToRegionStart:
477 case SnapToRegionEnd:
480 case SnapToRegionSync:
483 case SnapToRegionBoundary:
487 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
492 TimeAxisView *ontrack = 0;
494 while (pos < session->current_end_frame()) {
496 if (!selection->tracks.empty()) {
498 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
502 } else if (clicked_trackview) {
505 t.push_back (clicked_trackview);
507 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
513 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
521 case SnapToRegionStart:
522 rpos = r->first_frame();
524 case SnapToRegionEnd:
525 rpos = r->last_frame();
527 case SnapToRegionSync:
528 rpos = r->adjust_to_sync (r->first_frame());
531 case SnapToRegionBoundary:
532 rpos = r->last_frame();
539 AudioTimeAxisView *atav;
541 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
542 if (atav->get_diskstream() != 0) {
543 speed = atav->get_diskstream()->speed();
547 rpos = track_frame_to_session_frame(rpos, speed);
549 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
550 if (snap_type == SnapToRegionBoundary) {
551 region_boundary_cache.push_back (r->first_frame());
553 region_boundary_cache.push_back (rpos);
560 boost::shared_ptr<Region>
561 Editor::find_next_region (nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
563 TrackViewList::iterator i;
564 nframes_t closest = max_frames;
565 boost::shared_ptr<Region> ret;
569 nframes_t track_frame;
570 AudioTimeAxisView *atav;
572 for (i = tracks.begin(); i != tracks.end(); ++i) {
575 boost::shared_ptr<Region> r;
578 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
579 if (atav->get_diskstream()!=0)
580 track_speed = atav->get_diskstream()->speed();
583 track_frame = session_frame_to_track_frame(frame, track_speed);
585 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
591 rpos = r->first_frame ();
595 rpos = r->last_frame ();
599 rpos = r->adjust_to_sync (r->first_frame());
602 // rpos is a "track frame", converting it to "session frame"
603 rpos = track_frame_to_session_frame(rpos, track_speed);
606 distance = rpos - frame;
608 distance = frame - rpos;
611 if (distance < closest) {
623 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
625 boost::shared_ptr<Region> r;
626 nframes_t pos = cursor->current_frame;
632 TimeAxisView *ontrack = 0;
634 // so we don't find the current region again..
638 if (!selection->tracks.empty()) {
640 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
642 } else if (clicked_trackview) {
645 t.push_back (clicked_trackview);
647 r = find_next_region (pos, point, dir, t, &ontrack);
651 r = find_next_region (pos, point, dir, track_views, &ontrack);
660 pos = r->first_frame ();
664 pos = r->last_frame ();
668 pos = r->adjust_to_sync (r->first_frame());
673 AudioTimeAxisView *atav;
675 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
676 if (atav->get_diskstream() != 0) {
677 speed = atav->get_diskstream()->speed();
681 pos = track_frame_to_session_frame(pos, speed);
683 if (cursor == playhead_cursor) {
684 session->request_locate (pos);
686 cursor->set_position (pos);
691 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
693 cursor_to_region_point (cursor, point, 1);
697 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
699 cursor_to_region_point (cursor, point, -1);
703 Editor::cursor_to_selection_start (Cursor *cursor)
706 switch (mouse_mode) {
708 if (!selection->regions.empty()) {
709 pos = selection->regions.start();
714 if (!selection->time.empty()) {
715 pos = selection->time.start ();
723 if (cursor == playhead_cursor) {
724 session->request_locate (pos);
726 cursor->set_position (pos);
731 Editor::cursor_to_selection_end (Cursor *cursor)
735 switch (mouse_mode) {
737 if (!selection->regions.empty()) {
738 pos = selection->regions.end_frame();
743 if (!selection->time.empty()) {
744 pos = selection->time.end_frame ();
752 if (cursor == playhead_cursor) {
753 session->request_locate (pos);
755 cursor->set_position (pos);
760 Editor::scroll_playhead (bool forward)
762 nframes_t pos = playhead_cursor->current_frame;
763 nframes_t delta = (nframes_t) floor (current_page_frames() / 0.8);
766 if (pos == max_frames) {
770 if (pos < max_frames - delta) {
789 session->request_locate (pos);
793 Editor::playhead_backward ()
800 if (get_prefix (prefix, was_floating)) {
804 cnt = (nframes_t) floor (prefix * session->frame_rate ());
806 cnt = (nframes_t) prefix;
810 pos = playhead_cursor->current_frame;
812 if ((nframes_t) pos < cnt) {
818 /* XXX this is completely insane. with the current buffering
819 design, we'll force a complete track buffer flush and
820 reload, just to move 1 sample !!!
823 session->request_locate (pos);
827 Editor::playhead_forward ()
834 if (get_prefix (prefix, was_floating)) {
838 cnt = (nframes_t) floor (prefix * session->frame_rate ());
840 cnt = (nframes_t) floor (prefix);
844 pos = playhead_cursor->current_frame;
846 /* XXX this is completely insane. with the current buffering
847 design, we'll force a complete track buffer flush and
848 reload, just to move 1 sample !!!
851 session->request_locate (pos+cnt);
855 Editor::cursor_align (bool playhead_to_edit)
857 if (playhead_to_edit) {
859 session->request_locate (edit_cursor->current_frame);
862 edit_cursor->set_position (playhead_cursor->current_frame);
867 Editor::edit_cursor_backward ()
874 if (get_prefix (prefix, was_floating)) {
878 cnt = (nframes_t) floor (prefix * session->frame_rate ());
880 cnt = (nframes_t) prefix;
884 pos = edit_cursor->current_frame;
886 if ((nframes_t) pos < cnt) {
892 edit_cursor->set_position (pos);
896 Editor::edit_cursor_forward ()
903 if (get_prefix (prefix, was_floating)) {
907 cnt = (nframes_t) floor (prefix * session->frame_rate ());
909 cnt = (nframes_t) floor (prefix);
913 pos = edit_cursor->current_frame;
914 edit_cursor->set_position (pos+cnt);
918 Editor::goto_frame ()
924 if (get_prefix (prefix, was_floating)) {
929 frame = (nframes_t) floor (prefix * session->frame_rate());
931 frame = (nframes_t) floor (prefix);
934 session->request_locate (frame);
938 Editor::scroll_backward (float pages)
941 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
946 if (get_prefix (prefix, was_floating)) {
947 cnt = (nframes_t) floor (pages * one_page);
950 cnt = (nframes_t) floor (prefix * session->frame_rate());
952 cnt = (nframes_t) floor (prefix * one_page);
956 if (leftmost_frame < cnt) {
959 frame = leftmost_frame - cnt;
962 reset_x_origin (frame);
966 Editor::scroll_forward (float pages)
969 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
974 if (get_prefix (prefix, was_floating)) {
975 cnt = (nframes_t) floor (pages * one_page);
978 cnt = (nframes_t) floor (prefix * session->frame_rate());
980 cnt = (nframes_t) floor (prefix * one_page);
984 if (max_frames - cnt < leftmost_frame) {
985 frame = max_frames - cnt;
987 frame = leftmost_frame + cnt;
990 reset_x_origin (frame);
994 Editor::scroll_tracks_down ()
1000 if (get_prefix (prefix, was_floating)) {
1003 cnt = (int) floor (prefix);
1006 double vert_value = vertical_adjustment.get_value() + (cnt *
1007 vertical_adjustment.get_page_size());
1008 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
1009 vert_value = vertical_adjustment.get_upper() - canvas_height;
1011 vertical_adjustment.set_value (vert_value);
1015 Editor::scroll_tracks_up ()
1021 if (get_prefix (prefix, was_floating)) {
1024 cnt = (int) floor (prefix);
1027 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1031 Editor::scroll_tracks_down_line ()
1034 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1035 double vert_value = adj->get_value() + 20;
1037 if (vert_value>adj->get_upper() - canvas_height) {
1038 vert_value = adj->get_upper() - canvas_height;
1040 adj->set_value (vert_value);
1044 Editor::scroll_tracks_up_line ()
1046 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1047 adj->set_value (adj->get_value() - 20);
1053 Editor::temporal_zoom_step (bool coarser)
1055 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1059 nfpu = frames_per_unit;
1064 nfpu = max(1.0,(nfpu/1.61803399));
1067 temporal_zoom (nfpu);
1071 Editor::temporal_zoom (gdouble fpu)
1073 if (!session) return;
1075 nframes_t current_page = current_page_frames();
1076 nframes_t current_leftmost = leftmost_frame;
1077 nframes_t current_rightmost;
1078 nframes_t current_center;
1080 nframes_t leftmost_after_zoom = 0;
1085 new_page = (nframes_t) floor (canvas_width * nfpu);
1087 switch (zoom_focus) {
1089 leftmost_after_zoom = current_leftmost;
1092 case ZoomFocusRight:
1093 current_rightmost = leftmost_frame + current_page;
1094 if (current_rightmost > new_page) {
1095 leftmost_after_zoom = current_rightmost - new_page;
1097 leftmost_after_zoom = 0;
1101 case ZoomFocusCenter:
1102 current_center = current_leftmost + (current_page/2);
1103 if (current_center > (new_page/2)) {
1104 leftmost_after_zoom = current_center - (new_page / 2);
1106 leftmost_after_zoom = 0;
1110 case ZoomFocusPlayhead:
1111 /* try to keep the playhead in the center */
1112 if (playhead_cursor->current_frame > new_page/2) {
1113 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1115 leftmost_after_zoom = 0;
1120 /* try to keep the edit cursor in the center */
1121 if (edit_cursor->current_frame > new_page/2) {
1122 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1124 leftmost_after_zoom = 0;
1130 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1132 // begin_reversible_command (_("zoom"));
1133 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1134 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1135 // commit_reversible_command ();
1137 reposition_and_zoom (leftmost_after_zoom, nfpu);
1141 Editor::temporal_zoom_selection ()
1143 if (!selection) return;
1145 if (selection->time.empty()) {
1149 nframes_t start = selection->time[clicked_selection].start;
1150 nframes_t end = selection->time[clicked_selection].end;
1152 temporal_zoom_by_frame (start, end, "zoom to selection");
1156 Editor::temporal_zoom_session ()
1158 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1161 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1166 Editor::temporal_zoom_by_frame (nframes_t start, nframes_t end, const string & op)
1168 if (!session) return;
1170 if ((start == 0 && end == 0) || end < start) {
1174 nframes_t range = end - start;
1176 double new_fpu = (double)range / (double)canvas_width;
1179 // while (p2 < new_fpu) {
1184 nframes_t new_page = (nframes_t) floor (canvas_width * new_fpu);
1185 nframes_t middle = (nframes_t) floor( (double)start + ((double)range / 2.0f ));
1186 nframes_t new_leftmost = (nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1188 if (new_leftmost > middle) new_leftmost = 0;
1190 // begin_reversible_command (op);
1191 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1192 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1193 // commit_reversible_command ();
1195 reposition_and_zoom (new_leftmost, new_fpu);
1199 Editor::temporal_zoom_to_frame (bool coarser, nframes_t frame)
1201 if (!session) return;
1203 double range_before = frame - leftmost_frame;
1206 new_fpu = frames_per_unit;
1209 new_fpu *= 1.61803399;
1210 range_before *= 1.61803399;
1212 new_fpu = max(1.0,(new_fpu/1.61803399));
1213 range_before /= 1.61803399;
1216 if (new_fpu == frames_per_unit) return;
1218 nframes_t new_leftmost = frame - (nframes_t)range_before;
1220 if (new_leftmost > frame) new_leftmost = 0;
1222 // begin_reversible_command (_("zoom to frame"));
1223 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1224 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1225 // commit_reversible_command ();
1227 reposition_and_zoom (new_leftmost, new_fpu);
1231 Editor::add_location_from_selection ()
1235 if (selection->time.empty()) {
1239 if (session == 0 || clicked_trackview == 0) {
1243 nframes_t start = selection->time[clicked_selection].start;
1244 nframes_t end = selection->time[clicked_selection].end;
1246 session->locations()->next_available_name(rangename,"selection");
1247 Location *location = new Location (start, end, rangename, Location::IsRangeMarker);
1249 session->begin_reversible_command (_("add marker"));
1250 XMLNode &before = session->locations()->get_state();
1251 session->locations()->add (location, true);
1252 XMLNode &after = session->locations()->get_state();
1253 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1254 session->commit_reversible_command ();
1258 Editor::add_location_from_playhead_cursor ()
1262 nframes_t where = session->audible_frame();
1264 session->locations()->next_available_name(markername,"mark");
1265 Location *location = new Location (where, where, markername, Location::IsMark);
1266 session->begin_reversible_command (_("add marker"));
1267 XMLNode &before = session->locations()->get_state();
1268 session->locations()->add (location, true);
1269 XMLNode &after = session->locations()->get_state();
1270 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1271 session->commit_reversible_command ();
1275 Editor::add_location_from_audio_region ()
1277 if (selection->regions.empty()) {
1281 RegionView* rv = *(selection->regions.begin());
1282 boost::shared_ptr<Region> region = rv->region();
1284 Location *location = new Location (region->position(), region->last_frame(), region->name(), Location::IsRangeMarker);
1285 session->begin_reversible_command (_("add marker"));
1286 XMLNode &before = session->locations()->get_state();
1287 session->locations()->add (location, true);
1288 XMLNode &after = session->locations()->get_state();
1289 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1290 session->commit_reversible_command ();
1294 Editor::select_all_in_track (Selection::Operation op)
1296 list<Selectable *> touched;
1298 if (!clicked_trackview) {
1302 clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1305 case Selection::Toggle:
1306 selection->add (touched);
1308 case Selection::Set:
1309 selection->set (touched);
1311 case Selection::Extend:
1312 /* not defined yet */
1314 case Selection::Add:
1315 selection->add (touched);
1321 Editor::select_all (Selection::Operation op)
1323 list<Selectable *> touched;
1325 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1326 if ((*iter)->hidden()) {
1329 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1331 begin_reversible_command (_("select all"));
1333 case Selection::Add:
1334 case Selection::Toggle:
1335 selection->add (touched);
1337 case Selection::Set:
1338 selection->set (touched);
1340 case Selection::Extend:
1341 /* not defined yet */
1344 commit_reversible_command ();
1348 Editor::invert_selection_in_track ()
1350 list<Selectable *> touched;
1352 if (!clicked_trackview) {
1356 clicked_trackview->get_inverted_selectables (*selection, touched);
1357 selection->set (touched);
1361 Editor::invert_selection ()
1363 list<Selectable *> touched;
1365 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1366 if ((*iter)->hidden()) {
1369 (*iter)->get_inverted_selectables (*selection, touched);
1372 selection->set (touched);
1376 Editor::select_all_within (nframes_t start, nframes_t end, double top, double bot, Selection::Operation op)
1378 list<Selectable*> touched;
1379 list<Selectable*>::size_type n = 0;
1380 TrackViewList touched_tracks;
1382 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1383 if ((*iter)->hidden()) {
1389 (*iter)->get_selectables (start, end, top, bot, touched);
1391 if (n != touched.size()) {
1392 touched_tracks.push_back (*iter);
1396 if (!touched_tracks.empty()) {
1398 case Selection::Add:
1399 selection->add (touched_tracks);
1401 case Selection::Toggle:
1402 selection->toggle (touched_tracks);
1404 case Selection::Set:
1405 selection->set (touched_tracks);
1407 case Selection::Extend:
1408 /* not defined yet */
1413 begin_reversible_command (_("select all within"));
1415 case Selection::Add:
1416 selection->add (touched);
1418 case Selection::Toggle:
1419 selection->toggle (touched);
1421 case Selection::Set:
1422 selection->set (touched);
1424 case Selection::Extend:
1425 /* not defined yet */
1429 commit_reversible_command ();
1430 return !touched.empty();
1434 Editor::set_selection_from_audio_region ()
1436 if (selection->regions.empty()) {
1440 RegionView* rv = *(selection->regions.begin());
1441 boost::shared_ptr<Region> region = rv->region();
1443 begin_reversible_command (_("set selection from region"));
1444 selection->set (0, region->position(), region->last_frame());
1445 commit_reversible_command ();
1447 set_mouse_mode (Editing::MouseRange, false);
1451 Editor::set_selection_from_punch()
1455 if ((location = session->locations()->auto_punch_location()) == 0) {
1459 set_selection_from_range (*location);
1463 Editor::set_selection_from_loop()
1467 if ((location = session->locations()->auto_loop_location()) == 0) {
1470 set_selection_from_range (*location);
1474 Editor::set_selection_from_range (Location& loc)
1476 begin_reversible_command (_("set selection from range"));
1477 selection->set (0, loc.start(), loc.end());
1478 commit_reversible_command ();
1480 set_mouse_mode (Editing::MouseRange, false);
1484 Editor::select_all_selectables_using_time_selection ()
1486 list<Selectable *> touched;
1488 if (selection->time.empty()) {
1492 nframes_t start = selection->time[clicked_selection].start;
1493 nframes_t end = selection->time[clicked_selection].end;
1495 if (end - start < 1) {
1499 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1500 if ((*iter)->hidden()) {
1503 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1506 begin_reversible_command (_("select all from range"));
1507 selection->set (touched);
1508 commit_reversible_command ();
1513 Editor::select_all_selectables_using_punch()
1515 Location* location = session->locations()->auto_punch_location();
1516 list<Selectable *> touched;
1518 if (location == 0 || (location->end() - location->start() <= 1)) {
1522 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1523 if ((*iter)->hidden()) {
1526 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1528 begin_reversible_command (_("select all from punch"));
1529 selection->set (touched);
1530 commit_reversible_command ();
1535 Editor::select_all_selectables_using_loop()
1537 Location* location = session->locations()->auto_loop_location();
1538 list<Selectable *> touched;
1540 if (location == 0 || (location->end() - location->start() <= 1)) {
1544 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1545 if ((*iter)->hidden()) {
1548 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1550 begin_reversible_command (_("select all from loop"));
1551 selection->set (touched);
1552 commit_reversible_command ();
1557 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1561 list<Selectable *> touched;
1564 begin_reversible_command (_("select all after cursor"));
1565 start = cursor->current_frame ;
1566 end = session->current_end_frame();
1568 if (cursor->current_frame > 0) {
1569 begin_reversible_command (_("select all before cursor"));
1571 end = cursor->current_frame - 1;
1577 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1578 if ((*iter)->hidden()) {
1581 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1583 selection->set (touched);
1584 commit_reversible_command ();
1588 Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
1592 list<Selectable *> touched;
1593 bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
1595 if (cursor->current_frame == other_cursor->current_frame) {
1599 begin_reversible_command (_("select all between cursors"));
1600 if (other_cursor_is_first) {
1601 start = other_cursor->current_frame;
1602 end = cursor->current_frame - 1;
1605 start = cursor->current_frame;
1606 end = other_cursor->current_frame - 1;
1609 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1610 if ((*iter)->hidden()) {
1613 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1615 selection->set (touched);
1616 commit_reversible_command ();
1620 Editor::amplitude_zoom_step (bool in)
1634 #ifdef FIX_FOR_CANVAS
1635 /* XXX DO SOMETHING */
1644 Editor::delete_sample_forward ()
1649 Editor::delete_sample_backward ()
1654 Editor::delete_screen ()
1661 Editor::search_backwards ()
1667 Editor::search_forwards ()
1675 Editor::jump_forward_to_mark ()
1681 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1684 session->request_locate (location->start(), session->transport_rolling());
1686 session->request_locate (session->current_end_frame());
1691 Editor::jump_backward_to_mark ()
1697 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1700 session->request_locate (location->start(), session->transport_rolling());
1702 session->goto_start ();
1714 if (get_prefix (prefix, was_floating)) {
1715 pos = session->audible_frame ();
1718 pos = (nframes_t) floor (prefix * session->frame_rate ());
1720 pos = (nframes_t) floor (prefix);
1724 session->locations()->next_available_name(markername,"mark");
1725 session->locations()->add (new Location (pos, 0, markername, Location::IsMark), true);
1729 Editor::clear_markers ()
1732 session->begin_reversible_command (_("clear markers"));
1733 XMLNode &before = session->locations()->get_state();
1734 session->locations()->clear_markers ();
1735 XMLNode &after = session->locations()->get_state();
1736 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1737 session->commit_reversible_command ();
1742 Editor::clear_ranges ()
1745 session->begin_reversible_command (_("clear ranges"));
1746 XMLNode &before = session->locations()->get_state();
1748 Location * looploc = session->locations()->auto_loop_location();
1749 Location * punchloc = session->locations()->auto_punch_location();
1751 session->locations()->clear_ranges ();
1753 if (looploc) session->locations()->add (looploc);
1754 if (punchloc) session->locations()->add (punchloc);
1756 XMLNode &after = session->locations()->get_state();
1757 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1758 session->commit_reversible_command ();
1763 Editor::clear_locations ()
1765 session->begin_reversible_command (_("clear locations"));
1766 XMLNode &before = session->locations()->get_state();
1767 session->locations()->clear ();
1768 XMLNode &after = session->locations()->get_state();
1769 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1770 session->commit_reversible_command ();
1771 session->locations()->clear ();
1775 Editor::unhide_markers ()
1777 for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1778 Location *l = (*i).first;
1779 if (l->is_hidden() && l->is_mark()) {
1780 l->set_hidden(false, this);
1786 Editor::unhide_ranges ()
1788 for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) {
1789 Location *l = (*i).first;
1790 if (l->is_hidden() && l->is_range_marker()) {
1791 l->set_hidden(false, this);
1796 /* INSERT/REPLACE */
1799 Editor::insert_region_list_drag (boost::shared_ptr<AudioRegion> region, int x, int y)
1805 AudioTimeAxisView *atv = 0;
1806 boost::shared_ptr<Playlist> playlist;
1808 track_canvas.window_to_world (x, y, wx, wy);
1809 wx += horizontal_adjustment.get_value();
1810 wy += vertical_adjustment.get_value();
1813 event.type = GDK_BUTTON_RELEASE;
1814 event.button.x = wx;
1815 event.button.y = wy;
1817 where = event_frame (&event, &cx, &cy);
1819 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1820 /* clearly outside canvas area */
1824 if ((tv = trackview_by_y_position (cy)) == 0) {
1828 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1832 if ((playlist = atv->playlist()) == 0) {
1836 cerr << "drop target playlist, UC = " << playlist.use_count() << endl;
1840 begin_reversible_command (_("insert dragged region"));
1841 XMLNode &before = playlist->get_state();
1842 cerr << "pre add target playlist, UC = " << playlist.use_count() << endl;
1843 playlist->add_region (RegionFactory::create (region), where, 1.0);
1844 cerr << "post add target playlist, UC = " << playlist.use_count() << endl;
1845 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1846 commit_reversible_command ();
1848 cerr << "post drop target playlist, UC = " << playlist.use_count() << endl;
1852 Editor::insert_region_list_selection (float times)
1854 RouteTimeAxisView *tv = 0;
1855 boost::shared_ptr<Playlist> playlist;
1857 if (clicked_audio_trackview != 0) {
1858 tv = clicked_audio_trackview;
1859 } else if (!selection->tracks.empty()) {
1860 if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
1867 if ((playlist = tv->playlist()) == 0) {
1871 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1873 if (selected->count_selected_rows() != 1) {
1877 TreeView::Selection::ListHandle_Path rows = selected->get_selected_rows ();
1879 /* only one row selected, so rows.begin() is it */
1883 if ((iter = region_list_model->get_iter (*rows.begin()))) {
1885 boost::shared_ptr<Region> region = (*iter)[region_list_columns.region];
1887 begin_reversible_command (_("insert region"));
1888 XMLNode &before = playlist->get_state();
1889 playlist->add_region ((RegionFactory::create (region)), edit_cursor->current_frame, times);
1890 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1891 commit_reversible_command ();
1895 /* BUILT-IN EFFECTS */
1898 Editor::reverse_selection ()
1903 /* GAIN ENVELOPE EDITING */
1906 Editor::edit_envelope ()
1913 Editor::toggle_playback (bool with_abort)
1919 switch (Config->get_slave_source()) {
1924 /* transport controlled by the master */
1928 if (session->is_auditioning()) {
1929 session->cancel_audition ();
1933 if (session->transport_rolling()) {
1934 session->request_stop (with_abort);
1935 if (session->get_play_loop()) {
1936 session->request_play_loop (false);
1939 session->request_transport_speed (1.0f);
1944 Editor::play_from_start ()
1946 session->request_locate (session->current_start_frame(), true);
1950 Editor::play_from_edit_cursor ()
1952 session->request_locate (edit_cursor->current_frame, true);
1956 Editor::play_selection ()
1958 if (selection->time.empty()) {
1962 session->request_play_range (true);
1966 Editor::play_selected_region ()
1968 if (!selection->regions.empty()) {
1969 RegionView *rv = *(selection->regions.begin());
1971 session->request_bounded_roll (rv->region()->position(), rv->region()->last_frame());
1976 Editor::loop_selected_region ()
1978 if (!selection->regions.empty()) {
1979 RegionView *rv = *(selection->regions.begin());
1982 if ((tll = transport_loop_location()) != 0) {
1984 tll->set (rv->region()->position(), rv->region()->last_frame());
1986 // enable looping, reposition and start rolling
1988 session->request_play_loop (true);
1989 session->request_locate (tll->start(), false);
1990 session->request_transport_speed (1.0f);
1996 Editor::play_location (Location& location)
1998 if (location.start() <= location.end()) {
2002 session->request_bounded_roll (location.start(), location.end());
2006 Editor::loop_location (Location& location)
2008 if (location.start() <= location.end()) {
2014 if ((tll = transport_loop_location()) != 0) {
2015 tll->set (location.start(), location.end());
2017 // enable looping, reposition and start rolling
2018 session->request_play_loop (true);
2019 session->request_locate (tll->start(), true);
2024 Editor::raise_region ()
2026 selection->foreach_region (&Region::raise);
2030 Editor::raise_region_to_top ()
2032 selection->foreach_region (&Region::raise_to_top);
2036 Editor::lower_region ()
2038 selection->foreach_region (&Region::lower);
2042 Editor::lower_region_to_bottom ()
2044 selection->foreach_region (&Region::lower_to_bottom);
2048 Editor::edit_region ()
2050 if (clicked_regionview == 0) {
2054 clicked_regionview->show_region_editor ();
2058 Editor::rename_region ()
2062 Button ok_button (_("OK"));
2063 Button cancel_button (_("Cancel"));
2065 if (selection->regions.empty()) {
2069 dialog.set_title (_("ardour: rename region"));
2070 dialog.set_name ("RegionRenameWindow");
2071 dialog.set_size_request (300, -1);
2072 dialog.set_position (Gtk::WIN_POS_MOUSE);
2073 dialog.set_modal (true);
2075 dialog.get_vbox()->set_border_width (10);
2076 dialog.get_vbox()->pack_start (entry);
2077 dialog.get_action_area()->pack_start (ok_button);
2078 dialog.get_action_area()->pack_start (cancel_button);
2080 entry.set_name ("RegionNameDisplay");
2081 ok_button.set_name ("EditorGTKButton");
2082 cancel_button.set_name ("EditorGTKButton");
2084 region_renamed = false;
2086 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2087 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2088 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
2095 if (region_renamed) {
2096 (*selection->regions.begin())->region()->set_name (entry.get_text());
2097 redisplay_regions ();
2102 Editor::rename_region_finished (bool status)
2105 region_renamed = status;
2110 Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Route& route)
2112 if (session->is_auditioning()) {
2113 session->cancel_audition ();
2116 // note: some potential for creativity here, because region doesn't
2117 // have to belong to the playlist that Route is handling
2119 // bool was_soloed = route.soloed();
2121 route.set_solo (true, this);
2123 session->request_bounded_roll (region->position(), region->position() + region->length());
2125 /* XXX how to unset the solo state ? */
2129 Editor::audition_selected_region ()
2131 if (!selection->regions.empty()) {
2132 RegionView* rv = *(selection->regions.begin());
2133 session->audition_region (rv->region());
2138 Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
2140 session->audition_region (region);
2144 Editor::build_interthread_progress_window ()
2146 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
2148 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
2150 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
2151 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
2153 // GTK2FIX: this button needs a modifiable label
2155 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
2156 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
2158 interthread_cancel_button.add (interthread_cancel_label);
2160 interthread_progress_window->set_default_size (200, 100);
2164 Editor::interthread_cancel_clicked ()
2166 if (current_interthread_info) {
2167 current_interthread_info->cancel = true;
2172 Editor::region_from_selection ()
2174 if (clicked_trackview == 0) {
2178 if (selection->time.empty()) {
2182 nframes_t start = selection->time[clicked_selection].start;
2183 nframes_t end = selection->time[clicked_selection].end;
2185 nframes_t selection_cnt = end - start + 1;
2187 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2188 boost::shared_ptr<AudioRegion> current;
2189 boost::shared_ptr<Region> current_r;
2190 boost::shared_ptr<Playlist> pl;
2192 nframes_t internal_start;
2195 if ((pl = (*i)->playlist()) == 0) {
2199 if ((current_r = pl->top_region_at (start)) == 0) {
2203 current = boost::dynamic_pointer_cast<AudioRegion> (current_r);
2204 // FIXME: audio only
2206 internal_start = start - current->position();
2207 session->region_name (new_name, current->name(), true);
2208 boost::shared_ptr<Region> region (RegionFactory::create (current, internal_start, selection_cnt, new_name));
2214 Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& new_regions)
2216 if (selection->time.empty() || selection->tracks.empty()) {
2220 nframes_t start = selection->time[clicked_selection].start;
2221 nframes_t end = selection->time[clicked_selection].end;
2223 sort_track_selection ();
2225 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2227 boost::shared_ptr<AudioRegion> current;
2228 boost::shared_ptr<Region> current_r;
2229 boost::shared_ptr<Playlist> playlist;
2230 nframes_t internal_start;
2233 if ((playlist = (*i)->playlist()) == 0) {
2237 if ((current_r = playlist->top_region_at(start)) == 0) {
2241 if ((current = boost::dynamic_pointer_cast<AudioRegion>(current_r)) == 0) {
2245 internal_start = start - current->position();
2246 session->region_name (new_name, current->name(), true);
2248 new_regions.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (current, internal_start, end - start + 1, new_name)));
2253 Editor::split_multichannel_region ()
2255 vector<AudioRegion*> v;
2257 AudioRegionView* clicked_arv = dynamic_cast<AudioRegionView*>(clicked_regionview);
2259 if (!clicked_arv || clicked_arv->audio_region()->n_channels() < 2) {
2263 clicked_arv->audio_region()->separate_by_channel (*session, v);
2265 /* nothing else to do, really */
2269 Editor::new_region_from_selection ()
2271 region_from_selection ();
2272 cancel_selection ();
2276 Editor::separate_region_from_selection ()
2278 bool doing_undo = false;
2280 if (selection->time.empty()) {
2284 boost::shared_ptr<Playlist> playlist;
2286 sort_track_selection ();
2288 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2290 AudioTimeAxisView* atv;
2292 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2294 if (atv->is_audio_track()) {
2296 if ((playlist = atv->playlist()) != 0) {
2298 begin_reversible_command (_("separate"));
2303 before = &(playlist->get_state());
2305 /* XXX need to consider musical time selections here at some point */
2307 double speed = atv->get_diskstream()->speed();
2309 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2310 playlist->partition ((nframes_t)((*t).start * speed), (nframes_t)((*t).end * speed), true);
2314 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2320 if (doing_undo) commit_reversible_command ();
2324 Editor::separate_regions_using_location (Location& loc)
2326 bool doing_undo = false;
2328 if (loc.is_mark()) {
2332 boost::shared_ptr<Playlist> playlist;
2334 /* XXX i'm unsure as to whether this should operate on selected tracks only
2335 or the entire enchillada. uncomment the below line to correct the behaviour
2336 (currently set for all tracks)
2339 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2340 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2342 AudioTimeAxisView* atv;
2344 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2346 if (atv->is_audio_track()) {
2348 if ((playlist = atv->playlist()) != 0) {
2351 begin_reversible_command (_("separate"));
2355 before = &(playlist->get_state());
2358 /* XXX need to consider musical time selections here at some point */
2360 double speed = atv->get_diskstream()->speed();
2363 playlist->partition ((nframes_t)(loc.start() * speed), (nframes_t)(loc.end() * speed), true);
2365 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2371 if (doing_undo) commit_reversible_command ();
2375 Editor::crop_region_to_selection ()
2377 if (selection->time.empty()) {
2381 vector<boost::shared_ptr<Playlist> > playlists;
2382 boost::shared_ptr<Playlist> playlist;
2384 if (clicked_trackview != 0) {
2386 if ((playlist = clicked_trackview->playlist()) == 0) {
2390 playlists.push_back (playlist);
2394 sort_track_selection ();
2396 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2398 AudioTimeAxisView* atv;
2400 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2402 if (atv->is_audio_track()) {
2404 if ((playlist = atv->playlist()) != 0) {
2405 playlists.push_back (playlist);
2412 if (!playlists.empty()) {
2418 begin_reversible_command (_("trim to selection"));
2420 for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2422 boost::shared_ptr<Region> region;
2424 start = selection->time.start();
2426 if ((region = (*i)->top_region_at(start)) == 0) {
2430 /* now adjust lengths to that we do the right thing
2431 if the selection extends beyond the region
2434 start = max (start, region->position());
2435 end = min (selection->time.end_frame(), start + region->length() - 1);
2436 cnt = end - start + 1;
2438 XMLNode &before = (*i)->get_state();
2439 region->trim_to (start, cnt, this);
2440 XMLNode &after = (*i)->get_state();
2441 session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
2444 commit_reversible_command ();
2449 Editor::region_fill_track ()
2453 if (!session || selection->regions.empty()) {
2457 end = session->current_end_frame ();
2459 begin_reversible_command (_("region fill"));
2461 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2463 boost::shared_ptr<Region> region ((*i)->region());
2466 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
2470 boost::shared_ptr<Playlist> pl = region->playlist();
2472 if (end <= region->last_frame()) {
2476 double times = (double) (end - region->last_frame()) / (double) region->length();
2482 XMLNode &before = pl->get_state();
2483 pl->add_region (RegionFactory::create (ar), ar->last_frame(), times);
2484 session->add_command (new MementoCommand<Playlist>(*pl, &before, &pl->get_state()));
2487 commit_reversible_command ();
2491 Editor::region_fill_selection ()
2493 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2497 if (selection->time.empty()) {
2502 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2504 if (selected->count_selected_rows() != 1) {
2508 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2509 boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
2511 nframes_t start = selection->time[clicked_selection].start;
2512 nframes_t end = selection->time[clicked_selection].end;
2514 boost::shared_ptr<Playlist> playlist;
2516 if (selection->tracks.empty()) {
2520 nframes_t selection_length = end - start;
2521 float times = (float)selection_length / region->length();
2523 begin_reversible_command (_("fill selection"));
2525 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2527 if ((playlist = (*i)->playlist()) == 0) {
2531 XMLNode &before = playlist->get_state();
2532 playlist->add_region (RegionFactory::create (region), start, times);
2533 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
2536 commit_reversible_command ();
2540 Editor::set_a_regions_sync_position (boost::shared_ptr<Region> region, nframes_t position)
2543 if (!region->covers (position)) {
2544 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2547 begin_reversible_command (_("set region sync position"));
2548 XMLNode &before = region->playlist()->get_state();
2549 region->set_sync_position (position);
2550 XMLNode &after = region->playlist()->get_state();
2551 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2552 commit_reversible_command ();
2556 Editor::set_region_sync_from_edit_cursor ()
2558 if (clicked_regionview == 0) {
2562 if (!clicked_regionview->region()->covers (edit_cursor->current_frame)) {
2563 error << _("Place the edit cursor at the desired sync point") << endmsg;
2567 boost::shared_ptr<Region> region (clicked_regionview->region());
2568 begin_reversible_command (_("set sync from edit cursor"));
2569 XMLNode &before = region->playlist()->get_state();
2570 region->set_sync_position (edit_cursor->current_frame);
2571 XMLNode &after = region->playlist()->get_state();
2572 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2573 commit_reversible_command ();
2577 Editor::remove_region_sync ()
2579 if (clicked_regionview) {
2580 boost::shared_ptr<Region> region (clicked_regionview->region());
2581 begin_reversible_command (_("remove sync"));
2582 XMLNode &before = region->playlist()->get_state();
2583 region->clear_sync_position ();
2584 XMLNode &after = region->playlist()->get_state();
2585 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2586 commit_reversible_command ();
2591 Editor::naturalize ()
2593 if (selection->regions.empty()) {
2596 begin_reversible_command (_("naturalize"));
2597 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2598 XMLNode &before = (*i)->region()->get_state();
2599 (*i)->region()->move_to_natural_position (this);
2600 XMLNode &after = (*i)->region()->get_state();
2601 session->add_command (new MementoCommand<Region>(*((*i)->region().get()), &before, &after));
2603 commit_reversible_command ();
2607 Editor::align (RegionPoint what)
2609 align_selection (what, edit_cursor->current_frame);
2613 Editor::align_relative (RegionPoint what)
2615 align_selection_relative (what, edit_cursor->current_frame);
2618 struct RegionSortByTime {
2619 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2620 return a->region()->position() < b->region()->position();
2625 Editor::align_selection_relative (RegionPoint point, nframes_t position)
2627 if (selection->regions.empty()) {
2635 list<RegionView*> sorted;
2636 selection->regions.by_position (sorted);
2637 boost::shared_ptr<Region> r ((*sorted.begin())->region());
2641 pos = r->first_frame ();
2645 pos = r->last_frame();
2649 pos = r->adjust_to_sync (r->first_frame());
2653 if (pos > position) {
2654 distance = pos - position;
2657 distance = position - pos;
2661 begin_reversible_command (_("align selection (relative)"));
2663 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2665 boost::shared_ptr<Region> region ((*i)->region());
2667 XMLNode &before = region->playlist()->get_state();
2670 region->set_position (region->position() + distance, this);
2672 region->set_position (region->position() - distance, this);
2675 XMLNode &after = region->playlist()->get_state();
2676 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2680 commit_reversible_command ();
2684 Editor::align_selection (RegionPoint point, nframes_t position)
2686 if (selection->regions.empty()) {
2690 begin_reversible_command (_("align selection"));
2692 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2693 align_region_internal ((*i)->region(), point, position);
2696 commit_reversible_command ();
2700 Editor::align_region (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2702 begin_reversible_command (_("align region"));
2703 align_region_internal (region, point, position);
2704 commit_reversible_command ();
2708 Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2710 XMLNode &before = region->playlist()->get_state();
2714 region->set_position (region->adjust_to_sync (position), this);
2718 if (position > region->length()) {
2719 region->set_position (position - region->length(), this);
2724 region->set_position (position, this);
2728 XMLNode &after = region->playlist()->get_state();
2729 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2733 Editor::trim_region_to_edit_cursor ()
2735 if (clicked_regionview == 0) {
2739 boost::shared_ptr<Region> region (clicked_regionview->region());
2742 AudioTimeAxisView *atav;
2744 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2745 if (atav->get_diskstream() != 0) {
2746 speed = atav->get_diskstream()->speed();
2750 begin_reversible_command (_("trim to edit"));
2751 XMLNode &before = region->playlist()->get_state();
2752 region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2753 XMLNode &after = region->playlist()->get_state();
2754 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2755 commit_reversible_command ();
2759 Editor::trim_region_from_edit_cursor ()
2761 if (clicked_regionview == 0) {
2765 boost::shared_ptr<Region> region (clicked_regionview->region());
2768 AudioTimeAxisView *atav;
2770 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2771 if (atav->get_diskstream() != 0) {
2772 speed = atav->get_diskstream()->speed();
2776 begin_reversible_command (_("trim to edit"));
2777 XMLNode &before = region->playlist()->get_state();
2778 region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2779 XMLNode &after = region->playlist()->get_state();
2780 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2781 commit_reversible_command ();
2785 Editor::unfreeze_route ()
2787 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2791 clicked_audio_trackview->audio_track()->unfreeze ();
2795 Editor::_freeze_thread (void* arg)
2797 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2798 return static_cast<Editor*>(arg)->freeze_thread ();
2802 Editor::freeze_thread ()
2804 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2809 Editor::freeze_progress_timeout (void *arg)
2811 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2812 return !(current_interthread_info->done || current_interthread_info->cancel);
2816 Editor::freeze_route ()
2818 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2822 InterThreadInfo itt;
2824 if (interthread_progress_window == 0) {
2825 build_interthread_progress_window ();
2828 interthread_progress_window->set_title (_("ardour: freeze"));
2829 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2830 interthread_progress_window->show_all ();
2831 interthread_progress_bar.set_fraction (0.0f);
2832 interthread_progress_label.set_text ("");
2833 interthread_cancel_label.set_text (_("Cancel Freeze"));
2834 current_interthread_info = &itt;
2836 interthread_progress_connection =
2837 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2841 itt.progress = 0.0f;
2843 pthread_attr_t attr;
2844 pthread_attr_init(&attr);
2845 pthread_attr_setstacksize(&attr, 500000);
2847 pthread_create (&itt.thread, &attr, _freeze_thread, this);
2849 pthread_attr_destroy(&attr);
2851 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2853 while (!itt.done && !itt.cancel) {
2854 gtk_main_iteration ();
2857 interthread_progress_connection.disconnect ();
2858 interthread_progress_window->hide_all ();
2859 current_interthread_info = 0;
2860 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2864 Editor::bounce_range_selection ()
2866 if (selection->time.empty()) {
2870 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2872 nframes_t start = selection->time[clicked_selection].start;
2873 nframes_t end = selection->time[clicked_selection].end;
2874 nframes_t cnt = end - start + 1;
2876 begin_reversible_command (_("bounce range"));
2878 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2880 AudioTimeAxisView* atv;
2882 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2886 boost::shared_ptr<Playlist> playlist;
2888 if ((playlist = atv->playlist()) == 0) {
2892 InterThreadInfo itt;
2896 itt.progress = false;
2898 XMLNode &before = playlist->get_state();
2899 atv->audio_track()->bounce_range (start, cnt, itt);
2900 XMLNode &after = playlist->get_state();
2901 session->add_command (new MementoCommand<Playlist> (*playlist, &before, &after));
2904 commit_reversible_command ();
2922 Editor::cut_copy (CutCopyOp op)
2924 /* only cancel selection if cut/copy is successful.*/
2936 opname = _("clear");
2940 cut_buffer->clear ();
2942 switch (current_mouse_mode()) {
2944 if (!selection->regions.empty() || !selection->points.empty()) {
2946 begin_reversible_command (opname + _(" objects"));
2948 if (!selection->regions.empty()) {
2950 cut_copy_regions (op);
2953 selection->clear_regions ();
2957 if (!selection->points.empty()) {
2958 cut_copy_points (op);
2961 selection->clear_points ();
2965 commit_reversible_command ();
2970 if (!selection->time.empty()) {
2972 begin_reversible_command (opname + _(" range"));
2973 cut_copy_ranges (op);
2974 commit_reversible_command ();
2977 selection->clear_time ();
2989 Editor::cut_copy_points (CutCopyOp op)
2991 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2993 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2996 atv->cut_copy_clear_objects (selection->points, op);
3001 struct PlaylistState {
3002 boost::shared_ptr<Playlist> playlist;
3006 struct lt_playlist {
3007 bool operator () (const PlaylistState& a, const PlaylistState& b) {
3008 return a.playlist < b.playlist;
3012 struct PlaylistMapping {
3014 boost::shared_ptr<AudioPlaylist> pl;
3016 PlaylistMapping (TimeAxisView* tvp) : tv (tvp) {}
3020 Editor::cut_copy_regions (CutCopyOp op)
3022 /* we can't use a std::map here because the ordering is important, and we can't trivially sort
3023 a map when we want ordered access to both elements. i think.
3026 vector<PlaylistMapping> pmap;
3028 nframes_t first_position = max_frames;
3030 set<PlaylistState, lt_playlist> freezelist;
3031 pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
3033 /* get ordering correct before we cut/copy */
3035 selection->regions.sort_by_position_and_track ();
3037 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3039 first_position = min ((*x)->region()->position(), first_position);
3041 if (op == Cut || op == Clear) {
3042 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
3046 PlaylistState before;
3047 before.playlist = pl;
3048 before.before = &pl->get_state();
3050 insert_result = freezelist.insert (before);
3052 if (insert_result.second) {
3058 TimeAxisView* tv = &(*x)->get_trackview();
3059 vector<PlaylistMapping>::iterator z;
3061 for (z = pmap.begin(); z != pmap.end(); ++z) {
3062 if ((*z).tv == tv) {
3067 if (z == pmap.end()) {
3068 pmap.push_back (PlaylistMapping (tv));
3072 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
3074 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist>((*x)->region()->playlist());
3077 /* impossible, but this handles it for the future */
3081 TimeAxisView& tv = (*x)->get_trackview();
3082 boost::shared_ptr<AudioPlaylist> npl;
3083 RegionSelection::iterator tmp;
3088 vector<PlaylistMapping>::iterator z;
3090 for (z = pmap.begin(); z != pmap.end(); ++z) {
3091 if ((*z).tv == &tv) {
3096 assert (z != pmap.end());
3099 npl = boost::dynamic_pointer_cast<AudioPlaylist> (PlaylistFactory::create (*session, "cutlist", true));
3106 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
3112 npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
3113 pl->remove_region (((*x)->region()));
3119 npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
3123 pl->remove_region (((*x)->region()));
3130 list<boost::shared_ptr<Playlist> > foo;
3132 /* the pmap is in the same order as the tracks in which selected regions occured */
3134 for (vector<PlaylistMapping>::iterator i = pmap.begin(); i != pmap.end(); ++i) {
3136 foo.push_back ((*i).pl);
3140 cut_buffer->set (foo);
3143 for (set<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
3144 (*pl).playlist->thaw ();
3145 session->add_command (new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
3150 Editor::cut_copy_ranges (CutCopyOp op)
3152 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3153 (*i)->cut_copy_clear (*selection, op);
3158 Editor::paste (float times)
3160 paste_internal (edit_cursor->current_frame, times);
3164 Editor::mouse_paste ()
3169 track_canvas.get_pointer (x, y);
3170 track_canvas.window_to_world (x, y, wx, wy);
3171 wx += horizontal_adjustment.get_value();
3172 wy += vertical_adjustment.get_value();
3175 event.type = GDK_BUTTON_RELEASE;
3176 event.button.x = wx;
3177 event.button.y = wy;
3179 nframes_t where = event_frame (&event, 0, 0);
3181 paste_internal (where, 1);
3185 Editor::paste_internal (nframes_t position, float times)
3187 bool commit = false;
3189 if (cut_buffer->empty() || selection->tracks.empty()) {
3193 if (position == max_frames) {
3194 position = edit_cursor->current_frame;
3197 begin_reversible_command (_("paste"));
3199 TrackSelection::iterator i;
3202 /* get everything in the correct order */
3204 sort_track_selection ();
3206 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
3208 /* undo/redo is handled by individual tracks */
3210 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3216 commit_reversible_command ();
3221 Editor::paste_named_selection (float times)
3223 TrackSelection::iterator t;
3225 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3227 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3231 TreeModel::iterator i = selected->get_selected();
3232 NamedSelection* ns = (*i)[named_selection_columns.selection];
3234 list<boost::shared_ptr<Playlist> >::iterator chunk;
3235 list<boost::shared_ptr<Playlist> >::iterator tmp;
3237 chunk = ns->playlists.begin();
3239 begin_reversible_command (_("paste chunk"));
3241 sort_track_selection ();
3243 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3245 AudioTimeAxisView* atv;
3246 boost::shared_ptr<Playlist> pl;
3247 boost::shared_ptr<AudioPlaylist> apl;
3249 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3253 if ((pl = atv->playlist()) == 0) {
3257 if ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) == 0) {
3264 XMLNode &before = apl->get_state();
3265 apl->paste (*chunk, edit_cursor->current_frame, times);
3266 session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
3268 if (tmp != ns->playlists.end()) {
3273 commit_reversible_command();
3277 Editor::duplicate_some_regions (RegionSelection& regions, float times)
3279 boost::shared_ptr<Playlist> playlist;
3280 RegionSelection sel = regions; // clear (below) will clear the argument list
3282 begin_reversible_command (_("duplicate region"));
3284 selection->clear_regions ();
3286 for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3288 boost::shared_ptr<Region> r ((*i)->region());
3290 TimeAxisView& tv = (*i)->get_time_axis_view();
3291 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3292 sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3294 playlist = (*i)->region()->playlist();
3295 XMLNode &before = playlist->get_state();
3296 playlist->duplicate (r, r->last_frame(), times);
3297 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
3301 if (latest_regionview) {
3302 selection->add (latest_regionview);
3307 commit_reversible_command ();
3311 Editor::duplicate_selection (float times)
3313 if (selection->time.empty() || selection->tracks.empty()) {
3317 boost::shared_ptr<Playlist> playlist;
3318 vector<boost::shared_ptr<AudioRegion> > new_regions;
3319 vector<boost::shared_ptr<AudioRegion> >::iterator ri;
3321 create_region_from_selection (new_regions);
3323 if (new_regions.empty()) {
3327 begin_reversible_command (_("duplicate selection"));
3329 ri = new_regions.begin();
3331 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3332 if ((playlist = (*i)->playlist()) == 0) {
3335 XMLNode &before = playlist->get_state();
3336 playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
3337 XMLNode &after = playlist->get_state();
3338 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3341 if (ri == new_regions.end()) {
3346 commit_reversible_command ();
3350 Editor::reset_point_selection ()
3352 /* reset all selected points to the relevant default value */
3354 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3356 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3359 atv->reset_objects (selection->points);
3365 Editor::center_playhead ()
3367 float page = canvas_width * frames_per_unit;
3369 center_screen_internal (playhead_cursor->current_frame, page);
3373 Editor::center_edit_cursor ()
3375 float page = canvas_width * frames_per_unit;
3377 center_screen_internal (edit_cursor->current_frame, page);
3381 Editor::clear_playlist (boost::shared_ptr<Playlist> playlist)
3383 begin_reversible_command (_("clear playlist"));
3384 XMLNode &before = playlist->get_state();
3386 XMLNode &after = playlist->get_state();
3387 session->add_command (new MementoCommand<Playlist>(*playlist.get(), &before, &after));
3388 commit_reversible_command ();
3392 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3394 boost::shared_ptr<Playlist> playlist;
3396 nframes_t next_distance;
3399 if (use_edit_cursor) {
3400 start = edit_cursor->current_frame;
3405 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3409 if (selection->tracks.empty()) {
3413 begin_reversible_command (_("nudge track"));
3415 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3417 if ((playlist = (*i)->playlist()) == 0) {
3421 XMLNode &before = playlist->get_state();
3422 playlist->nudge_after (start, distance, forwards);
3423 XMLNode &after = playlist->get_state();
3424 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3427 commit_reversible_command ();
3431 Editor::remove_last_capture ()
3433 vector<string> choices;
3440 if (Config->get_verify_remove_last_capture()) {
3441 prompt = _("Do you really want to destroy the last capture?"
3442 "\n(This is destructive and cannot be undone)");
3444 choices.push_back (_("No, do nothing."));
3445 choices.push_back (_("Yes, destroy it."));
3447 Gtkmm2ext::Choice prompter (prompt, choices);
3449 if (prompter.run () == 1) {
3450 session->remove_last_capture ();
3454 session->remove_last_capture();
3459 Editor::normalize_region ()
3465 if (selection->regions.empty()) {
3469 begin_reversible_command (_("normalize"));
3471 track_canvas.get_window()->set_cursor (*wait_cursor);
3474 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3475 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3478 XMLNode &before = arv->region()->get_state();
3479 arv->audio_region()->normalize_to (0.0f);
3480 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3483 commit_reversible_command ();
3484 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3489 Editor::denormalize_region ()
3495 if (selection->regions.empty()) {
3499 begin_reversible_command ("denormalize");
3501 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3502 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3505 XMLNode &before = arv->region()->get_state();
3506 arv->audio_region()->set_scale_amplitude (1.0f);
3507 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3510 commit_reversible_command ();
3515 Editor::reverse_region ()
3521 Reverse rev (*session);
3522 apply_filter (rev, _("reverse regions"));
3526 Editor::apply_filter (AudioFilter& filter, string command)
3528 if (selection->regions.empty()) {
3532 begin_reversible_command (command);
3534 track_canvas.get_window()->set_cursor (*wait_cursor);
3537 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
3538 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3542 boost::shared_ptr<Playlist> playlist = arv->region()->playlist();
3544 RegionSelection::iterator tmp;
3549 if (arv->audio_region()->apply (filter) == 0) {
3551 XMLNode &before = playlist->get_state();
3552 playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
3553 XMLNode &after = playlist->get_state();
3554 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
3562 commit_reversible_command ();
3563 selection->regions.clear ();
3566 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3570 Editor::region_selection_op (void (Region::*pmf)(void))
3572 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3573 Region* region = (*i)->region().get();
3580 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3582 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3583 Region* region = (*i)->region().get();
3584 (region->*pmf)(arg);
3589 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3591 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3592 Region* region = (*i)->region().get();
3598 Editor::external_edit_region ()
3600 if (!clicked_regionview) {
3608 Editor::brush (nframes_t pos)
3610 RegionSelection sel;
3613 if (selection->regions.empty()) {
3614 /* XXX get selection from region list */
3616 sel = selection->regions;
3623 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3624 mouse_brush_insert_region ((*i), pos);
3629 Editor::reset_region_gain_envelopes ()
3631 if (!session || selection->regions.empty()) {
3635 session->begin_reversible_command (_("reset region gain"));
3637 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3638 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3640 AutomationList& alist (arv->audio_region()->envelope());
3641 XMLNode& before (alist.get_state());
3643 arv->audio_region()->set_default_envelope ();
3644 session->add_command (new MementoCommand<AutomationList>(arv->audio_region()->envelope(), &before, &alist.get_state()));
3648 session->commit_reversible_command ();
3652 Editor::toggle_gain_envelope_visibility ()
3654 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3655 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3657 bool x = region_envelope_visible_item->get_active();
3658 if (x != arv->envelope_visible()) {
3659 arv->set_envelope_visible (x);
3666 Editor::toggle_gain_envelope_active ()
3668 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3669 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3671 bool x = region_envelope_active_item->get_active();
3672 if (x != arv->audio_region()->envelope_active()) {
3673 arv->audio_region()->set_envelope_active (x);
3680 Editor::toggle_region_lock ()
3682 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3683 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3685 bool x = region_lock_item->get_active();
3686 if (x != arv->audio_region()->locked()) {
3687 arv->audio_region()->set_locked (x);
3694 Editor::toggle_region_mute ()
3696 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3697 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3699 bool x = region_mute_item->get_active();
3700 if (x != arv->audio_region()->muted()) {
3701 arv->audio_region()->set_muted (x);
3708 Editor::toggle_region_opaque ()
3710 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3711 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3713 bool x = region_opaque_item->get_active();
3714 if (x != arv->audio_region()->opaque()) {
3715 arv->audio_region()->set_opaque (x);
3722 Editor::set_fade_in_shape (AudioRegion::FadeShape shape)
3724 begin_reversible_command (_("set fade in shape"));
3726 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3727 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3733 AutomationList& alist = tmp->audio_region()->fade_in();
3734 XMLNode &before = alist.get_state();
3736 tmp->audio_region()->set_fade_in_shape (shape);
3738 XMLNode &after = alist.get_state();
3739 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3742 commit_reversible_command ();
3746 Editor::set_fade_out_shape (AudioRegion::FadeShape shape)
3748 begin_reversible_command (_("set fade out shape"));
3750 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3751 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3757 AutomationList& alist = tmp->audio_region()->fade_out();
3758 XMLNode &before = alist.get_state();
3760 tmp->audio_region()->set_fade_out_shape (shape);
3762 XMLNode &after = alist.get_state();
3763 session->add_command(new MementoCommand<AutomationList>(alist, &before, &after));
3766 commit_reversible_command ();
3770 Editor::set_fade_in_active (bool yn)
3772 begin_reversible_command (_("set fade in active"));
3774 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3775 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3782 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3784 XMLNode &before = ar->get_state();
3786 ar->set_fade_in_active (yn);
3788 XMLNode &after = ar->get_state();
3789 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));
3794 Editor::set_fade_out_active (bool yn)
3796 begin_reversible_command (_("set fade out active"));
3798 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3799 AudioRegionView* tmp = dynamic_cast<AudioRegionView*> (*x);
3805 boost::shared_ptr<AudioRegion> ar (tmp->audio_region());
3807 XMLNode &before = ar->get_state();
3809 ar->set_fade_out_active (yn);
3811 XMLNode &after = ar->get_state();
3812 session->add_command(new MementoCommand<AudioRegion>(*ar, &before, &after));