2 Copyright (C) 2000-2004 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <pbd/error.h>
29 #include <pbd/basename.h>
30 #include <pbd/pthread_utils.h>
31 #include <pbd/memento_command.h>
33 #include <gtkmm2ext/utils.h>
34 #include <gtkmm2ext/choice.h>
36 #include <ardour/audioengine.h>
37 #include <ardour/session.h>
38 #include <ardour/audioplaylist.h>
39 #include <ardour/audioregion.h>
40 #include <ardour/audio_diskstream.h>
41 #include <ardour/utils.h>
42 #include <ardour/location.h>
43 #include <ardour/named_selection.h>
44 #include <ardour/audio_track.h>
45 #include <ardour/audioplaylist.h>
46 #include <ardour/region_factory.h>
47 #include <ardour/reverse.h>
49 #include "ardour_ui.h"
51 #include "time_axis_view.h"
52 #include "audio_time_axis.h"
53 #include "automation_time_axis.h"
54 #include "streamview.h"
55 #include "audio_region_view.h"
56 #include "rgb_macros.h"
57 #include "selection_templates.h"
58 #include "selection.h"
61 #include "gtk-custom-hruler.h"
62 #include "gui_thread.h"
67 using namespace ARDOUR;
71 using namespace Editing;
73 /***********************************************************************
75 ***********************************************************************/
78 Editor::undo (uint32_t n)
86 Editor::redo (uint32_t n)
94 Editor::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)
125 float val = 0.0f; /* off */
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->regions);
194 Editor::split_regions_at (jack_nframes_t where, RegionSelection& regions)
196 begin_reversible_command (_("split"));
199 for (RegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
201 RegionSelection::iterator tmp;
206 Playlist* pl = (*a)->region().playlist();
208 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*a);
210 _new_regionviews_show_envelope = arv->envelope_visible();
213 XMLNode &before = pl->get_state();
214 pl->split_region ((*a)->region(), where);
215 XMLNode &after = pl->get_state();
216 session->add_command(new MementoCommand<Playlist>(*pl, before, after));
222 commit_reversible_command ();
223 _new_regionviews_show_envelope = false;
227 Editor::remove_clicked_region ()
229 if (clicked_routeview == 0 || clicked_regionview == 0) {
233 Playlist* playlist = clicked_routeview->playlist();
235 begin_reversible_command (_("remove region"));
236 XMLNode &before = playlist->get_state();
237 playlist->remove_region (&clicked_regionview->region());
238 XMLNode &after = playlist->get_state();
239 session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
240 commit_reversible_command ();
244 Editor::destroy_clicked_region ()
246 int32_t selected = selection->regions.size();
248 if (!session || clicked_regionview == 0 && selected == 0) {
252 vector<string> choices;
255 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
256 It cannot be undone\n\
257 Do you really want to destroy %1 ?"),
259 _("these regions") : _("this region")));
261 choices.push_back (_("No, do nothing."));
264 choices.push_back (_("Yes, destroy them."));
266 choices.push_back (_("Yes, destroy it."));
269 Gtkmm2ext::Choice prompter (prompt, choices);
271 if (prompter.run() == 0) { /* first choice */
278 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
279 r.push_back (&(*i)->region());
282 session->destroy_regions (r);
284 } else if (clicked_regionview) {
285 session->destroy_region (&clicked_regionview->region());
290 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
294 jack_nframes_t start = 0;
296 if (selection->time.start () == selection->time.end_frame ()) {
298 /* no current selection-> is there a selected regionview? */
300 if (selection->regions.empty()) {
308 if (!selection->regions.empty()) {
310 rv = *(selection->regions.begin());
311 (*tv) = &rv->get_time_axis_view();
312 region = &rv->region();
314 } else if (!selection->tracks.empty()) {
316 (*tv) = selection->tracks.front();
318 RouteTimeAxisView* rtv;
320 if ((rtv = dynamic_cast<RouteTimeAxisView*> (*tv)) != 0) {
323 if ((pl = rtv->playlist()) == 0) {
327 region = pl->top_region_at (start);
335 Editor::extend_selection_to_end_of_region (bool next)
339 jack_nframes_t start;
341 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
345 if (region && selection->time.start () == selection->time.end_frame ()) {
346 start = region->position();
348 start = selection->time.start ();
351 /* Try to leave the selection with the same route if possible */
353 if ((tv = selection->time.track) == 0) {
357 begin_reversible_command (_("extend selection"));
358 selection->set (tv, start, region->position() + region->length());
359 commit_reversible_command ();
363 Editor::extend_selection_to_start_of_region (bool previous)
369 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
373 if (region && selection->time.start () == selection->time.end_frame ()) {
374 end = region->position() + region->length();
376 end = selection->time.end_frame ();
379 /* Try to leave the selection with the same route if possible */
381 if ((tv = selection->time.track) == 0) {
385 begin_reversible_command (_("extend selection"));
386 selection->set (tv, region->position(), end);
387 commit_reversible_command ();
392 Editor::nudge_forward (bool next)
394 jack_nframes_t distance;
395 jack_nframes_t next_distance;
397 if (!session) return;
399 if (!selection->regions.empty()) {
401 begin_reversible_command (_("nudge forward"));
403 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
404 Region& r ((*i)->region());
406 distance = get_nudge_distance (r.position(), next_distance);
409 distance = next_distance;
412 XMLNode &before = r.playlist()->get_state();
413 r.set_position (r.position() + distance, this);
414 XMLNode &after = r.playlist()->get_state();
415 session->add_command (new MementoCommand<Playlist>(*(r.playlist()), before, after));
418 commit_reversible_command ();
421 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
422 session->request_locate (playhead_cursor->current_frame + distance);
427 Editor::nudge_backward (bool next)
429 jack_nframes_t distance;
430 jack_nframes_t next_distance;
432 if (!session) return;
434 if (!selection->regions.empty()) {
436 begin_reversible_command (_("nudge forward"));
438 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
439 Region& r ((*i)->region());
441 distance = get_nudge_distance (r.position(), next_distance);
444 distance = next_distance;
447 XMLNode &before = r.playlist()->get_state();
449 if (r.position() > distance) {
450 r.set_position (r.position() - distance, this);
452 r.set_position (0, this);
454 XMLNode &after = r.playlist()->get_state();
455 session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
458 commit_reversible_command ();
462 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
464 if (playhead_cursor->current_frame > distance) {
465 session->request_locate (playhead_cursor->current_frame - distance);
467 session->goto_start();
473 Editor::nudge_forward_capture_offset ()
475 jack_nframes_t distance;
477 if (!session) return;
479 if (!selection->regions.empty()) {
481 begin_reversible_command (_("nudge forward"));
483 distance = session->worst_output_latency();
485 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
486 Region& r ((*i)->region());
488 XMLNode &before = r.playlist()->get_state();
489 r.set_position (r.position() + distance, this);
490 XMLNode &after = r.playlist()->get_state();
491 session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
494 commit_reversible_command ();
500 Editor::nudge_backward_capture_offset ()
502 jack_nframes_t distance;
504 if (!session) return;
506 if (!selection->regions.empty()) {
508 begin_reversible_command (_("nudge forward"));
510 distance = session->worst_output_latency();
512 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
513 Region& r ((*i)->region());
515 XMLNode &before = r.playlist()->get_state();
517 if (r.position() > distance) {
518 r.set_position (r.position() - distance, this);
520 r.set_position (0, this);
522 XMLNode &after = r.playlist()->get_state();
523 session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
526 commit_reversible_command ();
533 Editor::move_to_start ()
535 session->goto_start ();
539 Editor::move_to_end ()
542 session->request_locate (session->current_end_frame());
546 Editor::build_region_boundary_cache ()
548 jack_nframes_t pos = 0;
551 TrackViewList tracks;
553 region_boundary_cache.clear ();
560 case SnapToRegionStart:
563 case SnapToRegionEnd:
566 case SnapToRegionSync:
569 case SnapToRegionBoundary:
573 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
578 TimeAxisView *ontrack = 0;
580 while (pos < session->current_end_frame()) {
582 if (!selection->tracks.empty()) {
584 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
588 } else if (clicked_axisview) {
591 t.push_back (clicked_axisview);
593 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
599 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
607 case SnapToRegionStart:
608 rpos = r->first_frame();
610 case SnapToRegionEnd:
611 rpos = r->last_frame();
613 case SnapToRegionSync:
614 rpos = r->adjust_to_sync (r->first_frame());
617 case SnapToRegionBoundary:
618 rpos = r->last_frame();
625 AudioTimeAxisView *atav;
627 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
628 if (atav->get_diskstream() != 0) {
629 speed = atav->get_diskstream()->speed();
633 rpos = track_frame_to_session_frame(rpos, speed);
635 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
636 if (snap_type == SnapToRegionBoundary) {
637 region_boundary_cache.push_back (r->first_frame());
639 region_boundary_cache.push_back (rpos);
647 Editor::find_next_region (jack_nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
649 TrackViewList::iterator i;
650 jack_nframes_t closest = max_frames;
652 jack_nframes_t rpos = 0;
655 jack_nframes_t track_frame;
656 AudioTimeAxisView *atav;
658 for (i = tracks.begin(); i != tracks.end(); ++i) {
660 jack_nframes_t distance;
664 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
665 if (atav->get_diskstream()!=0)
666 track_speed = atav->get_diskstream()->speed();
669 track_frame = session_frame_to_track_frame(frame, track_speed);
671 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
677 rpos = r->first_frame ();
681 rpos = r->last_frame ();
685 rpos = r->adjust_to_sync (r->first_frame());
688 // rpos is a "track frame", converting it to "session frame"
689 rpos = track_frame_to_session_frame(rpos, track_speed);
692 distance = rpos - frame;
694 distance = frame - rpos;
697 if (distance < closest) {
709 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
712 jack_nframes_t pos = cursor->current_frame;
718 TimeAxisView *ontrack = 0;
720 // so we don't find the current region again..
724 if (!selection->tracks.empty()) {
726 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
728 } else if (clicked_axisview) {
731 t.push_back (clicked_axisview);
733 r = find_next_region (pos, point, dir, t, &ontrack);
737 r = find_next_region (pos, point, dir, track_views, &ontrack);
746 pos = r->first_frame ();
750 pos = r->last_frame ();
754 pos = r->adjust_to_sync (r->first_frame());
759 AudioTimeAxisView *atav;
761 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
762 if (atav->get_diskstream() != 0) {
763 speed = atav->get_diskstream()->speed();
767 pos = track_frame_to_session_frame(pos, speed);
769 if (cursor == playhead_cursor) {
770 session->request_locate (pos);
772 cursor->set_position (pos);
777 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
779 cursor_to_region_point (cursor, point, 1);
783 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
785 cursor_to_region_point (cursor, point, -1);
789 Editor::cursor_to_selection_start (Cursor *cursor)
791 jack_nframes_t pos = 0;
792 switch (mouse_mode) {
794 if (!selection->regions.empty()) {
795 pos = selection->regions.start();
800 if (!selection->time.empty()) {
801 pos = selection->time.start ();
809 if (cursor == playhead_cursor) {
810 session->request_locate (pos);
812 cursor->set_position (pos);
817 Editor::cursor_to_selection_end (Cursor *cursor)
819 jack_nframes_t pos = 0;
821 switch (mouse_mode) {
823 if (!selection->regions.empty()) {
824 pos = selection->regions.end_frame();
829 if (!selection->time.empty()) {
830 pos = selection->time.end_frame ();
838 if (cursor == playhead_cursor) {
839 session->request_locate (pos);
841 cursor->set_position (pos);
846 Editor::playhead_backward ()
853 if (get_prefix (prefix, was_floating)) {
857 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
859 cnt = (jack_nframes_t) prefix;
863 pos = playhead_cursor->current_frame;
865 if ((jack_nframes_t) pos < cnt) {
871 /* XXX this is completely insane. with the current buffering
872 design, we'll force a complete track buffer flush and
873 reload, just to move 1 sample !!!
876 session->request_locate (pos);
880 Editor::playhead_forward ()
887 if (get_prefix (prefix, was_floating)) {
891 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
893 cnt = (jack_nframes_t) floor (prefix);
897 pos = playhead_cursor->current_frame;
899 /* XXX this is completely insane. with the current buffering
900 design, we'll force a complete track buffer flush and
901 reload, just to move 1 sample !!!
904 session->request_locate (pos+cnt);
908 Editor::cursor_align (bool playhead_to_edit)
910 if (playhead_to_edit) {
912 session->request_locate (edit_cursor->current_frame);
915 edit_cursor->set_position (playhead_cursor->current_frame);
920 Editor::edit_cursor_backward ()
927 if (get_prefix (prefix, was_floating)) {
931 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
933 cnt = (jack_nframes_t) prefix;
937 pos = edit_cursor->current_frame;
939 if ((jack_nframes_t) pos < cnt) {
945 edit_cursor->set_position (pos);
949 Editor::edit_cursor_forward ()
956 if (get_prefix (prefix, was_floating)) {
960 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
962 cnt = (jack_nframes_t) floor (prefix);
966 pos = edit_cursor->current_frame;
967 edit_cursor->set_position (pos+cnt);
971 Editor::goto_frame ()
975 jack_nframes_t frame;
977 if (get_prefix (prefix, was_floating)) {
982 frame = (jack_nframes_t) floor (prefix * session->frame_rate());
984 frame = (jack_nframes_t) floor (prefix);
987 session->request_locate (frame);
991 Editor::scroll_backward (float pages)
993 jack_nframes_t frame;
994 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
999 if (get_prefix (prefix, was_floating)) {
1000 cnt = (jack_nframes_t) floor (pages * one_page);
1003 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
1005 cnt = (jack_nframes_t) floor (prefix * one_page);
1009 if (leftmost_frame < cnt) {
1012 frame = leftmost_frame - cnt;
1015 reposition_x_origin (frame);
1019 Editor::scroll_forward (float pages)
1021 jack_nframes_t frame;
1022 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
1027 if (get_prefix (prefix, was_floating)) {
1028 cnt = (jack_nframes_t) floor (pages * one_page);
1031 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
1033 cnt = (jack_nframes_t) floor (prefix * one_page);
1037 if (ULONG_MAX - cnt < leftmost_frame) {
1038 frame = ULONG_MAX - cnt;
1040 frame = leftmost_frame + cnt;
1043 reposition_x_origin (frame);
1047 Editor::scroll_tracks_down ()
1053 if (get_prefix (prefix, was_floating)) {
1056 cnt = (int) floor (prefix);
1059 double vert_value = vertical_adjustment.get_value() + (cnt *
1060 vertical_adjustment.get_page_size());
1061 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
1062 vert_value = vertical_adjustment.get_upper() - canvas_height;
1064 vertical_adjustment.set_value (vert_value);
1068 Editor::scroll_tracks_up ()
1074 if (get_prefix (prefix, was_floating)) {
1077 cnt = (int) floor (prefix);
1080 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1084 Editor::scroll_tracks_down_line ()
1087 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1088 double vert_value = adj->get_value() + 20;
1090 if (vert_value>adj->get_upper() - canvas_height) {
1091 vert_value = adj->get_upper() - canvas_height;
1093 adj->set_value (vert_value);
1097 Editor::scroll_tracks_up_line ()
1099 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1100 adj->set_value (adj->get_value() - 20);
1106 Editor::temporal_zoom_step (bool coarser)
1108 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1112 nfpu = frames_per_unit;
1117 nfpu = max(1.0,(nfpu/2.0));
1120 temporal_zoom (nfpu);
1124 Editor::temporal_zoom (gdouble fpu)
1126 if (!session) return;
1128 jack_nframes_t current_page = current_page_frames();
1129 jack_nframes_t current_leftmost = leftmost_frame;
1130 jack_nframes_t current_rightmost;
1131 jack_nframes_t current_center;
1132 jack_nframes_t new_page;
1133 jack_nframes_t leftmost_after_zoom = 0;
1138 new_page = (jack_nframes_t) floor (canvas_width * nfpu);
1140 switch (zoom_focus) {
1142 leftmost_after_zoom = current_leftmost;
1145 case ZoomFocusRight:
1146 current_rightmost = leftmost_frame + current_page;
1147 if (current_rightmost > new_page) {
1148 leftmost_after_zoom = current_rightmost - new_page;
1150 leftmost_after_zoom = 0;
1154 case ZoomFocusCenter:
1155 current_center = current_leftmost + (current_page/2);
1156 if (current_center > (new_page/2)) {
1157 leftmost_after_zoom = current_center - (new_page / 2);
1159 leftmost_after_zoom = 0;
1163 case ZoomFocusPlayhead:
1164 /* try to keep the playhead in the center */
1165 if (playhead_cursor->current_frame > new_page/2) {
1166 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1168 leftmost_after_zoom = 0;
1173 /* try to keep the edit cursor in the center */
1174 if (edit_cursor->current_frame > leftmost_frame + (new_page/2)) {
1175 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1177 leftmost_after_zoom = 0;
1183 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1185 // begin_reversible_command (_("zoom"));
1186 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1187 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1188 // commit_reversible_command ();
1190 reposition_and_zoom (leftmost_after_zoom, nfpu);
1194 Editor::temporal_zoom_selection ()
1196 if (!selection) return;
1198 if (selection->time.empty()) {
1202 jack_nframes_t start = selection->time[clicked_selection].start;
1203 jack_nframes_t end = selection->time[clicked_selection].end;
1205 temporal_zoom_by_frame (start, end, "zoom to selection");
1209 Editor::temporal_zoom_session ()
1211 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1214 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1219 Editor::temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, const string & op)
1221 if (!session) return;
1223 if ((start == 0 && end == 0) || end < start) {
1227 jack_nframes_t range = end - start;
1229 double new_fpu = (double)range / (double)canvas_width;
1232 // while (p2 < new_fpu) {
1237 jack_nframes_t new_page = (jack_nframes_t) floor (canvas_width * new_fpu);
1238 jack_nframes_t middle = (jack_nframes_t) floor( (double)start + ((double)range / 2.0f ));
1239 jack_nframes_t new_leftmost = (jack_nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1241 if (new_leftmost > middle) new_leftmost = 0;
1243 // begin_reversible_command (op);
1244 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1245 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1246 // commit_reversible_command ();
1248 reposition_and_zoom (new_leftmost, new_fpu);
1252 Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
1254 if (!session) return;
1256 jack_nframes_t range_before = frame - leftmost_frame;
1259 new_fpu = frames_per_unit;
1265 new_fpu = max(1.0,(new_fpu/2.0));
1269 if (new_fpu == frames_per_unit) return;
1271 jack_nframes_t new_leftmost = frame - range_before;
1273 if (new_leftmost > frame) new_leftmost = 0;
1275 // begin_reversible_command (_("zoom to frame"));
1276 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1277 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1278 // commit_reversible_command ();
1280 reposition_and_zoom (new_leftmost, new_fpu);
1284 Editor::add_location_from_selection ()
1286 if (selection->time.empty()) {
1290 if (session == 0 || clicked_axisview == 0) {
1294 jack_nframes_t start = selection->time[clicked_selection].start;
1295 jack_nframes_t end = selection->time[clicked_selection].end;
1297 Location *location = new Location (start, end, "selection");
1299 session->begin_reversible_command (_("add marker"));
1300 XMLNode &before = session->locations()->get_state();
1301 session->locations()->add (location, true);
1302 XMLNode &after = session->locations()->get_state();
1303 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1304 session->commit_reversible_command ();
1308 Editor::add_location_from_playhead_cursor ()
1310 jack_nframes_t where = session->audible_frame();
1312 Location *location = new Location (where, where, "mark", Location::IsMark);
1313 session->begin_reversible_command (_("add marker"));
1314 XMLNode &before = session->locations()->get_state();
1315 session->locations()->add (location, true);
1316 XMLNode &after = session->locations()->get_state();
1317 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1318 session->commit_reversible_command ();
1322 Editor::add_location_from_audio_region ()
1324 if (selection->regions.empty()) {
1328 RegionView* rv = *(selection->regions.begin());
1329 Region& region = rv->region();
1331 Location *location = new Location (region.position(), region.last_frame(), region.name());
1332 session->begin_reversible_command (_("add marker"));
1333 XMLNode &before = session->locations()->get_state();
1334 session->locations()->add (location, true);
1335 XMLNode &after = session->locations()->get_state();
1336 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1337 session->commit_reversible_command ();
1341 Editor::select_all_in_track (Selection::Operation op)
1343 list<Selectable *> touched;
1345 if (!clicked_axisview) {
1349 clicked_axisview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1352 case Selection::Toggle:
1353 selection->add (touched);
1355 case Selection::Set:
1356 selection->set (touched);
1358 case Selection::Extend:
1359 /* not defined yet */
1365 Editor::select_all (Selection::Operation op)
1367 list<Selectable *> touched;
1369 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1370 if ((*iter)->hidden()) {
1373 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1375 begin_reversible_command (_("select all"));
1377 case Selection::Toggle:
1378 selection->add (touched);
1380 case Selection::Set:
1381 selection->set (touched);
1383 case Selection::Extend:
1384 /* not defined yet */
1387 commit_reversible_command ();
1391 Editor::invert_selection_in_track ()
1393 list<Selectable *> touched;
1395 if (!clicked_axisview) {
1399 clicked_axisview->get_inverted_selectables (*selection, touched);
1400 selection->set (touched);
1404 Editor::invert_selection ()
1406 list<Selectable *> touched;
1408 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1409 if ((*iter)->hidden()) {
1412 (*iter)->get_inverted_selectables (*selection, touched);
1415 selection->set (touched);
1419 Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, Selection::Operation op)
1421 list<Selectable *> touched;
1423 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1424 if ((*iter)->hidden()) {
1427 (*iter)->get_selectables (start, end, top, bot, touched);
1430 cerr << "select all within found " << touched.size() << endl;
1432 begin_reversible_command (_("select all within"));
1434 case Selection::Toggle:
1436 selection->add (touched);
1438 case Selection::Set:
1440 selection->set (touched);
1442 case Selection::Extend:
1444 /* not defined yet */
1448 cerr << "selection now has " << selection->points.size() << endl;
1450 commit_reversible_command ();
1451 return !touched.empty();
1455 Editor::set_selection_from_audio_region ()
1457 if (selection->regions.empty()) {
1461 RegionView* rv = *(selection->regions.begin());
1462 Region& region = rv->region();
1464 begin_reversible_command (_("set selection from region"));
1465 selection->set (0, region.position(), region.last_frame());
1466 commit_reversible_command ();
1468 set_mouse_mode (Editing::MouseRange, false);
1472 Editor::set_selection_from_punch()
1476 if ((location = session->locations()->auto_punch_location()) == 0) {
1480 set_selection_from_range (*location);
1484 Editor::set_selection_from_loop()
1488 if ((location = session->locations()->auto_loop_location()) == 0) {
1491 set_selection_from_range (*location);
1495 Editor::set_selection_from_range (Location& loc)
1497 begin_reversible_command (_("set selection from range"));
1498 selection->set (0, loc.start(), loc.end());
1499 commit_reversible_command ();
1501 set_mouse_mode (Editing::MouseRange, false);
1505 Editor::select_all_selectables_using_time_selection ()
1507 list<Selectable *> touched;
1509 if (selection->time.empty()) {
1513 jack_nframes_t start = selection->time[clicked_selection].start;
1514 jack_nframes_t end = selection->time[clicked_selection].end;
1516 if (end - start < 1) {
1520 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1521 if ((*iter)->hidden()) {
1524 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1527 begin_reversible_command (_("select all from range"));
1528 selection->set (touched);
1529 commit_reversible_command ();
1534 Editor::select_all_selectables_using_punch()
1536 Location* location = session->locations()->auto_punch_location();
1537 list<Selectable *> touched;
1539 if (location == 0 || (location->end() - location->start() <= 1)) {
1543 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1544 if ((*iter)->hidden()) {
1547 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1549 begin_reversible_command (_("select all from punch"));
1550 selection->set (touched);
1551 commit_reversible_command ();
1556 Editor::select_all_selectables_using_loop()
1558 Location* location = session->locations()->auto_loop_location();
1559 list<Selectable *> touched;
1561 if (location == 0 || (location->end() - location->start() <= 1)) {
1565 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1566 if ((*iter)->hidden()) {
1569 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1571 begin_reversible_command (_("select all from loop"));
1572 selection->set (touched);
1573 commit_reversible_command ();
1578 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1580 jack_nframes_t start;
1582 list<Selectable *> touched;
1585 begin_reversible_command (_("select all after cursor"));
1586 start = cursor->current_frame ;
1587 end = session->current_end_frame();
1589 if (cursor->current_frame > 0) {
1590 begin_reversible_command (_("select all before cursor"));
1592 end = cursor->current_frame - 1;
1598 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1599 if ((*iter)->hidden()) {
1602 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1604 selection->set (touched);
1605 commit_reversible_command ();
1609 Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
1611 jack_nframes_t start;
1613 list<Selectable *> touched;
1614 bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
1616 if (cursor->current_frame == other_cursor->current_frame) {
1620 begin_reversible_command (_("select all between cursors"));
1621 if (other_cursor_is_first) {
1622 start = other_cursor->current_frame;
1623 end = cursor->current_frame - 1;
1626 start = cursor->current_frame;
1627 end = other_cursor->current_frame - 1;
1630 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1631 if ((*iter)->hidden()) {
1634 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1636 selection->set (touched);
1637 commit_reversible_command ();
1641 Editor::amplitude_zoom_step (bool in)
1655 #ifdef FIX_FOR_CANVAS
1656 /* XXX DO SOMETHING */
1665 Editor::delete_sample_forward ()
1670 Editor::delete_sample_backward ()
1675 Editor::delete_screen ()
1682 Editor::search_backwards ()
1688 Editor::search_forwards ()
1696 Editor::jump_forward_to_mark ()
1702 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1705 session->request_locate (location->start(), session->transport_rolling());
1707 session->request_locate (session->current_end_frame());
1712 Editor::jump_backward_to_mark ()
1718 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1721 session->request_locate (location->start(), session->transport_rolling());
1723 session->goto_start ();
1734 if (get_prefix (prefix, was_floating)) {
1735 pos = session->audible_frame ();
1738 pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
1740 pos = (jack_nframes_t) floor (prefix);
1744 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1748 Editor::clear_markers ()
1751 session->begin_reversible_command (_("clear markers"));
1752 XMLNode &before = session->locations()->get_state();
1753 session->locations()->clear_markers ();
1754 XMLNode &after = session->locations()->get_state();
1755 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1756 session->commit_reversible_command ();
1761 Editor::clear_ranges ()
1764 session->begin_reversible_command (_("clear ranges"));
1765 XMLNode &before = session->locations()->get_state();
1767 Location * looploc = session->locations()->auto_loop_location();
1768 Location * punchloc = session->locations()->auto_punch_location();
1770 session->locations()->clear_ranges ();
1772 if (looploc) session->locations()->add (looploc);
1773 if (punchloc) session->locations()->add (punchloc);
1775 XMLNode &after = session->locations()->get_state();
1776 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1777 session->commit_reversible_command ();
1782 Editor::clear_locations ()
1784 session->begin_reversible_command (_("clear locations"));
1785 XMLNode &before = session->locations()->get_state();
1786 session->locations()->clear ();
1787 XMLNode &after = session->locations()->get_state();
1788 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1789 session->commit_reversible_command ();
1790 session->locations()->clear ();
1793 /* INSERT/REPLACE */
1796 Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
1801 jack_nframes_t where;
1802 AudioTimeAxisView *atv = 0;
1805 track_canvas.window_to_world (x, y, wx, wy);
1806 wx += horizontal_adjustment.get_value();
1807 wy += vertical_adjustment.get_value();
1810 event.type = GDK_BUTTON_RELEASE;
1811 event.button.x = wx;
1812 event.button.y = wy;
1814 where = event_frame (&event, &cx, &cy);
1816 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1817 /* clearly outside canvas area */
1821 if ((tv = trackview_by_y_position (cy)) == 0) {
1825 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1829 if ((playlist = atv->playlist()) == 0) {
1835 begin_reversible_command (_("insert dragged region"));
1836 XMLNode &before = playlist->get_state();
1837 playlist->add_region (*(new AudioRegion (region)), where, 1.0);
1838 session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
1839 commit_reversible_command ();
1843 Editor::insert_region_list_selection (float times)
1845 RouteTimeAxisView *tv = 0;
1848 if (clicked_routeview != 0) {
1849 tv = clicked_routeview;
1850 } else if (!selection->tracks.empty()) {
1851 if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
1858 if ((playlist = tv->playlist()) == 0) {
1862 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1864 if (selected->count_selected_rows() != 1) {
1868 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
1869 Region* region = (*i)[region_list_columns.region];
1871 begin_reversible_command (_("insert region"));
1872 XMLNode &before = playlist->get_state();
1873 playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
1874 session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
1875 commit_reversible_command ();
1879 /* BUILT-IN EFFECTS */
1882 Editor::reverse_selection ()
1887 /* GAIN ENVELOPE EDITING */
1890 Editor::edit_envelope ()
1897 Editor::toggle_playback (bool with_abort)
1903 switch (session->slave_source()) {
1908 /* transport controlled by the master */
1912 if (session->is_auditioning()) {
1913 session->cancel_audition ();
1917 if (session->transport_rolling()) {
1918 session->request_stop (with_abort);
1919 if (session->get_auto_loop()) {
1920 session->request_auto_loop (false);
1923 session->request_transport_speed (1.0f);
1928 Editor::play_from_start ()
1930 session->request_locate (session->current_start_frame(), true);
1934 Editor::play_selection ()
1936 if (selection->time.empty()) {
1940 session->request_play_range (true);
1944 Editor::play_selected_region ()
1946 if (!selection->regions.empty()) {
1947 RegionView *rv = *(selection->regions.begin());
1949 session->request_bounded_roll (rv->region().position(), rv->region().last_frame());
1954 Editor::loop_selected_region ()
1956 if (!selection->regions.empty()) {
1957 RegionView *rv = *(selection->regions.begin());
1960 if ((tll = transport_loop_location()) != 0) {
1962 tll->set (rv->region().position(), rv->region().last_frame());
1964 // enable looping, reposition and start rolling
1966 session->request_auto_loop (true);
1967 session->request_locate (tll->start(), false);
1968 session->request_transport_speed (1.0f);
1974 Editor::play_location (Location& location)
1976 if (location.start() <= location.end()) {
1980 session->request_bounded_roll (location.start(), location.end());
1984 Editor::loop_location (Location& location)
1986 if (location.start() <= location.end()) {
1992 if ((tll = transport_loop_location()) != 0) {
1993 tll->set (location.start(), location.end());
1995 // enable looping, reposition and start rolling
1996 session->request_auto_loop (true);
1997 session->request_locate (tll->start(), true);
2002 Editor::toggle_region_mute ()
2004 if (clicked_regionview) {
2005 clicked_regionview->region().set_muted (!clicked_regionview->region().muted());
2006 } else if (!selection->regions.empty()) {
2007 bool yn = ! (*selection->regions.begin())->region().muted();
2008 selection->foreach_region (&Region::set_muted, yn);
2013 Editor::toggle_region_opaque ()
2015 if (clicked_regionview) {
2016 clicked_regionview->region().set_opaque (!clicked_regionview->region().opaque());
2017 } else if (!selection->regions.empty()) {
2018 bool yn = ! (*selection->regions.begin())->region().opaque();
2019 selection->foreach_region (&Region::set_opaque, yn);
2024 Editor::raise_region ()
2026 selection->foreach_region (&Region::raise);
2030 Editor::raise_region_to_top ()
2032 selection->foreach_region (&Region::raise_to_top);
2036 Editor::lower_region ()
2038 selection->foreach_region (&Region::lower);
2042 Editor::lower_region_to_bottom ()
2044 selection->foreach_region (&Region::lower_to_bottom);
2048 Editor::edit_region ()
2050 if (clicked_regionview == 0) {
2054 clicked_regionview->show_region_editor ();
2058 Editor::rename_region ()
2062 Button ok_button (_("OK"));
2063 Button cancel_button (_("Cancel"));
2065 if (selection->regions.empty()) {
2069 dialog.set_title (_("ardour: rename region"));
2070 dialog.set_name ("RegionRenameWindow");
2071 dialog.set_size_request (300, -1);
2072 dialog.set_position (Gtk::WIN_POS_MOUSE);
2073 dialog.set_modal (true);
2075 dialog.get_vbox()->set_border_width (10);
2076 dialog.get_vbox()->pack_start (entry);
2077 dialog.get_action_area()->pack_start (ok_button);
2078 dialog.get_action_area()->pack_start (cancel_button);
2080 entry.set_name ("RegionNameDisplay");
2081 ok_button.set_name ("EditorGTKButton");
2082 cancel_button.set_name ("EditorGTKButton");
2084 region_renamed = false;
2086 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2087 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2088 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
2095 if (region_renamed) {
2096 (*selection->regions.begin())->region().set_name (entry.get_text());
2097 redisplay_regions ();
2102 Editor::rename_region_finished (bool status)
2105 region_renamed = status;
2110 Editor::audition_playlist_region_via_route (Region& region, Route& route)
2112 if (session->is_auditioning()) {
2113 session->cancel_audition ();
2116 // note: some potential for creativity here, because region doesn't
2117 // have to belong to the playlist that Route is handling
2119 // bool was_soloed = route.soloed();
2121 route.set_solo (true, this);
2123 session->request_bounded_roll (region.position(), region.position() + region.length());
2125 /* XXX how to unset the solo state ? */
2129 Editor::audition_selected_region ()
2131 if (!selection->regions.empty()) {
2132 RegionView* rv = *(selection->regions.begin());
2133 session->audition_region (rv->region());
2138 Editor::audition_playlist_region_standalone (Region& region)
2140 session->audition_region (region);
2144 Editor::build_interthread_progress_window ()
2146 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
2148 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
2150 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
2151 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
2153 // GTK2FIX: this button needs a modifiable label
2155 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
2156 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
2158 interthread_cancel_button.add (interthread_cancel_label);
2160 interthread_progress_window->set_default_size (200, 100);
2164 Editor::interthread_cancel_clicked ()
2166 if (current_interthread_info) {
2167 current_interthread_info->cancel = true;
2172 Editor::region_from_selection ()
2174 if (clicked_axisview == 0) {
2178 if (selection->time.empty()) {
2182 jack_nframes_t start = selection->time[clicked_selection].start;
2183 jack_nframes_t end = selection->time[clicked_selection].end;
2185 jack_nframes_t selection_cnt = end - start + 1;
2187 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2189 AudioRegion *region;
2190 AudioRegion *current;
2194 jack_nframes_t internal_start;
2197 if ((pl = (*i)->playlist()) == 0) {
2201 if ((current_r = pl->top_region_at (start)) == 0) {
2205 current = dynamic_cast<AudioRegion*> (current_r);
2206 assert(current); // FIXME
2208 internal_start = start - current->position();
2209 session->region_name (new_name, current->name(), true);
2210 region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
2216 Editor::create_region_from_selection (vector<AudioRegion *>& new_regions)
2218 if (selection->time.empty() || selection->tracks.empty()) {
2222 jack_nframes_t start = selection->time[clicked_selection].start;
2223 jack_nframes_t end = selection->time[clicked_selection].end;
2225 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2227 AudioRegion* current;
2230 jack_nframes_t internal_start;
2233 if ((playlist = (*i)->playlist()) == 0) {
2237 if ((current_r = playlist->top_region_at(start)) == 0) {
2241 if ((current = dynamic_cast<AudioRegion*>(current_r)) == 0) {
2245 internal_start = start - current->position();
2246 session->region_name (new_name, current->name(), true);
2248 new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name));
2253 Editor::split_multichannel_region ()
2255 vector<AudioRegion*> v;
2257 AudioRegionView* clicked_arv = dynamic_cast<AudioRegionView*>(clicked_regionview);
2259 if (!clicked_arv || clicked_arv->audio_region().n_channels() < 2) {
2263 clicked_arv->audio_region().separate_by_channel (*session, v);
2265 /* nothing else to do, really */
2269 Editor::new_region_from_selection ()
2271 region_from_selection ();
2272 cancel_selection ();
2276 Editor::separate_region_from_selection ()
2280 bool doing_undo = false;
2282 if (selection->time.empty()) {
2288 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2290 AudioTimeAxisView* atv;
2292 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2294 if (atv->is_audio_track()) {
2296 if ((playlist = atv->playlist()) != 0) {
2298 begin_reversible_command (_("separate"));
2303 before = &(playlist->get_state());
2305 /* XXX need to consider musical time selections here at some point */
2307 double speed = atv->get_diskstream()->speed();
2309 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2310 playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
2314 session->add_command(new MementoCommand<Playlist>(*playlist, *before, playlist->get_state()));
2320 if (doing_undo) commit_reversible_command ();
2324 Editor::separate_regions_using_location (Location& loc)
2328 bool doing_undo = false;
2330 if (loc.is_mark()) {
2336 /* XXX i'm unsure as to whether this should operate on selected tracks only
2337 or the entire enchillada. uncomment the below line to correct the behaviour
2338 (currently set for all tracks)
2341 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2342 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2344 AudioTimeAxisView* atv;
2346 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2348 if (atv->is_audio_track()) {
2350 if ((playlist = atv->playlist()) != 0) {
2353 begin_reversible_command (_("separate"));
2357 before = &(playlist->get_state());
2360 /* XXX need to consider musical time selections here at some point */
2362 double speed = atv->get_diskstream()->speed();
2365 playlist->partition ((jack_nframes_t)(loc.start() * speed), (jack_nframes_t)(loc.end() * speed), true);
2367 session->add_command(new MementoCommand<Playlist>(*playlist, *before, playlist->get_state()));
2373 if (doing_undo) commit_reversible_command ();
2377 Editor::crop_region_to_selection ()
2379 if (selection->time.empty()) {
2383 vector<Playlist*> playlists;
2386 if (clicked_axisview != 0) {
2388 if ((playlist = clicked_axisview->playlist()) == 0) {
2392 playlists.push_back (playlist);
2396 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2398 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*i);
2400 if (rtv && rtv->is_track()) {
2402 if ((playlist = rtv->playlist()) != 0) {
2403 playlists.push_back (playlist);
2409 if (!playlists.empty()) {
2411 jack_nframes_t start;
2415 begin_reversible_command (_("trim to selection"));
2417 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2421 start = selection->time.start();
2423 if ((region = (*i)->top_region_at(start)) == 0) {
2427 /* now adjust lengths to that we do the right thing
2428 if the selection extends beyond the region
2431 start = max (start, region->position());
2432 end = min (selection->time.end_frame(), start + region->length() - 1);
2433 cnt = end - start + 1;
2435 XMLNode &before = (*i)->get_state();
2436 region->trim_to (start, cnt, this);
2437 XMLNode &after = (*i)->get_state();
2438 session->add_command (new MementoCommand<Playlist>(*(*i), before, after));
2441 commit_reversible_command ();
2446 Editor::region_fill_track ()
2450 if (!session || selection->regions.empty()) {
2454 end = session->current_end_frame ();
2456 begin_reversible_command (_("region fill"));
2458 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2460 Region& region ((*i)->region());
2463 AudioRegion* const ar = dynamic_cast<AudioRegion*>(®ion);
2466 Playlist* pl = region.playlist();
2468 if (end <= region.last_frame()) {
2472 double times = (double) (end - region.last_frame()) / (double) region.length();
2478 XMLNode &before = pl->get_state();
2479 pl->add_region (*(new AudioRegion (*ar)), ar->last_frame(), times);
2480 session->add_command (new MementoCommand<Playlist>(*pl, before, pl->get_state()));
2483 commit_reversible_command ();
2487 Editor::region_fill_selection ()
2489 if (clicked_routeview == 0 || !clicked_routeview->is_audio_track()) {
2493 if (selection->time.empty()) {
2499 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2501 if (selected->count_selected_rows() != 1) {
2505 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2506 region = (*i)[region_list_columns.region];
2508 jack_nframes_t start = selection->time[clicked_selection].start;
2509 jack_nframes_t end = selection->time[clicked_selection].end;
2513 if (selection->tracks.empty()) {
2517 jack_nframes_t selection_length = end - start;
2518 float times = (float)selection_length / region->length();
2520 begin_reversible_command (_("fill selection"));
2522 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2524 if ((playlist = (*i)->playlist()) == 0) {
2528 XMLNode &before = playlist->get_state();
2529 playlist->add_region (*(createRegion (*region)), start, times);
2530 session->add_command (new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
2533 commit_reversible_command ();
2537 Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
2540 if (!region.covers (position)) {
2541 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2544 begin_reversible_command (_("set region sync position"));
2545 XMLNode &before = region.playlist()->get_state();
2546 region.set_sync_position (position);
2547 XMLNode &after = region.playlist()->get_state();
2548 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2549 commit_reversible_command ();
2553 Editor::set_region_sync_from_edit_cursor ()
2555 if (clicked_regionview == 0) {
2559 if (!clicked_regionview->region().covers (edit_cursor->current_frame)) {
2560 error << _("Place the edit cursor at the desired sync point") << endmsg;
2564 Region& region (clicked_regionview->region());
2565 begin_reversible_command (_("set sync from edit cursor"));
2566 XMLNode &before = region.playlist()->get_state();
2567 region.set_sync_position (edit_cursor->current_frame);
2568 XMLNode &after = region.playlist()->get_state();
2569 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2570 commit_reversible_command ();
2574 Editor::remove_region_sync ()
2576 if (clicked_regionview) {
2577 Region& region (clicked_regionview->region());
2578 begin_reversible_command (_("remove sync"));
2579 XMLNode &before = region.playlist()->get_state();
2580 region.clear_sync_position ();
2581 XMLNode &after = region.playlist()->get_state();
2582 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2583 commit_reversible_command ();
2588 Editor::naturalize ()
2590 if (selection->regions.empty()) {
2593 begin_reversible_command (_("naturalize"));
2594 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2595 XMLNode &before = (*i)->region().get_state();
2596 (*i)->region().move_to_natural_position (this);
2597 XMLNode &after = (*i)->region().get_state();
2598 session->add_command (new MementoCommand<Region>((*i)->region(), before, after));
2600 commit_reversible_command ();
2604 Editor::align (RegionPoint what)
2606 align_selection (what, edit_cursor->current_frame);
2610 Editor::align_relative (RegionPoint what)
2612 align_selection_relative (what, edit_cursor->current_frame);
2615 struct RegionSortByTime {
2616 bool operator() (const RegionView* a, const RegionView* b) {
2617 return a->region().position() < b->region().position();
2622 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
2624 if (selection->regions.empty()) {
2628 jack_nframes_t distance;
2629 jack_nframes_t pos = 0;
2632 list<RegionView*> sorted;
2633 selection->regions.by_position (sorted);
2634 Region& r ((*sorted.begin())->region());
2638 pos = r.first_frame ();
2642 pos = r.last_frame();
2646 pos = r.adjust_to_sync (r.first_frame());
2650 if (pos > position) {
2651 distance = pos - position;
2654 distance = position - pos;
2658 begin_reversible_command (_("align selection (relative)"));
2660 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2662 Region& region ((*i)->region());
2664 XMLNode &before = region.playlist()->get_state();
2667 region.set_position (region.position() + distance, this);
2669 region.set_position (region.position() - distance, this);
2672 XMLNode &after = region.playlist()->get_state();
2673 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2677 commit_reversible_command ();
2681 Editor::align_selection (RegionPoint point, jack_nframes_t position)
2683 if (selection->regions.empty()) {
2687 begin_reversible_command (_("align selection"));
2689 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
2690 align_region_internal ((*i)->region(), point, position);
2693 commit_reversible_command ();
2697 Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position)
2699 begin_reversible_command (_("align region"));
2700 align_region_internal (region, point, position);
2701 commit_reversible_command ();
2705 Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
2707 XMLNode &before = region.playlist()->get_state();
2711 region.set_position (region.adjust_to_sync (position), this);
2715 if (position > region.length()) {
2716 region.set_position (position - region.length(), this);
2721 region.set_position (position, this);
2725 XMLNode &after = region.playlist()->get_state();
2726 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2730 Editor::trim_region_to_edit_cursor ()
2732 if (clicked_regionview == 0) {
2736 Region& region (clicked_regionview->region());
2739 AudioTimeAxisView *atav;
2741 if ( clicked_axisview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_axisview)) != 0 ) {
2742 if (atav->get_diskstream() != 0) {
2743 speed = atav->get_diskstream()->speed();
2747 begin_reversible_command (_("trim to edit"));
2748 XMLNode &before = region.playlist()->get_state();
2749 region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2750 XMLNode &after = region.playlist()->get_state();
2751 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2752 commit_reversible_command ();
2756 Editor::trim_region_from_edit_cursor ()
2758 if (clicked_regionview == 0) {
2762 Region& region (clicked_regionview->region());
2765 AudioTimeAxisView *atav;
2767 if ( clicked_axisview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_axisview)) != 0 ) {
2768 if (atav->get_diskstream() != 0) {
2769 speed = atav->get_diskstream()->speed();
2773 begin_reversible_command (_("trim to edit"));
2774 XMLNode &before = region.playlist()->get_state();
2775 region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2776 XMLNode &after = region.playlist()->get_state();
2777 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2778 commit_reversible_command ();
2782 Editor::unfreeze_route ()
2784 if (clicked_routeview == 0 || !clicked_routeview->is_track()) {
2788 clicked_routeview->track()->unfreeze ();
2792 Editor::_freeze_thread (void* arg)
2794 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2795 return static_cast<Editor*>(arg)->freeze_thread ();
2799 Editor::freeze_thread ()
2801 clicked_routeview->audio_track()->freeze (*current_interthread_info);
2806 Editor::freeze_progress_timeout (void *arg)
2808 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2809 return !(current_interthread_info->done || current_interthread_info->cancel);
2813 Editor::freeze_route ()
2815 if (clicked_routeview == 0 || !clicked_routeview->is_track()) {
2819 InterThreadInfo itt;
2821 if (interthread_progress_window == 0) {
2822 build_interthread_progress_window ();
2825 interthread_progress_window->set_title (_("ardour: freeze"));
2826 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2827 interthread_progress_window->show_all ();
2828 interthread_progress_bar.set_fraction (0.0f);
2829 interthread_progress_label.set_text ("");
2830 interthread_cancel_label.set_text (_("Cancel Freeze"));
2831 current_interthread_info = &itt;
2833 interthread_progress_connection =
2834 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2838 itt.progress = 0.0f;
2840 pthread_create (&itt.thread, 0, _freeze_thread, this);
2842 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2844 while (!itt.done && !itt.cancel) {
2845 gtk_main_iteration ();
2848 interthread_progress_connection.disconnect ();
2849 interthread_progress_window->hide_all ();
2850 current_interthread_info = 0;
2851 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2855 Editor::bounce_range_selection ()
2857 if (selection->time.empty()) {
2861 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2863 jack_nframes_t start = selection->time[clicked_selection].start;
2864 jack_nframes_t end = selection->time[clicked_selection].end;
2865 jack_nframes_t cnt = end - start + 1;
2867 begin_reversible_command (_("bounce range"));
2869 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2871 AudioTimeAxisView* atv;
2873 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2879 if ((playlist = atv->playlist()) == 0) {
2883 InterThreadInfo itt;
2887 itt.progress = false;
2889 XMLNode &before = playlist->get_state();
2890 atv->audio_track()->bounce_range (start, cnt, itt);
2891 XMLNode &after = playlist->get_state();
2892 session->add_command (new MementoCommand<Playlist> (*playlist, before, after));
2895 commit_reversible_command ();
2913 Editor::cut_copy (CutCopyOp op)
2915 /* only cancel selection if cut/copy is successful.*/
2927 opname = _("clear");
2931 cut_buffer->clear ();
2933 switch (current_mouse_mode()) {
2935 if (!selection->regions.empty() || !selection->points.empty()) {
2937 begin_reversible_command (opname + _(" objects"));
2939 if (!selection->regions.empty()) {
2941 cut_copy_regions (op);
2944 selection->clear_regions ();
2948 if (!selection->points.empty()) {
2949 cut_copy_points (op);
2952 selection->clear_points ();
2956 commit_reversible_command ();
2961 if (!selection->time.empty()) {
2963 begin_reversible_command (opname + _(" range"));
2964 cut_copy_ranges (op);
2965 commit_reversible_command ();
2968 selection->clear_time ();
2980 Editor::cut_copy_points (CutCopyOp op)
2982 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2984 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2987 atv->cut_copy_clear_objects (selection->points, op);
2993 Editor::cut_copy_regions (CutCopyOp op)
2995 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
2996 PlaylistMapping pmap;
2997 jack_nframes_t first_position = max_frames;
2998 set<Playlist*> freezelist;
2999 pair<set<Playlist*>::iterator,bool> insert_result;
3001 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
3002 first_position = min ((*x)->region().position(), first_position);
3004 if (op == Cut || op == Clear) {
3005 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region().playlist());
3007 insert_result = freezelist.insert (pl);
3008 if (insert_result.second) {
3010 session->add_command (new MementoUndoCommand<Playlist>(*pl, pl->get_state()));
3016 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ) {
3018 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region().playlist());
3020 RegionSelection::iterator tmp;
3027 PlaylistMapping::iterator pi = pmap.find (pl);
3029 if (pi == pmap.end()) {
3030 npl = new AudioPlaylist (*session, "cutlist", true);
3038 AudioRegion* const ar = dynamic_cast<AudioRegion*>(&(*x)->region());
3043 npl->add_region (*(new AudioRegion (*ar)), (*x)->region().position() - first_position);
3044 pl->remove_region (&((*x)->region()));
3050 npl->add_region (*(new AudioRegion (*ar)), (*x)->region().position() - first_position);
3054 pl->remove_region (&((*x)->region()));
3062 list<Playlist*> foo;
3064 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
3065 foo.push_back (i->second);
3069 cut_buffer->set (foo);
3072 for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
3074 session->add_command (new MementoRedoCommand<Playlist>(*(*pl), (*pl)->get_state()));
3079 Editor::cut_copy_ranges (CutCopyOp op)
3081 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3082 (*i)->cut_copy_clear (*selection, op);
3087 Editor::paste (float times)
3089 paste_internal (edit_cursor->current_frame, times);
3093 Editor::mouse_paste ()
3098 track_canvas.get_pointer (x, y);
3099 track_canvas.window_to_world (x, y, wx, wy);
3100 wx += horizontal_adjustment.get_value();
3101 wy += vertical_adjustment.get_value();
3104 event.type = GDK_BUTTON_RELEASE;
3105 event.button.x = wx;
3106 event.button.y = wy;
3108 jack_nframes_t where = event_frame (&event, 0, 0);
3110 paste_internal (where, 1);
3114 Editor::paste_internal (jack_nframes_t position, float times)
3116 bool commit = false;
3118 if (cut_buffer->empty() || selection->tracks.empty()) {
3122 if (position == max_frames) {
3123 position = edit_cursor->current_frame;
3126 begin_reversible_command (_("paste"));
3128 TrackSelection::iterator i;
3131 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
3133 /* undo/redo is handled by individual tracks */
3135 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3141 commit_reversible_command ();
3146 Editor::paste_named_selection (float times)
3148 TrackSelection::iterator t;
3150 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3152 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3156 TreeModel::iterator i = selected->get_selected();
3157 NamedSelection* ns = (*i)[named_selection_columns.selection];
3159 list<Playlist*>::iterator chunk;
3160 list<Playlist*>::iterator tmp;
3162 chunk = ns->playlists.begin();
3164 begin_reversible_command (_("paste chunk"));
3166 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3168 AudioTimeAxisView* atv;
3172 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3176 if ((pl = atv->playlist()) == 0) {
3180 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
3187 XMLNode &before = apl->get_state();
3188 apl->paste (**chunk, edit_cursor->current_frame, times);
3189 session->add_command(new MementoCommand<AudioPlaylist>(*apl, before, apl->get_state()));
3191 if (tmp != ns->playlists.end()) {
3196 commit_reversible_command();
3200 Editor::duplicate_some_regions (RegionSelection& regions, float times)
3203 RegionSelection sel = regions; // clear (below) will clear the argument list
3205 begin_reversible_command (_("duplicate region"));
3207 selection->clear_regions ();
3209 for (RegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3211 Region& r ((*i)->region());
3213 TimeAxisView& tv = (*i)->get_time_axis_view();
3214 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3215 sigc::connection c = atv->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3217 playlist = (*i)->region().playlist();
3218 XMLNode &before = playlist->get_state();
3219 playlist->duplicate (r, r.last_frame(), times);
3220 session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
3224 if (latest_regionview) {
3225 selection->add (latest_regionview);
3230 commit_reversible_command ();
3234 Editor::duplicate_selection (float times)
3236 if (selection->time.empty() || selection->tracks.empty()) {
3241 vector<AudioRegion*> new_regions;
3242 vector<AudioRegion*>::iterator ri;
3244 create_region_from_selection (new_regions);
3246 if (new_regions.empty()) {
3250 begin_reversible_command (_("duplicate selection"));
3252 ri = new_regions.begin();
3254 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3255 if ((playlist = (*i)->playlist()) == 0) {
3258 XMLNode &before = playlist->get_state();
3259 playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
3260 XMLNode &after = playlist->get_state();
3261 session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
3264 if (ri == new_regions.end()) {
3269 commit_reversible_command ();
3273 Editor::reset_point_selection ()
3275 /* reset all selected points to the relevant default value */
3277 cerr << "point selection has " << selection->points.size() << " entries\n";
3279 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3281 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3284 atv->reset_objects (selection->points);
3290 Editor::center_playhead ()
3292 float page = canvas_width * frames_per_unit;
3294 center_screen_internal (playhead_cursor->current_frame, page);
3298 Editor::center_edit_cursor ()
3300 float page = canvas_width * frames_per_unit;
3302 center_screen_internal (edit_cursor->current_frame, page);
3306 Editor::clear_playlist (Playlist& playlist)
3308 begin_reversible_command (_("clear playlist"));
3309 XMLNode &before = playlist.get_state();
3311 XMLNode &after = playlist.get_state();
3312 session->add_command (new MementoCommand<Playlist>(playlist, before, after));
3313 commit_reversible_command ();
3317 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3320 jack_nframes_t distance;
3321 jack_nframes_t next_distance;
3322 jack_nframes_t start;
3324 if (use_edit_cursor) {
3325 start = edit_cursor->current_frame;
3330 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3334 if (selection->tracks.empty()) {
3338 begin_reversible_command (_("nudge track"));
3340 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3342 if ((playlist = (*i)->playlist()) == 0) {
3346 XMLNode &before = playlist->get_state();
3347 playlist->nudge_after (start, distance, forwards);
3348 XMLNode &after = playlist->get_state();
3349 session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
3352 commit_reversible_command ();
3356 Editor::remove_last_capture ()
3358 vector<string> choices;
3365 if (Config->get_verify_remove_last_capture()) {
3366 prompt = _("Do you really want to destroy the last capture?"
3367 "\n(This is destructive and cannot be undone)");
3369 choices.push_back (_("No, do nothing."));
3370 choices.push_back (_("Yes, destroy it."));
3372 Gtkmm2ext::Choice prompter (prompt, choices);
3374 if (prompter.run () == 1) {
3375 session->remove_last_capture ();
3379 session->remove_last_capture();
3384 Editor::normalize_region ()
3390 if (selection->regions.empty()) {
3394 begin_reversible_command (_("normalize"));
3396 track_canvas.get_window()->set_cursor (*wait_cursor);
3399 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3400 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3403 XMLNode &before = arv->region().get_state();
3404 arv->audio_region().normalize_to (0.0f);
3405 session->add_command (new MementoCommand<Region>(arv->region(), before, arv->region().get_state()));
3408 commit_reversible_command ();
3409 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3414 Editor::denormalize_region ()
3420 if (selection->regions.empty()) {
3424 begin_reversible_command ("denormalize");
3426 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
3427 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3430 XMLNode &before = arv->region().get_state();
3431 arv->audio_region().set_scale_amplitude (1.0f);
3432 session->add_command (new MementoCommand<Region>(arv->region(), before, arv->region().get_state()));
3435 commit_reversible_command ();
3440 Editor::reverse_region ()
3446 Reverse rev (*session);
3447 apply_filter (rev, _("reverse regions"));
3451 Editor::apply_filter (AudioFilter& filter, string command)
3453 if (selection->regions.empty()) {
3457 begin_reversible_command (command);
3459 track_canvas.get_window()->set_cursor (*wait_cursor);
3462 for (RegionSelection::iterator r = selection->regions.begin(); r != selection->regions.end(); ) {
3463 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*r);
3467 Playlist* playlist = arv->region().playlist();
3469 RegionSelection::iterator tmp;
3474 if (arv->audio_region().apply (filter) == 0) {
3476 XMLNode &before = playlist->get_state();
3477 playlist->replace_region (arv->region(), *(filter.results.front()), arv->region().position());
3478 XMLNode &after = playlist->get_state();
3479 session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
3487 commit_reversible_command ();
3488 selection->regions.clear ();
3491 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3495 Editor::region_selection_op (void (Region::*pmf)(void))
3497 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3498 ((*i)->region().*pmf)();
3504 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3506 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3507 ((*i)->region().*pmf)(arg);
3512 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3514 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3515 ((*i)->region().*pmf)(yn);
3520 Editor::external_edit_region ()
3522 if (!clicked_regionview) {
3530 Editor::brush (jack_nframes_t pos)
3532 RegionSelection sel;
3535 if (selection->regions.empty()) {
3536 /* XXX get selection from region list */
3538 sel = selection->regions;
3545 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3546 mouse_brush_insert_region ((*i), pos);
3551 Editor::toggle_gain_envelope_visibility ()
3553 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3554 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3556 arv->set_envelope_visible (!arv->envelope_visible());
3561 Editor::toggle_gain_envelope_active ()
3563 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
3564 AudioRegionView* const arv = dynamic_cast<AudioRegionView*>(*i);
3566 arv->audio_region().set_envelope_active (true);