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>
32 #include <gtkmm2ext/utils.h>
33 #include <gtkmm2ext/choice.h>
35 #include <ardour/audioengine.h>
36 #include <ardour/session.h>
37 #include <ardour/audioplaylist.h>
38 #include <ardour/audioregion.h>
39 #include <ardour/diskstream.h>
40 #include <ardour/filesource.h>
41 #include <ardour/externalsource.h>
42 #include <ardour/utils.h>
43 #include <ardour/location.h>
44 #include <ardour/named_selection.h>
45 #include <ardour/audio_track.h>
46 #include <ardour/audioplaylist.h>
47 #include <ardour/region_factory.h>
48 #include <ardour/reverse.h>
50 #include "ardour_ui.h"
52 #include "time_axis_view.h"
53 #include "audio_time_axis.h"
54 #include "automation_time_axis.h"
55 #include "streamview.h"
56 #include "regionview.h"
57 #include "rgb_macros.h"
58 #include "selection_templates.h"
59 #include "selection.h"
62 #include "gtk-custom-hruler.h"
63 #include "gui_thread.h"
68 using namespace ARDOUR;
71 using namespace Editing;
73 /***********************************************************************
75 ***********************************************************************/
78 Editor::undo (uint32_t n)
86 Editor::redo (uint32_t n)
94 Editor::set_meter_hold (int32_t cnt)
96 Config->set_meter_hold_off(false);
97 Config->set_meter_hold_short(false);
98 Config->set_meter_hold_medium(false);
99 Config->set_meter_hold_long(false);
104 Config->set_meter_hold_off(true);
107 Config->set_meter_hold_short(true);
110 Config->set_meter_hold_medium(true);
113 Config->set_meter_hold_long(true);
118 session->set_meter_hold (cnt);
123 Editor::set_meter_falloff (int intval)
127 cerr << "set_meter_falloff () called: intval = " << intval << endl;
128 Config->set_meter_falloff_off(false);
129 Config->set_meter_falloff_slowest(false);
130 Config->set_meter_falloff_slow(false);
131 Config->set_meter_falloff_medium(false);
132 Config->set_meter_falloff_fast(false);
133 Config->set_meter_falloff_faster(false);
134 Config->set_meter_falloff_fastest(false);
140 Config->set_meter_falloff_off(true);
144 Config->set_meter_falloff_slowest(true);
148 Config->set_meter_falloff_slow(true);
152 Config->set_meter_falloff_medium(true);
156 Config->set_meter_falloff_fast(true);
160 Config->set_meter_falloff_faster(true);
164 Config->set_meter_falloff_fastest(true);
169 session->set_meter_falloff (val);
175 Editor::ensure_cursor (jack_nframes_t *pos)
177 *pos = edit_cursor->current_frame;
182 Editor::split_region ()
184 split_region_at (edit_cursor->current_frame);
188 Editor::split_region_at (jack_nframes_t where)
190 split_regions_at (where, selection->audio_regions);
194 Editor::split_regions_at (jack_nframes_t where, AudioRegionSelection& regions)
196 begin_reversible_command (_("split"));
199 for (AudioRegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
201 AudioRegionSelection::iterator tmp;
206 Playlist* pl = (*a)->region.playlist();
208 _new_regionviews_show_envelope = (*a)->envelope_visible();
211 session->add_undo (pl->get_memento());
212 pl->split_region ((*a)->region, where);
213 session->add_redo_no_execute (pl->get_memento());
219 commit_reversible_command ();
220 _new_regionviews_show_envelope = false;
224 Editor::remove_clicked_region ()
226 if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
230 Playlist* playlist = clicked_audio_trackview->playlist();
232 begin_reversible_command (_("remove region"));
233 session->add_undo (playlist->get_memento());
234 playlist->remove_region (&clicked_regionview->region);
235 session->add_redo_no_execute (playlist->get_memento());
236 commit_reversible_command ();
240 Editor::destroy_clicked_region ()
242 int32_t selected = selection->audio_regions.size();
244 if (!session || clicked_regionview == 0 && selected == 0) {
248 vector<string> choices;
251 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
252 It cannot be undone\n\
253 Do you really want to destroy %1 ?"),
255 _("these regions") : _("this region")));
257 choices.push_back (_("No, do nothing."));
260 choices.push_back (_("Yes, destroy them."));
262 choices.push_back (_("Yes, destroy it."));
265 Gtkmm2ext::Choice prompter (prompt, choices);
267 if (prompter.run() == 0) { /* first choice */
274 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
275 r.push_back (&(*i)->region);
278 session->destroy_regions (r);
280 } else if (clicked_regionview) {
281 session->destroy_region (&clicked_regionview->region);
286 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
290 jack_nframes_t start = 0;
292 if (selection->time.start () == selection->time.end_frame ()) {
294 /* no current selection-> is there a selected regionview? */
296 if (selection->audio_regions.empty()) {
304 if (!selection->audio_regions.empty()) {
306 rv = *(selection->audio_regions.begin());
307 (*tv) = &rv->get_time_axis_view();
308 region = &rv->region;
310 } else if (!selection->tracks.empty()) {
312 (*tv) = selection->tracks.front();
314 AudioTimeAxisView* atv;
316 if ((atv = dynamic_cast<AudioTimeAxisView*> (*tv)) != 0) {
319 if ((pl = atv->playlist()) == 0) {
323 region = dynamic_cast<AudioRegion*> (pl->top_region_at (start));
331 Editor::extend_selection_to_end_of_region (bool next)
335 jack_nframes_t start;
337 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
341 if (region && selection->time.start () == selection->time.end_frame ()) {
342 start = region->position();
344 start = selection->time.start ();
347 /* Try to leave the selection with the same route if possible */
349 if ((tv = selection->time.track) == 0) {
353 begin_reversible_command (_("extend selection"));
354 selection->set (tv, start, region->position() + region->length());
355 commit_reversible_command ();
359 Editor::extend_selection_to_start_of_region (bool previous)
365 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
369 if (region && selection->time.start () == selection->time.end_frame ()) {
370 end = region->position() + region->length();
372 end = selection->time.end_frame ();
375 /* Try to leave the selection with the same route if possible */
377 if ((tv = selection->time.track) == 0) {
381 begin_reversible_command (_("extend selection"));
382 selection->set (tv, region->position(), end);
383 commit_reversible_command ();
388 Editor::nudge_forward (bool next)
390 jack_nframes_t distance;
391 jack_nframes_t next_distance;
393 if (!session) return;
395 if (!selection->audio_regions.empty()) {
397 begin_reversible_command (_("nudge forward"));
399 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
400 AudioRegion& r ((*i)->region);
402 distance = get_nudge_distance (r.position(), next_distance);
405 distance = next_distance;
408 session->add_undo (r.playlist()->get_memento());
409 r.set_position (r.position() + distance, this);
410 session->add_redo_no_execute (r.playlist()->get_memento());
413 commit_reversible_command ();
416 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
417 session->request_locate (playhead_cursor->current_frame + distance);
422 Editor::nudge_backward (bool next)
424 jack_nframes_t distance;
425 jack_nframes_t next_distance;
427 if (!session) return;
429 if (!selection->audio_regions.empty()) {
431 begin_reversible_command (_("nudge forward"));
433 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
434 AudioRegion& r ((*i)->region);
436 distance = get_nudge_distance (r.position(), next_distance);
439 distance = next_distance;
442 session->add_undo (r.playlist()->get_memento());
444 if (r.position() > distance) {
445 r.set_position (r.position() - distance, this);
447 r.set_position (0, this);
449 session->add_redo_no_execute (r.playlist()->get_memento());
452 commit_reversible_command ();
456 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
458 if (playhead_cursor->current_frame > distance) {
459 session->request_locate (playhead_cursor->current_frame - distance);
461 session->goto_start();
467 Editor::nudge_forward_capture_offset ()
469 jack_nframes_t distance;
471 if (!session) return;
473 if (!selection->audio_regions.empty()) {
475 begin_reversible_command (_("nudge forward"));
477 distance = session->worst_output_latency();
479 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
480 AudioRegion& r ((*i)->region);
482 session->add_undo (r.playlist()->get_memento());
483 r.set_position (r.position() + distance, this);
484 session->add_redo_no_execute (r.playlist()->get_memento());
487 commit_reversible_command ();
493 Editor::nudge_backward_capture_offset ()
495 jack_nframes_t distance;
497 if (!session) return;
499 if (!selection->audio_regions.empty()) {
501 begin_reversible_command (_("nudge forward"));
503 distance = session->worst_output_latency();
505 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
506 AudioRegion& r ((*i)->region);
508 session->add_undo (r.playlist()->get_memento());
510 if (r.position() > distance) {
511 r.set_position (r.position() - distance, this);
513 r.set_position (0, this);
515 session->add_redo_no_execute (r.playlist()->get_memento());
518 commit_reversible_command ();
525 Editor::move_to_start ()
527 session->goto_start ();
531 Editor::move_to_end ()
534 session->request_locate (session->current_end_frame());
538 Editor::build_region_boundary_cache ()
540 jack_nframes_t pos = 0;
543 TrackViewList tracks;
545 region_boundary_cache.clear ();
552 case SnapToRegionStart:
555 case SnapToRegionEnd:
558 case SnapToRegionSync:
561 case SnapToRegionBoundary:
565 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
570 TimeAxisView *ontrack = 0;
572 while (pos < session->current_end_frame()) {
574 if (!selection->tracks.empty()) {
576 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
580 } else if (clicked_trackview) {
583 t.push_back (clicked_trackview);
585 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
591 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
599 case SnapToRegionStart:
600 rpos = r->first_frame();
602 case SnapToRegionEnd:
603 rpos = r->last_frame();
605 case SnapToRegionSync:
606 rpos = r->adjust_to_sync (r->first_frame());
609 case SnapToRegionBoundary:
610 rpos = r->last_frame();
617 AudioTimeAxisView *atav;
619 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
620 if (atav->get_diskstream() != 0) {
621 speed = atav->get_diskstream()->speed();
625 rpos = track_frame_to_session_frame(rpos, speed);
627 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
628 if (snap_type == SnapToRegionBoundary) {
629 region_boundary_cache.push_back (r->first_frame());
631 region_boundary_cache.push_back (rpos);
639 Editor::find_next_region (jack_nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
641 TrackViewList::iterator i;
642 jack_nframes_t closest = max_frames;
644 jack_nframes_t rpos = 0;
647 jack_nframes_t track_frame;
648 AudioTimeAxisView *atav;
650 for (i = tracks.begin(); i != tracks.end(); ++i) {
652 jack_nframes_t distance;
656 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
657 if (atav->get_diskstream()!=0)
658 track_speed = atav->get_diskstream()->speed();
661 track_frame = session_frame_to_track_frame(frame, track_speed);
663 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
669 rpos = r->first_frame ();
673 rpos = r->last_frame ();
677 rpos = r->adjust_to_sync (r->first_frame());
680 // rpos is a "track frame", converting it to "session frame"
681 rpos = track_frame_to_session_frame(rpos, track_speed);
684 distance = rpos - frame;
686 distance = frame - rpos;
689 if (distance < closest) {
701 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
704 jack_nframes_t pos = cursor->current_frame;
710 TimeAxisView *ontrack = 0;
712 // so we don't find the current region again..
716 if (!selection->tracks.empty()) {
718 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
720 } else if (clicked_trackview) {
723 t.push_back (clicked_trackview);
725 r = find_next_region (pos, point, dir, t, &ontrack);
729 r = find_next_region (pos, point, dir, track_views, &ontrack);
738 pos = r->first_frame ();
742 pos = r->last_frame ();
746 pos = r->adjust_to_sync (r->first_frame());
751 AudioTimeAxisView *atav;
753 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
754 if (atav->get_diskstream() != 0) {
755 speed = atav->get_diskstream()->speed();
759 pos = track_frame_to_session_frame(pos, speed);
761 if (cursor == playhead_cursor) {
762 session->request_locate (pos);
764 cursor->set_position (pos);
769 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
771 cursor_to_region_point (cursor, point, 1);
775 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
777 cursor_to_region_point (cursor, point, -1);
781 Editor::cursor_to_selection_start (Cursor *cursor)
783 jack_nframes_t pos = 0;
784 switch (mouse_mode) {
786 if (!selection->audio_regions.empty()) {
787 pos = selection->audio_regions.start();
792 if (!selection->time.empty()) {
793 pos = selection->time.start ();
801 if (cursor == playhead_cursor) {
802 session->request_locate (pos);
804 cursor->set_position (pos);
809 Editor::cursor_to_selection_end (Cursor *cursor)
811 jack_nframes_t pos = 0;
813 switch (mouse_mode) {
815 if (!selection->audio_regions.empty()) {
816 pos = selection->audio_regions.end_frame();
821 if (!selection->time.empty()) {
822 pos = selection->time.end_frame ();
830 if (cursor == playhead_cursor) {
831 session->request_locate (pos);
833 cursor->set_position (pos);
838 Editor::playhead_backward ()
845 if (get_prefix (prefix, was_floating)) {
849 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
851 cnt = (jack_nframes_t) prefix;
855 pos = playhead_cursor->current_frame;
857 if ((jack_nframes_t) pos < cnt) {
863 /* XXX this is completely insane. with the current buffering
864 design, we'll force a complete track buffer flush and
865 reload, just to move 1 sample !!!
868 session->request_locate (pos);
872 Editor::playhead_forward ()
879 if (get_prefix (prefix, was_floating)) {
883 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
885 cnt = (jack_nframes_t) floor (prefix);
889 pos = playhead_cursor->current_frame;
891 /* XXX this is completely insane. with the current buffering
892 design, we'll force a complete track buffer flush and
893 reload, just to move 1 sample !!!
896 session->request_locate (pos+cnt);
900 Editor::cursor_align (bool playhead_to_edit)
902 if (playhead_to_edit) {
904 session->request_locate (edit_cursor->current_frame);
907 edit_cursor->set_position (playhead_cursor->current_frame);
912 Editor::edit_cursor_backward ()
919 if (get_prefix (prefix, was_floating)) {
923 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
925 cnt = (jack_nframes_t) prefix;
929 pos = edit_cursor->current_frame;
931 if ((jack_nframes_t) pos < cnt) {
937 edit_cursor->set_position (pos);
941 Editor::edit_cursor_forward ()
948 if (get_prefix (prefix, was_floating)) {
952 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
954 cnt = (jack_nframes_t) floor (prefix);
958 pos = edit_cursor->current_frame;
959 edit_cursor->set_position (pos+cnt);
963 Editor::goto_frame ()
967 jack_nframes_t frame;
969 if (get_prefix (prefix, was_floating)) {
974 frame = (jack_nframes_t) floor (prefix * session->frame_rate());
976 frame = (jack_nframes_t) floor (prefix);
979 session->request_locate (frame);
983 Editor::scroll_backward (float pages)
985 jack_nframes_t frame;
986 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
991 if (get_prefix (prefix, was_floating)) {
992 cnt = (jack_nframes_t) floor (pages * one_page);
995 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
997 cnt = (jack_nframes_t) floor (prefix * one_page);
1001 if (leftmost_frame < cnt) {
1004 frame = leftmost_frame - cnt;
1007 reposition_x_origin (frame);
1011 Editor::scroll_forward (float pages)
1013 jack_nframes_t frame;
1014 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
1019 if (get_prefix (prefix, was_floating)) {
1020 cnt = (jack_nframes_t) floor (pages * one_page);
1023 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
1025 cnt = (jack_nframes_t) floor (prefix * one_page);
1029 if (ULONG_MAX - cnt < leftmost_frame) {
1030 frame = ULONG_MAX - cnt;
1032 frame = leftmost_frame + cnt;
1035 reposition_x_origin (frame);
1039 Editor::scroll_tracks_down ()
1045 if (get_prefix (prefix, was_floating)) {
1048 cnt = (int) floor (prefix);
1051 double vert_value = vertical_adjustment.get_value() + (cnt *
1052 vertical_adjustment.get_page_size());
1053 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
1054 vert_value = vertical_adjustment.get_upper() - canvas_height;
1056 vertical_adjustment.set_value (vert_value);
1060 Editor::scroll_tracks_up ()
1066 if (get_prefix (prefix, was_floating)) {
1069 cnt = (int) floor (prefix);
1072 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1076 Editor::scroll_tracks_down_line ()
1079 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1080 double vert_value = adj->get_value() + 20;
1082 if (vert_value>adj->get_upper() - canvas_height) {
1083 vert_value = adj->get_upper() - canvas_height;
1085 adj->set_value (vert_value);
1089 Editor::scroll_tracks_up_line ()
1091 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1092 adj->set_value (adj->get_value() - 20);
1098 Editor::temporal_zoom_step (bool coarser)
1100 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1104 nfpu = frames_per_unit;
1109 nfpu = max(1.0,(nfpu/2.0));
1112 temporal_zoom (nfpu);
1116 Editor::temporal_zoom (gdouble fpu)
1118 if (!session) return;
1120 jack_nframes_t current_page = current_page_frames();
1121 jack_nframes_t current_leftmost = leftmost_frame;
1122 jack_nframes_t current_rightmost;
1123 jack_nframes_t current_center;
1124 jack_nframes_t new_page;
1125 jack_nframes_t leftmost_after_zoom = 0;
1130 new_page = (jack_nframes_t) floor (canvas_width * nfpu);
1132 switch (zoom_focus) {
1134 leftmost_after_zoom = current_leftmost;
1137 case ZoomFocusRight:
1138 current_rightmost = leftmost_frame + current_page;
1139 if (current_rightmost > new_page) {
1140 leftmost_after_zoom = current_rightmost - new_page;
1142 leftmost_after_zoom = 0;
1146 case ZoomFocusCenter:
1147 current_center = current_leftmost + (current_page/2);
1148 if (current_center > (new_page/2)) {
1149 leftmost_after_zoom = current_center - (new_page / 2);
1151 leftmost_after_zoom = 0;
1155 case ZoomFocusPlayhead:
1156 /* try to keep the playhead in the center */
1157 if (playhead_cursor->current_frame > new_page/2) {
1158 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1160 leftmost_after_zoom = 0;
1165 /* try to keep the edit cursor in the center */
1166 if (edit_cursor->current_frame > leftmost_frame + (new_page/2)) {
1167 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1169 leftmost_after_zoom = 0;
1175 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1177 // begin_reversible_command (_("zoom"));
1178 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1179 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1180 // commit_reversible_command ();
1182 reposition_and_zoom (leftmost_after_zoom, nfpu);
1186 Editor::temporal_zoom_selection ()
1188 if (!selection) return;
1190 if (selection->time.empty()) {
1194 jack_nframes_t start = selection->time[clicked_selection].start;
1195 jack_nframes_t end = selection->time[clicked_selection].end;
1197 temporal_zoom_by_frame (start, end, "zoom to selection");
1201 Editor::temporal_zoom_session ()
1203 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1206 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1211 Editor::temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, const string & op)
1213 if (!session) return;
1215 if ((start == 0 && end == 0) || end < start) {
1219 jack_nframes_t range = end - start;
1221 double new_fpu = (double)range / (double)canvas_width;
1224 // while (p2 < new_fpu) {
1229 jack_nframes_t new_page = (jack_nframes_t) floor (canvas_width * new_fpu);
1230 jack_nframes_t middle = (jack_nframes_t) floor( (double)start + ((double)range / 2.0f ));
1231 jack_nframes_t new_leftmost = (jack_nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1233 if (new_leftmost > middle) new_leftmost = 0;
1235 // begin_reversible_command (op);
1236 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1237 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1238 // commit_reversible_command ();
1240 reposition_and_zoom (new_leftmost, new_fpu);
1244 Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
1246 if (!session) return;
1248 jack_nframes_t range_before = frame - leftmost_frame;
1251 new_fpu = frames_per_unit;
1257 new_fpu = max(1.0,(new_fpu/2.0));
1261 if (new_fpu == frames_per_unit) return;
1263 jack_nframes_t new_leftmost = frame - range_before;
1265 if (new_leftmost > frame) new_leftmost = 0;
1267 // begin_reversible_command (_("zoom to frame"));
1268 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1269 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1270 // commit_reversible_command ();
1272 reposition_and_zoom (new_leftmost, new_fpu);
1276 Editor::add_location_from_selection ()
1278 if (selection->time.empty()) {
1282 if (session == 0 || clicked_trackview == 0) {
1286 jack_nframes_t start = selection->time[clicked_selection].start;
1287 jack_nframes_t end = selection->time[clicked_selection].end;
1289 Location *location = new Location (start, end, "selection");
1291 session->begin_reversible_command (_("add marker"));
1292 session->add_undo (session->locations()->get_memento());
1293 session->locations()->add (location, true);
1294 session->add_redo_no_execute (session->locations()->get_memento());
1295 session->commit_reversible_command ();
1299 Editor::add_location_from_playhead_cursor ()
1301 jack_nframes_t where = session->audible_frame();
1303 Location *location = new Location (where, where, "mark", Location::IsMark);
1304 session->begin_reversible_command (_("add marker"));
1305 session->add_undo (session->locations()->get_memento());
1306 session->locations()->add (location, true);
1307 session->add_redo_no_execute (session->locations()->get_memento());
1308 session->commit_reversible_command ();
1312 Editor::add_location_from_audio_region ()
1314 if (selection->audio_regions.empty()) {
1318 AudioRegionView* rv = *(selection->audio_regions.begin());
1319 Region& region = rv->region;
1321 Location *location = new Location (region.position(), region.last_frame(), region.name());
1322 session->begin_reversible_command (_("add marker"));
1323 session->add_undo (session->locations()->get_memento());
1324 session->locations()->add (location, true);
1325 session->add_redo_no_execute (session->locations()->get_memento());
1326 session->commit_reversible_command ();
1330 Editor::select_all_in_track (Selection::Operation op)
1332 list<Selectable *> touched;
1334 if (!clicked_trackview) {
1338 clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1341 case Selection::Toggle:
1342 selection->add (touched);
1344 case Selection::Set:
1345 selection->set (touched);
1347 case Selection::Extend:
1348 /* not defined yet */
1354 Editor::select_all (Selection::Operation op)
1356 list<Selectable *> touched;
1358 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1359 if ((*iter)->hidden()) {
1362 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1364 begin_reversible_command (_("select all"));
1366 case Selection::Toggle:
1367 selection->add (touched);
1369 case Selection::Set:
1370 selection->set (touched);
1372 case Selection::Extend:
1373 /* not defined yet */
1376 commit_reversible_command ();
1380 Editor::invert_selection_in_track ()
1382 list<Selectable *> touched;
1384 if (!clicked_trackview) {
1388 clicked_trackview->get_inverted_selectables (*selection, touched);
1389 selection->set (touched);
1393 Editor::invert_selection ()
1395 list<Selectable *> touched;
1397 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1398 if ((*iter)->hidden()) {
1401 (*iter)->get_inverted_selectables (*selection, touched);
1404 selection->set (touched);
1408 Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, Selection::Operation op)
1410 list<Selectable *> touched;
1412 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1413 if ((*iter)->hidden()) {
1416 (*iter)->get_selectables (start, end, top, bot, touched);
1419 cerr << "select all within found " << touched.size() << endl;
1421 begin_reversible_command (_("select all within"));
1423 case Selection::Toggle:
1425 selection->add (touched);
1427 case Selection::Set:
1429 selection->set (touched);
1431 case Selection::Extend:
1433 /* not defined yet */
1437 cerr << "selection now has " << selection->points.size() << endl;
1439 commit_reversible_command ();
1440 return !touched.empty();
1444 Editor::set_selection_from_audio_region ()
1446 if (selection->audio_regions.empty()) {
1450 AudioRegionView* rv = *(selection->audio_regions.begin());
1451 Region& region = rv->region;
1453 begin_reversible_command (_("set selection from region"));
1454 selection->set (0, region.position(), region.last_frame());
1455 commit_reversible_command ();
1457 set_mouse_mode (Editing::MouseRange, false);
1461 Editor::set_selection_from_punch()
1465 if ((location = session->locations()->auto_punch_location()) == 0) {
1469 set_selection_from_range (*location);
1473 Editor::set_selection_from_loop()
1477 if ((location = session->locations()->auto_loop_location()) == 0) {
1480 set_selection_from_range (*location);
1484 Editor::set_selection_from_range (Location& loc)
1486 begin_reversible_command (_("set selection from range"));
1487 selection->set (0, loc.start(), loc.end());
1488 commit_reversible_command ();
1490 set_mouse_mode (Editing::MouseRange, false);
1494 Editor::select_all_selectables_using_time_selection ()
1496 list<Selectable *> touched;
1498 if (selection->time.empty()) {
1502 jack_nframes_t start = selection->time[clicked_selection].start;
1503 jack_nframes_t end = selection->time[clicked_selection].end;
1505 if (end - start < 1) {
1509 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1510 if ((*iter)->hidden()) {
1513 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1516 begin_reversible_command (_("select all from range"));
1517 selection->set (touched);
1518 commit_reversible_command ();
1523 Editor::select_all_selectables_using_punch()
1525 Location* location = session->locations()->auto_punch_location();
1526 list<Selectable *> touched;
1528 if (location == 0 || (location->end() - location->start() <= 1)) {
1532 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1533 if ((*iter)->hidden()) {
1536 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1538 begin_reversible_command (_("select all from punch"));
1539 selection->set (touched);
1540 commit_reversible_command ();
1545 Editor::select_all_selectables_using_loop()
1547 Location* location = session->locations()->auto_loop_location();
1548 list<Selectable *> touched;
1550 if (location == 0 || (location->end() - location->start() <= 1)) {
1554 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1555 if ((*iter)->hidden()) {
1558 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1560 begin_reversible_command (_("select all from loop"));
1561 selection->set (touched);
1562 commit_reversible_command ();
1567 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1569 jack_nframes_t start;
1571 list<Selectable *> touched;
1574 begin_reversible_command (_("select all after cursor"));
1575 start = cursor->current_frame ;
1576 end = session->current_end_frame();
1578 if (cursor->current_frame > 0) {
1579 begin_reversible_command (_("select all before cursor"));
1581 end = cursor->current_frame - 1;
1587 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1588 if ((*iter)->hidden()) {
1591 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1593 selection->set (touched);
1594 commit_reversible_command ();
1598 Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
1600 jack_nframes_t start;
1602 list<Selectable *> touched;
1603 bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
1605 if (cursor->current_frame == other_cursor->current_frame) {
1609 begin_reversible_command (_("select all between cursors"));
1610 if (other_cursor_is_first) {
1611 start = other_cursor->current_frame;
1612 end = cursor->current_frame - 1;
1615 start = cursor->current_frame;
1616 end = other_cursor->current_frame - 1;
1619 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1620 if ((*iter)->hidden()) {
1623 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1625 selection->set (touched);
1626 commit_reversible_command ();
1630 Editor::amplitude_zoom_step (bool in)
1644 #ifdef FIX_FOR_CANVAS
1645 /* XXX DO SOMETHING */
1654 Editor::delete_sample_forward ()
1659 Editor::delete_sample_backward ()
1664 Editor::delete_screen ()
1671 Editor::search_backwards ()
1677 Editor::search_forwards ()
1685 Editor::jump_forward_to_mark ()
1691 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1694 session->request_locate (location->start(), session->transport_rolling());
1696 session->request_locate (session->current_end_frame());
1701 Editor::jump_backward_to_mark ()
1707 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1710 session->request_locate (location->start(), session->transport_rolling());
1712 session->goto_start ();
1723 if (get_prefix (prefix, was_floating)) {
1724 pos = session->audible_frame ();
1727 pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
1729 pos = (jack_nframes_t) floor (prefix);
1733 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1737 Editor::clear_markers ()
1740 session->begin_reversible_command (_("clear markers"));
1741 session->add_undo (session->locations()->get_memento());
1742 session->locations()->clear_markers ();
1743 session->add_redo_no_execute (session->locations()->get_memento());
1744 session->commit_reversible_command ();
1749 Editor::clear_ranges ()
1752 session->begin_reversible_command (_("clear ranges"));
1753 session->add_undo (session->locations()->get_memento());
1755 Location * looploc = session->locations()->auto_loop_location();
1756 Location * punchloc = session->locations()->auto_punch_location();
1758 session->locations()->clear_ranges ();
1760 if (looploc) session->locations()->add (looploc);
1761 if (punchloc) session->locations()->add (punchloc);
1763 session->add_redo_no_execute (session->locations()->get_memento());
1764 session->commit_reversible_command ();
1769 Editor::clear_locations ()
1771 session->begin_reversible_command (_("clear locations"));
1772 session->add_undo (session->locations()->get_memento());
1773 session->locations()->clear ();
1774 session->add_redo_no_execute (session->locations()->get_memento());
1775 session->commit_reversible_command ();
1776 session->locations()->clear ();
1779 /* INSERT/REPLACE */
1782 Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
1787 jack_nframes_t where;
1788 AudioTimeAxisView *atv = 0;
1791 track_canvas.window_to_world (x, y, wx, wy);
1792 wx += horizontal_adjustment.get_value();
1793 wy += vertical_adjustment.get_value();
1796 event.type = GDK_BUTTON_RELEASE;
1797 event.button.x = wx;
1798 event.button.y = wy;
1800 where = event_frame (&event, &cx, &cy);
1802 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1803 /* clearly outside canvas area */
1807 if ((tv = trackview_by_y_position (cy)) == 0) {
1811 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1815 if ((playlist = atv->playlist()) == 0) {
1821 begin_reversible_command (_("insert dragged region"));
1822 session->add_undo (playlist->get_memento());
1823 playlist->add_region (*(new AudioRegion (region)), where, 1.0);
1824 session->add_redo_no_execute (playlist->get_memento());
1825 commit_reversible_command ();
1829 Editor::insert_region_list_selection (float times)
1831 AudioTimeAxisView *tv = 0;
1834 if (clicked_audio_trackview != 0) {
1835 tv = clicked_audio_trackview;
1836 } else if (!selection->tracks.empty()) {
1837 if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
1844 if ((playlist = tv->playlist()) == 0) {
1848 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1850 if (selected->count_selected_rows() != 1) {
1854 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
1855 Region* region = (*i)[region_list_columns.region];
1857 begin_reversible_command (_("insert region"));
1858 session->add_undo (playlist->get_memento());
1859 playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
1860 session->add_redo_no_execute (playlist->get_memento());
1861 commit_reversible_command ();
1865 /* BUILT-IN EFFECTS */
1868 Editor::reverse_selection ()
1873 /* GAIN ENVELOPE EDITING */
1876 Editor::edit_envelope ()
1883 Editor::toggle_playback (bool with_abort)
1889 switch (session->slave_source()) {
1894 /* transport controlled by the master */
1898 if (session->is_auditioning()) {
1899 session->cancel_audition ();
1903 if (session->transport_rolling()) {
1904 session->request_stop (with_abort);
1905 if (session->get_auto_loop()) {
1906 session->request_auto_loop (false);
1909 session->request_transport_speed (1.0f);
1914 Editor::play_from_start ()
1916 session->request_locate (session->current_start_frame(), true);
1920 Editor::play_selection ()
1922 if (selection->time.empty()) {
1926 session->request_play_range (true);
1930 Editor::play_selected_region ()
1932 if (!selection->audio_regions.empty()) {
1933 AudioRegionView *rv = *(selection->audio_regions.begin());
1935 session->request_bounded_roll (rv->region.position(), rv->region.last_frame());
1940 Editor::loop_selected_region ()
1942 if (!selection->audio_regions.empty()) {
1943 AudioRegionView *rv = *(selection->audio_regions.begin());
1946 if ((tll = transport_loop_location()) != 0) {
1948 tll->set (rv->region.position(), rv->region.last_frame());
1950 // enable looping, reposition and start rolling
1952 session->request_auto_loop (true);
1953 session->request_locate (tll->start(), false);
1954 session->request_transport_speed (1.0f);
1960 Editor::play_location (Location& location)
1962 if (location.start() <= location.end()) {
1966 session->request_bounded_roll (location.start(), location.end());
1970 Editor::loop_location (Location& location)
1972 if (location.start() <= location.end()) {
1978 if ((tll = transport_loop_location()) != 0) {
1979 tll->set (location.start(), location.end());
1981 // enable looping, reposition and start rolling
1982 session->request_auto_loop (true);
1983 session->request_locate (tll->start(), true);
1988 Editor::toggle_region_mute ()
1990 if (clicked_regionview) {
1991 clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
1992 } else if (!selection->audio_regions.empty()) {
1993 bool yn = ! (*selection->audio_regions.begin())->region.muted();
1994 selection->foreach_audio_region (&AudioRegion::set_muted, yn);
1999 Editor::toggle_region_opaque ()
2001 if (clicked_regionview) {
2002 clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
2003 } else if (!selection->audio_regions.empty()) {
2004 bool yn = ! (*selection->audio_regions.begin())->region.opaque();
2005 selection->foreach_audio_region (&Region::set_opaque, yn);
2010 Editor::raise_region ()
2012 selection->foreach_audio_region (&Region::raise);
2016 Editor::raise_region_to_top ()
2018 selection->foreach_audio_region (&Region::raise_to_top);
2022 Editor::lower_region ()
2024 selection->foreach_audio_region (&Region::lower);
2028 Editor::lower_region_to_bottom ()
2030 selection->foreach_audio_region (&Region::lower_to_bottom);
2034 Editor::edit_region ()
2036 if (clicked_regionview == 0) {
2040 clicked_regionview->show_region_editor ();
2044 Editor::rename_region ()
2048 Button ok_button (_("OK"));
2049 Button cancel_button (_("Cancel"));
2051 if (selection->audio_regions.empty()) {
2055 dialog.set_title (_("ardour: rename region"));
2056 dialog.set_name ("RegionRenameWindow");
2057 dialog.set_size_request (300, -1);
2058 dialog.set_position (Gtk::WIN_POS_MOUSE);
2059 dialog.set_modal (true);
2061 dialog.get_vbox()->set_border_width (10);
2062 dialog.get_vbox()->pack_start (entry);
2063 dialog.get_action_area()->pack_start (ok_button);
2064 dialog.get_action_area()->pack_start (cancel_button);
2066 entry.set_name ("RegionNameDisplay");
2067 ok_button.set_name ("EditorGTKButton");
2068 cancel_button.set_name ("EditorGTKButton");
2070 region_renamed = false;
2072 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2073 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2074 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
2081 if (region_renamed) {
2082 (*selection->audio_regions.begin())->region.set_name (entry.get_text());
2083 redisplay_regions ();
2088 Editor::rename_region_finished (bool status)
2091 region_renamed = status;
2096 Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
2098 if (session->is_auditioning()) {
2099 session->cancel_audition ();
2102 // note: some potential for creativity here, because region doesn't
2103 // have to belong to the playlist that Route is handling
2105 // bool was_soloed = route.soloed();
2107 route.set_solo (true, this);
2109 session->request_bounded_roll (region.position(), region.position() + region.length());
2111 /* XXX how to unset the solo state ? */
2115 Editor::audition_selected_region ()
2117 if (!selection->audio_regions.empty()) {
2118 AudioRegionView* rv = *(selection->audio_regions.begin());
2119 session->audition_region (rv->region);
2124 Editor::audition_playlist_region_standalone (AudioRegion& region)
2126 session->audition_region (region);
2130 Editor::build_interthread_progress_window ()
2132 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
2134 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
2136 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
2137 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
2139 // GTK2FIX: this button needs a modifiable label
2141 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
2142 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
2144 interthread_cancel_button.add (interthread_cancel_label);
2146 interthread_progress_window->set_default_size (200, 100);
2150 Editor::interthread_cancel_clicked ()
2152 if (current_interthread_info) {
2153 current_interthread_info->cancel = true;
2158 Editor::region_from_selection ()
2160 if (clicked_trackview == 0) {
2164 if (selection->time.empty()) {
2168 jack_nframes_t start = selection->time[clicked_selection].start;
2169 jack_nframes_t end = selection->time[clicked_selection].end;
2171 jack_nframes_t selection_cnt = end - start + 1;
2173 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2175 AudioRegion *region;
2176 AudioRegion *current;
2180 jack_nframes_t internal_start;
2183 if ((pl = (*i)->playlist()) == 0) {
2187 if ((current_r = pl->top_region_at (start)) == 0) {
2191 if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
2192 internal_start = start - current->position();
2193 session->region_name (new_name, current->name(), true);
2194 region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
2200 Editor::create_region_from_selection (vector<AudioRegion *>& new_regions)
2202 if (selection->time.empty() || selection->tracks.empty()) {
2206 jack_nframes_t start = selection->time[clicked_selection].start;
2207 jack_nframes_t end = selection->time[clicked_selection].end;
2209 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2211 AudioRegion* current;
2214 jack_nframes_t internal_start;
2217 if ((playlist = (*i)->playlist()) == 0) {
2221 if ((current_r = playlist->top_region_at(start)) == 0) {
2225 if ((current = dynamic_cast<AudioRegion*>(current_r)) == 0) {
2229 internal_start = start - current->position();
2230 session->region_name (new_name, current->name(), true);
2232 new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name));
2237 Editor::split_multichannel_region ()
2239 vector<AudioRegion*> v;
2241 if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
2245 clicked_regionview->region.separate_by_channel (*session, v);
2247 /* nothing else to do, really */
2251 Editor::new_region_from_selection ()
2253 region_from_selection ();
2254 cancel_selection ();
2258 Editor::separate_region_from_selection ()
2260 bool doing_undo = false;
2262 if (selection->time.empty()) {
2268 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2270 AudioTimeAxisView* atv;
2272 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2274 if (atv->is_audio_track()) {
2276 if ((playlist = atv->playlist()) != 0) {
2278 begin_reversible_command (_("separate"));
2281 if (doing_undo) session->add_undo ((playlist)->get_memento());
2283 /* XXX need to consider musical time selections here at some point */
2285 double speed = atv->get_diskstream()->speed();
2287 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2288 playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
2291 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2297 if (doing_undo) commit_reversible_command ();
2301 Editor::separate_regions_using_location (Location& loc)
2303 bool doing_undo = false;
2305 if (loc.is_mark()) {
2311 /* XXX i'm unsure as to whether this should operate on selected tracks only
2312 or the entire enchillada. uncomment the below line to correct the behaviour
2313 (currently set for all tracks)
2316 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2317 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2319 AudioTimeAxisView* atv;
2321 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2323 if (atv->is_audio_track()) {
2325 if ((playlist = atv->playlist()) != 0) {
2327 begin_reversible_command (_("separate"));
2330 if (doing_undo) session->add_undo ((playlist)->get_memento());
2332 /* XXX need to consider musical time selections here at some point */
2334 double speed = atv->get_diskstream()->speed();
2337 playlist->partition ((jack_nframes_t)(loc.start() * speed), (jack_nframes_t)(loc.end() * speed), true);
2338 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2344 if (doing_undo) commit_reversible_command ();
2348 Editor::crop_region_to_selection ()
2350 if (selection->time.empty()) {
2354 vector<Playlist*> playlists;
2357 if (clicked_trackview != 0) {
2359 if ((playlist = clicked_trackview->playlist()) == 0) {
2363 playlists.push_back (playlist);
2367 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2369 AudioTimeAxisView* atv;
2371 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2373 if (atv->is_audio_track()) {
2375 if ((playlist = atv->playlist()) != 0) {
2376 playlists.push_back (playlist);
2383 if (!playlists.empty()) {
2385 jack_nframes_t start;
2389 begin_reversible_command (_("trim to selection"));
2391 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2395 start = selection->time.start();
2397 if ((region = (*i)->top_region_at(start)) == 0) {
2401 /* now adjust lengths to that we do the right thing
2402 if the selection extends beyond the region
2405 start = max (start, region->position());
2406 end = min (selection->time.end_frame(), start + region->length() - 1);
2407 cnt = end - start + 1;
2409 session->add_undo ((*i)->get_memento());
2410 region->trim_to (start, cnt, this);
2411 session->add_redo_no_execute ((*i)->get_memento());
2414 commit_reversible_command ();
2419 Editor::region_fill_track ()
2423 if (!session || selection->audio_regions.empty()) {
2427 end = session->current_end_frame ();
2429 begin_reversible_command (_("region fill"));
2431 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2433 AudioRegion& region ((*i)->region);
2434 Playlist* pl = region.playlist();
2436 if (end <= region.last_frame()) {
2440 double times = (double) (end - region.last_frame()) / (double) region.length();
2446 session->add_undo (pl->get_memento());
2447 pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
2448 session->add_redo_no_execute (pl->get_memento());
2451 commit_reversible_command ();
2455 Editor::region_fill_selection ()
2457 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2461 if (selection->time.empty()) {
2467 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2469 if (selected->count_selected_rows() != 1) {
2473 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2474 region = (*i)[region_list_columns.region];
2476 jack_nframes_t start = selection->time[clicked_selection].start;
2477 jack_nframes_t end = selection->time[clicked_selection].end;
2481 if (selection->tracks.empty()) {
2485 jack_nframes_t selection_length = end - start;
2486 float times = (float)selection_length / region->length();
2488 begin_reversible_command (_("fill selection"));
2490 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2492 if ((playlist = (*i)->playlist()) == 0) {
2496 session->add_undo (playlist->get_memento());
2497 playlist->add_region (*(createRegion (*region)), start, times);
2498 session->add_redo_no_execute (playlist->get_memento());
2501 commit_reversible_command ();
2505 Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
2508 if (!region.covers (position)) {
2509 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2512 begin_reversible_command (_("set region sync position"));
2513 session->add_undo (region.playlist()->get_memento());
2514 region.set_sync_position (position);
2515 session->add_redo_no_execute (region.playlist()->get_memento());
2516 commit_reversible_command ();
2520 Editor::set_region_sync_from_edit_cursor ()
2522 if (clicked_regionview == 0) {
2526 if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
2527 error << _("Place the edit cursor at the desired sync point") << endmsg;
2531 Region& region (clicked_regionview->region);
2532 begin_reversible_command (_("set sync from edit cursor"));
2533 session->add_undo (region.playlist()->get_memento());
2534 region.set_sync_position (edit_cursor->current_frame);
2535 session->add_redo_no_execute (region.playlist()->get_memento());
2536 commit_reversible_command ();
2540 Editor::remove_region_sync ()
2542 if (clicked_regionview) {
2543 Region& region (clicked_regionview->region);
2544 begin_reversible_command (_("remove sync"));
2545 session->add_undo (region.playlist()->get_memento());
2546 region.clear_sync_position ();
2547 session->add_redo_no_execute (region.playlist()->get_memento());
2548 commit_reversible_command ();
2553 Editor::naturalize ()
2555 if (selection->audio_regions.empty()) {
2558 begin_reversible_command (_("naturalize"));
2559 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2560 session->add_undo ((*i)->region.get_memento());
2561 (*i)->region.move_to_natural_position (this);
2562 session->add_redo_no_execute ((*i)->region.get_memento());
2564 commit_reversible_command ();
2568 Editor::align (RegionPoint what)
2570 align_selection (what, edit_cursor->current_frame);
2574 Editor::align_relative (RegionPoint what)
2576 align_selection_relative (what, edit_cursor->current_frame);
2579 struct RegionSortByTime {
2580 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2581 return a->region.position() < b->region.position();
2586 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
2588 if (selection->audio_regions.empty()) {
2592 jack_nframes_t distance;
2593 jack_nframes_t pos = 0;
2596 list<AudioRegionView*> sorted;
2597 selection->audio_regions.by_position (sorted);
2598 Region& r ((*sorted.begin())->region);
2602 pos = r.first_frame ();
2606 pos = r.last_frame();
2610 pos = r.adjust_to_sync (r.first_frame());
2614 if (pos > position) {
2615 distance = pos - position;
2618 distance = position - pos;
2622 begin_reversible_command (_("align selection (relative)"));
2624 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2626 Region& region ((*i)->region);
2628 session->add_undo (region.playlist()->get_memento());
2631 region.set_position (region.position() + distance, this);
2633 region.set_position (region.position() - distance, this);
2636 session->add_redo_no_execute (region.playlist()->get_memento());
2640 commit_reversible_command ();
2644 Editor::align_selection (RegionPoint point, jack_nframes_t position)
2646 if (selection->audio_regions.empty()) {
2650 begin_reversible_command (_("align selection"));
2652 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2653 align_region_internal ((*i)->region, point, position);
2656 commit_reversible_command ();
2660 Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position)
2662 begin_reversible_command (_("align region"));
2663 align_region_internal (region, point, position);
2664 commit_reversible_command ();
2668 Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
2670 session->add_undo (region.playlist()->get_memento());
2674 region.set_position (region.adjust_to_sync (position), this);
2678 if (position > region.length()) {
2679 region.set_position (position - region.length(), this);
2684 region.set_position (position, this);
2688 session->add_redo_no_execute (region.playlist()->get_memento());
2692 Editor::trim_region_to_edit_cursor ()
2694 if (clicked_regionview == 0) {
2698 Region& region (clicked_regionview->region);
2701 AudioTimeAxisView *atav;
2703 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2704 if (atav->get_diskstream() != 0) {
2705 speed = atav->get_diskstream()->speed();
2709 begin_reversible_command (_("trim to edit"));
2710 session->add_undo (region.playlist()->get_memento());
2711 region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2712 session->add_redo_no_execute (region.playlist()->get_memento());
2713 commit_reversible_command ();
2717 Editor::trim_region_from_edit_cursor ()
2719 if (clicked_regionview == 0) {
2723 Region& region (clicked_regionview->region);
2726 AudioTimeAxisView *atav;
2728 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2729 if (atav->get_diskstream() != 0) {
2730 speed = atav->get_diskstream()->speed();
2734 begin_reversible_command (_("trim to edit"));
2735 session->add_undo (region.playlist()->get_memento());
2736 region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2737 session->add_redo_no_execute (region.playlist()->get_memento());
2738 commit_reversible_command ();
2742 Editor::unfreeze_route ()
2744 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2748 clicked_audio_trackview->audio_track()->unfreeze ();
2752 Editor::_freeze_thread (void* arg)
2754 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2755 return static_cast<Editor*>(arg)->freeze_thread ();
2759 Editor::freeze_thread ()
2761 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2766 Editor::freeze_progress_timeout (void *arg)
2768 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2769 return !(current_interthread_info->done || current_interthread_info->cancel);
2773 Editor::freeze_route ()
2775 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2779 InterThreadInfo itt;
2781 if (interthread_progress_window == 0) {
2782 build_interthread_progress_window ();
2785 interthread_progress_window->set_title (_("ardour: freeze"));
2786 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2787 interthread_progress_window->show_all ();
2788 interthread_progress_bar.set_fraction (0.0f);
2789 interthread_progress_label.set_text ("");
2790 interthread_cancel_label.set_text (_("Cancel Freeze"));
2791 current_interthread_info = &itt;
2793 interthread_progress_connection =
2794 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2798 itt.progress = 0.0f;
2800 pthread_create (&itt.thread, 0, _freeze_thread, this);
2802 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2804 while (!itt.done && !itt.cancel) {
2805 gtk_main_iteration ();
2808 interthread_progress_connection.disconnect ();
2809 interthread_progress_window->hide_all ();
2810 current_interthread_info = 0;
2811 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2815 Editor::bounce_range_selection ()
2817 if (selection->time.empty()) {
2821 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2823 jack_nframes_t start = selection->time[clicked_selection].start;
2824 jack_nframes_t end = selection->time[clicked_selection].end;
2825 jack_nframes_t cnt = end - start + 1;
2827 begin_reversible_command (_("bounce range"));
2829 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2831 AudioTimeAxisView* atv;
2833 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2839 if ((playlist = atv->playlist()) == 0) {
2843 InterThreadInfo itt;
2847 itt.progress = false;
2849 session->add_undo (playlist->get_memento());
2850 atv->audio_track()->bounce_range (start, cnt, itt);
2851 session->add_redo_no_execute (playlist->get_memento());
2854 commit_reversible_command ();
2872 Editor::cut_copy (CutCopyOp op)
2874 /* only cancel selection if cut/copy is successful.*/
2886 opname = _("clear");
2890 cut_buffer->clear ();
2892 switch (current_mouse_mode()) {
2894 if (!selection->audio_regions.empty() || !selection->points.empty()) {
2896 begin_reversible_command (opname + _(" objects"));
2898 if (!selection->audio_regions.empty()) {
2900 cut_copy_regions (op);
2903 selection->clear_audio_regions ();
2907 if (!selection->points.empty()) {
2908 cut_copy_points (op);
2911 selection->clear_points ();
2915 commit_reversible_command ();
2920 if (!selection->time.empty()) {
2922 begin_reversible_command (opname + _(" range"));
2923 cut_copy_ranges (op);
2924 commit_reversible_command ();
2927 selection->clear_time ();
2939 Editor::cut_copy_points (CutCopyOp op)
2941 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2943 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2946 atv->cut_copy_clear_objects (selection->points, op);
2952 Editor::cut_copy_regions (CutCopyOp op)
2954 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
2955 PlaylistMapping pmap;
2956 jack_nframes_t first_position = max_frames;
2957 set<Playlist*> freezelist;
2958 pair<set<Playlist*>::iterator,bool> insert_result;
2960 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
2961 first_position = min ((*x)->region.position(), first_position);
2963 if (op == Cut || op == Clear) {
2964 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2966 insert_result = freezelist.insert (pl);
2967 if (insert_result.second) {
2969 session->add_undo (pl->get_memento());
2975 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
2977 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2979 AudioRegionSelection::iterator tmp;
2986 PlaylistMapping::iterator pi = pmap.find (pl);
2988 if (pi == pmap.end()) {
2989 npl = new AudioPlaylist (*session, "cutlist", true);
2998 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
2999 pl->remove_region (&((*x)->region));
3003 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
3007 pl->remove_region (&((*x)->region));
3015 list<Playlist*> foo;
3017 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
3018 foo.push_back (i->second);
3022 cut_buffer->set (foo);
3025 for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
3027 session->add_redo_no_execute ((*pl)->get_memento());
3032 Editor::cut_copy_ranges (CutCopyOp op)
3034 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3035 (*i)->cut_copy_clear (*selection, op);
3040 Editor::paste (float times)
3042 paste_internal (edit_cursor->current_frame, times);
3046 Editor::mouse_paste ()
3051 track_canvas.get_pointer (x, y);
3052 track_canvas.window_to_world (x, y, wx, wy);
3053 wx += horizontal_adjustment.get_value();
3054 wy += vertical_adjustment.get_value();
3057 event.type = GDK_BUTTON_RELEASE;
3058 event.button.x = wx;
3059 event.button.y = wy;
3061 jack_nframes_t where = event_frame (&event, 0, 0);
3063 paste_internal (where, 1);
3067 Editor::paste_internal (jack_nframes_t position, float times)
3069 bool commit = false;
3071 if (cut_buffer->empty() || selection->tracks.empty()) {
3075 if (position == max_frames) {
3076 position = edit_cursor->current_frame;
3079 begin_reversible_command (_("paste"));
3081 TrackSelection::iterator i;
3084 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
3086 /* undo/redo is handled by individual tracks */
3088 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3094 commit_reversible_command ();
3099 Editor::paste_named_selection (float times)
3101 TrackSelection::iterator t;
3103 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3105 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3109 TreeModel::iterator i = selected->get_selected();
3110 NamedSelection* ns = (*i)[named_selection_columns.selection];
3112 list<Playlist*>::iterator chunk;
3113 list<Playlist*>::iterator tmp;
3115 chunk = ns->playlists.begin();
3117 begin_reversible_command (_("paste chunk"));
3119 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3121 AudioTimeAxisView* atv;
3125 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3129 if ((pl = atv->playlist()) == 0) {
3133 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
3140 session->add_undo (apl->get_memento());
3141 apl->paste (**chunk, edit_cursor->current_frame, times);
3142 session->add_redo_no_execute (apl->get_memento());
3144 if (tmp != ns->playlists.end()) {
3149 commit_reversible_command();
3153 Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
3156 AudioRegionSelection sel = regions; // clear (below) will clear the argument list
3158 begin_reversible_command (_("duplicate region"));
3160 selection->clear_audio_regions ();
3162 for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3164 Region& r ((*i)->region);
3166 TimeAxisView& tv = (*i)->get_time_axis_view();
3167 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3168 sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3170 playlist = (*i)->region.playlist();
3171 session->add_undo (playlist->get_memento());
3172 playlist->duplicate (r, r.last_frame(), times);
3173 session->add_redo_no_execute (playlist->get_memento());
3177 if (latest_regionview) {
3178 selection->add (latest_regionview);
3183 commit_reversible_command ();
3187 Editor::duplicate_selection (float times)
3189 if (selection->time.empty() || selection->tracks.empty()) {
3194 vector<AudioRegion*> new_regions;
3195 vector<AudioRegion*>::iterator ri;
3197 create_region_from_selection (new_regions);
3199 if (new_regions.empty()) {
3203 begin_reversible_command (_("duplicate selection"));
3205 ri = new_regions.begin();
3207 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3208 if ((playlist = (*i)->playlist()) == 0) {
3211 session->add_undo (playlist->get_memento());
3212 playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
3213 session->add_redo_no_execute (playlist->get_memento());
3216 if (ri == new_regions.end()) {
3221 commit_reversible_command ();
3225 Editor::reset_point_selection ()
3227 /* reset all selected points to the relevant default value */
3229 cerr << "point selection has " << selection->points.size() << " entries\n";
3231 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3233 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3236 atv->reset_objects (selection->points);
3242 Editor::center_playhead ()
3244 float page = canvas_width * frames_per_unit;
3246 center_screen_internal (playhead_cursor->current_frame, page);
3250 Editor::center_edit_cursor ()
3252 float page = canvas_width * frames_per_unit;
3254 center_screen_internal (edit_cursor->current_frame, page);
3258 Editor::clear_playlist (Playlist& playlist)
3260 begin_reversible_command (_("clear playlist"));
3261 session->add_undo (playlist.get_memento());
3263 session->add_redo_no_execute (playlist.get_memento());
3264 commit_reversible_command ();
3268 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3271 jack_nframes_t distance;
3272 jack_nframes_t next_distance;
3273 jack_nframes_t start;
3275 if (use_edit_cursor) {
3276 start = edit_cursor->current_frame;
3281 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3285 if (selection->tracks.empty()) {
3289 begin_reversible_command (_("nudge track"));
3291 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3293 if ((playlist = (*i)->playlist()) == 0) {
3297 session->add_undo (playlist->get_memento());
3298 playlist->nudge_after (start, distance, forwards);
3299 session->add_redo_no_execute (playlist->get_memento());
3302 commit_reversible_command ();
3306 Editor::remove_last_capture ()
3308 vector<string> choices;
3315 if (Config->get_verify_remove_last_capture()) {
3316 prompt = _("Do you really want to destroy the last capture?"
3317 "\n(This is destructive and cannot be undone)");
3319 choices.push_back (_("No, do nothing."));
3320 choices.push_back (_("Yes, destroy it."));
3322 Gtkmm2ext::Choice prompter (prompt, choices);
3324 if (prompter.run () == 1) {
3325 session->remove_last_capture ();
3329 session->remove_last_capture();
3334 Editor::normalize_region ()
3340 if (selection->audio_regions.empty()) {
3344 begin_reversible_command (_("normalize"));
3346 track_canvas.get_window()->set_cursor (*wait_cursor);
3349 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3350 session->add_undo ((*r)->region.get_memento());
3351 (*r)->region.normalize_to (0.0f);
3352 session->add_redo_no_execute ((*r)->region.get_memento());
3355 commit_reversible_command ();
3356 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3361 Editor::denormalize_region ()
3367 if (selection->audio_regions.empty()) {
3371 begin_reversible_command ("denormalize");
3373 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3374 session->add_undo ((*r)->region.get_memento());
3375 (*r)->region.set_scale_amplitude (1.0f);
3376 session->add_redo_no_execute ((*r)->region.get_memento());
3379 commit_reversible_command ();
3384 Editor::reverse_region ()
3390 Reverse rev (*session);
3391 apply_filter (rev, _("reverse regions"));
3395 Editor::apply_filter (AudioFilter& filter, string command)
3397 if (selection->audio_regions.empty()) {
3401 begin_reversible_command (command);
3403 track_canvas.get_window()->set_cursor (*wait_cursor);
3406 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
3408 AudioRegion& region ((*r)->region);
3409 Playlist* playlist = region.playlist();
3411 AudioRegionSelection::iterator tmp;
3416 if (region.apply (filter) == 0) {
3418 session->add_undo (playlist->get_memento());
3419 playlist->replace_region (region, *(filter.results.front()), region.position());
3420 session->add_redo_no_execute (playlist->get_memento());
3428 commit_reversible_command ();
3429 selection->audio_regions.clear ();
3432 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3436 Editor::region_selection_op (void (Region::*pmf)(void))
3438 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3439 ((*i)->region.*pmf)();
3445 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3447 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3448 ((*i)->region.*pmf)(arg);
3453 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3455 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3456 ((*i)->region.*pmf)(yn);
3461 Editor::external_edit_region ()
3463 if (!clicked_regionview) {
3471 Editor::brush (jack_nframes_t pos)
3473 AudioRegionSelection sel;
3476 if (selection->audio_regions.empty()) {
3477 /* XXX get selection from region list */
3479 sel = selection->audio_regions;
3486 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3487 mouse_brush_insert_region ((*i), pos);
3492 Editor::toggle_gain_envelope_visibility ()
3494 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3495 (*i)->set_envelope_visible (!(*i)->envelope_visible());
3500 Editor::toggle_gain_envelope_active ()
3502 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3503 AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
3505 ar->set_envelope_active (true);