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/reverse.h>
49 #include "ardour_ui.h"
51 #include "time_axis_view.h"
52 #include "audio_time_axis.h"
53 #include "automation_time_axis.h"
54 #include "streamview.h"
55 #include "audio_region_view.h"
56 #include "rgb_macros.h"
57 #include "selection_templates.h"
58 #include "selection.h"
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 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_routeview == 0 || clicked_regionview == 0) {
152 Playlist* playlist = clicked_routeview->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) {
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_axisview) {
505 t.push_back (clicked_axisview);
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_axisview) {
645 t.push_back (clicked_axisview);
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::playhead_backward ()
767 if (get_prefix (prefix, was_floating)) {
771 cnt = (nframes_t) floor (prefix * session->frame_rate ());
773 cnt = (nframes_t) prefix;
777 pos = playhead_cursor->current_frame;
779 if ((nframes_t) pos < cnt) {
785 /* XXX this is completely insane. with the current buffering
786 design, we'll force a complete track buffer flush and
787 reload, just to move 1 sample !!!
790 session->request_locate (pos);
794 Editor::playhead_forward ()
801 if (get_prefix (prefix, was_floating)) {
805 cnt = (nframes_t) floor (prefix * session->frame_rate ());
807 cnt = (nframes_t) floor (prefix);
811 pos = playhead_cursor->current_frame;
813 /* XXX this is completely insane. with the current buffering
814 design, we'll force a complete track buffer flush and
815 reload, just to move 1 sample !!!
818 session->request_locate (pos+cnt);
822 Editor::cursor_align (bool playhead_to_edit)
824 if (playhead_to_edit) {
826 session->request_locate (edit_cursor->current_frame);
829 edit_cursor->set_position (playhead_cursor->current_frame);
834 Editor::edit_cursor_backward ()
841 if (get_prefix (prefix, was_floating)) {
845 cnt = (nframes_t) floor (prefix * session->frame_rate ());
847 cnt = (nframes_t) prefix;
851 pos = edit_cursor->current_frame;
853 if ((nframes_t) pos < cnt) {
859 edit_cursor->set_position (pos);
863 Editor::edit_cursor_forward ()
870 if (get_prefix (prefix, was_floating)) {
874 cnt = (nframes_t) floor (prefix * session->frame_rate ());
876 cnt = (nframes_t) floor (prefix);
880 pos = edit_cursor->current_frame;
881 edit_cursor->set_position (pos+cnt);
885 Editor::goto_frame ()
891 if (get_prefix (prefix, was_floating)) {
896 frame = (nframes_t) floor (prefix * session->frame_rate());
898 frame = (nframes_t) floor (prefix);
901 session->request_locate (frame);
905 Editor::scroll_backward (float pages)
908 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
913 if (get_prefix (prefix, was_floating)) {
914 cnt = (nframes_t) floor (pages * one_page);
917 cnt = (nframes_t) floor (prefix * session->frame_rate());
919 cnt = (nframes_t) floor (prefix * one_page);
923 if (leftmost_frame < cnt) {
926 frame = leftmost_frame - cnt;
929 reposition_x_origin (frame);
933 Editor::scroll_forward (float pages)
936 nframes_t one_page = (nframes_t) rint (canvas_width * frames_per_unit);
941 if (get_prefix (prefix, was_floating)) {
942 cnt = (nframes_t) floor (pages * one_page);
945 cnt = (nframes_t) floor (prefix * session->frame_rate());
947 cnt = (nframes_t) floor (prefix * one_page);
951 if (max_frames - cnt < leftmost_frame) {
952 frame = max_frames - cnt;
954 frame = leftmost_frame + cnt;
957 reposition_x_origin (frame);
961 Editor::scroll_tracks_down ()
967 if (get_prefix (prefix, was_floating)) {
970 cnt = (int) floor (prefix);
973 double vert_value = vertical_adjustment.get_value() + (cnt *
974 vertical_adjustment.get_page_size());
975 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
976 vert_value = vertical_adjustment.get_upper() - canvas_height;
978 vertical_adjustment.set_value (vert_value);
982 Editor::scroll_tracks_up ()
988 if (get_prefix (prefix, was_floating)) {
991 cnt = (int) floor (prefix);
994 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
998 Editor::scroll_tracks_down_line ()
1001 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1002 double vert_value = adj->get_value() + 20;
1004 if (vert_value>adj->get_upper() - canvas_height) {
1005 vert_value = adj->get_upper() - canvas_height;
1007 adj->set_value (vert_value);
1011 Editor::scroll_tracks_up_line ()
1013 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1014 adj->set_value (adj->get_value() - 20);
1020 Editor::temporal_zoom_step (bool coarser)
1022 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1026 nfpu = frames_per_unit;
1031 nfpu = max(1.0,(nfpu/1.61803399));
1034 temporal_zoom (nfpu);
1038 Editor::temporal_zoom (gdouble fpu)
1040 if (!session) return;
1042 nframes_t current_page = current_page_frames();
1043 nframes_t current_leftmost = leftmost_frame;
1044 nframes_t current_rightmost;
1045 nframes_t current_center;
1047 nframes_t leftmost_after_zoom = 0;
1052 new_page = (nframes_t) floor (canvas_width * nfpu);
1054 switch (zoom_focus) {
1056 leftmost_after_zoom = current_leftmost;
1059 case ZoomFocusRight:
1060 current_rightmost = leftmost_frame + current_page;
1061 if (current_rightmost > new_page) {
1062 leftmost_after_zoom = current_rightmost - new_page;
1064 leftmost_after_zoom = 0;
1068 case ZoomFocusCenter:
1069 current_center = current_leftmost + (current_page/2);
1070 if (current_center > (new_page/2)) {
1071 leftmost_after_zoom = current_center - (new_page / 2);
1073 leftmost_after_zoom = 0;
1077 case ZoomFocusPlayhead:
1078 /* try to keep the playhead in the center */
1079 if (playhead_cursor->current_frame > new_page/2) {
1080 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1082 leftmost_after_zoom = 0;
1087 /* try to keep the edit cursor in the center */
1088 if (edit_cursor->current_frame > new_page/2) {
1089 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1091 leftmost_after_zoom = 0;
1097 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1099 // begin_reversible_command (_("zoom"));
1100 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1101 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1102 // commit_reversible_command ();
1104 reposition_and_zoom (leftmost_after_zoom, nfpu);
1108 Editor::temporal_zoom_selection ()
1110 if (!selection) return;
1112 if (selection->time.empty()) {
1116 nframes_t start = selection->time[clicked_selection].start;
1117 nframes_t end = selection->time[clicked_selection].end;
1119 temporal_zoom_by_frame (start, end, "zoom to selection");
1123 Editor::temporal_zoom_session ()
1125 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1128 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1133 Editor::temporal_zoom_by_frame (nframes_t start, nframes_t end, const string & op)
1135 if (!session) return;
1137 if ((start == 0 && end == 0) || end < start) {
1141 nframes_t range = end - start;
1143 double new_fpu = (double)range / (double)canvas_width;
1146 // while (p2 < new_fpu) {
1151 nframes_t new_page = (nframes_t) floor (canvas_width * new_fpu);
1152 nframes_t middle = (nframes_t) floor( (double)start + ((double)range / 2.0f ));
1153 nframes_t new_leftmost = (nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1155 if (new_leftmost > middle) new_leftmost = 0;
1157 // begin_reversible_command (op);
1158 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1159 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1160 // commit_reversible_command ();
1162 reposition_and_zoom (new_leftmost, new_fpu);
1166 Editor::temporal_zoom_to_frame (bool coarser, nframes_t frame)
1168 if (!session) return;
1170 double range_before = frame - leftmost_frame;
1173 new_fpu = frames_per_unit;
1176 new_fpu *= 1.61803399;
1177 range_before *= 1.61803399;
1179 new_fpu = max(1.0,(new_fpu/1.61803399));
1180 range_before /= 1.61803399;
1183 if (new_fpu == frames_per_unit) return;
1185 nframes_t new_leftmost = frame - (nframes_t)range_before;
1187 if (new_leftmost > frame) new_leftmost = 0;
1189 // begin_reversible_command (_("zoom to frame"));
1190 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1191 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1192 // commit_reversible_command ();
1194 reposition_and_zoom (new_leftmost, new_fpu);
1198 Editor::add_location_from_selection ()
1200 if (selection->time.empty()) {
1204 if (session == 0 || clicked_axisview == 0) {
1208 nframes_t start = selection->time[clicked_selection].start;
1209 nframes_t end = selection->time[clicked_selection].end;
1211 Location *location = new Location (start, end, "selection");
1213 session->begin_reversible_command (_("add marker"));
1214 XMLNode &before = session->locations()->get_state();
1215 session->locations()->add (location, true);
1216 XMLNode &after = session->locations()->get_state();
1217 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1218 session->commit_reversible_command ();
1222 Editor::add_location_from_playhead_cursor ()
1224 nframes_t where = session->audible_frame();
1226 Location *location = new Location (where, where, "mark", Location::IsMark);
1227 session->begin_reversible_command (_("add marker"));
1228 XMLNode &before = session->locations()->get_state();
1229 session->locations()->add (location, true);
1230 XMLNode &after = session->locations()->get_state();
1231 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1232 session->commit_reversible_command ();
1236 Editor::add_location_from_audio_region ()
1238 if (selection->regions.empty()) {
1242 RegionView* rv = *(selection->regions.begin());
1243 boost::shared_ptr<Region> region = rv->region();
1245 Location *location = new Location (region->position(), region->last_frame(), region->name());
1246 session->begin_reversible_command (_("add marker"));
1247 XMLNode &before = session->locations()->get_state();
1248 session->locations()->add (location, true);
1249 XMLNode &after = session->locations()->get_state();
1250 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1251 session->commit_reversible_command ();
1255 Editor::select_all_in_track (Selection::Operation op)
1257 list<Selectable *> touched;
1259 if (!clicked_axisview) {
1263 clicked_axisview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1266 case Selection::Toggle:
1267 selection->add (touched);
1269 case Selection::Set:
1270 selection->set (touched);
1272 case Selection::Extend:
1273 /* not defined yet */
1275 case Selection::Add:
1276 selection->add (touched);
1282 Editor::select_all (Selection::Operation op)
1284 list<Selectable *> touched;
1286 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1287 if ((*iter)->hidden()) {
1290 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1292 begin_reversible_command (_("select all"));
1294 case Selection::Add:
1295 case Selection::Toggle:
1296 selection->add (touched);
1298 case Selection::Set:
1299 selection->set (touched);
1301 case Selection::Extend:
1302 /* not defined yet */
1305 commit_reversible_command ();
1309 Editor::invert_selection_in_track ()
1311 list<Selectable *> touched;
1313 if (!clicked_axisview) {
1317 clicked_axisview->get_inverted_selectables (*selection, touched);
1318 selection->set (touched);
1322 Editor::invert_selection ()
1324 list<Selectable *> touched;
1326 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1327 if ((*iter)->hidden()) {
1330 (*iter)->get_inverted_selectables (*selection, touched);
1333 selection->set (touched);
1337 Editor::select_all_within (nframes_t start, nframes_t end, double top, double bot, Selection::Operation op)
1339 list<Selectable *> touched;
1341 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1342 if ((*iter)->hidden()) {
1345 (*iter)->get_selectables (start, end, top, bot, touched);
1348 cerr << "select all within found " << touched.size() << endl;
1350 begin_reversible_command (_("select all within"));
1352 case Selection::Add:
1353 case Selection::Toggle:
1355 selection->add (touched);
1357 case Selection::Set:
1359 selection->set (touched);
1361 case Selection::Extend:
1363 /* not defined yet */
1367 cerr << "selection now has " << selection->points.size() << endl;
1369 commit_reversible_command ();
1370 return !touched.empty();
1374 Editor::set_selection_from_audio_region ()
1376 if (selection->regions.empty()) {
1380 RegionView* rv = *(selection->regions.begin());
1381 boost::shared_ptr<Region> region = rv->region();
1383 begin_reversible_command (_("set selection from region"));
1384 selection->set (0, region->position(), region->last_frame());
1385 commit_reversible_command ();
1387 set_mouse_mode (Editing::MouseRange, false);
1391 Editor::set_selection_from_punch()
1395 if ((location = session->locations()->auto_punch_location()) == 0) {
1399 set_selection_from_range (*location);
1403 Editor::set_selection_from_loop()
1407 if ((location = session->locations()->auto_loop_location()) == 0) {
1410 set_selection_from_range (*location);
1414 Editor::set_selection_from_range (Location& loc)
1416 begin_reversible_command (_("set selection from range"));
1417 selection->set (0, loc.start(), loc.end());
1418 commit_reversible_command ();
1420 set_mouse_mode (Editing::MouseRange, false);
1424 Editor::select_all_selectables_using_time_selection ()
1426 list<Selectable *> touched;
1428 if (selection->time.empty()) {
1432 nframes_t start = selection->time[clicked_selection].start;
1433 nframes_t end = selection->time[clicked_selection].end;
1435 if (end - start < 1) {
1439 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1440 if ((*iter)->hidden()) {
1443 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1446 begin_reversible_command (_("select all from range"));
1447 selection->set (touched);
1448 commit_reversible_command ();
1453 Editor::select_all_selectables_using_punch()
1455 Location* location = session->locations()->auto_punch_location();
1456 list<Selectable *> touched;
1458 if (location == 0 || (location->end() - location->start() <= 1)) {
1462 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1463 if ((*iter)->hidden()) {
1466 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1468 begin_reversible_command (_("select all from punch"));
1469 selection->set (touched);
1470 commit_reversible_command ();
1475 Editor::select_all_selectables_using_loop()
1477 Location* location = session->locations()->auto_loop_location();
1478 list<Selectable *> touched;
1480 if (location == 0 || (location->end() - location->start() <= 1)) {
1484 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1485 if ((*iter)->hidden()) {
1488 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1490 begin_reversible_command (_("select all from loop"));
1491 selection->set (touched);
1492 commit_reversible_command ();
1497 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1501 list<Selectable *> touched;
1504 begin_reversible_command (_("select all after cursor"));
1505 start = cursor->current_frame ;
1506 end = session->current_end_frame();
1508 if (cursor->current_frame > 0) {
1509 begin_reversible_command (_("select all before cursor"));
1511 end = cursor->current_frame - 1;
1517 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1518 if ((*iter)->hidden()) {
1521 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1523 selection->set (touched);
1524 commit_reversible_command ();
1528 Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
1532 list<Selectable *> touched;
1533 bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
1535 if (cursor->current_frame == other_cursor->current_frame) {
1539 begin_reversible_command (_("select all between cursors"));
1540 if (other_cursor_is_first) {
1541 start = other_cursor->current_frame;
1542 end = cursor->current_frame - 1;
1545 start = cursor->current_frame;
1546 end = other_cursor->current_frame - 1;
1549 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1550 if ((*iter)->hidden()) {
1553 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1555 selection->set (touched);
1556 commit_reversible_command ();
1560 Editor::amplitude_zoom_step (bool in)
1574 #ifdef FIX_FOR_CANVAS
1575 /* XXX DO SOMETHING */
1584 Editor::delete_sample_forward ()
1589 Editor::delete_sample_backward ()
1594 Editor::delete_screen ()
1601 Editor::search_backwards ()
1607 Editor::search_forwards ()
1615 Editor::jump_forward_to_mark ()
1621 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1624 session->request_locate (location->start(), session->transport_rolling());
1626 session->request_locate (session->current_end_frame());
1631 Editor::jump_backward_to_mark ()
1637 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1640 session->request_locate (location->start(), session->transport_rolling());
1642 session->goto_start ();
1653 if (get_prefix (prefix, was_floating)) {
1654 pos = session->audible_frame ();
1657 pos = (nframes_t) floor (prefix * session->frame_rate ());
1659 pos = (nframes_t) floor (prefix);
1663 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1667 Editor::clear_markers ()
1670 session->begin_reversible_command (_("clear markers"));
1671 XMLNode &before = session->locations()->get_state();
1672 session->locations()->clear_markers ();
1673 XMLNode &after = session->locations()->get_state();
1674 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1675 session->commit_reversible_command ();
1680 Editor::clear_ranges ()
1683 session->begin_reversible_command (_("clear ranges"));
1684 XMLNode &before = session->locations()->get_state();
1686 Location * looploc = session->locations()->auto_loop_location();
1687 Location * punchloc = session->locations()->auto_punch_location();
1689 session->locations()->clear_ranges ();
1691 if (looploc) session->locations()->add (looploc);
1692 if (punchloc) session->locations()->add (punchloc);
1694 XMLNode &after = session->locations()->get_state();
1695 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1696 session->commit_reversible_command ();
1701 Editor::clear_locations ()
1703 session->begin_reversible_command (_("clear locations"));
1704 XMLNode &before = session->locations()->get_state();
1705 session->locations()->clear ();
1706 XMLNode &after = session->locations()->get_state();
1707 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1708 session->commit_reversible_command ();
1709 session->locations()->clear ();
1712 /* INSERT/REPLACE */
1715 Editor::insert_region_list_drag (boost::shared_ptr<Region> region, int x, int y)
1721 AudioTimeAxisView *atv = 0;
1724 track_canvas.window_to_world (x, y, wx, wy);
1725 wx += horizontal_adjustment.get_value();
1726 wy += vertical_adjustment.get_value();
1729 event.type = GDK_BUTTON_RELEASE;
1730 event.button.x = wx;
1731 event.button.y = wy;
1733 where = event_frame (&event, &cx, &cy);
1735 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1736 /* clearly outside canvas area */
1740 if ((tv = trackview_by_y_position (cy)) == 0) {
1744 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1748 if ((playlist = atv->playlist()) == 0) {
1754 begin_reversible_command (_("insert dragged region"));
1755 XMLNode &before = playlist->get_state();
1756 playlist->add_region (RegionFactory::create (region), where, 1.0);
1757 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1758 commit_reversible_command ();
1762 Editor::insert_region_list_selection (float times)
1764 RouteTimeAxisView *tv = 0;
1767 if (clicked_routeview != 0) {
1768 tv = clicked_routeview;
1769 } else if (!selection->tracks.empty()) {
1770 if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
1777 if ((playlist = tv->playlist()) == 0) {
1781 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1783 if (selected->count_selected_rows() != 1) {
1787 TreeView::Selection::ListHandle_Path rows = selected->get_selected_rows ();
1789 /* only one row selected, so rows.begin() is it */
1793 if ((iter = region_list_model->get_iter (*rows.begin()))) {
1795 boost::shared_ptr<Region> region = (*iter)[region_list_columns.region];
1797 begin_reversible_command (_("insert region"));
1798 XMLNode &before = playlist->get_state();
1799 playlist->add_region ((RegionFactory::create (region)), edit_cursor->current_frame, times);
1800 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1801 commit_reversible_command ();
1805 /* BUILT-IN EFFECTS */
1808 Editor::reverse_selection ()
1813 /* GAIN ENVELOPE EDITING */
1816 Editor::edit_envelope ()
1823 Editor::toggle_playback (bool with_abort)
1829 switch (Config->get_slave_source()) {
1834 /* transport controlled by the master */
1838 if (session->is_auditioning()) {
1839 session->cancel_audition ();
1843 if (session->transport_rolling()) {
1844 session->request_stop (with_abort);
1845 if (session->get_play_loop()) {
1846 session->request_play_loop (false);
1849 session->request_transport_speed (1.0f);
1854 Editor::play_from_start ()
1856 session->request_locate (session->current_start_frame(), true);
1860 Editor::play_from_edit_cursor ()
1862 session->request_locate (edit_cursor->current_frame, true);
1866 Editor::play_selection ()
1868 if (selection->time.empty()) {
1872 session->request_play_range (true);
1876 Editor::play_selected_region ()
1878 if (!selection->regions.empty()) {
1879 RegionView *rv = *(selection->regions.begin());
1881 session->request_bounded_roll (rv->region()->position(), rv->region()->last_frame());
1886 Editor::loop_selected_region ()
1888 if (!selection->regions.empty()) {
1889 RegionView *rv = *(selection->regions.begin());
1892 if ((tll = transport_loop_location()) != 0) {
1894 tll->set (rv->region()->position(), rv->region()->last_frame());
1896 // enable looping, reposition and start rolling
1898 session->request_play_loop (true);
1899 session->request_locate (tll->start(), false);
1900 session->request_transport_speed (1.0f);
1906 Editor::play_location (Location& location)
1908 if (location.start() <= location.end()) {
1912 session->request_bounded_roll (location.start(), location.end());
1916 Editor::loop_location (Location& location)
1918 if (location.start() <= location.end()) {
1924 if ((tll = transport_loop_location()) != 0) {
1925 tll->set (location.start(), location.end());
1927 // enable looping, reposition and start rolling
1928 session->request_play_loop (true);
1929 session->request_locate (tll->start(), true);
1934 Editor::raise_region ()
1936 selection->foreach_region (&Region::raise);
1940 Editor::raise_region_to_top ()
1942 selection->foreach_region (&Region::raise_to_top);
1946 Editor::lower_region ()
1948 selection->foreach_region (&Region::lower);
1952 Editor::lower_region_to_bottom ()
1954 selection->foreach_region (&Region::lower_to_bottom);
1958 Editor::edit_region ()
1960 if (clicked_regionview == 0) {
1964 clicked_regionview->show_region_editor ();
1968 Editor::rename_region ()
1972 Button ok_button (_("OK"));
1973 Button cancel_button (_("Cancel"));
1975 if (selection->regions.empty()) {
1979 dialog.set_title (_("ardour: rename region"));
1980 dialog.set_name ("RegionRenameWindow");
1981 dialog.set_size_request (300, -1);
1982 dialog.set_position (Gtk::WIN_POS_MOUSE);
1983 dialog.set_modal (true);
1985 dialog.get_vbox()->set_border_width (10);
1986 dialog.get_vbox()->pack_start (entry);
1987 dialog.get_action_area()->pack_start (ok_button);
1988 dialog.get_action_area()->pack_start (cancel_button);
1990 entry.set_name ("RegionNameDisplay");
1991 ok_button.set_name ("EditorGTKButton");
1992 cancel_button.set_name ("EditorGTKButton");
1994 region_renamed = false;
1996 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1997 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
1998 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
2005 if (region_renamed) {
2006 (*selection->regions.begin())->region()->set_name (entry.get_text());
2007 redisplay_regions ();
2012 Editor::rename_region_finished (bool status)
2015 region_renamed = status;
2020 Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Route& route)
2022 if (session->is_auditioning()) {
2023 session->cancel_audition ();
2026 // note: some potential for creativity here, because region doesn't
2027 // have to belong to the playlist that Route is handling
2029 // bool was_soloed = route.soloed();
2031 route.set_solo (true, this);
2033 session->request_bounded_roll (region->position(), region->position() + region->length());
2035 /* XXX how to unset the solo state ? */
2039 Editor::audition_selected_region ()
2041 if (!selection->regions.empty()) {
2042 RegionView* rv = *(selection->regions.begin());
2043 session->audition_region (rv->region());
2048 Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
2050 session->audition_region (region);
2054 Editor::build_interthread_progress_window ()
2056 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
2058 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
2060 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
2061 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
2063 // GTK2FIX: this button needs a modifiable label
2065 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
2066 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
2068 interthread_cancel_button.add (interthread_cancel_label);
2070 interthread_progress_window->set_default_size (200, 100);
2074 Editor::interthread_cancel_clicked ()
2076 if (current_interthread_info) {
2077 current_interthread_info->cancel = true;
2082 Editor::region_from_selection ()
2084 if (clicked_axisview == 0) {
2088 if (selection->time.empty()) {
2092 nframes_t start = selection->time[clicked_selection].start;
2093 nframes_t end = selection->time[clicked_selection].end;
2095 nframes_t selection_cnt = end - start + 1;
2097 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2098 boost::shared_ptr<AudioRegion> current;
2099 boost::shared_ptr<Region> current_r;
2102 nframes_t internal_start;
2105 if ((pl = (*i)->playlist()) == 0) {
2109 if ((current_r = pl->top_region_at (start)) == 0) {
2113 current = boost::dynamic_pointer_cast<AudioRegion> (current_r);
2114 assert(current); // FIXME
2116 internal_start = start - current->position();
2117 session->region_name (new_name, current->name(), true);
2118 boost::shared_ptr<Region> region (RegionFactory::create (current, internal_start, selection_cnt, new_name));
2124 Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& new_regions)
2126 if (selection->time.empty() || selection->tracks.empty()) {
2130 nframes_t start = selection->time[clicked_selection].start;
2131 nframes_t end = selection->time[clicked_selection].end;
2133 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2135 boost::shared_ptr<AudioRegion> current;
2136 boost::shared_ptr<Region> current_r;
2138 nframes_t internal_start;
2141 if ((playlist = (*i)->playlist()) == 0) {
2145 if ((current_r = playlist->top_region_at(start)) == 0) {
2149 if ((current = boost::dynamic_pointer_cast<AudioRegion>(current_r)) == 0) {
2153 internal_start = start - current->position();
2154 session->region_name (new_name, current->name(), true);
2156 new_regions.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (current, internal_start, end - start + 1, new_name)));
2161 Editor::split_multichannel_region ()
2163 vector<AudioRegion*> v;
2165 AudioRegionView* clicked_arv = dynamic_cast<AudioRegionView*>(clicked_regionview);
2167 if (!clicked_arv || clicked_arv->audio_region()->n_channels() < 2) {
2171 clicked_arv->audio_region()->separate_by_channel (*session, v);
2173 /* nothing else to do, really */
2177 Editor::new_region_from_selection ()
2179 region_from_selection ();
2180 cancel_selection ();
2184 Editor::separate_region_from_selection ()
2188 bool doing_undo = false;
2190 if (selection->time.empty()) {
2196 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2198 AudioTimeAxisView* atv;
2200 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2202 if (atv->is_audio_track()) {
2204 if ((playlist = atv->playlist()) != 0) {
2206 begin_reversible_command (_("separate"));
2211 before = &(playlist->get_state());
2213 /* XXX need to consider musical time selections here at some point */
2215 double speed = atv->get_diskstream()->speed();
2217 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2218 playlist->partition ((nframes_t)((*t).start * speed), (nframes_t)((*t).end * speed), true);
2222 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2228 if (doing_undo) commit_reversible_command ();
2232 Editor::separate_regions_using_location (Location& loc)
2236 bool doing_undo = false;
2238 if (loc.is_mark()) {
2244 /* XXX i'm unsure as to whether this should operate on selected tracks only
2245 or the entire enchillada. uncomment the below line to correct the behaviour
2246 (currently set for all tracks)
2249 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2250 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2252 AudioTimeAxisView* atv;
2254 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2256 if (atv->is_audio_track()) {
2258 if ((playlist = atv->playlist()) != 0) {
2261 begin_reversible_command (_("separate"));
2265 before = &(playlist->get_state());
2268 /* XXX need to consider musical time selections here at some point */
2270 double speed = atv->get_diskstream()->speed();
2273 playlist->partition ((nframes_t)(loc.start() * speed), (nframes_t)(loc.end() * speed), true);
2275 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2281 if (doing_undo) commit_reversible_command ();
2285 Editor::crop_region_to_selection ()
2287 if (selection->time.empty()) {
2291 vector<Playlist*> playlists;
2294 if (clicked_axisview != 0) {
2296 if ((playlist = clicked_axisview->playlist()) == 0) {
2300 playlists.push_back (playlist);
2304 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2306 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*i);
2308 if (rtv && rtv->is_track()) {
2310 if ((playlist = rtv->playlist()) != 0) {
2311 playlists.push_back (playlist);
2317 if (!playlists.empty()) {
2323 begin_reversible_command (_("trim to selection"));
2325 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2327 boost::shared_ptr<Region> region;
2329 start = selection->time.start();
2331 if ((region = (*i)->top_region_at(start)) == 0) {
2335 /* now adjust lengths to that we do the right thing
2336 if the selection extends beyond the region
2339 start = max (start, region->position());
2340 end = min (selection->time.end_frame(), start + region->length() - 1);
2341 cnt = end - start + 1;
2343 XMLNode &before = (*i)->get_state();
2344 region->trim_to (start, cnt, this);
2345 XMLNode &after = (*i)->get_state();
2346 session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
2349 commit_reversible_command ();
2354 Editor::region_fill_track ()
2358 if (!session || selection->regions.empty()) {
2362 end = session->current_end_frame ();
2364 begin_reversible_command (_("region fill"));
2366 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2368 boost::shared_ptr<Region> region ((*i)->region());
2371 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
2374 Playlist* pl = region->playlist();
2376 if (end <= region->last_frame()) {
2380 double times = (double) (end - region->last_frame()) / (double) region->length();
2386 XMLNode &before = pl->get_state();
2387 pl->add_region (RegionFactory::create (ar), ar->last_frame(), times);
2388 session->add_command (new MementoCommand<Playlist>(*pl, &before, &pl->get_state()));
2391 commit_reversible_command ();
2395 Editor::region_fill_selection ()
2397 if (clicked_routeview == 0 || !clicked_routeview->is_audio_track()) {
2401 if (selection->time.empty()) {
2406 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2408 if (selected->count_selected_rows() != 1) {
2412 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2413 boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
2415 nframes_t start = selection->time[clicked_selection].start;
2416 nframes_t end = selection->time[clicked_selection].end;
2420 if (selection->tracks.empty()) {
2424 nframes_t selection_length = end - start;
2425 float times = (float)selection_length / region->length();
2427 begin_reversible_command (_("fill selection"));
2429 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2431 if ((playlist = (*i)->playlist()) == 0) {
2435 XMLNode &before = playlist->get_state();
2436 playlist->add_region (RegionFactory::create (region), start, times);
2437 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
2440 commit_reversible_command ();
2444 Editor::set_a_regions_sync_position (boost::shared_ptr<Region> region, nframes_t position)
2447 if (!region->covers (position)) {
2448 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2451 begin_reversible_command (_("set region sync position"));
2452 XMLNode &before = region->playlist()->get_state();
2453 region->set_sync_position (position);
2454 XMLNode &after = region->playlist()->get_state();
2455 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2456 commit_reversible_command ();
2460 Editor::set_region_sync_from_edit_cursor ()
2462 if (clicked_regionview == 0) {
2466 if (!clicked_regionview->region()->covers (edit_cursor->current_frame)) {
2467 error << _("Place the edit cursor at the desired sync point") << endmsg;
2471 boost::shared_ptr<Region> region (clicked_regionview->region());
2472 begin_reversible_command (_("set sync from edit cursor"));
2473 XMLNode &before = region->playlist()->get_state();
2474 region->set_sync_position (edit_cursor->current_frame);
2475 XMLNode &after = region->playlist()->get_state();
2476 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2477 commit_reversible_command ();
2481 Editor::remove_region_sync ()
2483 if (clicked_regionview) {
2484 boost::shared_ptr<Region> region (clicked_regionview->region());
2485 begin_reversible_command (_("remove sync"));
2486 XMLNode &before = region->playlist()->get_state();
2487 region->clear_sync_position ();
2488 XMLNode &after = region->playlist()->get_state();
2489 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2490 commit_reversible_command ();
2495 Editor::naturalize ()
2497 if (selection->regions.empty()) {
2500 begin_reversible_command (_("naturalize"));
2501 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2502 XMLNode &before = (*i)->region()->get_state();
2503 (*i)->region()->move_to_natural_position (this);
2504 XMLNode &after = (*i)->region()->get_state();
2505 session->add_command (new MementoCommand<Region>(*((*i)->region().get()), &before, &after));
2507 commit_reversible_command ();
2511 Editor::align (RegionPoint what)
2513 align_selection (what, edit_cursor->current_frame);
2517 Editor::align_relative (RegionPoint what)
2519 align_selection_relative (what, edit_cursor->current_frame);
2522 struct RegionSortByTime {
2523 bool operator() (const RegionView* a, const RegionView* b) {
2524 return a->region()->position() < b->region()->position();
2529 Editor::align_selection_relative (RegionPoint point, nframes_t position)
2531 if (selection->regions.empty()) {
2539 list<RegionView*> sorted;
2540 selection->regions.by_position (sorted);
2541 boost::shared_ptr<Region> r ((*sorted.begin())->region());
2545 pos = r->first_frame ();
2549 pos = r->last_frame();
2553 pos = r->adjust_to_sync (r->first_frame());
2557 if (pos > position) {
2558 distance = pos - position;
2561 distance = position - pos;
2565 begin_reversible_command (_("align selection (relative)"));
2567 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2569 boost::shared_ptr<Region> region ((*i)->region());
2571 XMLNode &before = region->playlist()->get_state();
2574 region->set_position (region->position() + distance, this);
2576 region->set_position (region->position() - distance, this);
2579 XMLNode &after = region->playlist()->get_state();
2580 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2584 commit_reversible_command ();
2588 Editor::align_selection (RegionPoint point, nframes_t position)
2590 if (selection->regions.empty()) {
2594 begin_reversible_command (_("align selection"));
2596 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2597 align_region_internal ((*i)->region(), point, position);
2600 commit_reversible_command ();
2604 Editor::align_region (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2606 begin_reversible_command (_("align region"));
2607 align_region_internal (region, point, position);
2608 commit_reversible_command ();
2612 Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, nframes_t position)
2614 XMLNode &before = region->playlist()->get_state();
2618 region->set_position (region->adjust_to_sync (position), this);
2622 if (position > region->length()) {
2623 region->set_position (position - region->length(), this);
2628 region->set_position (position, this);
2632 XMLNode &after = region->playlist()->get_state();
2633 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2637 Editor::trim_region_to_edit_cursor ()
2639 if (clicked_regionview == 0) {
2643 boost::shared_ptr<Region> region (clicked_regionview->region());
2646 AudioTimeAxisView *atav;
2648 if ( clicked_axisview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_axisview)) != 0 ) {
2649 if (atav->get_diskstream() != 0) {
2650 speed = atav->get_diskstream()->speed();
2654 begin_reversible_command (_("trim to edit"));
2655 XMLNode &before = region->playlist()->get_state();
2656 region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2657 XMLNode &after = region->playlist()->get_state();
2658 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2659 commit_reversible_command ();
2663 Editor::trim_region_from_edit_cursor ()
2665 if (clicked_regionview == 0) {
2669 boost::shared_ptr<Region> region (clicked_regionview->region());
2672 AudioTimeAxisView *atav;
2674 if ( clicked_axisview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_axisview)) != 0 ) {
2675 if (atav->get_diskstream() != 0) {
2676 speed = atav->get_diskstream()->speed();
2680 begin_reversible_command (_("trim to edit"));
2681 XMLNode &before = region->playlist()->get_state();
2682 region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2683 XMLNode &after = region->playlist()->get_state();
2684 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2685 commit_reversible_command ();
2689 Editor::unfreeze_route ()
2691 if (clicked_routeview == 0 || !clicked_routeview->is_track()) {
2695 clicked_routeview->track()->unfreeze ();
2699 Editor::_freeze_thread (void* arg)
2701 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2702 return static_cast<Editor*>(arg)->freeze_thread ();
2706 Editor::freeze_thread ()
2708 clicked_routeview->audio_track()->freeze (*current_interthread_info);
2713 Editor::freeze_progress_timeout (void *arg)
2715 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2716 return !(current_interthread_info->done || current_interthread_info->cancel);
2720 Editor::freeze_route ()
2722 if (clicked_routeview == 0 || !clicked_routeview->is_track()) {
2726 InterThreadInfo itt;
2728 if (interthread_progress_window == 0) {
2729 build_interthread_progress_window ();
2732 interthread_progress_window->set_title (_("ardour: freeze"));
2733 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2734 interthread_progress_window->show_all ();
2735 interthread_progress_bar.set_fraction (0.0f);
2736 interthread_progress_label.set_text ("");
2737 interthread_cancel_label.set_text (_("Cancel Freeze"));
2738 current_interthread_info = &itt;
2740 interthread_progress_connection =
2741 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2745 itt.progress = 0.0f;
2747 pthread_create (&itt.thread, 0, _freeze_thread, this);
2749 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2751 while (!itt.done && !itt.cancel) {
2752 gtk_main_iteration ();
2755 interthread_progress_connection.disconnect ();
2756 interthread_progress_window->hide_all ();
2757 current_interthread_info = 0;
2758 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2762 Editor::bounce_range_selection ()
2764 if (selection->time.empty()) {
2768 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2770 nframes_t start = selection->time[clicked_selection].start;
2771 nframes_t end = selection->time[clicked_selection].end;
2772 nframes_t cnt = end - start + 1;
2774 begin_reversible_command (_("bounce range"));
2776 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2778 AudioTimeAxisView* atv;
2780 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2786 if ((playlist = atv->playlist()) == 0) {
2790 InterThreadInfo itt;
2794 itt.progress = false;
2796 XMLNode &before = playlist->get_state();
2797 atv->audio_track()->bounce_range (start, cnt, itt);
2798 XMLNode &after = playlist->get_state();
2799 session->add_command (new MementoCommand<Playlist> (*playlist, &before, &after));
2802 commit_reversible_command ();
2820 Editor::cut_copy (CutCopyOp op)
2822 /* only cancel selection if cut/copy is successful.*/
2834 opname = _("clear");
2838 cut_buffer->clear ();
2840 switch (current_mouse_mode()) {
2842 if (!selection->regions.empty() || !selection->points.empty()) {
2844 begin_reversible_command (opname + _(" objects"));
2846 if (!selection->regions.empty()) {
2848 cut_copy_regions (op);
2851 selection->clear_regions ();
2855 if (!selection->points.empty()) {
2856 cut_copy_points (op);
2859 selection->clear_points ();
2863 commit_reversible_command ();
2868 if (!selection->time.empty()) {
2870 begin_reversible_command (opname + _(" range"));
2871 cut_copy_ranges (op);
2872 commit_reversible_command ();
2875 selection->clear_time ();
2887 Editor::cut_copy_points (CutCopyOp op)
2889 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2891 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2894 atv->cut_copy_clear_objects (selection->points, op);
2899 struct PlaylistState {
2904 struct lt_playlist {
2905 bool operator () (const PlaylistState& a, const PlaylistState& b) {
2906 return a.playlist < b.playlist;
2911 Editor::cut_copy_regions (CutCopyOp op)
2913 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
2914 PlaylistMapping pmap;
2915 nframes_t first_position = max_frames;
2917 set<PlaylistState, lt_playlist> freezelist;
2918 pair<set<PlaylistState, lt_playlist>::iterator,bool> insert_result;
2920 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
2921 first_position = min ((*x)->region()->position(), first_position);
2923 if (op == Cut || op == Clear) {
2924 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region()->playlist());
2927 PlaylistState before;
2928 before.playlist = pl;
2929 before.before = &pl->get_state();
2931 insert_result = freezelist.insert (before);
2933 if (insert_result.second) {
2940 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
2942 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region()->playlist());
2944 RegionSelection::iterator tmp;
2951 PlaylistMapping::iterator pi = pmap.find (pl);
2953 if (pi == pmap.end()) {
2954 npl = new AudioPlaylist (*session, "cutlist", true);
2962 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
2967 npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
2968 pl->remove_region (((*x)->region()));
2974 npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
2978 pl->remove_region (((*x)->region()));
2986 list<Playlist*> foo;
2988 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2989 foo.push_back (i->second);
2993 cut_buffer->set (foo);
2996 for (set<PlaylistState, lt_playlist>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2997 (*pl).playlist->thaw ();
2998 session->add_command (new MementoCommand<Playlist>(*(*pl).playlist, (*pl).before, &(*pl).playlist->get_state()));
3003 Editor::cut_copy_ranges (CutCopyOp op)
3005 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3006 (*i)->cut_copy_clear (*selection, op);
3011 Editor::paste (float times)
3013 paste_internal (edit_cursor->current_frame, times);
3017 Editor::mouse_paste ()
3022 track_canvas.get_pointer (x, y);
3023 track_canvas.window_to_world (x, y, wx, wy);
3024 wx += horizontal_adjustment.get_value();
3025 wy += vertical_adjustment.get_value();
3028 event.type = GDK_BUTTON_RELEASE;
3029 event.button.x = wx;
3030 event.button.y = wy;
3032 nframes_t where = event_frame (&event, 0, 0);
3034 paste_internal (where, 1);
3038 Editor::paste_internal (nframes_t position, float times)
3040 bool commit = false;
3042 if (cut_buffer->empty() || selection->tracks.empty()) {
3046 if (position == max_frames) {
3047 position = edit_cursor->current_frame;
3050 begin_reversible_command (_("paste"));
3052 TrackSelection::iterator i;
3055 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
3057 /* undo/redo is handled by individual tracks */
3059 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3065 commit_reversible_command ();
3070 Editor::paste_named_selection (float times)
3072 TrackSelection::iterator t;
3074 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3076 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3080 TreeModel::iterator i = selected->get_selected();
3081 NamedSelection* ns = (*i)[named_selection_columns.selection];
3083 list<Playlist*>::iterator chunk;
3084 list<Playlist*>::iterator tmp;
3086 chunk = ns->playlists.begin();
3088 begin_reversible_command (_("paste chunk"));
3090 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3092 AudioTimeAxisView* atv;
3096 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3100 if ((pl = atv->playlist()) == 0) {
3104 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
3111 XMLNode &before = apl->get_state();
3112 apl->paste (**chunk, edit_cursor->current_frame, times);
3113 session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
3115 if (tmp != ns->playlists.end()) {
3120 commit_reversible_command();
3124 Editor::duplicate_some_regions (RegionSelection& regions, float times)
3127 RegionSelection sel = regions; // clear (below) will clear the argument list
3129 begin_reversible_command (_("duplicate region"));
3131 selection->clear_regions ();
3133 for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3135 boost::shared_ptr<Region> r ((*i)->region());
3137 TimeAxisView& tv = (*i)->get_time_axis_view();
3138 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3139 sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3141 playlist = (*i)->region()->playlist();
3142 XMLNode &before = playlist->get_state();
3143 playlist->duplicate (r, r->last_frame(), times);
3144 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
3148 if (latest_regionview) {
3149 selection->add (latest_regionview);
3154 commit_reversible_command ();
3158 Editor::duplicate_selection (float times)
3160 if (selection->time.empty() || selection->tracks.empty()) {
3165 vector<boost::shared_ptr<AudioRegion> > new_regions;
3166 vector<boost::shared_ptr<AudioRegion> >::iterator ri;
3168 create_region_from_selection (new_regions);
3170 if (new_regions.empty()) {
3174 begin_reversible_command (_("duplicate selection"));
3176 ri = new_regions.begin();
3178 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3179 if ((playlist = (*i)->playlist()) == 0) {
3182 XMLNode &before = playlist->get_state();
3183 playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
3184 XMLNode &after = playlist->get_state();
3185 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3188 if (ri == new_regions.end()) {
3193 commit_reversible_command ();
3197 Editor::reset_point_selection ()
3199 /* reset all selected points to the relevant default value */
3201 cerr << "point selection has " << selection->points.size() << " entries\n";
3203 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3205 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3208 atv->reset_objects (selection->points);
3214 Editor::center_playhead ()
3216 float page = canvas_width * frames_per_unit;
3218 center_screen_internal (playhead_cursor->current_frame, page);
3222 Editor::center_edit_cursor ()
3224 float page = canvas_width * frames_per_unit;
3226 center_screen_internal (edit_cursor->current_frame, page);
3230 Editor::clear_playlist (Playlist& playlist)
3232 begin_reversible_command (_("clear playlist"));
3233 XMLNode &before = playlist.get_state();
3235 XMLNode &after = playlist.get_state();
3236 session->add_command (new MementoCommand<Playlist>(playlist, &before, &after));
3237 commit_reversible_command ();
3241 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3245 nframes_t next_distance;
3248 if (use_edit_cursor) {
3249 start = edit_cursor->current_frame;
3254 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3258 if (selection->tracks.empty()) {
3262 begin_reversible_command (_("nudge track"));
3264 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3266 if ((playlist = (*i)->playlist()) == 0) {
3270 XMLNode &before = playlist->get_state();
3271 playlist->nudge_after (start, distance, forwards);
3272 XMLNode &after = playlist->get_state();
3273 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3276 commit_reversible_command ();
3280 Editor::remove_last_capture ()
3282 vector<string> choices;
3289 if (Config->get_verify_remove_last_capture()) {
3290 prompt = _("Do you really want to destroy the last capture?"
3291 "\n(This is destructive and cannot be undone)");
3293 choices.push_back (_("No, do nothing."));
3294 choices.push_back (_("Yes, destroy it."));
3296 Gtkmm2ext::Choice prompter (prompt, choices);
3298 if (prompter.run () == 1) {
3299 session->remove_last_capture ();
3303 session->remove_last_capture();
3308 Editor::normalize_region ()
3314 if (selection->regions.empty()) {
3318 begin_reversible_command (_("normalize"));
3320 track_canvas.get_window()->set_cursor (*wait_cursor);
3323 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3324 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3327 XMLNode &before = arv->region()->get_state();
3328 arv->audio_region()->normalize_to (0.0f);
3329 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3332 commit_reversible_command ();
3333 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3338 Editor::denormalize_region ()
3344 if (selection->regions.empty()) {
3348 begin_reversible_command ("denormalize");
3350 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3351 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3354 XMLNode &before = arv->region()->get_state();
3355 arv->audio_region()->set_scale_amplitude (1.0f);
3356 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3359 commit_reversible_command ();
3364 Editor::reverse_region ()
3370 Reverse rev (*session);
3371 apply_filter (rev, _("reverse regions"));
3375 Editor::apply_filter (AudioFilter& filter, string command)
3377 if (selection->regions.empty()) {
3381 begin_reversible_command (command);
3383 track_canvas.get_window()->set_cursor (*wait_cursor);
3386 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
3387 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3391 Playlist* playlist = arv->region()->playlist();
3393 RegionSelection::iterator tmp;
3398 if (arv->audio_region()->apply (filter) == 0) {
3400 XMLNode &before = playlist->get_state();
3401 playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
3402 XMLNode &after = playlist->get_state();
3403 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
3411 commit_reversible_command ();
3412 selection->regions.clear ();
3415 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3419 Editor::region_selection_op (void (Region::*pmf)(void))
3421 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3422 Region* region = (*i)->region().get();
3429 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3431 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3432 Region* region = (*i)->region().get();
3433 (region->*pmf)(arg);
3438 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3440 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3441 Region* region = (*i)->region().get();
3447 Editor::external_edit_region ()
3449 if (!clicked_regionview) {
3457 Editor::brush (nframes_t pos)
3459 RegionSelection sel;
3462 if (selection->regions.empty()) {
3463 /* XXX get selection from region list */
3465 sel = selection->regions;
3472 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3473 mouse_brush_insert_region ((*i), pos);
3478 Editor::reset_region_gain_envelopes ()
3480 if (!session || selection->regions.empty()) {
3484 session->begin_reversible_command (_("reset region gain"));
3486 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3487 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3489 AutomationList& alist (arv->audio_region()->envelope());
3490 XMLNode& before (alist.get_state());
3492 arv->audio_region()->set_default_envelope ();
3493 session->add_command (new MementoCommand<AutomationList>(arv->audio_region()->envelope(), &before, &alist.get_state()));
3497 session->commit_reversible_command ();
3501 Editor::toggle_gain_envelope_visibility ()
3503 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3504 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3506 bool x = region_envelope_visible_item->get_active();
3507 if (x != arv->envelope_visible()) {
3508 arv->set_envelope_visible (x);
3515 Editor::toggle_gain_envelope_active ()
3517 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3518 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3520 bool x = region_envelope_active_item->get_active();
3521 if (x != arv->audio_region()->envelope_active()) {
3522 arv->audio_region()->set_envelope_active (x);
3529 Editor::toggle_region_lock ()
3531 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3532 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3534 bool x = region_lock_item->get_active();
3535 if (x != arv->audio_region()->locked()) {
3536 arv->audio_region()->set_locked (x);
3543 Editor::toggle_region_mute ()
3545 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3546 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3548 bool x = region_mute_item->get_active();
3549 if (x != arv->audio_region()->muted()) {
3550 arv->audio_region()->set_muted (x);
3557 Editor::toggle_region_opaque ()
3559 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3560 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3562 bool x = region_opaque_item->get_active();
3563 if (x != arv->audio_region()->opaque()) {
3564 arv->audio_region()->set_opaque (x);