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 (jack_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 (jack_nframes_t where)
109 split_regions_at (where, selection->regions);
113 Editor::split_regions_at (jack_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_audio_trackview == 0 || clicked_regionview == 0) {
152 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 int32_t selected = selection->regions.size();
167 if (!session || clicked_regionview == 0 && selected == 0) {
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);
203 } else if (clicked_regionview) {
204 session->destroy_region (clicked_regionview->region());
208 boost::shared_ptr<Region>
209 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
212 boost::shared_ptr<Region> region;
213 jack_nframes_t start = 0;
215 if (selection->time.start () == selection->time.end_frame ()) {
217 /* no current selection-> is there a selected regionview? */
219 if (selection->regions.empty()) {
225 if (!selection->regions.empty()) {
227 rv = *(selection->regions.begin());
228 (*tv) = &rv->get_time_axis_view();
229 region = rv->region();
231 } else if (!selection->tracks.empty()) {
233 (*tv) = selection->tracks.front();
235 RouteTimeAxisView* rtv;
237 if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
240 if ((pl = rtv->playlist()) == 0) {
244 region = pl->top_region_at (start);
252 Editor::extend_selection_to_end_of_region (bool next)
255 boost::shared_ptr<Region> region;
256 jack_nframes_t start;
258 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
262 if (region && selection->time.start () == selection->time.end_frame ()) {
263 start = region->position();
265 start = selection->time.start ();
268 /* Try to leave the selection with the same route if possible */
270 if ((tv = selection->time.track) == 0) {
274 begin_reversible_command (_("extend selection"));
275 selection->set (tv, start, region->position() + region->length());
276 commit_reversible_command ();
280 Editor::extend_selection_to_start_of_region (bool previous)
283 boost::shared_ptr<Region> region;
286 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
290 if (region && selection->time.start () == selection->time.end_frame ()) {
291 end = region->position() + region->length();
293 end = selection->time.end_frame ();
296 /* Try to leave the selection with the same route if possible */
298 if ((tv = selection->time.track) == 0) {
302 begin_reversible_command (_("extend selection"));
303 selection->set (tv, region->position(), end);
304 commit_reversible_command ();
309 Editor::nudge_forward (bool next)
311 jack_nframes_t distance;
312 jack_nframes_t next_distance;
314 if (!session) return;
316 if (!selection->regions.empty()) {
318 begin_reversible_command (_("nudge forward"));
320 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
321 boost::shared_ptr<Region> r ((*i)->region());
323 distance = get_nudge_distance (r->position(), next_distance);
326 distance = next_distance;
329 XMLNode &before = r->playlist()->get_state();
330 r->set_position (r->position() + distance, this);
331 XMLNode &after = r->playlist()->get_state();
332 session->add_command (new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
335 commit_reversible_command ();
338 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
339 session->request_locate (playhead_cursor->current_frame + distance);
344 Editor::nudge_backward (bool next)
346 jack_nframes_t distance;
347 jack_nframes_t next_distance;
349 if (!session) return;
351 if (!selection->regions.empty()) {
353 begin_reversible_command (_("nudge forward"));
355 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
356 boost::shared_ptr<Region> r ((*i)->region());
358 distance = get_nudge_distance (r->position(), next_distance);
361 distance = next_distance;
364 XMLNode &before = r->playlist()->get_state();
366 if (r->position() > distance) {
367 r->set_position (r->position() - distance, this);
369 r->set_position (0, this);
371 XMLNode &after = r->playlist()->get_state();
372 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
375 commit_reversible_command ();
379 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
381 if (playhead_cursor->current_frame > distance) {
382 session->request_locate (playhead_cursor->current_frame - distance);
384 session->goto_start();
390 Editor::nudge_forward_capture_offset ()
392 jack_nframes_t distance;
394 if (!session) return;
396 if (!selection->regions.empty()) {
398 begin_reversible_command (_("nudge forward"));
400 distance = session->worst_output_latency();
402 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
403 boost::shared_ptr<Region> r ((*i)->region());
405 XMLNode &before = r->playlist()->get_state();
406 r->set_position (r->position() + distance, this);
407 XMLNode &after = r->playlist()->get_state();
408 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
411 commit_reversible_command ();
417 Editor::nudge_backward_capture_offset ()
419 jack_nframes_t distance;
421 if (!session) return;
423 if (!selection->regions.empty()) {
425 begin_reversible_command (_("nudge forward"));
427 distance = session->worst_output_latency();
429 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
430 boost::shared_ptr<Region> r ((*i)->region());
432 XMLNode &before = r->playlist()->get_state();
434 if (r->position() > distance) {
435 r->set_position (r->position() - distance, this);
437 r->set_position (0, this);
439 XMLNode &after = r->playlist()->get_state();
440 session->add_command(new MementoCommand<Playlist>(*(r->playlist()), &before, &after));
443 commit_reversible_command ();
450 Editor::move_to_start ()
452 session->goto_start ();
456 Editor::move_to_end ()
459 session->request_locate (session->current_end_frame());
463 Editor::build_region_boundary_cache ()
465 jack_nframes_t pos = 0;
467 boost::shared_ptr<Region> r;
468 TrackViewList tracks;
470 region_boundary_cache.clear ();
477 case SnapToRegionStart:
480 case SnapToRegionEnd:
483 case SnapToRegionSync:
486 case SnapToRegionBoundary:
490 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
495 TimeAxisView *ontrack = 0;
497 while (pos < session->current_end_frame()) {
499 if (!selection->tracks.empty()) {
501 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
505 } else if (clicked_trackview) {
508 t.push_back (clicked_trackview);
510 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
516 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
524 case SnapToRegionStart:
525 rpos = r->first_frame();
527 case SnapToRegionEnd:
528 rpos = r->last_frame();
530 case SnapToRegionSync:
531 rpos = r->adjust_to_sync (r->first_frame());
534 case SnapToRegionBoundary:
535 rpos = r->last_frame();
542 AudioTimeAxisView *atav;
544 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
545 if (atav->get_diskstream() != 0) {
546 speed = atav->get_diskstream()->speed();
550 rpos = track_frame_to_session_frame(rpos, speed);
552 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
553 if (snap_type == SnapToRegionBoundary) {
554 region_boundary_cache.push_back (r->first_frame());
556 region_boundary_cache.push_back (rpos);
563 boost::shared_ptr<Region>
564 Editor::find_next_region (jack_nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
566 TrackViewList::iterator i;
567 jack_nframes_t closest = max_frames;
568 boost::shared_ptr<Region> ret;
569 jack_nframes_t rpos = 0;
572 jack_nframes_t track_frame;
573 AudioTimeAxisView *atav;
575 for (i = tracks.begin(); i != tracks.end(); ++i) {
577 jack_nframes_t distance;
578 boost::shared_ptr<Region> r;
581 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
582 if (atav->get_diskstream()!=0)
583 track_speed = atav->get_diskstream()->speed();
586 track_frame = session_frame_to_track_frame(frame, track_speed);
588 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
594 rpos = r->first_frame ();
598 rpos = r->last_frame ();
602 rpos = r->adjust_to_sync (r->first_frame());
605 // rpos is a "track frame", converting it to "session frame"
606 rpos = track_frame_to_session_frame(rpos, track_speed);
609 distance = rpos - frame;
611 distance = frame - rpos;
614 if (distance < closest) {
626 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
628 boost::shared_ptr<Region> r;
629 jack_nframes_t pos = cursor->current_frame;
635 TimeAxisView *ontrack = 0;
637 // so we don't find the current region again..
641 if (!selection->tracks.empty()) {
643 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
645 } else if (clicked_trackview) {
648 t.push_back (clicked_trackview);
650 r = find_next_region (pos, point, dir, t, &ontrack);
654 r = find_next_region (pos, point, dir, track_views, &ontrack);
663 pos = r->first_frame ();
667 pos = r->last_frame ();
671 pos = r->adjust_to_sync (r->first_frame());
676 AudioTimeAxisView *atav;
678 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
679 if (atav->get_diskstream() != 0) {
680 speed = atav->get_diskstream()->speed();
684 pos = track_frame_to_session_frame(pos, speed);
686 if (cursor == playhead_cursor) {
687 session->request_locate (pos);
689 cursor->set_position (pos);
694 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
696 cursor_to_region_point (cursor, point, 1);
700 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
702 cursor_to_region_point (cursor, point, -1);
706 Editor::cursor_to_selection_start (Cursor *cursor)
708 jack_nframes_t pos = 0;
709 switch (mouse_mode) {
711 if (!selection->regions.empty()) {
712 pos = selection->regions.start();
717 if (!selection->time.empty()) {
718 pos = selection->time.start ();
726 if (cursor == playhead_cursor) {
727 session->request_locate (pos);
729 cursor->set_position (pos);
734 Editor::cursor_to_selection_end (Cursor *cursor)
736 jack_nframes_t pos = 0;
738 switch (mouse_mode) {
740 if (!selection->regions.empty()) {
741 pos = selection->regions.end_frame();
746 if (!selection->time.empty()) {
747 pos = selection->time.end_frame ();
755 if (cursor == playhead_cursor) {
756 session->request_locate (pos);
758 cursor->set_position (pos);
763 Editor::playhead_backward ()
770 if (get_prefix (prefix, was_floating)) {
774 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
776 cnt = (jack_nframes_t) prefix;
780 pos = playhead_cursor->current_frame;
782 if ((jack_nframes_t) pos < cnt) {
788 /* XXX this is completely insane. with the current buffering
789 design, we'll force a complete track buffer flush and
790 reload, just to move 1 sample !!!
793 session->request_locate (pos);
797 Editor::playhead_forward ()
804 if (get_prefix (prefix, was_floating)) {
808 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
810 cnt = (jack_nframes_t) floor (prefix);
814 pos = playhead_cursor->current_frame;
816 /* XXX this is completely insane. with the current buffering
817 design, we'll force a complete track buffer flush and
818 reload, just to move 1 sample !!!
821 session->request_locate (pos+cnt);
825 Editor::cursor_align (bool playhead_to_edit)
827 if (playhead_to_edit) {
829 session->request_locate (edit_cursor->current_frame);
832 edit_cursor->set_position (playhead_cursor->current_frame);
837 Editor::edit_cursor_backward ()
844 if (get_prefix (prefix, was_floating)) {
848 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
850 cnt = (jack_nframes_t) prefix;
854 pos = edit_cursor->current_frame;
856 if ((jack_nframes_t) pos < cnt) {
862 edit_cursor->set_position (pos);
866 Editor::edit_cursor_forward ()
873 if (get_prefix (prefix, was_floating)) {
877 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
879 cnt = (jack_nframes_t) floor (prefix);
883 pos = edit_cursor->current_frame;
884 edit_cursor->set_position (pos+cnt);
888 Editor::goto_frame ()
892 jack_nframes_t frame;
894 if (get_prefix (prefix, was_floating)) {
899 frame = (jack_nframes_t) floor (prefix * session->frame_rate());
901 frame = (jack_nframes_t) floor (prefix);
904 session->request_locate (frame);
908 Editor::scroll_backward (float pages)
910 jack_nframes_t frame;
911 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
916 if (get_prefix (prefix, was_floating)) {
917 cnt = (jack_nframes_t) floor (pages * one_page);
920 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
922 cnt = (jack_nframes_t) floor (prefix * one_page);
926 if (leftmost_frame < cnt) {
929 frame = leftmost_frame - cnt;
932 reposition_x_origin (frame);
936 Editor::scroll_forward (float pages)
938 jack_nframes_t frame;
939 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
944 if (get_prefix (prefix, was_floating)) {
945 cnt = (jack_nframes_t) floor (pages * one_page);
948 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
950 cnt = (jack_nframes_t) floor (prefix * one_page);
954 if (ULONG_MAX - cnt < leftmost_frame) {
955 frame = ULONG_MAX - cnt;
957 frame = leftmost_frame + cnt;
960 reposition_x_origin (frame);
964 Editor::scroll_tracks_down ()
970 if (get_prefix (prefix, was_floating)) {
973 cnt = (int) floor (prefix);
976 double vert_value = vertical_adjustment.get_value() + (cnt *
977 vertical_adjustment.get_page_size());
978 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
979 vert_value = vertical_adjustment.get_upper() - canvas_height;
981 vertical_adjustment.set_value (vert_value);
985 Editor::scroll_tracks_up ()
991 if (get_prefix (prefix, was_floating)) {
994 cnt = (int) floor (prefix);
997 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1001 Editor::scroll_tracks_down_line ()
1004 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1005 double vert_value = adj->get_value() + 20;
1007 if (vert_value>adj->get_upper() - canvas_height) {
1008 vert_value = adj->get_upper() - canvas_height;
1010 adj->set_value (vert_value);
1014 Editor::scroll_tracks_up_line ()
1016 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1017 adj->set_value (adj->get_value() - 20);
1023 Editor::temporal_zoom_step (bool coarser)
1025 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1029 nfpu = frames_per_unit;
1034 nfpu = max(1.0,(nfpu/1.61803399));
1037 temporal_zoom (nfpu);
1041 Editor::temporal_zoom (gdouble fpu)
1043 if (!session) return;
1045 jack_nframes_t current_page = current_page_frames();
1046 jack_nframes_t current_leftmost = leftmost_frame;
1047 jack_nframes_t current_rightmost;
1048 jack_nframes_t current_center;
1049 jack_nframes_t new_page;
1050 jack_nframes_t leftmost_after_zoom = 0;
1055 new_page = (jack_nframes_t) floor (canvas_width * nfpu);
1057 switch (zoom_focus) {
1059 leftmost_after_zoom = current_leftmost;
1062 case ZoomFocusRight:
1063 current_rightmost = leftmost_frame + current_page;
1064 if (current_rightmost > new_page) {
1065 leftmost_after_zoom = current_rightmost - new_page;
1067 leftmost_after_zoom = 0;
1071 case ZoomFocusCenter:
1072 current_center = current_leftmost + (current_page/2);
1073 if (current_center > (new_page/2)) {
1074 leftmost_after_zoom = current_center - (new_page / 2);
1076 leftmost_after_zoom = 0;
1080 case ZoomFocusPlayhead:
1081 /* try to keep the playhead in the center */
1082 if (playhead_cursor->current_frame > new_page/2) {
1083 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1085 leftmost_after_zoom = 0;
1090 /* try to keep the edit cursor in the center */
1091 if (edit_cursor->current_frame > leftmost_frame + (new_page/2)) {
1092 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1094 leftmost_after_zoom = 0;
1100 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1102 // begin_reversible_command (_("zoom"));
1103 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1104 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1105 // commit_reversible_command ();
1107 reposition_and_zoom (leftmost_after_zoom, nfpu);
1111 Editor::temporal_zoom_selection ()
1113 if (!selection) return;
1115 if (selection->time.empty()) {
1119 jack_nframes_t start = selection->time[clicked_selection].start;
1120 jack_nframes_t end = selection->time[clicked_selection].end;
1122 temporal_zoom_by_frame (start, end, "zoom to selection");
1126 Editor::temporal_zoom_session ()
1128 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1131 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1136 Editor::temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, const string & op)
1138 if (!session) return;
1140 if ((start == 0 && end == 0) || end < start) {
1144 jack_nframes_t range = end - start;
1146 double new_fpu = (double)range / (double)canvas_width;
1149 // while (p2 < new_fpu) {
1154 jack_nframes_t new_page = (jack_nframes_t) floor (canvas_width * new_fpu);
1155 jack_nframes_t middle = (jack_nframes_t) floor( (double)start + ((double)range / 2.0f ));
1156 jack_nframes_t new_leftmost = (jack_nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1158 if (new_leftmost > middle) new_leftmost = 0;
1160 // begin_reversible_command (op);
1161 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1162 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1163 // commit_reversible_command ();
1165 reposition_and_zoom (new_leftmost, new_fpu);
1169 Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
1171 if (!session) return;
1173 double range_before = frame - leftmost_frame;
1176 new_fpu = frames_per_unit;
1179 new_fpu *= 1.61803399;
1180 range_before *= 1.61803399;
1182 new_fpu = max(1.0,(new_fpu/1.61803399));
1183 range_before /= 1.61803399;
1186 if (new_fpu == frames_per_unit) return;
1188 jack_nframes_t new_leftmost = frame - (jack_nframes_t)range_before;
1190 if (new_leftmost > frame) new_leftmost = 0;
1192 // begin_reversible_command (_("zoom to frame"));
1193 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1194 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1195 // commit_reversible_command ();
1197 reposition_and_zoom (new_leftmost, new_fpu);
1201 Editor::add_location_from_selection ()
1203 if (selection->time.empty()) {
1207 if (session == 0 || clicked_trackview == 0) {
1211 jack_nframes_t start = selection->time[clicked_selection].start;
1212 jack_nframes_t end = selection->time[clicked_selection].end;
1214 Location *location = new Location (start, end, "selection");
1216 session->begin_reversible_command (_("add marker"));
1217 XMLNode &before = session->locations()->get_state();
1218 session->locations()->add (location, true);
1219 XMLNode &after = session->locations()->get_state();
1220 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1221 session->commit_reversible_command ();
1225 Editor::add_location_from_playhead_cursor ()
1227 jack_nframes_t where = session->audible_frame();
1229 Location *location = new Location (where, where, "mark", Location::IsMark);
1230 session->begin_reversible_command (_("add marker"));
1231 XMLNode &before = session->locations()->get_state();
1232 session->locations()->add (location, true);
1233 XMLNode &after = session->locations()->get_state();
1234 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1235 session->commit_reversible_command ();
1239 Editor::add_location_from_audio_region ()
1241 if (selection->regions.empty()) {
1245 RegionView* rv = *(selection->regions.begin());
1246 boost::shared_ptr<Region> region = rv->region();
1248 Location *location = new Location (region->position(), region->last_frame(), region->name());
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::select_all_in_track (Selection::Operation op)
1260 list<Selectable *> touched;
1262 if (!clicked_trackview) {
1266 clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1269 case Selection::Toggle:
1270 selection->add (touched);
1272 case Selection::Set:
1273 selection->set (touched);
1275 case Selection::Extend:
1276 /* not defined yet */
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::Toggle:
1295 selection->add (touched);
1297 case Selection::Set:
1298 selection->set (touched);
1300 case Selection::Extend:
1301 /* not defined yet */
1304 commit_reversible_command ();
1308 Editor::invert_selection_in_track ()
1310 list<Selectable *> touched;
1312 if (!clicked_trackview) {
1316 clicked_trackview->get_inverted_selectables (*selection, touched);
1317 selection->set (touched);
1321 Editor::invert_selection ()
1323 list<Selectable *> touched;
1325 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1326 if ((*iter)->hidden()) {
1329 (*iter)->get_inverted_selectables (*selection, touched);
1332 selection->set (touched);
1336 Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, Selection::Operation op)
1338 list<Selectable *> touched;
1340 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1341 if ((*iter)->hidden()) {
1344 (*iter)->get_selectables (start, end, top, bot, touched);
1347 cerr << "select all within found " << touched.size() << endl;
1349 begin_reversible_command (_("select all within"));
1351 case Selection::Toggle:
1353 selection->add (touched);
1355 case Selection::Set:
1357 selection->set (touched);
1359 case Selection::Extend:
1361 /* not defined yet */
1365 cerr << "selection now has " << selection->points.size() << endl;
1367 commit_reversible_command ();
1368 return !touched.empty();
1372 Editor::set_selection_from_audio_region ()
1374 if (selection->regions.empty()) {
1378 RegionView* rv = *(selection->regions.begin());
1379 boost::shared_ptr<Region> region = rv->region();
1381 begin_reversible_command (_("set selection from region"));
1382 selection->set (0, region->position(), region->last_frame());
1383 commit_reversible_command ();
1385 set_mouse_mode (Editing::MouseRange, false);
1389 Editor::set_selection_from_punch()
1393 if ((location = session->locations()->auto_punch_location()) == 0) {
1397 set_selection_from_range (*location);
1401 Editor::set_selection_from_loop()
1405 if ((location = session->locations()->auto_loop_location()) == 0) {
1408 set_selection_from_range (*location);
1412 Editor::set_selection_from_range (Location& loc)
1414 begin_reversible_command (_("set selection from range"));
1415 selection->set (0, loc.start(), loc.end());
1416 commit_reversible_command ();
1418 set_mouse_mode (Editing::MouseRange, false);
1422 Editor::select_all_selectables_using_time_selection ()
1424 list<Selectable *> touched;
1426 if (selection->time.empty()) {
1430 jack_nframes_t start = selection->time[clicked_selection].start;
1431 jack_nframes_t end = selection->time[clicked_selection].end;
1433 if (end - start < 1) {
1437 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1438 if ((*iter)->hidden()) {
1441 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1444 begin_reversible_command (_("select all from range"));
1445 selection->set (touched);
1446 commit_reversible_command ();
1451 Editor::select_all_selectables_using_punch()
1453 Location* location = session->locations()->auto_punch_location();
1454 list<Selectable *> touched;
1456 if (location == 0 || (location->end() - location->start() <= 1)) {
1460 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1461 if ((*iter)->hidden()) {
1464 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1466 begin_reversible_command (_("select all from punch"));
1467 selection->set (touched);
1468 commit_reversible_command ();
1473 Editor::select_all_selectables_using_loop()
1475 Location* location = session->locations()->auto_loop_location();
1476 list<Selectable *> touched;
1478 if (location == 0 || (location->end() - location->start() <= 1)) {
1482 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1483 if ((*iter)->hidden()) {
1486 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1488 begin_reversible_command (_("select all from loop"));
1489 selection->set (touched);
1490 commit_reversible_command ();
1495 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1497 jack_nframes_t start;
1499 list<Selectable *> touched;
1502 begin_reversible_command (_("select all after cursor"));
1503 start = cursor->current_frame ;
1504 end = session->current_end_frame();
1506 if (cursor->current_frame > 0) {
1507 begin_reversible_command (_("select all before cursor"));
1509 end = cursor->current_frame - 1;
1515 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1516 if ((*iter)->hidden()) {
1519 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1521 selection->set (touched);
1522 commit_reversible_command ();
1526 Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
1528 jack_nframes_t start;
1530 list<Selectable *> touched;
1531 bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
1533 if (cursor->current_frame == other_cursor->current_frame) {
1537 begin_reversible_command (_("select all between cursors"));
1538 if (other_cursor_is_first) {
1539 start = other_cursor->current_frame;
1540 end = cursor->current_frame - 1;
1543 start = cursor->current_frame;
1544 end = other_cursor->current_frame - 1;
1547 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1548 if ((*iter)->hidden()) {
1551 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1553 selection->set (touched);
1554 commit_reversible_command ();
1558 Editor::amplitude_zoom_step (bool in)
1572 #ifdef FIX_FOR_CANVAS
1573 /* XXX DO SOMETHING */
1582 Editor::delete_sample_forward ()
1587 Editor::delete_sample_backward ()
1592 Editor::delete_screen ()
1599 Editor::search_backwards ()
1605 Editor::search_forwards ()
1613 Editor::jump_forward_to_mark ()
1619 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1622 session->request_locate (location->start(), session->transport_rolling());
1624 session->request_locate (session->current_end_frame());
1629 Editor::jump_backward_to_mark ()
1635 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1638 session->request_locate (location->start(), session->transport_rolling());
1640 session->goto_start ();
1651 if (get_prefix (prefix, was_floating)) {
1652 pos = session->audible_frame ();
1655 pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
1657 pos = (jack_nframes_t) floor (prefix);
1661 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1665 Editor::clear_markers ()
1668 session->begin_reversible_command (_("clear markers"));
1669 XMLNode &before = session->locations()->get_state();
1670 session->locations()->clear_markers ();
1671 XMLNode &after = session->locations()->get_state();
1672 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1673 session->commit_reversible_command ();
1678 Editor::clear_ranges ()
1681 session->begin_reversible_command (_("clear ranges"));
1682 XMLNode &before = session->locations()->get_state();
1684 Location * looploc = session->locations()->auto_loop_location();
1685 Location * punchloc = session->locations()->auto_punch_location();
1687 session->locations()->clear_ranges ();
1689 if (looploc) session->locations()->add (looploc);
1690 if (punchloc) session->locations()->add (punchloc);
1692 XMLNode &after = session->locations()->get_state();
1693 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1694 session->commit_reversible_command ();
1699 Editor::clear_locations ()
1701 session->begin_reversible_command (_("clear locations"));
1702 XMLNode &before = session->locations()->get_state();
1703 session->locations()->clear ();
1704 XMLNode &after = session->locations()->get_state();
1705 session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
1706 session->commit_reversible_command ();
1707 session->locations()->clear ();
1710 /* INSERT/REPLACE */
1713 Editor::insert_region_list_drag (boost::shared_ptr<AudioRegion> region, int x, int y)
1718 jack_nframes_t where;
1719 AudioTimeAxisView *atv = 0;
1722 track_canvas.window_to_world (x, y, wx, wy);
1723 wx += horizontal_adjustment.get_value();
1724 wy += vertical_adjustment.get_value();
1727 event.type = GDK_BUTTON_RELEASE;
1728 event.button.x = wx;
1729 event.button.y = wy;
1731 where = event_frame (&event, &cx, &cy);
1733 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1734 /* clearly outside canvas area */
1738 if ((tv = trackview_by_y_position (cy)) == 0) {
1742 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1746 if ((playlist = atv->playlist()) == 0) {
1752 begin_reversible_command (_("insert dragged region"));
1753 XMLNode &before = playlist->get_state();
1754 playlist->add_region (RegionFactory::create (region), where, 1.0);
1755 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1756 commit_reversible_command ();
1760 Editor::insert_region_list_selection (float times)
1762 RouteTimeAxisView *tv = 0;
1765 if (clicked_audio_trackview != 0) {
1766 tv = clicked_audio_trackview;
1767 } else if (!selection->tracks.empty()) {
1768 if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
1775 if ((playlist = tv->playlist()) == 0) {
1779 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1781 if (selected->count_selected_rows() != 1) {
1785 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
1786 boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
1788 begin_reversible_command (_("insert region"));
1789 XMLNode &before = playlist->get_state();
1790 playlist->add_region ((RegionFactory::create (region)), edit_cursor->current_frame, times);
1791 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
1792 commit_reversible_command ();
1796 /* BUILT-IN EFFECTS */
1799 Editor::reverse_selection ()
1804 /* GAIN ENVELOPE EDITING */
1807 Editor::edit_envelope ()
1814 Editor::toggle_playback (bool with_abort)
1820 switch (Config->get_slave_source()) {
1825 /* transport controlled by the master */
1829 if (session->is_auditioning()) {
1830 session->cancel_audition ();
1834 if (session->transport_rolling()) {
1835 session->request_stop (with_abort);
1836 if (Config->get_auto_loop()) {
1837 session->request_play_loop (false);
1840 session->request_transport_speed (1.0f);
1845 Editor::play_from_start ()
1847 session->request_locate (session->current_start_frame(), true);
1851 Editor::play_selection ()
1853 if (selection->time.empty()) {
1857 session->request_play_range (true);
1861 Editor::play_selected_region ()
1863 if (!selection->regions.empty()) {
1864 RegionView *rv = *(selection->regions.begin());
1866 session->request_bounded_roll (rv->region()->position(), rv->region()->last_frame());
1871 Editor::loop_selected_region ()
1873 if (!selection->regions.empty()) {
1874 RegionView *rv = *(selection->regions.begin());
1877 if ((tll = transport_loop_location()) != 0) {
1879 tll->set (rv->region()->position(), rv->region()->last_frame());
1881 // enable looping, reposition and start rolling
1883 session->request_play_loop (true);
1884 session->request_locate (tll->start(), false);
1885 session->request_transport_speed (1.0f);
1891 Editor::play_location (Location& location)
1893 if (location.start() <= location.end()) {
1897 session->request_bounded_roll (location.start(), location.end());
1901 Editor::loop_location (Location& location)
1903 if (location.start() <= location.end()) {
1909 if ((tll = transport_loop_location()) != 0) {
1910 tll->set (location.start(), location.end());
1912 // enable looping, reposition and start rolling
1913 session->request_play_loop (true);
1914 session->request_locate (tll->start(), true);
1919 Editor::toggle_region_mute ()
1921 if (clicked_regionview) {
1922 clicked_regionview->region()->set_muted (!clicked_regionview->region()->muted());
1923 } else if (!selection->regions.empty()) {
1924 bool yn = ! (*selection->regions.begin())->region()->muted();
1925 selection->foreach_region (&Region::set_muted, yn);
1930 Editor::toggle_region_opaque ()
1932 if (clicked_regionview) {
1933 clicked_regionview->region()->set_opaque (!clicked_regionview->region()->opaque());
1934 } else if (!selection->regions.empty()) {
1935 bool yn = ! (*selection->regions.begin())->region()->opaque();
1936 selection->foreach_region (&Region::set_opaque, yn);
1941 Editor::raise_region ()
1943 selection->foreach_region (&Region::raise);
1947 Editor::raise_region_to_top ()
1949 selection->foreach_region (&Region::raise_to_top);
1953 Editor::lower_region ()
1955 selection->foreach_region (&Region::lower);
1959 Editor::lower_region_to_bottom ()
1961 selection->foreach_region (&Region::lower_to_bottom);
1965 Editor::edit_region ()
1967 if (clicked_regionview == 0) {
1971 clicked_regionview->show_region_editor ();
1975 Editor::rename_region ()
1979 Button ok_button (_("OK"));
1980 Button cancel_button (_("Cancel"));
1982 if (selection->regions.empty()) {
1986 dialog.set_title (_("ardour: rename region"));
1987 dialog.set_name ("RegionRenameWindow");
1988 dialog.set_size_request (300, -1);
1989 dialog.set_position (Gtk::WIN_POS_MOUSE);
1990 dialog.set_modal (true);
1992 dialog.get_vbox()->set_border_width (10);
1993 dialog.get_vbox()->pack_start (entry);
1994 dialog.get_action_area()->pack_start (ok_button);
1995 dialog.get_action_area()->pack_start (cancel_button);
1997 entry.set_name ("RegionNameDisplay");
1998 ok_button.set_name ("EditorGTKButton");
1999 cancel_button.set_name ("EditorGTKButton");
2001 region_renamed = false;
2003 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2004 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2005 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
2012 if (region_renamed) {
2013 (*selection->regions.begin())->region()->set_name (entry.get_text());
2014 redisplay_regions ();
2019 Editor::rename_region_finished (bool status)
2022 region_renamed = status;
2027 Editor::audition_playlist_region_via_route (boost::shared_ptr<Region> region, Route& route)
2029 if (session->is_auditioning()) {
2030 session->cancel_audition ();
2033 // note: some potential for creativity here, because region doesn't
2034 // have to belong to the playlist that Route is handling
2036 // bool was_soloed = route.soloed();
2038 route.set_solo (true, this);
2040 session->request_bounded_roll (region->position(), region->position() + region->length());
2042 /* XXX how to unset the solo state ? */
2046 Editor::audition_selected_region ()
2048 if (!selection->regions.empty()) {
2049 RegionView* rv = *(selection->regions.begin());
2050 session->audition_region (rv->region());
2055 Editor::audition_playlist_region_standalone (boost::shared_ptr<Region> region)
2057 session->audition_region (region);
2061 Editor::build_interthread_progress_window ()
2063 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
2065 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
2067 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
2068 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
2070 // GTK2FIX: this button needs a modifiable label
2072 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
2073 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
2075 interthread_cancel_button.add (interthread_cancel_label);
2077 interthread_progress_window->set_default_size (200, 100);
2081 Editor::interthread_cancel_clicked ()
2083 if (current_interthread_info) {
2084 current_interthread_info->cancel = true;
2089 Editor::region_from_selection ()
2091 if (clicked_trackview == 0) {
2095 if (selection->time.empty()) {
2099 jack_nframes_t start = selection->time[clicked_selection].start;
2100 jack_nframes_t end = selection->time[clicked_selection].end;
2102 jack_nframes_t selection_cnt = end - start + 1;
2104 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2105 boost::shared_ptr<AudioRegion> current;
2106 boost::shared_ptr<Region> current_r;
2109 jack_nframes_t internal_start;
2112 if ((pl = (*i)->playlist()) == 0) {
2116 if ((current_r = pl->top_region_at (start)) == 0) {
2120 current = boost::dynamic_pointer_cast<AudioRegion> (current_r);
2121 // FIXME: audio only
2123 internal_start = start - current->position();
2124 session->region_name (new_name, current->name(), true);
2125 boost::shared_ptr<Region> region (RegionFactory::create (current, internal_start, selection_cnt, new_name));
2131 Editor::create_region_from_selection (vector<boost::shared_ptr<AudioRegion> >& new_regions)
2133 if (selection->time.empty() || selection->tracks.empty()) {
2137 jack_nframes_t start = selection->time[clicked_selection].start;
2138 jack_nframes_t end = selection->time[clicked_selection].end;
2140 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2142 boost::shared_ptr<AudioRegion> current;
2143 boost::shared_ptr<Region> current_r;
2145 jack_nframes_t internal_start;
2148 if ((playlist = (*i)->playlist()) == 0) {
2152 if ((current_r = playlist->top_region_at(start)) == 0) {
2156 if ((current = boost::dynamic_pointer_cast<AudioRegion>(current_r)) == 0) {
2160 internal_start = start - current->position();
2161 session->region_name (new_name, current->name(), true);
2163 new_regions.push_back (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (current, internal_start, end - start + 1, new_name)));
2168 Editor::split_multichannel_region ()
2170 vector<AudioRegion*> v;
2172 AudioRegionView* clicked_arv = dynamic_cast<AudioRegionView*>(clicked_regionview);
2174 if (!clicked_arv || clicked_arv->audio_region()->n_channels() < 2) {
2178 clicked_arv->audio_region()->separate_by_channel (*session, v);
2180 /* nothing else to do, really */
2184 Editor::new_region_from_selection ()
2186 region_from_selection ();
2187 cancel_selection ();
2191 Editor::separate_region_from_selection ()
2193 bool doing_undo = false;
2195 if (selection->time.empty()) {
2201 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2203 AudioTimeAxisView* atv;
2205 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2207 if (atv->is_audio_track()) {
2209 if ((playlist = atv->playlist()) != 0) {
2211 begin_reversible_command (_("separate"));
2216 before = &(playlist->get_state());
2218 /* XXX need to consider musical time selections here at some point */
2220 double speed = atv->get_diskstream()->speed();
2222 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2223 playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
2227 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2233 if (doing_undo) commit_reversible_command ();
2237 Editor::separate_regions_using_location (Location& loc)
2239 bool doing_undo = false;
2241 if (loc.is_mark()) {
2247 /* XXX i'm unsure as to whether this should operate on selected tracks only
2248 or the entire enchillada. uncomment the below line to correct the behaviour
2249 (currently set for all tracks)
2252 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2253 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2255 AudioTimeAxisView* atv;
2257 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2259 if (atv->is_audio_track()) {
2261 if ((playlist = atv->playlist()) != 0) {
2264 begin_reversible_command (_("separate"));
2268 before = &(playlist->get_state());
2271 /* XXX need to consider musical time selections here at some point */
2273 double speed = atv->get_diskstream()->speed();
2276 playlist->partition ((jack_nframes_t)(loc.start() * speed), (jack_nframes_t)(loc.end() * speed), true);
2278 session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
2284 if (doing_undo) commit_reversible_command ();
2288 Editor::crop_region_to_selection ()
2290 if (selection->time.empty()) {
2294 vector<Playlist*> playlists;
2297 if (clicked_trackview != 0) {
2299 if ((playlist = clicked_trackview->playlist()) == 0) {
2303 playlists.push_back (playlist);
2307 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2309 AudioTimeAxisView* atv;
2311 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2313 if (atv->is_audio_track()) {
2315 if ((playlist = atv->playlist()) != 0) {
2316 playlists.push_back (playlist);
2323 if (!playlists.empty()) {
2325 jack_nframes_t start;
2329 begin_reversible_command (_("trim to selection"));
2331 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2333 boost::shared_ptr<Region> region;
2335 start = selection->time.start();
2337 if ((region = (*i)->top_region_at(start)) == 0) {
2341 /* now adjust lengths to that we do the right thing
2342 if the selection extends beyond the region
2345 start = max (start, region->position());
2346 end = min (selection->time.end_frame(), start + region->length() - 1);
2347 cnt = end - start + 1;
2349 XMLNode &before = (*i)->get_state();
2350 region->trim_to (start, cnt, this);
2351 XMLNode &after = (*i)->get_state();
2352 session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
2355 commit_reversible_command ();
2360 Editor::region_fill_track ()
2364 if (!session || selection->regions.empty()) {
2368 end = session->current_end_frame ();
2370 begin_reversible_command (_("region fill"));
2372 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2374 boost::shared_ptr<Region> region ((*i)->region());
2377 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>(region);
2381 Playlist* pl = region->playlist();
2383 if (end <= region->last_frame()) {
2387 double times = (double) (end - region->last_frame()) / (double) region->length();
2393 XMLNode &before = pl->get_state();
2394 pl->add_region (RegionFactory::create (ar), ar->last_frame(), times);
2395 session->add_command (new MementoCommand<Playlist>(*pl, &before, &pl->get_state()));
2398 commit_reversible_command ();
2402 Editor::region_fill_selection ()
2404 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2408 if (selection->time.empty()) {
2413 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2415 if (selected->count_selected_rows() != 1) {
2419 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2420 boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
2422 jack_nframes_t start = selection->time[clicked_selection].start;
2423 jack_nframes_t end = selection->time[clicked_selection].end;
2427 if (selection->tracks.empty()) {
2431 jack_nframes_t selection_length = end - start;
2432 float times = (float)selection_length / region->length();
2434 begin_reversible_command (_("fill selection"));
2436 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2438 if ((playlist = (*i)->playlist()) == 0) {
2442 XMLNode &before = playlist->get_state();
2443 playlist->add_region (RegionFactory::create (region), start, times);
2444 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
2447 commit_reversible_command ();
2451 Editor::set_a_regions_sync_position (boost::shared_ptr<Region> region, jack_nframes_t position)
2454 if (!region->covers (position)) {
2455 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2458 begin_reversible_command (_("set region sync position"));
2459 XMLNode &before = region->playlist()->get_state();
2460 region->set_sync_position (position);
2461 XMLNode &after = region->playlist()->get_state();
2462 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2463 commit_reversible_command ();
2467 Editor::set_region_sync_from_edit_cursor ()
2469 if (clicked_regionview == 0) {
2473 if (!clicked_regionview->region()->covers (edit_cursor->current_frame)) {
2474 error << _("Place the edit cursor at the desired sync point") << endmsg;
2478 boost::shared_ptr<Region> region (clicked_regionview->region());
2479 begin_reversible_command (_("set sync from edit cursor"));
2480 XMLNode &before = region->playlist()->get_state();
2481 region->set_sync_position (edit_cursor->current_frame);
2482 XMLNode &after = region->playlist()->get_state();
2483 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2484 commit_reversible_command ();
2488 Editor::remove_region_sync ()
2490 if (clicked_regionview) {
2491 boost::shared_ptr<Region> region (clicked_regionview->region());
2492 begin_reversible_command (_("remove sync"));
2493 XMLNode &before = region->playlist()->get_state();
2494 region->clear_sync_position ();
2495 XMLNode &after = region->playlist()->get_state();
2496 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2497 commit_reversible_command ();
2502 Editor::naturalize ()
2504 if (selection->regions.empty()) {
2507 begin_reversible_command (_("naturalize"));
2508 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2509 XMLNode &before = (*i)->region()->get_state();
2510 (*i)->region()->move_to_natural_position (this);
2511 XMLNode &after = (*i)->region()->get_state();
2512 session->add_command (new MementoCommand<Region>(*((*i)->region().get()), &before, &after));
2514 commit_reversible_command ();
2518 Editor::align (RegionPoint what)
2520 align_selection (what, edit_cursor->current_frame);
2524 Editor::align_relative (RegionPoint what)
2526 align_selection_relative (what, edit_cursor->current_frame);
2529 struct RegionSortByTime {
2530 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2531 return a->region()->position() < b->region()->position();
2536 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
2538 if (selection->regions.empty()) {
2542 jack_nframes_t distance;
2543 jack_nframes_t pos = 0;
2546 list<RegionView*> sorted;
2547 selection->regions.by_position (sorted);
2548 boost::shared_ptr<Region> r ((*sorted.begin())->region());
2552 pos = r->first_frame ();
2556 pos = r->last_frame();
2560 pos = r->adjust_to_sync (r->first_frame());
2564 if (pos > position) {
2565 distance = pos - position;
2568 distance = position - pos;
2572 begin_reversible_command (_("align selection (relative)"));
2574 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2576 boost::shared_ptr<Region> region ((*i)->region());
2578 XMLNode &before = region->playlist()->get_state();
2581 region->set_position (region->position() + distance, this);
2583 region->set_position (region->position() - distance, this);
2586 XMLNode &after = region->playlist()->get_state();
2587 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2591 commit_reversible_command ();
2595 Editor::align_selection (RegionPoint point, jack_nframes_t position)
2597 if (selection->regions.empty()) {
2601 begin_reversible_command (_("align selection"));
2603 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2604 align_region_internal ((*i)->region(), point, position);
2607 commit_reversible_command ();
2611 Editor::align_region (boost::shared_ptr<Region> region, RegionPoint point, jack_nframes_t position)
2613 begin_reversible_command (_("align region"));
2614 align_region_internal (region, point, position);
2615 commit_reversible_command ();
2619 Editor::align_region_internal (boost::shared_ptr<Region> region, RegionPoint point, jack_nframes_t position)
2621 XMLNode &before = region->playlist()->get_state();
2625 region->set_position (region->adjust_to_sync (position), this);
2629 if (position > region->length()) {
2630 region->set_position (position - region->length(), this);
2635 region->set_position (position, this);
2639 XMLNode &after = region->playlist()->get_state();
2640 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2644 Editor::trim_region_to_edit_cursor ()
2646 if (clicked_regionview == 0) {
2650 boost::shared_ptr<Region> region (clicked_regionview->region());
2653 AudioTimeAxisView *atav;
2655 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2656 if (atav->get_diskstream() != 0) {
2657 speed = atav->get_diskstream()->speed();
2661 begin_reversible_command (_("trim to edit"));
2662 XMLNode &before = region->playlist()->get_state();
2663 region->trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2664 XMLNode &after = region->playlist()->get_state();
2665 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2666 commit_reversible_command ();
2670 Editor::trim_region_from_edit_cursor ()
2672 if (clicked_regionview == 0) {
2676 boost::shared_ptr<Region> region (clicked_regionview->region());
2679 AudioTimeAxisView *atav;
2681 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2682 if (atav->get_diskstream() != 0) {
2683 speed = atav->get_diskstream()->speed();
2687 begin_reversible_command (_("trim to edit"));
2688 XMLNode &before = region->playlist()->get_state();
2689 region->trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2690 XMLNode &after = region->playlist()->get_state();
2691 session->add_command(new MementoCommand<Playlist>(*(region->playlist()), &before, &after));
2692 commit_reversible_command ();
2696 Editor::unfreeze_route ()
2698 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2702 clicked_audio_trackview->audio_track()->unfreeze ();
2706 Editor::_freeze_thread (void* arg)
2708 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2709 return static_cast<Editor*>(arg)->freeze_thread ();
2713 Editor::freeze_thread ()
2715 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2720 Editor::freeze_progress_timeout (void *arg)
2722 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2723 return !(current_interthread_info->done || current_interthread_info->cancel);
2727 Editor::freeze_route ()
2729 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2733 InterThreadInfo itt;
2735 if (interthread_progress_window == 0) {
2736 build_interthread_progress_window ();
2739 interthread_progress_window->set_title (_("ardour: freeze"));
2740 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2741 interthread_progress_window->show_all ();
2742 interthread_progress_bar.set_fraction (0.0f);
2743 interthread_progress_label.set_text ("");
2744 interthread_cancel_label.set_text (_("Cancel Freeze"));
2745 current_interthread_info = &itt;
2747 interthread_progress_connection =
2748 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2752 itt.progress = 0.0f;
2754 pthread_create (&itt.thread, 0, _freeze_thread, this);
2756 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2758 while (!itt.done && !itt.cancel) {
2759 gtk_main_iteration ();
2762 interthread_progress_connection.disconnect ();
2763 interthread_progress_window->hide_all ();
2764 current_interthread_info = 0;
2765 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2769 Editor::bounce_range_selection ()
2771 if (selection->time.empty()) {
2775 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2777 jack_nframes_t start = selection->time[clicked_selection].start;
2778 jack_nframes_t end = selection->time[clicked_selection].end;
2779 jack_nframes_t cnt = end - start + 1;
2781 begin_reversible_command (_("bounce range"));
2783 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2785 AudioTimeAxisView* atv;
2787 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2793 if ((playlist = atv->playlist()) == 0) {
2797 InterThreadInfo itt;
2801 itt.progress = false;
2803 XMLNode &before = playlist->get_state();
2804 atv->audio_track()->bounce_range (start, cnt, itt);
2805 XMLNode &after = playlist->get_state();
2806 session->add_command (new MementoCommand<Playlist> (*playlist, &before, &after));
2809 commit_reversible_command ();
2827 Editor::cut_copy (CutCopyOp op)
2829 /* only cancel selection if cut/copy is successful.*/
2841 opname = _("clear");
2845 cut_buffer->clear ();
2847 switch (current_mouse_mode()) {
2849 if (!selection->regions.empty() || !selection->points.empty()) {
2851 begin_reversible_command (opname + _(" objects"));
2853 if (!selection->regions.empty()) {
2855 cut_copy_regions (op);
2858 selection->clear_regions ();
2862 if (!selection->points.empty()) {
2863 cut_copy_points (op);
2866 selection->clear_points ();
2870 commit_reversible_command ();
2875 if (!selection->time.empty()) {
2877 begin_reversible_command (opname + _(" range"));
2878 cut_copy_ranges (op);
2879 commit_reversible_command ();
2882 selection->clear_time ();
2894 Editor::cut_copy_points (CutCopyOp op)
2896 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2898 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2901 atv->cut_copy_clear_objects (selection->points, op);
2907 Editor::cut_copy_regions (CutCopyOp op)
2909 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
2910 PlaylistMapping pmap;
2911 jack_nframes_t first_position = max_frames;
2912 set<Playlist*> freezelist;
2913 pair<set<Playlist*>::iterator,bool> insert_result;
2915 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
2916 first_position = min ((*x)->region()->position(), first_position);
2918 if (op == Cut || op == Clear) {
2919 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region()->playlist());
2921 insert_result = freezelist.insert (pl);
2922 if (insert_result.second) {
2924 session->add_command (new MementoCommand<Playlist>(*pl, &pl->get_state(), 0));
2930 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
2932 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region()->playlist());
2934 RegionSelection::iterator tmp;
2941 PlaylistMapping::iterator pi = pmap.find (pl);
2943 if (pi == pmap.end()) {
2944 npl = new AudioPlaylist (*session, "cutlist", true);
2952 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion>((*x)->region());
2957 npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
2958 pl->remove_region (((*x)->region()));
2964 npl->add_region (RegionFactory::create (ar), (*x)->region()->position() - first_position);
2968 pl->remove_region (((*x)->region()));
2976 list<Playlist*> foo;
2978 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
2979 foo.push_back (i->second);
2983 cut_buffer->set (foo);
2986 for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
2988 session->add_command (new MementoCommand<Playlist>(*(*pl), 0, &(*pl)->get_state()));
2993 Editor::cut_copy_ranges (CutCopyOp op)
2995 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2996 (*i)->cut_copy_clear (*selection, op);
3001 Editor::paste (float times)
3003 paste_internal (edit_cursor->current_frame, times);
3007 Editor::mouse_paste ()
3012 track_canvas.get_pointer (x, y);
3013 track_canvas.window_to_world (x, y, wx, wy);
3014 wx += horizontal_adjustment.get_value();
3015 wy += vertical_adjustment.get_value();
3018 event.type = GDK_BUTTON_RELEASE;
3019 event.button.x = wx;
3020 event.button.y = wy;
3022 jack_nframes_t where = event_frame (&event, 0, 0);
3024 paste_internal (where, 1);
3028 Editor::paste_internal (jack_nframes_t position, float times)
3030 bool commit = false;
3032 if (cut_buffer->empty() || selection->tracks.empty()) {
3036 if (position == max_frames) {
3037 position = edit_cursor->current_frame;
3040 begin_reversible_command (_("paste"));
3042 TrackSelection::iterator i;
3045 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
3047 /* undo/redo is handled by individual tracks */
3049 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3055 commit_reversible_command ();
3060 Editor::paste_named_selection (float times)
3062 TrackSelection::iterator t;
3064 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3066 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3070 TreeModel::iterator i = selected->get_selected();
3071 NamedSelection* ns = (*i)[named_selection_columns.selection];
3073 list<Playlist*>::iterator chunk;
3074 list<Playlist*>::iterator tmp;
3076 chunk = ns->playlists.begin();
3078 begin_reversible_command (_("paste chunk"));
3080 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3082 AudioTimeAxisView* atv;
3086 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3090 if ((pl = atv->playlist()) == 0) {
3094 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
3101 XMLNode &before = apl->get_state();
3102 apl->paste (**chunk, edit_cursor->current_frame, times);
3103 session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
3105 if (tmp != ns->playlists.end()) {
3110 commit_reversible_command();
3114 Editor::duplicate_some_regions (RegionSelection& regions, float times)
3117 RegionSelection sel = regions; // clear (below) will clear the argument list
3119 begin_reversible_command (_("duplicate region"));
3121 selection->clear_regions ();
3123 for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3125 boost::shared_ptr<Region> r ((*i)->region());
3127 TimeAxisView& tv = (*i)->get_time_axis_view();
3128 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3129 sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3131 playlist = (*i)->region()->playlist();
3132 XMLNode &before = playlist->get_state();
3133 playlist->duplicate (r, r->last_frame(), times);
3134 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
3138 if (latest_regionview) {
3139 selection->add (latest_regionview);
3144 commit_reversible_command ();
3148 Editor::duplicate_selection (float times)
3150 if (selection->time.empty() || selection->tracks.empty()) {
3155 vector<boost::shared_ptr<AudioRegion> > new_regions;
3156 vector<boost::shared_ptr<AudioRegion> >::iterator ri;
3158 create_region_from_selection (new_regions);
3160 if (new_regions.empty()) {
3164 begin_reversible_command (_("duplicate selection"));
3166 ri = new_regions.begin();
3168 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3169 if ((playlist = (*i)->playlist()) == 0) {
3172 XMLNode &before = playlist->get_state();
3173 playlist->duplicate (*ri, selection->time[clicked_selection].end, times);
3174 XMLNode &after = playlist->get_state();
3175 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3178 if (ri == new_regions.end()) {
3183 commit_reversible_command ();
3187 Editor::reset_point_selection ()
3189 /* reset all selected points to the relevant default value */
3191 cerr << "point selection has " << selection->points.size() << " entries\n";
3193 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3195 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3198 atv->reset_objects (selection->points);
3204 Editor::center_playhead ()
3206 float page = canvas_width * frames_per_unit;
3208 center_screen_internal (playhead_cursor->current_frame, page);
3212 Editor::center_edit_cursor ()
3214 float page = canvas_width * frames_per_unit;
3216 center_screen_internal (edit_cursor->current_frame, page);
3220 Editor::clear_playlist (Playlist& playlist)
3222 begin_reversible_command (_("clear playlist"));
3223 XMLNode &before = playlist.get_state();
3225 XMLNode &after = playlist.get_state();
3226 session->add_command (new MementoCommand<Playlist>(playlist, &before, &after));
3227 commit_reversible_command ();
3231 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3234 jack_nframes_t distance;
3235 jack_nframes_t next_distance;
3236 jack_nframes_t start;
3238 if (use_edit_cursor) {
3239 start = edit_cursor->current_frame;
3244 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3248 if (selection->tracks.empty()) {
3252 begin_reversible_command (_("nudge track"));
3254 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3256 if ((playlist = (*i)->playlist()) == 0) {
3260 XMLNode &before = playlist->get_state();
3261 playlist->nudge_after (start, distance, forwards);
3262 XMLNode &after = playlist->get_state();
3263 session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
3266 commit_reversible_command ();
3270 Editor::remove_last_capture ()
3272 vector<string> choices;
3279 if (Config->get_verify_remove_last_capture()) {
3280 prompt = _("Do you really want to destroy the last capture?"
3281 "\n(This is destructive and cannot be undone)");
3283 choices.push_back (_("No, do nothing."));
3284 choices.push_back (_("Yes, destroy it."));
3286 Gtkmm2ext::Choice prompter (prompt, choices);
3288 if (prompter.run () == 1) {
3289 session->remove_last_capture ();
3293 session->remove_last_capture();
3298 Editor::normalize_region ()
3304 if (selection->regions.empty()) {
3308 begin_reversible_command (_("normalize"));
3310 track_canvas.get_window()->set_cursor (*wait_cursor);
3313 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3314 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3317 XMLNode &before = arv->region()->get_state();
3318 arv->audio_region()->normalize_to (0.0f);
3319 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3322 commit_reversible_command ();
3323 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3328 Editor::denormalize_region ()
3334 if (selection->regions.empty()) {
3338 begin_reversible_command ("denormalize");
3340 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3341 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3344 XMLNode &before = arv->region()->get_state();
3345 arv->audio_region()->set_scale_amplitude (1.0f);
3346 session->add_command (new MementoCommand<Region>(*(arv->region().get()), &before, &arv->region()->get_state()));
3349 commit_reversible_command ();
3354 Editor::reverse_region ()
3360 Reverse rev (*session);
3361 apply_filter (rev, _("reverse regions"));
3365 Editor::apply_filter (AudioFilter& filter, string command)
3367 if (selection->regions.empty()) {
3371 begin_reversible_command (command);
3373 track_canvas.get_window()->set_cursor (*wait_cursor);
3376 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
3377 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3381 Playlist* playlist = arv->region()->playlist();
3383 RegionSelection::iterator tmp;
3388 if (arv->audio_region()->apply (filter) == 0) {
3390 XMLNode &before = playlist->get_state();
3391 playlist->replace_region (arv->region(), filter.results.front(), arv->region()->position());
3392 XMLNode &after = playlist->get_state();
3393 session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
3401 commit_reversible_command ();
3402 selection->regions.clear ();
3405 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3409 Editor::region_selection_op (void (Region::*pmf)(void))
3411 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3412 Region* region = (*i)->region().get();
3419 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3421 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3422 Region* region = (*i)->region().get();
3423 (region->*pmf)(arg);
3428 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3430 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3431 Region* region = (*i)->region().get();
3437 Editor::external_edit_region ()
3439 if (!clicked_regionview) {
3447 Editor::brush (jack_nframes_t pos)
3449 RegionSelection sel;
3452 if (selection->regions.empty()) {
3453 /* XXX get selection from region list */
3455 sel = selection->regions;
3462 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3463 mouse_brush_insert_region ((*i), pos);
3468 Editor::toggle_gain_envelope_visibility ()
3470 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3471 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3473 arv->set_envelope_visible (!arv->envelope_visible());
3478 Editor::toggle_gain_envelope_active ()
3480 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3481 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3483 arv->audio_region()->set_envelope_active (true);