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/audio_diskstream.h>
40 #include <ardour/utils.h>
41 #include <ardour/location.h>
42 #include <ardour/named_selection.h>
43 #include <ardour/audio_track.h>
44 #include <ardour/audioplaylist.h>
45 #include <ardour/region_factory.h>
46 #include <ardour/reverse.h>
48 #include "ardour_ui.h"
50 #include "time_axis_view.h"
51 #include "audio_time_axis.h"
52 #include "automation_time_axis.h"
53 #include "streamview.h"
54 #include "regionview.h"
55 #include "rgb_macros.h"
56 #include "selection_templates.h"
57 #include "selection.h"
60 #include "gtk-custom-hruler.h"
61 #include "gui_thread.h"
66 using namespace ARDOUR;
70 using namespace Editing;
72 /***********************************************************************
74 ***********************************************************************/
77 Editor::undo (uint32_t n)
85 Editor::redo (uint32_t n)
93 Editor::set_meter_hold (int32_t cnt)
95 Config->set_meter_hold_off(false);
96 Config->set_meter_hold_short(false);
97 Config->set_meter_hold_medium(false);
98 Config->set_meter_hold_long(false);
103 Config->set_meter_hold_off(true);
106 Config->set_meter_hold_short(true);
109 Config->set_meter_hold_medium(true);
112 Config->set_meter_hold_long(true);
117 session->set_meter_hold (cnt);
122 Editor::set_meter_falloff (int intval)
124 float val = 0.0f; /* off */
127 Config->set_meter_falloff_off(false);
128 Config->set_meter_falloff_slowest(false);
129 Config->set_meter_falloff_slow(false);
130 Config->set_meter_falloff_medium(false);
131 Config->set_meter_falloff_fast(false);
132 Config->set_meter_falloff_faster(false);
133 Config->set_meter_falloff_fastest(false);
139 Config->set_meter_falloff_off(true);
143 Config->set_meter_falloff_slowest(true);
147 Config->set_meter_falloff_slow(true);
151 Config->set_meter_falloff_medium(true);
155 Config->set_meter_falloff_fast(true);
159 Config->set_meter_falloff_faster(true);
163 Config->set_meter_falloff_fastest(true);
168 session->set_meter_falloff (val);
174 Editor::ensure_cursor (jack_nframes_t *pos)
176 *pos = edit_cursor->current_frame;
181 Editor::split_region ()
183 split_region_at (edit_cursor->current_frame);
187 Editor::split_region_at (jack_nframes_t where)
189 split_regions_at (where, selection->audio_regions);
193 Editor::split_regions_at (jack_nframes_t where, AudioRegionSelection& regions)
195 begin_reversible_command (_("split"));
198 for (AudioRegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
200 AudioRegionSelection::iterator tmp;
205 Playlist* pl = (*a)->region.playlist();
207 _new_regionviews_show_envelope = (*a)->envelope_visible();
210 session->add_undo (pl->get_memento());
211 pl->split_region ((*a)->region, where);
212 session->add_redo_no_execute (pl->get_memento());
218 commit_reversible_command ();
219 _new_regionviews_show_envelope = false;
223 Editor::remove_clicked_region ()
225 if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
229 Playlist* playlist = clicked_audio_trackview->playlist();
231 begin_reversible_command (_("remove region"));
232 session->add_undo (playlist->get_memento());
233 playlist->remove_region (&clicked_regionview->region);
234 session->add_redo_no_execute (playlist->get_memento());
235 commit_reversible_command ();
239 Editor::destroy_clicked_region ()
241 int32_t selected = selection->audio_regions.size();
243 if (!session || clicked_regionview == 0 && selected == 0) {
247 vector<string> choices;
250 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
251 It cannot be undone\n\
252 Do you really want to destroy %1 ?"),
254 _("these regions") : _("this region")));
256 choices.push_back (_("No, do nothing."));
259 choices.push_back (_("Yes, destroy them."));
261 choices.push_back (_("Yes, destroy it."));
264 Gtkmm2ext::Choice prompter (prompt, choices);
266 if (prompter.run() == 0) { /* first choice */
273 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
274 r.push_back (&(*i)->region);
277 session->destroy_regions (r);
279 } else if (clicked_regionview) {
280 session->destroy_region (&clicked_regionview->region);
285 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
289 jack_nframes_t start = 0;
291 if (selection->time.start () == selection->time.end_frame ()) {
293 /* no current selection-> is there a selected regionview? */
295 if (selection->audio_regions.empty()) {
303 if (!selection->audio_regions.empty()) {
305 rv = *(selection->audio_regions.begin());
306 (*tv) = &rv->get_time_axis_view();
307 region = &rv->region;
309 } else if (!selection->tracks.empty()) {
311 (*tv) = selection->tracks.front();
313 AudioTimeAxisView* atv;
315 if ((atv = dynamic_cast<AudioTimeAxisView*> (*tv)) != 0) {
318 if ((pl = atv->playlist()) == 0) {
322 region = dynamic_cast<AudioRegion*> (pl->top_region_at (start));
330 Editor::extend_selection_to_end_of_region (bool next)
334 jack_nframes_t start;
336 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
340 if (region && selection->time.start () == selection->time.end_frame ()) {
341 start = region->position();
343 start = selection->time.start ();
346 /* Try to leave the selection with the same route if possible */
348 if ((tv = selection->time.track) == 0) {
352 begin_reversible_command (_("extend selection"));
353 selection->set (tv, start, region->position() + region->length());
354 commit_reversible_command ();
358 Editor::extend_selection_to_start_of_region (bool previous)
364 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
368 if (region && selection->time.start () == selection->time.end_frame ()) {
369 end = region->position() + region->length();
371 end = selection->time.end_frame ();
374 /* Try to leave the selection with the same route if possible */
376 if ((tv = selection->time.track) == 0) {
380 begin_reversible_command (_("extend selection"));
381 selection->set (tv, region->position(), end);
382 commit_reversible_command ();
387 Editor::nudge_forward (bool next)
389 jack_nframes_t distance;
390 jack_nframes_t next_distance;
392 if (!session) return;
394 if (!selection->audio_regions.empty()) {
396 begin_reversible_command (_("nudge forward"));
398 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
399 AudioRegion& r ((*i)->region);
401 distance = get_nudge_distance (r.position(), next_distance);
404 distance = next_distance;
407 session->add_undo (r.playlist()->get_memento());
408 r.set_position (r.position() + distance, this);
409 session->add_redo_no_execute (r.playlist()->get_memento());
412 commit_reversible_command ();
415 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
416 session->request_locate (playhead_cursor->current_frame + distance);
421 Editor::nudge_backward (bool next)
423 jack_nframes_t distance;
424 jack_nframes_t next_distance;
426 if (!session) return;
428 if (!selection->audio_regions.empty()) {
430 begin_reversible_command (_("nudge forward"));
432 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
433 AudioRegion& r ((*i)->region);
435 distance = get_nudge_distance (r.position(), next_distance);
438 distance = next_distance;
441 session->add_undo (r.playlist()->get_memento());
443 if (r.position() > distance) {
444 r.set_position (r.position() - distance, this);
446 r.set_position (0, this);
448 session->add_redo_no_execute (r.playlist()->get_memento());
451 commit_reversible_command ();
455 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
457 if (playhead_cursor->current_frame > distance) {
458 session->request_locate (playhead_cursor->current_frame - distance);
460 session->goto_start();
466 Editor::nudge_forward_capture_offset ()
468 jack_nframes_t distance;
470 if (!session) return;
472 if (!selection->audio_regions.empty()) {
474 begin_reversible_command (_("nudge forward"));
476 distance = session->worst_output_latency();
478 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
479 AudioRegion& r ((*i)->region);
481 session->add_undo (r.playlist()->get_memento());
482 r.set_position (r.position() + distance, this);
483 session->add_redo_no_execute (r.playlist()->get_memento());
486 commit_reversible_command ();
492 Editor::nudge_backward_capture_offset ()
494 jack_nframes_t distance;
496 if (!session) return;
498 if (!selection->audio_regions.empty()) {
500 begin_reversible_command (_("nudge forward"));
502 distance = session->worst_output_latency();
504 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
505 AudioRegion& r ((*i)->region);
507 session->add_undo (r.playlist()->get_memento());
509 if (r.position() > distance) {
510 r.set_position (r.position() - distance, this);
512 r.set_position (0, this);
514 session->add_redo_no_execute (r.playlist()->get_memento());
517 commit_reversible_command ();
524 Editor::move_to_start ()
526 session->goto_start ();
530 Editor::move_to_end ()
533 session->request_locate (session->current_end_frame());
537 Editor::build_region_boundary_cache ()
539 jack_nframes_t pos = 0;
542 TrackViewList tracks;
544 region_boundary_cache.clear ();
551 case SnapToRegionStart:
554 case SnapToRegionEnd:
557 case SnapToRegionSync:
560 case SnapToRegionBoundary:
564 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
569 TimeAxisView *ontrack = 0;
571 while (pos < session->current_end_frame()) {
573 if (!selection->tracks.empty()) {
575 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
579 } else if (clicked_trackview) {
582 t.push_back (clicked_trackview);
584 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
590 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
598 case SnapToRegionStart:
599 rpos = r->first_frame();
601 case SnapToRegionEnd:
602 rpos = r->last_frame();
604 case SnapToRegionSync:
605 rpos = r->adjust_to_sync (r->first_frame());
608 case SnapToRegionBoundary:
609 rpos = r->last_frame();
616 AudioTimeAxisView *atav;
618 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
619 if (atav->get_diskstream() != 0) {
620 speed = atav->get_diskstream()->speed();
624 rpos = track_frame_to_session_frame(rpos, speed);
626 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
627 if (snap_type == SnapToRegionBoundary) {
628 region_boundary_cache.push_back (r->first_frame());
630 region_boundary_cache.push_back (rpos);
638 Editor::find_next_region (jack_nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
640 TrackViewList::iterator i;
641 jack_nframes_t closest = max_frames;
643 jack_nframes_t rpos = 0;
646 jack_nframes_t track_frame;
647 AudioTimeAxisView *atav;
649 for (i = tracks.begin(); i != tracks.end(); ++i) {
651 jack_nframes_t distance;
655 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
656 if (atav->get_diskstream()!=0)
657 track_speed = atav->get_diskstream()->speed();
660 track_frame = session_frame_to_track_frame(frame, track_speed);
662 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
668 rpos = r->first_frame ();
672 rpos = r->last_frame ();
676 rpos = r->adjust_to_sync (r->first_frame());
679 // rpos is a "track frame", converting it to "session frame"
680 rpos = track_frame_to_session_frame(rpos, track_speed);
683 distance = rpos - frame;
685 distance = frame - rpos;
688 if (distance < closest) {
700 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
703 jack_nframes_t pos = cursor->current_frame;
709 TimeAxisView *ontrack = 0;
711 // so we don't find the current region again..
715 if (!selection->tracks.empty()) {
717 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
719 } else if (clicked_trackview) {
722 t.push_back (clicked_trackview);
724 r = find_next_region (pos, point, dir, t, &ontrack);
728 r = find_next_region (pos, point, dir, track_views, &ontrack);
737 pos = r->first_frame ();
741 pos = r->last_frame ();
745 pos = r->adjust_to_sync (r->first_frame());
750 AudioTimeAxisView *atav;
752 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
753 if (atav->get_diskstream() != 0) {
754 speed = atav->get_diskstream()->speed();
758 pos = track_frame_to_session_frame(pos, speed);
760 if (cursor == playhead_cursor) {
761 session->request_locate (pos);
763 cursor->set_position (pos);
768 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
770 cursor_to_region_point (cursor, point, 1);
774 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
776 cursor_to_region_point (cursor, point, -1);
780 Editor::cursor_to_selection_start (Cursor *cursor)
782 jack_nframes_t pos = 0;
783 switch (mouse_mode) {
785 if (!selection->audio_regions.empty()) {
786 pos = selection->audio_regions.start();
791 if (!selection->time.empty()) {
792 pos = selection->time.start ();
800 if (cursor == playhead_cursor) {
801 session->request_locate (pos);
803 cursor->set_position (pos);
808 Editor::cursor_to_selection_end (Cursor *cursor)
810 jack_nframes_t pos = 0;
812 switch (mouse_mode) {
814 if (!selection->audio_regions.empty()) {
815 pos = selection->audio_regions.end_frame();
820 if (!selection->time.empty()) {
821 pos = selection->time.end_frame ();
829 if (cursor == playhead_cursor) {
830 session->request_locate (pos);
832 cursor->set_position (pos);
837 Editor::playhead_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 = playhead_cursor->current_frame;
856 if ((jack_nframes_t) pos < cnt) {
862 /* XXX this is completely insane. with the current buffering
863 design, we'll force a complete track buffer flush and
864 reload, just to move 1 sample !!!
867 session->request_locate (pos);
871 Editor::playhead_forward ()
878 if (get_prefix (prefix, was_floating)) {
882 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
884 cnt = (jack_nframes_t) floor (prefix);
888 pos = playhead_cursor->current_frame;
890 /* XXX this is completely insane. with the current buffering
891 design, we'll force a complete track buffer flush and
892 reload, just to move 1 sample !!!
895 session->request_locate (pos+cnt);
899 Editor::cursor_align (bool playhead_to_edit)
901 if (playhead_to_edit) {
903 session->request_locate (edit_cursor->current_frame);
906 edit_cursor->set_position (playhead_cursor->current_frame);
911 Editor::edit_cursor_backward ()
918 if (get_prefix (prefix, was_floating)) {
922 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
924 cnt = (jack_nframes_t) prefix;
928 pos = edit_cursor->current_frame;
930 if ((jack_nframes_t) pos < cnt) {
936 edit_cursor->set_position (pos);
940 Editor::edit_cursor_forward ()
947 if (get_prefix (prefix, was_floating)) {
951 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
953 cnt = (jack_nframes_t) floor (prefix);
957 pos = edit_cursor->current_frame;
958 edit_cursor->set_position (pos+cnt);
962 Editor::goto_frame ()
966 jack_nframes_t frame;
968 if (get_prefix (prefix, was_floating)) {
973 frame = (jack_nframes_t) floor (prefix * session->frame_rate());
975 frame = (jack_nframes_t) floor (prefix);
978 session->request_locate (frame);
982 Editor::scroll_backward (float pages)
984 jack_nframes_t frame;
985 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
990 if (get_prefix (prefix, was_floating)) {
991 cnt = (jack_nframes_t) floor (pages * one_page);
994 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
996 cnt = (jack_nframes_t) floor (prefix * one_page);
1000 if (leftmost_frame < cnt) {
1003 frame = leftmost_frame - cnt;
1006 reposition_x_origin (frame);
1010 Editor::scroll_forward (float pages)
1012 jack_nframes_t frame;
1013 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
1018 if (get_prefix (prefix, was_floating)) {
1019 cnt = (jack_nframes_t) floor (pages * one_page);
1022 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
1024 cnt = (jack_nframes_t) floor (prefix * one_page);
1028 if (ULONG_MAX - cnt < leftmost_frame) {
1029 frame = ULONG_MAX - cnt;
1031 frame = leftmost_frame + cnt;
1034 reposition_x_origin (frame);
1038 Editor::scroll_tracks_down ()
1044 if (get_prefix (prefix, was_floating)) {
1047 cnt = (int) floor (prefix);
1050 double vert_value = vertical_adjustment.get_value() + (cnt *
1051 vertical_adjustment.get_page_size());
1052 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
1053 vert_value = vertical_adjustment.get_upper() - canvas_height;
1055 vertical_adjustment.set_value (vert_value);
1059 Editor::scroll_tracks_up ()
1065 if (get_prefix (prefix, was_floating)) {
1068 cnt = (int) floor (prefix);
1071 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1075 Editor::scroll_tracks_down_line ()
1078 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1079 double vert_value = adj->get_value() + 20;
1081 if (vert_value>adj->get_upper() - canvas_height) {
1082 vert_value = adj->get_upper() - canvas_height;
1084 adj->set_value (vert_value);
1088 Editor::scroll_tracks_up_line ()
1090 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1091 adj->set_value (adj->get_value() - 20);
1097 Editor::temporal_zoom_step (bool coarser)
1099 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1103 nfpu = frames_per_unit;
1108 nfpu = max(1.0,(nfpu/2.0));
1111 temporal_zoom (nfpu);
1115 Editor::temporal_zoom (gdouble fpu)
1117 if (!session) return;
1119 jack_nframes_t current_page = current_page_frames();
1120 jack_nframes_t current_leftmost = leftmost_frame;
1121 jack_nframes_t current_rightmost;
1122 jack_nframes_t current_center;
1123 jack_nframes_t new_page;
1124 jack_nframes_t leftmost_after_zoom = 0;
1129 new_page = (jack_nframes_t) floor (canvas_width * nfpu);
1131 switch (zoom_focus) {
1133 leftmost_after_zoom = current_leftmost;
1136 case ZoomFocusRight:
1137 current_rightmost = leftmost_frame + current_page;
1138 if (current_rightmost > new_page) {
1139 leftmost_after_zoom = current_rightmost - new_page;
1141 leftmost_after_zoom = 0;
1145 case ZoomFocusCenter:
1146 current_center = current_leftmost + (current_page/2);
1147 if (current_center > (new_page/2)) {
1148 leftmost_after_zoom = current_center - (new_page / 2);
1150 leftmost_after_zoom = 0;
1154 case ZoomFocusPlayhead:
1155 /* try to keep the playhead in the center */
1156 if (playhead_cursor->current_frame > new_page/2) {
1157 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1159 leftmost_after_zoom = 0;
1164 /* try to keep the edit cursor in the center */
1165 if (edit_cursor->current_frame > leftmost_frame + (new_page/2)) {
1166 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1168 leftmost_after_zoom = 0;
1174 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1176 // begin_reversible_command (_("zoom"));
1177 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1178 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1179 // commit_reversible_command ();
1181 reposition_and_zoom (leftmost_after_zoom, nfpu);
1185 Editor::temporal_zoom_selection ()
1187 if (!selection) return;
1189 if (selection->time.empty()) {
1193 jack_nframes_t start = selection->time[clicked_selection].start;
1194 jack_nframes_t end = selection->time[clicked_selection].end;
1196 temporal_zoom_by_frame (start, end, "zoom to selection");
1200 Editor::temporal_zoom_session ()
1202 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1205 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1210 Editor::temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, const string & op)
1212 if (!session) return;
1214 if ((start == 0 && end == 0) || end < start) {
1218 jack_nframes_t range = end - start;
1220 double new_fpu = (double)range / (double)canvas_width;
1223 // while (p2 < new_fpu) {
1228 jack_nframes_t new_page = (jack_nframes_t) floor (canvas_width * new_fpu);
1229 jack_nframes_t middle = (jack_nframes_t) floor( (double)start + ((double)range / 2.0f ));
1230 jack_nframes_t new_leftmost = (jack_nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1232 if (new_leftmost > middle) new_leftmost = 0;
1234 // begin_reversible_command (op);
1235 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1236 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1237 // commit_reversible_command ();
1239 reposition_and_zoom (new_leftmost, new_fpu);
1243 Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
1245 if (!session) return;
1247 jack_nframes_t range_before = frame - leftmost_frame;
1250 new_fpu = frames_per_unit;
1256 new_fpu = max(1.0,(new_fpu/2.0));
1260 if (new_fpu == frames_per_unit) return;
1262 jack_nframes_t new_leftmost = frame - range_before;
1264 if (new_leftmost > frame) new_leftmost = 0;
1266 // begin_reversible_command (_("zoom to frame"));
1267 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1268 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1269 // commit_reversible_command ();
1271 reposition_and_zoom (new_leftmost, new_fpu);
1275 Editor::add_location_from_selection ()
1277 if (selection->time.empty()) {
1281 if (session == 0 || clicked_trackview == 0) {
1285 jack_nframes_t start = selection->time[clicked_selection].start;
1286 jack_nframes_t end = selection->time[clicked_selection].end;
1288 Location *location = new Location (start, end, "selection");
1290 session->begin_reversible_command (_("add marker"));
1291 session->add_undo (session->locations()->get_memento());
1292 session->locations()->add (location, true);
1293 session->add_redo_no_execute (session->locations()->get_memento());
1294 session->commit_reversible_command ();
1298 Editor::add_location_from_playhead_cursor ()
1300 jack_nframes_t where = session->audible_frame();
1302 Location *location = new Location (where, where, "mark", Location::IsMark);
1303 session->begin_reversible_command (_("add marker"));
1304 session->add_undo (session->locations()->get_memento());
1305 session->locations()->add (location, true);
1306 session->add_redo_no_execute (session->locations()->get_memento());
1307 session->commit_reversible_command ();
1311 Editor::add_location_from_audio_region ()
1313 if (selection->audio_regions.empty()) {
1317 AudioRegionView* rv = *(selection->audio_regions.begin());
1318 Region& region = rv->region;
1320 Location *location = new Location (region.position(), region.last_frame(), region.name());
1321 session->begin_reversible_command (_("add marker"));
1322 session->add_undo (session->locations()->get_memento());
1323 session->locations()->add (location, true);
1324 session->add_redo_no_execute (session->locations()->get_memento());
1325 session->commit_reversible_command ();
1329 Editor::select_all_in_track (Selection::Operation op)
1331 list<Selectable *> touched;
1333 if (!clicked_trackview) {
1337 clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1340 case Selection::Toggle:
1341 selection->add (touched);
1343 case Selection::Set:
1344 selection->set (touched);
1346 case Selection::Extend:
1347 /* not defined yet */
1353 Editor::select_all (Selection::Operation op)
1355 list<Selectable *> touched;
1357 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1358 if ((*iter)->hidden()) {
1361 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1363 begin_reversible_command (_("select all"));
1365 case Selection::Toggle:
1366 selection->add (touched);
1368 case Selection::Set:
1369 selection->set (touched);
1371 case Selection::Extend:
1372 /* not defined yet */
1375 commit_reversible_command ();
1379 Editor::invert_selection_in_track ()
1381 list<Selectable *> touched;
1383 if (!clicked_trackview) {
1387 clicked_trackview->get_inverted_selectables (*selection, touched);
1388 selection->set (touched);
1392 Editor::invert_selection ()
1394 list<Selectable *> touched;
1396 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1397 if ((*iter)->hidden()) {
1400 (*iter)->get_inverted_selectables (*selection, touched);
1403 selection->set (touched);
1407 Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, Selection::Operation op)
1409 list<Selectable *> touched;
1411 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1412 if ((*iter)->hidden()) {
1415 (*iter)->get_selectables (start, end, top, bot, touched);
1418 cerr << "select all within found " << touched.size() << endl;
1420 begin_reversible_command (_("select all within"));
1422 case Selection::Toggle:
1424 selection->add (touched);
1426 case Selection::Set:
1428 selection->set (touched);
1430 case Selection::Extend:
1432 /* not defined yet */
1436 cerr << "selection now has " << selection->points.size() << endl;
1438 commit_reversible_command ();
1439 return !touched.empty();
1443 Editor::set_selection_from_audio_region ()
1445 if (selection->audio_regions.empty()) {
1449 AudioRegionView* rv = *(selection->audio_regions.begin());
1450 Region& region = rv->region;
1452 begin_reversible_command (_("set selection from region"));
1453 selection->set (0, region.position(), region.last_frame());
1454 commit_reversible_command ();
1456 set_mouse_mode (Editing::MouseRange, false);
1460 Editor::set_selection_from_punch()
1464 if ((location = session->locations()->auto_punch_location()) == 0) {
1468 set_selection_from_range (*location);
1472 Editor::set_selection_from_loop()
1476 if ((location = session->locations()->auto_loop_location()) == 0) {
1479 set_selection_from_range (*location);
1483 Editor::set_selection_from_range (Location& loc)
1485 begin_reversible_command (_("set selection from range"));
1486 selection->set (0, loc.start(), loc.end());
1487 commit_reversible_command ();
1489 set_mouse_mode (Editing::MouseRange, false);
1493 Editor::select_all_selectables_using_time_selection ()
1495 list<Selectable *> touched;
1497 if (selection->time.empty()) {
1501 jack_nframes_t start = selection->time[clicked_selection].start;
1502 jack_nframes_t end = selection->time[clicked_selection].end;
1504 if (end - start < 1) {
1508 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1509 if ((*iter)->hidden()) {
1512 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1515 begin_reversible_command (_("select all from range"));
1516 selection->set (touched);
1517 commit_reversible_command ();
1522 Editor::select_all_selectables_using_punch()
1524 Location* location = session->locations()->auto_punch_location();
1525 list<Selectable *> touched;
1527 if (location == 0 || (location->end() - location->start() <= 1)) {
1531 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1532 if ((*iter)->hidden()) {
1535 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1537 begin_reversible_command (_("select all from punch"));
1538 selection->set (touched);
1539 commit_reversible_command ();
1544 Editor::select_all_selectables_using_loop()
1546 Location* location = session->locations()->auto_loop_location();
1547 list<Selectable *> touched;
1549 if (location == 0 || (location->end() - location->start() <= 1)) {
1553 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1554 if ((*iter)->hidden()) {
1557 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1559 begin_reversible_command (_("select all from loop"));
1560 selection->set (touched);
1561 commit_reversible_command ();
1566 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1568 jack_nframes_t start;
1570 list<Selectable *> touched;
1573 begin_reversible_command (_("select all after cursor"));
1574 start = cursor->current_frame ;
1575 end = session->current_end_frame();
1577 if (cursor->current_frame > 0) {
1578 begin_reversible_command (_("select all before cursor"));
1580 end = cursor->current_frame - 1;
1586 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1587 if ((*iter)->hidden()) {
1590 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1592 selection->set (touched);
1593 commit_reversible_command ();
1597 Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
1599 jack_nframes_t start;
1601 list<Selectable *> touched;
1602 bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
1604 if (cursor->current_frame == other_cursor->current_frame) {
1608 begin_reversible_command (_("select all between cursors"));
1609 if (other_cursor_is_first) {
1610 start = other_cursor->current_frame;
1611 end = cursor->current_frame - 1;
1614 start = cursor->current_frame;
1615 end = other_cursor->current_frame - 1;
1618 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1619 if ((*iter)->hidden()) {
1622 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1624 selection->set (touched);
1625 commit_reversible_command ();
1629 Editor::amplitude_zoom_step (bool in)
1643 #ifdef FIX_FOR_CANVAS
1644 /* XXX DO SOMETHING */
1653 Editor::delete_sample_forward ()
1658 Editor::delete_sample_backward ()
1663 Editor::delete_screen ()
1670 Editor::search_backwards ()
1676 Editor::search_forwards ()
1684 Editor::jump_forward_to_mark ()
1690 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1693 session->request_locate (location->start(), session->transport_rolling());
1695 session->request_locate (session->current_end_frame());
1700 Editor::jump_backward_to_mark ()
1706 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1709 session->request_locate (location->start(), session->transport_rolling());
1711 session->goto_start ();
1722 if (get_prefix (prefix, was_floating)) {
1723 pos = session->audible_frame ();
1726 pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
1728 pos = (jack_nframes_t) floor (prefix);
1732 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1736 Editor::clear_markers ()
1739 session->begin_reversible_command (_("clear markers"));
1740 session->add_undo (session->locations()->get_memento());
1741 session->locations()->clear_markers ();
1742 session->add_redo_no_execute (session->locations()->get_memento());
1743 session->commit_reversible_command ();
1748 Editor::clear_ranges ()
1751 session->begin_reversible_command (_("clear ranges"));
1752 session->add_undo (session->locations()->get_memento());
1754 Location * looploc = session->locations()->auto_loop_location();
1755 Location * punchloc = session->locations()->auto_punch_location();
1757 session->locations()->clear_ranges ();
1759 if (looploc) session->locations()->add (looploc);
1760 if (punchloc) session->locations()->add (punchloc);
1762 session->add_redo_no_execute (session->locations()->get_memento());
1763 session->commit_reversible_command ();
1768 Editor::clear_locations ()
1770 session->begin_reversible_command (_("clear locations"));
1771 session->add_undo (session->locations()->get_memento());
1772 session->locations()->clear ();
1773 session->add_redo_no_execute (session->locations()->get_memento());
1774 session->commit_reversible_command ();
1775 session->locations()->clear ();
1778 /* INSERT/REPLACE */
1781 Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
1786 jack_nframes_t where;
1787 AudioTimeAxisView *atv = 0;
1790 track_canvas.window_to_world (x, y, wx, wy);
1791 wx += horizontal_adjustment.get_value();
1792 wy += vertical_adjustment.get_value();
1795 event.type = GDK_BUTTON_RELEASE;
1796 event.button.x = wx;
1797 event.button.y = wy;
1799 where = event_frame (&event, &cx, &cy);
1801 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1802 /* clearly outside canvas area */
1806 if ((tv = trackview_by_y_position (cy)) == 0) {
1810 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1814 if ((playlist = atv->playlist()) == 0) {
1820 begin_reversible_command (_("insert dragged region"));
1821 session->add_undo (playlist->get_memento());
1822 playlist->add_region (*(new AudioRegion (region)), where, 1.0);
1823 session->add_redo_no_execute (playlist->get_memento());
1824 commit_reversible_command ();
1828 Editor::insert_region_list_selection (float times)
1830 AudioTimeAxisView *tv = 0;
1833 if (clicked_audio_trackview != 0) {
1834 tv = clicked_audio_trackview;
1835 } else if (!selection->tracks.empty()) {
1836 if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
1843 if ((playlist = tv->playlist()) == 0) {
1847 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1849 if (selected->count_selected_rows() != 1) {
1853 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
1854 Region* region = (*i)[region_list_columns.region];
1856 begin_reversible_command (_("insert region"));
1857 session->add_undo (playlist->get_memento());
1858 playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
1859 session->add_redo_no_execute (playlist->get_memento());
1860 commit_reversible_command ();
1864 /* BUILT-IN EFFECTS */
1867 Editor::reverse_selection ()
1872 /* GAIN ENVELOPE EDITING */
1875 Editor::edit_envelope ()
1882 Editor::toggle_playback (bool with_abort)
1888 switch (session->slave_source()) {
1893 /* transport controlled by the master */
1897 if (session->is_auditioning()) {
1898 session->cancel_audition ();
1902 if (session->transport_rolling()) {
1903 session->request_stop (with_abort);
1904 if (session->get_auto_loop()) {
1905 session->request_auto_loop (false);
1908 session->request_transport_speed (1.0f);
1913 Editor::play_from_start ()
1915 session->request_locate (session->current_start_frame(), true);
1919 Editor::play_selection ()
1921 if (selection->time.empty()) {
1925 session->request_play_range (true);
1929 Editor::play_selected_region ()
1931 if (!selection->audio_regions.empty()) {
1932 AudioRegionView *rv = *(selection->audio_regions.begin());
1934 session->request_bounded_roll (rv->region.position(), rv->region.last_frame());
1939 Editor::loop_selected_region ()
1941 if (!selection->audio_regions.empty()) {
1942 AudioRegionView *rv = *(selection->audio_regions.begin());
1945 if ((tll = transport_loop_location()) != 0) {
1947 tll->set (rv->region.position(), rv->region.last_frame());
1949 // enable looping, reposition and start rolling
1951 session->request_auto_loop (true);
1952 session->request_locate (tll->start(), false);
1953 session->request_transport_speed (1.0f);
1959 Editor::play_location (Location& location)
1961 if (location.start() <= location.end()) {
1965 session->request_bounded_roll (location.start(), location.end());
1969 Editor::loop_location (Location& location)
1971 if (location.start() <= location.end()) {
1977 if ((tll = transport_loop_location()) != 0) {
1978 tll->set (location.start(), location.end());
1980 // enable looping, reposition and start rolling
1981 session->request_auto_loop (true);
1982 session->request_locate (tll->start(), true);
1987 Editor::toggle_region_mute ()
1989 if (clicked_regionview) {
1990 clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
1991 } else if (!selection->audio_regions.empty()) {
1992 bool yn = ! (*selection->audio_regions.begin())->region.muted();
1993 selection->foreach_audio_region (&AudioRegion::set_muted, yn);
1998 Editor::toggle_region_opaque ()
2000 if (clicked_regionview) {
2001 clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
2002 } else if (!selection->audio_regions.empty()) {
2003 bool yn = ! (*selection->audio_regions.begin())->region.opaque();
2004 selection->foreach_audio_region (&Region::set_opaque, yn);
2009 Editor::raise_region ()
2011 selection->foreach_audio_region (&Region::raise);
2015 Editor::raise_region_to_top ()
2017 selection->foreach_audio_region (&Region::raise_to_top);
2021 Editor::lower_region ()
2023 selection->foreach_audio_region (&Region::lower);
2027 Editor::lower_region_to_bottom ()
2029 selection->foreach_audio_region (&Region::lower_to_bottom);
2033 Editor::edit_region ()
2035 if (clicked_regionview == 0) {
2039 clicked_regionview->show_region_editor ();
2043 Editor::rename_region ()
2047 Button ok_button (_("OK"));
2048 Button cancel_button (_("Cancel"));
2050 if (selection->audio_regions.empty()) {
2054 dialog.set_title (_("ardour: rename region"));
2055 dialog.set_name ("RegionRenameWindow");
2056 dialog.set_size_request (300, -1);
2057 dialog.set_position (Gtk::WIN_POS_MOUSE);
2058 dialog.set_modal (true);
2060 dialog.get_vbox()->set_border_width (10);
2061 dialog.get_vbox()->pack_start (entry);
2062 dialog.get_action_area()->pack_start (ok_button);
2063 dialog.get_action_area()->pack_start (cancel_button);
2065 entry.set_name ("RegionNameDisplay");
2066 ok_button.set_name ("EditorGTKButton");
2067 cancel_button.set_name ("EditorGTKButton");
2069 region_renamed = false;
2071 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2072 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2073 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
2080 if (region_renamed) {
2081 (*selection->audio_regions.begin())->region.set_name (entry.get_text());
2082 redisplay_regions ();
2087 Editor::rename_region_finished (bool status)
2090 region_renamed = status;
2095 Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
2097 if (session->is_auditioning()) {
2098 session->cancel_audition ();
2101 // note: some potential for creativity here, because region doesn't
2102 // have to belong to the playlist that Route is handling
2104 // bool was_soloed = route.soloed();
2106 route.set_solo (true, this);
2108 session->request_bounded_roll (region.position(), region.position() + region.length());
2110 /* XXX how to unset the solo state ? */
2114 Editor::audition_selected_region ()
2116 if (!selection->audio_regions.empty()) {
2117 AudioRegionView* rv = *(selection->audio_regions.begin());
2118 session->audition_region (rv->region);
2123 Editor::audition_playlist_region_standalone (AudioRegion& region)
2125 session->audition_region (region);
2129 Editor::build_interthread_progress_window ()
2131 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
2133 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
2135 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
2136 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
2138 // GTK2FIX: this button needs a modifiable label
2140 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
2141 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
2143 interthread_cancel_button.add (interthread_cancel_label);
2145 interthread_progress_window->set_default_size (200, 100);
2149 Editor::interthread_cancel_clicked ()
2151 if (current_interthread_info) {
2152 current_interthread_info->cancel = true;
2157 Editor::region_from_selection ()
2159 if (clicked_trackview == 0) {
2163 if (selection->time.empty()) {
2167 jack_nframes_t start = selection->time[clicked_selection].start;
2168 jack_nframes_t end = selection->time[clicked_selection].end;
2170 jack_nframes_t selection_cnt = end - start + 1;
2172 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2174 AudioRegion *region;
2175 AudioRegion *current;
2179 jack_nframes_t internal_start;
2182 if ((pl = (*i)->playlist()) == 0) {
2186 if ((current_r = pl->top_region_at (start)) == 0) {
2190 if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
2191 internal_start = start - current->position();
2192 session->region_name (new_name, current->name(), true);
2193 region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
2199 Editor::create_region_from_selection (vector<AudioRegion *>& new_regions)
2201 if (selection->time.empty() || selection->tracks.empty()) {
2205 jack_nframes_t start = selection->time[clicked_selection].start;
2206 jack_nframes_t end = selection->time[clicked_selection].end;
2208 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2210 AudioRegion* current;
2213 jack_nframes_t internal_start;
2216 if ((playlist = (*i)->playlist()) == 0) {
2220 if ((current_r = playlist->top_region_at(start)) == 0) {
2224 if ((current = dynamic_cast<AudioRegion*>(current_r)) == 0) {
2228 internal_start = start - current->position();
2229 session->region_name (new_name, current->name(), true);
2231 new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name));
2236 Editor::split_multichannel_region ()
2238 vector<AudioRegion*> v;
2240 if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
2244 clicked_regionview->region.separate_by_channel (*session, v);
2246 /* nothing else to do, really */
2250 Editor::new_region_from_selection ()
2252 region_from_selection ();
2253 cancel_selection ();
2257 Editor::separate_region_from_selection ()
2259 bool doing_undo = false;
2261 if (selection->time.empty()) {
2267 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2269 AudioTimeAxisView* atv;
2271 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2273 if (atv->is_audio_track()) {
2275 if ((playlist = atv->playlist()) != 0) {
2277 begin_reversible_command (_("separate"));
2280 if (doing_undo) session->add_undo ((playlist)->get_memento());
2282 /* XXX need to consider musical time selections here at some point */
2284 double speed = atv->get_diskstream()->speed();
2286 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2287 playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
2290 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2296 if (doing_undo) commit_reversible_command ();
2300 Editor::separate_regions_using_location (Location& loc)
2302 bool doing_undo = false;
2304 if (loc.is_mark()) {
2310 /* XXX i'm unsure as to whether this should operate on selected tracks only
2311 or the entire enchillada. uncomment the below line to correct the behaviour
2312 (currently set for all tracks)
2315 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2316 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2318 AudioTimeAxisView* atv;
2320 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2322 if (atv->is_audio_track()) {
2324 if ((playlist = atv->playlist()) != 0) {
2326 begin_reversible_command (_("separate"));
2329 if (doing_undo) session->add_undo ((playlist)->get_memento());
2331 /* XXX need to consider musical time selections here at some point */
2333 double speed = atv->get_diskstream()->speed();
2336 playlist->partition ((jack_nframes_t)(loc.start() * speed), (jack_nframes_t)(loc.end() * speed), true);
2337 if (doing_undo) session->add_redo_no_execute (playlist->get_memento());
2343 if (doing_undo) commit_reversible_command ();
2347 Editor::crop_region_to_selection ()
2349 if (selection->time.empty()) {
2353 vector<Playlist*> playlists;
2356 if (clicked_trackview != 0) {
2358 if ((playlist = clicked_trackview->playlist()) == 0) {
2362 playlists.push_back (playlist);
2366 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2368 AudioTimeAxisView* atv;
2370 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2372 if (atv->is_audio_track()) {
2374 if ((playlist = atv->playlist()) != 0) {
2375 playlists.push_back (playlist);
2382 if (!playlists.empty()) {
2384 jack_nframes_t start;
2388 begin_reversible_command (_("trim to selection"));
2390 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2394 start = selection->time.start();
2396 if ((region = (*i)->top_region_at(start)) == 0) {
2400 /* now adjust lengths to that we do the right thing
2401 if the selection extends beyond the region
2404 start = max (start, region->position());
2405 end = min (selection->time.end_frame(), start + region->length() - 1);
2406 cnt = end - start + 1;
2408 session->add_undo ((*i)->get_memento());
2409 region->trim_to (start, cnt, this);
2410 session->add_redo_no_execute ((*i)->get_memento());
2413 commit_reversible_command ();
2418 Editor::region_fill_track ()
2422 if (!session || selection->audio_regions.empty()) {
2426 end = session->current_end_frame ();
2428 begin_reversible_command (_("region fill"));
2430 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2432 AudioRegion& region ((*i)->region);
2433 Playlist* pl = region.playlist();
2435 if (end <= region.last_frame()) {
2439 double times = (double) (end - region.last_frame()) / (double) region.length();
2445 session->add_undo (pl->get_memento());
2446 pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
2447 session->add_redo_no_execute (pl->get_memento());
2450 commit_reversible_command ();
2454 Editor::region_fill_selection ()
2456 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2460 if (selection->time.empty()) {
2466 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2468 if (selected->count_selected_rows() != 1) {
2472 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2473 region = (*i)[region_list_columns.region];
2475 jack_nframes_t start = selection->time[clicked_selection].start;
2476 jack_nframes_t end = selection->time[clicked_selection].end;
2480 if (selection->tracks.empty()) {
2484 jack_nframes_t selection_length = end - start;
2485 float times = (float)selection_length / region->length();
2487 begin_reversible_command (_("fill selection"));
2489 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2491 if ((playlist = (*i)->playlist()) == 0) {
2495 session->add_undo (playlist->get_memento());
2496 playlist->add_region (*(createRegion (*region)), start, times);
2497 session->add_redo_no_execute (playlist->get_memento());
2500 commit_reversible_command ();
2504 Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
2507 if (!region.covers (position)) {
2508 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2511 begin_reversible_command (_("set region sync position"));
2512 session->add_undo (region.playlist()->get_memento());
2513 region.set_sync_position (position);
2514 session->add_redo_no_execute (region.playlist()->get_memento());
2515 commit_reversible_command ();
2519 Editor::set_region_sync_from_edit_cursor ()
2521 if (clicked_regionview == 0) {
2525 if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
2526 error << _("Place the edit cursor at the desired sync point") << endmsg;
2530 Region& region (clicked_regionview->region);
2531 begin_reversible_command (_("set sync from edit cursor"));
2532 session->add_undo (region.playlist()->get_memento());
2533 region.set_sync_position (edit_cursor->current_frame);
2534 session->add_redo_no_execute (region.playlist()->get_memento());
2535 commit_reversible_command ();
2539 Editor::remove_region_sync ()
2541 if (clicked_regionview) {
2542 Region& region (clicked_regionview->region);
2543 begin_reversible_command (_("remove sync"));
2544 session->add_undo (region.playlist()->get_memento());
2545 region.clear_sync_position ();
2546 session->add_redo_no_execute (region.playlist()->get_memento());
2547 commit_reversible_command ();
2552 Editor::naturalize ()
2554 if (selection->audio_regions.empty()) {
2557 begin_reversible_command (_("naturalize"));
2558 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2559 session->add_undo ((*i)->region.get_memento());
2560 (*i)->region.move_to_natural_position (this);
2561 session->add_redo_no_execute ((*i)->region.get_memento());
2563 commit_reversible_command ();
2567 Editor::align (RegionPoint what)
2569 align_selection (what, edit_cursor->current_frame);
2573 Editor::align_relative (RegionPoint what)
2575 align_selection_relative (what, edit_cursor->current_frame);
2578 struct RegionSortByTime {
2579 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2580 return a->region.position() < b->region.position();
2585 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
2587 if (selection->audio_regions.empty()) {
2591 jack_nframes_t distance;
2592 jack_nframes_t pos = 0;
2595 list<AudioRegionView*> sorted;
2596 selection->audio_regions.by_position (sorted);
2597 Region& r ((*sorted.begin())->region);
2601 pos = r.first_frame ();
2605 pos = r.last_frame();
2609 pos = r.adjust_to_sync (r.first_frame());
2613 if (pos > position) {
2614 distance = pos - position;
2617 distance = position - pos;
2621 begin_reversible_command (_("align selection (relative)"));
2623 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2625 Region& region ((*i)->region);
2627 session->add_undo (region.playlist()->get_memento());
2630 region.set_position (region.position() + distance, this);
2632 region.set_position (region.position() - distance, this);
2635 session->add_redo_no_execute (region.playlist()->get_memento());
2639 commit_reversible_command ();
2643 Editor::align_selection (RegionPoint point, jack_nframes_t position)
2645 if (selection->audio_regions.empty()) {
2649 begin_reversible_command (_("align selection"));
2651 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2652 align_region_internal ((*i)->region, point, position);
2655 commit_reversible_command ();
2659 Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position)
2661 begin_reversible_command (_("align region"));
2662 align_region_internal (region, point, position);
2663 commit_reversible_command ();
2667 Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
2669 session->add_undo (region.playlist()->get_memento());
2673 region.set_position (region.adjust_to_sync (position), this);
2677 if (position > region.length()) {
2678 region.set_position (position - region.length(), this);
2683 region.set_position (position, this);
2687 session->add_redo_no_execute (region.playlist()->get_memento());
2691 Editor::trim_region_to_edit_cursor ()
2693 if (clicked_regionview == 0) {
2697 Region& region (clicked_regionview->region);
2700 AudioTimeAxisView *atav;
2702 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2703 if (atav->get_diskstream() != 0) {
2704 speed = atav->get_diskstream()->speed();
2708 begin_reversible_command (_("trim to edit"));
2709 session->add_undo (region.playlist()->get_memento());
2710 region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2711 session->add_redo_no_execute (region.playlist()->get_memento());
2712 commit_reversible_command ();
2716 Editor::trim_region_from_edit_cursor ()
2718 if (clicked_regionview == 0) {
2722 Region& region (clicked_regionview->region);
2725 AudioTimeAxisView *atav;
2727 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2728 if (atav->get_diskstream() != 0) {
2729 speed = atav->get_diskstream()->speed();
2733 begin_reversible_command (_("trim to edit"));
2734 session->add_undo (region.playlist()->get_memento());
2735 region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2736 session->add_redo_no_execute (region.playlist()->get_memento());
2737 commit_reversible_command ();
2741 Editor::unfreeze_route ()
2743 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2747 clicked_audio_trackview->audio_track()->unfreeze ();
2751 Editor::_freeze_thread (void* arg)
2753 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2754 return static_cast<Editor*>(arg)->freeze_thread ();
2758 Editor::freeze_thread ()
2760 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2765 Editor::freeze_progress_timeout (void *arg)
2767 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2768 return !(current_interthread_info->done || current_interthread_info->cancel);
2772 Editor::freeze_route ()
2774 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2778 InterThreadInfo itt;
2780 if (interthread_progress_window == 0) {
2781 build_interthread_progress_window ();
2784 interthread_progress_window->set_title (_("ardour: freeze"));
2785 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2786 interthread_progress_window->show_all ();
2787 interthread_progress_bar.set_fraction (0.0f);
2788 interthread_progress_label.set_text ("");
2789 interthread_cancel_label.set_text (_("Cancel Freeze"));
2790 current_interthread_info = &itt;
2792 interthread_progress_connection =
2793 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2797 itt.progress = 0.0f;
2799 pthread_create (&itt.thread, 0, _freeze_thread, this);
2801 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2803 while (!itt.done && !itt.cancel) {
2804 gtk_main_iteration ();
2807 interthread_progress_connection.disconnect ();
2808 interthread_progress_window->hide_all ();
2809 current_interthread_info = 0;
2810 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2814 Editor::bounce_range_selection ()
2816 if (selection->time.empty()) {
2820 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2822 jack_nframes_t start = selection->time[clicked_selection].start;
2823 jack_nframes_t end = selection->time[clicked_selection].end;
2824 jack_nframes_t cnt = end - start + 1;
2826 begin_reversible_command (_("bounce range"));
2828 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2830 AudioTimeAxisView* atv;
2832 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2838 if ((playlist = atv->playlist()) == 0) {
2842 InterThreadInfo itt;
2846 itt.progress = false;
2848 session->add_undo (playlist->get_memento());
2849 atv->audio_track()->bounce_range (start, cnt, itt);
2850 session->add_redo_no_execute (playlist->get_memento());
2853 commit_reversible_command ();
2871 Editor::cut_copy (CutCopyOp op)
2873 /* only cancel selection if cut/copy is successful.*/
2885 opname = _("clear");
2889 cut_buffer->clear ();
2891 switch (current_mouse_mode()) {
2893 if (!selection->audio_regions.empty() || !selection->points.empty()) {
2895 begin_reversible_command (opname + _(" objects"));
2897 if (!selection->audio_regions.empty()) {
2899 cut_copy_regions (op);
2902 selection->clear_audio_regions ();
2906 if (!selection->points.empty()) {
2907 cut_copy_points (op);
2910 selection->clear_points ();
2914 commit_reversible_command ();
2919 if (!selection->time.empty()) {
2921 begin_reversible_command (opname + _(" range"));
2922 cut_copy_ranges (op);
2923 commit_reversible_command ();
2926 selection->clear_time ();
2938 Editor::cut_copy_points (CutCopyOp op)
2940 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2942 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2945 atv->cut_copy_clear_objects (selection->points, op);
2951 Editor::cut_copy_regions (CutCopyOp op)
2953 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
2954 PlaylistMapping pmap;
2955 jack_nframes_t first_position = max_frames;
2956 set<Playlist*> freezelist;
2957 pair<set<Playlist*>::iterator,bool> insert_result;
2959 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
2960 first_position = min ((*x)->region.position(), first_position);
2962 if (op == Cut || op == Clear) {
2963 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2965 insert_result = freezelist.insert (pl);
2966 if (insert_result.second) {
2968 session->add_undo (pl->get_memento());
2974 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
2976 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2978 AudioRegionSelection::iterator tmp;
2985 PlaylistMapping::iterator pi = pmap.find (pl);
2987 if (pi == pmap.end()) {
2988 npl = new AudioPlaylist (*session, "cutlist", true);
2997 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
2998 pl->remove_region (&((*x)->region));
3002 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
3006 pl->remove_region (&((*x)->region));
3014 list<Playlist*> foo;
3016 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
3017 foo.push_back (i->second);
3021 cut_buffer->set (foo);
3024 for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
3026 session->add_redo_no_execute ((*pl)->get_memento());
3031 Editor::cut_copy_ranges (CutCopyOp op)
3033 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3034 (*i)->cut_copy_clear (*selection, op);
3039 Editor::paste (float times)
3041 paste_internal (edit_cursor->current_frame, times);
3045 Editor::mouse_paste ()
3050 track_canvas.get_pointer (x, y);
3051 track_canvas.window_to_world (x, y, wx, wy);
3052 wx += horizontal_adjustment.get_value();
3053 wy += vertical_adjustment.get_value();
3056 event.type = GDK_BUTTON_RELEASE;
3057 event.button.x = wx;
3058 event.button.y = wy;
3060 jack_nframes_t where = event_frame (&event, 0, 0);
3062 paste_internal (where, 1);
3066 Editor::paste_internal (jack_nframes_t position, float times)
3068 bool commit = false;
3070 if (cut_buffer->empty() || selection->tracks.empty()) {
3074 if (position == max_frames) {
3075 position = edit_cursor->current_frame;
3078 begin_reversible_command (_("paste"));
3080 TrackSelection::iterator i;
3083 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
3085 /* undo/redo is handled by individual tracks */
3087 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3093 commit_reversible_command ();
3098 Editor::paste_named_selection (float times)
3100 TrackSelection::iterator t;
3102 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3104 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3108 TreeModel::iterator i = selected->get_selected();
3109 NamedSelection* ns = (*i)[named_selection_columns.selection];
3111 list<Playlist*>::iterator chunk;
3112 list<Playlist*>::iterator tmp;
3114 chunk = ns->playlists.begin();
3116 begin_reversible_command (_("paste chunk"));
3118 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3120 AudioTimeAxisView* atv;
3124 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3128 if ((pl = atv->playlist()) == 0) {
3132 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
3139 session->add_undo (apl->get_memento());
3140 apl->paste (**chunk, edit_cursor->current_frame, times);
3141 session->add_redo_no_execute (apl->get_memento());
3143 if (tmp != ns->playlists.end()) {
3148 commit_reversible_command();
3152 Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
3155 AudioRegionSelection sel = regions; // clear (below) will clear the argument list
3157 begin_reversible_command (_("duplicate region"));
3159 selection->clear_audio_regions ();
3161 for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3163 Region& r ((*i)->region);
3165 TimeAxisView& tv = (*i)->get_time_axis_view();
3166 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3167 sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3169 playlist = (*i)->region.playlist();
3170 session->add_undo (playlist->get_memento());
3171 playlist->duplicate (r, r.last_frame(), times);
3172 session->add_redo_no_execute (playlist->get_memento());
3176 if (latest_regionview) {
3177 selection->add (latest_regionview);
3182 commit_reversible_command ();
3186 Editor::duplicate_selection (float times)
3188 if (selection->time.empty() || selection->tracks.empty()) {
3193 vector<AudioRegion*> new_regions;
3194 vector<AudioRegion*>::iterator ri;
3196 create_region_from_selection (new_regions);
3198 if (new_regions.empty()) {
3202 begin_reversible_command (_("duplicate selection"));
3204 ri = new_regions.begin();
3206 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3207 if ((playlist = (*i)->playlist()) == 0) {
3210 session->add_undo (playlist->get_memento());
3211 playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
3212 session->add_redo_no_execute (playlist->get_memento());
3215 if (ri == new_regions.end()) {
3220 commit_reversible_command ();
3224 Editor::reset_point_selection ()
3226 /* reset all selected points to the relevant default value */
3228 cerr << "point selection has " << selection->points.size() << " entries\n";
3230 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3232 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3235 atv->reset_objects (selection->points);
3241 Editor::center_playhead ()
3243 float page = canvas_width * frames_per_unit;
3245 center_screen_internal (playhead_cursor->current_frame, page);
3249 Editor::center_edit_cursor ()
3251 float page = canvas_width * frames_per_unit;
3253 center_screen_internal (edit_cursor->current_frame, page);
3257 Editor::clear_playlist (Playlist& playlist)
3259 begin_reversible_command (_("clear playlist"));
3260 session->add_undo (playlist.get_memento());
3262 session->add_redo_no_execute (playlist.get_memento());
3263 commit_reversible_command ();
3267 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3270 jack_nframes_t distance;
3271 jack_nframes_t next_distance;
3272 jack_nframes_t start;
3274 if (use_edit_cursor) {
3275 start = edit_cursor->current_frame;
3280 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3284 if (selection->tracks.empty()) {
3288 begin_reversible_command (_("nudge track"));
3290 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3292 if ((playlist = (*i)->playlist()) == 0) {
3296 session->add_undo (playlist->get_memento());
3297 playlist->nudge_after (start, distance, forwards);
3298 session->add_redo_no_execute (playlist->get_memento());
3301 commit_reversible_command ();
3305 Editor::remove_last_capture ()
3307 vector<string> choices;
3314 if (Config->get_verify_remove_last_capture()) {
3315 prompt = _("Do you really want to destroy the last capture?"
3316 "\n(This is destructive and cannot be undone)");
3318 choices.push_back (_("No, do nothing."));
3319 choices.push_back (_("Yes, destroy it."));
3321 Gtkmm2ext::Choice prompter (prompt, choices);
3323 if (prompter.run () == 1) {
3324 session->remove_last_capture ();
3328 session->remove_last_capture();
3333 Editor::normalize_region ()
3339 if (selection->audio_regions.empty()) {
3343 begin_reversible_command (_("normalize"));
3345 track_canvas.get_window()->set_cursor (*wait_cursor);
3348 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3349 session->add_undo ((*r)->region.get_memento());
3350 (*r)->region.normalize_to (0.0f);
3351 session->add_redo_no_execute ((*r)->region.get_memento());
3354 commit_reversible_command ();
3355 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3360 Editor::denormalize_region ()
3366 if (selection->audio_regions.empty()) {
3370 begin_reversible_command ("denormalize");
3372 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3373 session->add_undo ((*r)->region.get_memento());
3374 (*r)->region.set_scale_amplitude (1.0f);
3375 session->add_redo_no_execute ((*r)->region.get_memento());
3378 commit_reversible_command ();
3383 Editor::reverse_region ()
3389 Reverse rev (*session);
3390 apply_filter (rev, _("reverse regions"));
3394 Editor::apply_filter (AudioFilter& filter, string command)
3396 if (selection->audio_regions.empty()) {
3400 begin_reversible_command (command);
3402 track_canvas.get_window()->set_cursor (*wait_cursor);
3405 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
3407 AudioRegion& region ((*r)->region);
3408 Playlist* playlist = region.playlist();
3410 AudioRegionSelection::iterator tmp;
3415 if (region.apply (filter) == 0) {
3417 session->add_undo (playlist->get_memento());
3418 playlist->replace_region (region, *(filter.results.front()), region.position());
3419 session->add_redo_no_execute (playlist->get_memento());
3427 commit_reversible_command ();
3428 selection->audio_regions.clear ();
3431 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3435 Editor::region_selection_op (void (Region::*pmf)(void))
3437 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3438 ((*i)->region.*pmf)();
3444 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3446 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3447 ((*i)->region.*pmf)(arg);
3452 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3454 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3455 ((*i)->region.*pmf)(yn);
3460 Editor::external_edit_region ()
3462 if (!clicked_regionview) {
3470 Editor::brush (jack_nframes_t pos)
3472 AudioRegionSelection sel;
3475 if (selection->audio_regions.empty()) {
3476 /* XXX get selection from region list */
3478 sel = selection->audio_regions;
3485 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3486 mouse_brush_insert_region ((*i), pos);
3491 Editor::toggle_gain_envelope_visibility ()
3493 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3494 (*i)->set_envelope_visible (!(*i)->envelope_visible());
3499 Editor::toggle_gain_envelope_active ()
3501 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3502 AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
3504 ar->set_envelope_active (true);