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 "regionview.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->audio_regions);
194 Editor::split_regions_at (jack_nframes_t where, AudioRegionSelection& regions)
196 begin_reversible_command (_("split"));
199 for (AudioRegionSelection::iterator a = regions.begin(); a != regions.end(); ) {
201 AudioRegionSelection::iterator tmp;
206 Playlist* pl = (*a)->region.playlist();
208 _new_regionviews_show_envelope = (*a)->envelope_visible();
211 XMLNode &before = pl->get_state();
212 pl->split_region ((*a)->region, where);
213 XMLNode &after = pl->get_state();
214 session->add_command(new MementoCommand<Playlist>(*pl, before, after));
220 commit_reversible_command ();
221 _new_regionviews_show_envelope = false;
225 Editor::remove_clicked_region ()
227 if (clicked_audio_trackview == 0 || clicked_regionview == 0) {
231 Playlist* playlist = clicked_audio_trackview->playlist();
233 begin_reversible_command (_("remove region"));
234 XMLNode &before = playlist->get_state();
235 playlist->remove_region (&clicked_regionview->region);
236 XMLNode &after = playlist->get_state();
237 session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
238 commit_reversible_command ();
242 Editor::destroy_clicked_region ()
244 int32_t selected = selection->audio_regions.size();
246 if (!session || clicked_regionview == 0 && selected == 0) {
250 vector<string> choices;
253 prompt = string_compose (_(" This is destructive, will possibly delete audio files\n\
254 It cannot be undone\n\
255 Do you really want to destroy %1 ?"),
257 _("these regions") : _("this region")));
259 choices.push_back (_("No, do nothing."));
262 choices.push_back (_("Yes, destroy them."));
264 choices.push_back (_("Yes, destroy it."));
267 Gtkmm2ext::Choice prompter (prompt, choices);
269 if (prompter.run() == 0) { /* first choice */
276 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
277 r.push_back (&(*i)->region);
280 session->destroy_regions (r);
282 } else if (clicked_regionview) {
283 session->destroy_region (&clicked_regionview->region);
288 Editor::select_region_for_operation (int dir, TimeAxisView **tv)
292 jack_nframes_t start = 0;
294 if (selection->time.start () == selection->time.end_frame ()) {
296 /* no current selection-> is there a selected regionview? */
298 if (selection->audio_regions.empty()) {
306 if (!selection->audio_regions.empty()) {
308 rv = *(selection->audio_regions.begin());
309 (*tv) = &rv->get_time_axis_view();
310 region = &rv->region;
312 } else if (!selection->tracks.empty()) {
314 (*tv) = selection->tracks.front();
316 AudioTimeAxisView* atv;
318 if ((atv = dynamic_cast<AudioTimeAxisView*> (*tv)) != 0) {
321 if ((pl = atv->playlist()) == 0) {
325 region = dynamic_cast<AudioRegion*> (pl->top_region_at (start));
333 Editor::extend_selection_to_end_of_region (bool next)
337 jack_nframes_t start;
339 if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) {
343 if (region && selection->time.start () == selection->time.end_frame ()) {
344 start = region->position();
346 start = selection->time.start ();
349 /* Try to leave the selection with the same route if possible */
351 if ((tv = selection->time.track) == 0) {
355 begin_reversible_command (_("extend selection"));
356 selection->set (tv, start, region->position() + region->length());
357 commit_reversible_command ();
361 Editor::extend_selection_to_start_of_region (bool previous)
367 if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) {
371 if (region && selection->time.start () == selection->time.end_frame ()) {
372 end = region->position() + region->length();
374 end = selection->time.end_frame ();
377 /* Try to leave the selection with the same route if possible */
379 if ((tv = selection->time.track) == 0) {
383 begin_reversible_command (_("extend selection"));
384 selection->set (tv, region->position(), end);
385 commit_reversible_command ();
390 Editor::nudge_forward (bool next)
392 jack_nframes_t distance;
393 jack_nframes_t next_distance;
395 if (!session) return;
397 if (!selection->audio_regions.empty()) {
399 begin_reversible_command (_("nudge forward"));
401 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
402 AudioRegion& r ((*i)->region);
404 distance = get_nudge_distance (r.position(), next_distance);
407 distance = next_distance;
410 XMLNode &before = r.playlist()->get_state();
411 r.set_position (r.position() + distance, this);
412 XMLNode &after = r.playlist()->get_state();
413 session->add_command (new MementoCommand<Playlist>(*(r.playlist()), before, after));
416 commit_reversible_command ();
419 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
420 session->request_locate (playhead_cursor->current_frame + distance);
425 Editor::nudge_backward (bool next)
427 jack_nframes_t distance;
428 jack_nframes_t next_distance;
430 if (!session) return;
432 if (!selection->audio_regions.empty()) {
434 begin_reversible_command (_("nudge forward"));
436 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
437 AudioRegion& r ((*i)->region);
439 distance = get_nudge_distance (r.position(), next_distance);
442 distance = next_distance;
445 XMLNode &before = r.playlist()->get_state();
447 if (r.position() > distance) {
448 r.set_position (r.position() - distance, this);
450 r.set_position (0, this);
452 XMLNode &after = r.playlist()->get_state();
453 session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
456 commit_reversible_command ();
460 distance = get_nudge_distance (playhead_cursor->current_frame, next_distance);
462 if (playhead_cursor->current_frame > distance) {
463 session->request_locate (playhead_cursor->current_frame - distance);
465 session->goto_start();
471 Editor::nudge_forward_capture_offset ()
473 jack_nframes_t distance;
475 if (!session) return;
477 if (!selection->audio_regions.empty()) {
479 begin_reversible_command (_("nudge forward"));
481 distance = session->worst_output_latency();
483 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
484 AudioRegion& r ((*i)->region);
486 XMLNode &before = r.playlist()->get_state();
487 r.set_position (r.position() + distance, this);
488 XMLNode &after = r.playlist()->get_state();
489 session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
492 commit_reversible_command ();
498 Editor::nudge_backward_capture_offset ()
500 jack_nframes_t distance;
502 if (!session) return;
504 if (!selection->audio_regions.empty()) {
506 begin_reversible_command (_("nudge forward"));
508 distance = session->worst_output_latency();
510 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
511 AudioRegion& r ((*i)->region);
513 XMLNode &before = r.playlist()->get_state();
515 if (r.position() > distance) {
516 r.set_position (r.position() - distance, this);
518 r.set_position (0, this);
520 XMLNode &after = r.playlist()->get_state();
521 session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
524 commit_reversible_command ();
531 Editor::move_to_start ()
533 session->goto_start ();
537 Editor::move_to_end ()
540 session->request_locate (session->current_end_frame());
544 Editor::build_region_boundary_cache ()
546 jack_nframes_t pos = 0;
549 TrackViewList tracks;
551 region_boundary_cache.clear ();
558 case SnapToRegionStart:
561 case SnapToRegionEnd:
564 case SnapToRegionSync:
567 case SnapToRegionBoundary:
571 fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg;
576 TimeAxisView *ontrack = 0;
578 while (pos < session->current_end_frame()) {
580 if (!selection->tracks.empty()) {
582 if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) {
586 } else if (clicked_trackview) {
589 t.push_back (clicked_trackview);
591 if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) {
597 if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) {
605 case SnapToRegionStart:
606 rpos = r->first_frame();
608 case SnapToRegionEnd:
609 rpos = r->last_frame();
611 case SnapToRegionSync:
612 rpos = r->adjust_to_sync (r->first_frame());
615 case SnapToRegionBoundary:
616 rpos = r->last_frame();
623 AudioTimeAxisView *atav;
625 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
626 if (atav->get_diskstream() != 0) {
627 speed = atav->get_diskstream()->speed();
631 rpos = track_frame_to_session_frame(rpos, speed);
633 if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) {
634 if (snap_type == SnapToRegionBoundary) {
635 region_boundary_cache.push_back (r->first_frame());
637 region_boundary_cache.push_back (rpos);
645 Editor::find_next_region (jack_nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack)
647 TrackViewList::iterator i;
648 jack_nframes_t closest = max_frames;
650 jack_nframes_t rpos = 0;
653 jack_nframes_t track_frame;
654 AudioTimeAxisView *atav;
656 for (i = tracks.begin(); i != tracks.end(); ++i) {
658 jack_nframes_t distance;
662 if ( (atav = dynamic_cast<AudioTimeAxisView*>(*i)) != 0 ) {
663 if (atav->get_diskstream()!=0)
664 track_speed = atav->get_diskstream()->speed();
667 track_frame = session_frame_to_track_frame(frame, track_speed);
669 if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) {
675 rpos = r->first_frame ();
679 rpos = r->last_frame ();
683 rpos = r->adjust_to_sync (r->first_frame());
686 // rpos is a "track frame", converting it to "session frame"
687 rpos = track_frame_to_session_frame(rpos, track_speed);
690 distance = rpos - frame;
692 distance = frame - rpos;
695 if (distance < closest) {
707 Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir)
710 jack_nframes_t pos = cursor->current_frame;
716 TimeAxisView *ontrack = 0;
718 // so we don't find the current region again..
722 if (!selection->tracks.empty()) {
724 r = find_next_region (pos, point, dir, selection->tracks, &ontrack);
726 } else if (clicked_trackview) {
729 t.push_back (clicked_trackview);
731 r = find_next_region (pos, point, dir, t, &ontrack);
735 r = find_next_region (pos, point, dir, track_views, &ontrack);
744 pos = r->first_frame ();
748 pos = r->last_frame ();
752 pos = r->adjust_to_sync (r->first_frame());
757 AudioTimeAxisView *atav;
759 if ( ontrack != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(ontrack)) != 0 ) {
760 if (atav->get_diskstream() != 0) {
761 speed = atav->get_diskstream()->speed();
765 pos = track_frame_to_session_frame(pos, speed);
767 if (cursor == playhead_cursor) {
768 session->request_locate (pos);
770 cursor->set_position (pos);
775 Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point)
777 cursor_to_region_point (cursor, point, 1);
781 Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point)
783 cursor_to_region_point (cursor, point, -1);
787 Editor::cursor_to_selection_start (Cursor *cursor)
789 jack_nframes_t pos = 0;
790 switch (mouse_mode) {
792 if (!selection->audio_regions.empty()) {
793 pos = selection->audio_regions.start();
798 if (!selection->time.empty()) {
799 pos = selection->time.start ();
807 if (cursor == playhead_cursor) {
808 session->request_locate (pos);
810 cursor->set_position (pos);
815 Editor::cursor_to_selection_end (Cursor *cursor)
817 jack_nframes_t pos = 0;
819 switch (mouse_mode) {
821 if (!selection->audio_regions.empty()) {
822 pos = selection->audio_regions.end_frame();
827 if (!selection->time.empty()) {
828 pos = selection->time.end_frame ();
836 if (cursor == playhead_cursor) {
837 session->request_locate (pos);
839 cursor->set_position (pos);
844 Editor::playhead_backward ()
851 if (get_prefix (prefix, was_floating)) {
855 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
857 cnt = (jack_nframes_t) prefix;
861 pos = playhead_cursor->current_frame;
863 if ((jack_nframes_t) pos < cnt) {
869 /* XXX this is completely insane. with the current buffering
870 design, we'll force a complete track buffer flush and
871 reload, just to move 1 sample !!!
874 session->request_locate (pos);
878 Editor::playhead_forward ()
885 if (get_prefix (prefix, was_floating)) {
889 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
891 cnt = (jack_nframes_t) floor (prefix);
895 pos = playhead_cursor->current_frame;
897 /* XXX this is completely insane. with the current buffering
898 design, we'll force a complete track buffer flush and
899 reload, just to move 1 sample !!!
902 session->request_locate (pos+cnt);
906 Editor::cursor_align (bool playhead_to_edit)
908 if (playhead_to_edit) {
910 session->request_locate (edit_cursor->current_frame);
913 edit_cursor->set_position (playhead_cursor->current_frame);
918 Editor::edit_cursor_backward ()
925 if (get_prefix (prefix, was_floating)) {
929 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
931 cnt = (jack_nframes_t) prefix;
935 pos = edit_cursor->current_frame;
937 if ((jack_nframes_t) pos < cnt) {
943 edit_cursor->set_position (pos);
947 Editor::edit_cursor_forward ()
954 if (get_prefix (prefix, was_floating)) {
958 cnt = (jack_nframes_t) floor (prefix * session->frame_rate ());
960 cnt = (jack_nframes_t) floor (prefix);
964 pos = edit_cursor->current_frame;
965 edit_cursor->set_position (pos+cnt);
969 Editor::goto_frame ()
973 jack_nframes_t frame;
975 if (get_prefix (prefix, was_floating)) {
980 frame = (jack_nframes_t) floor (prefix * session->frame_rate());
982 frame = (jack_nframes_t) floor (prefix);
985 session->request_locate (frame);
989 Editor::scroll_backward (float pages)
991 jack_nframes_t frame;
992 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
997 if (get_prefix (prefix, was_floating)) {
998 cnt = (jack_nframes_t) floor (pages * one_page);
1001 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
1003 cnt = (jack_nframes_t) floor (prefix * one_page);
1007 if (leftmost_frame < cnt) {
1010 frame = leftmost_frame - cnt;
1013 reposition_x_origin (frame);
1017 Editor::scroll_forward (float pages)
1019 jack_nframes_t frame;
1020 jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit);
1025 if (get_prefix (prefix, was_floating)) {
1026 cnt = (jack_nframes_t) floor (pages * one_page);
1029 cnt = (jack_nframes_t) floor (prefix * session->frame_rate());
1031 cnt = (jack_nframes_t) floor (prefix * one_page);
1035 if (ULONG_MAX - cnt < leftmost_frame) {
1036 frame = ULONG_MAX - cnt;
1038 frame = leftmost_frame + cnt;
1041 reposition_x_origin (frame);
1045 Editor::scroll_tracks_down ()
1051 if (get_prefix (prefix, was_floating)) {
1054 cnt = (int) floor (prefix);
1057 double vert_value = vertical_adjustment.get_value() + (cnt *
1058 vertical_adjustment.get_page_size());
1059 if (vert_value > vertical_adjustment.get_upper() - canvas_height) {
1060 vert_value = vertical_adjustment.get_upper() - canvas_height;
1062 vertical_adjustment.set_value (vert_value);
1066 Editor::scroll_tracks_up ()
1072 if (get_prefix (prefix, was_floating)) {
1075 cnt = (int) floor (prefix);
1078 vertical_adjustment.set_value (vertical_adjustment.get_value() - (cnt * vertical_adjustment.get_page_size()));
1082 Editor::scroll_tracks_down_line ()
1085 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1086 double vert_value = adj->get_value() + 20;
1088 if (vert_value>adj->get_upper() - canvas_height) {
1089 vert_value = adj->get_upper() - canvas_height;
1091 adj->set_value (vert_value);
1095 Editor::scroll_tracks_up_line ()
1097 Gtk::Adjustment* adj = edit_vscrollbar.get_adjustment();
1098 adj->set_value (adj->get_value() - 20);
1104 Editor::temporal_zoom_step (bool coarser)
1106 ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::temporal_zoom_step), coarser));
1110 nfpu = frames_per_unit;
1115 nfpu = max(1.0,(nfpu/2.0));
1118 temporal_zoom (nfpu);
1122 Editor::temporal_zoom (gdouble fpu)
1124 if (!session) return;
1126 jack_nframes_t current_page = current_page_frames();
1127 jack_nframes_t current_leftmost = leftmost_frame;
1128 jack_nframes_t current_rightmost;
1129 jack_nframes_t current_center;
1130 jack_nframes_t new_page;
1131 jack_nframes_t leftmost_after_zoom = 0;
1136 new_page = (jack_nframes_t) floor (canvas_width * nfpu);
1138 switch (zoom_focus) {
1140 leftmost_after_zoom = current_leftmost;
1143 case ZoomFocusRight:
1144 current_rightmost = leftmost_frame + current_page;
1145 if (current_rightmost > new_page) {
1146 leftmost_after_zoom = current_rightmost - new_page;
1148 leftmost_after_zoom = 0;
1152 case ZoomFocusCenter:
1153 current_center = current_leftmost + (current_page/2);
1154 if (current_center > (new_page/2)) {
1155 leftmost_after_zoom = current_center - (new_page / 2);
1157 leftmost_after_zoom = 0;
1161 case ZoomFocusPlayhead:
1162 /* try to keep the playhead in the center */
1163 if (playhead_cursor->current_frame > new_page/2) {
1164 leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2);
1166 leftmost_after_zoom = 0;
1171 /* try to keep the edit cursor in the center */
1172 if (edit_cursor->current_frame > leftmost_frame + (new_page/2)) {
1173 leftmost_after_zoom = edit_cursor->current_frame - (new_page/2);
1175 leftmost_after_zoom = 0;
1181 // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame());
1183 // begin_reversible_command (_("zoom"));
1184 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit));
1185 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu));
1186 // commit_reversible_command ();
1188 reposition_and_zoom (leftmost_after_zoom, nfpu);
1192 Editor::temporal_zoom_selection ()
1194 if (!selection) return;
1196 if (selection->time.empty()) {
1200 jack_nframes_t start = selection->time[clicked_selection].start;
1201 jack_nframes_t end = selection->time[clicked_selection].end;
1203 temporal_zoom_by_frame (start, end, "zoom to selection");
1207 Editor::temporal_zoom_session ()
1209 ENSURE_GUI_THREAD (mem_fun (*this, &Editor::temporal_zoom_session));
1212 temporal_zoom_by_frame (session->current_start_frame(), session->current_end_frame(), "zoom to session");
1217 Editor::temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, const string & op)
1219 if (!session) return;
1221 if ((start == 0 && end == 0) || end < start) {
1225 jack_nframes_t range = end - start;
1227 double new_fpu = (double)range / (double)canvas_width;
1230 // while (p2 < new_fpu) {
1235 jack_nframes_t new_page = (jack_nframes_t) floor (canvas_width * new_fpu);
1236 jack_nframes_t middle = (jack_nframes_t) floor( (double)start + ((double)range / 2.0f ));
1237 jack_nframes_t new_leftmost = (jack_nframes_t) floor( (double)middle - ((double)new_page/2.0f));
1239 if (new_leftmost > middle) new_leftmost = 0;
1241 // begin_reversible_command (op);
1242 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1243 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1244 // commit_reversible_command ();
1246 reposition_and_zoom (new_leftmost, new_fpu);
1250 Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame)
1252 if (!session) return;
1254 jack_nframes_t range_before = frame - leftmost_frame;
1257 new_fpu = frames_per_unit;
1263 new_fpu = max(1.0,(new_fpu/2.0));
1267 if (new_fpu == frames_per_unit) return;
1269 jack_nframes_t new_leftmost = frame - range_before;
1271 if (new_leftmost > frame) new_leftmost = 0;
1273 // begin_reversible_command (_("zoom to frame"));
1274 // session->add_undo (bind (mem_fun(*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit));
1275 // session->add_redo (bind (mem_fun(*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu));
1276 // commit_reversible_command ();
1278 reposition_and_zoom (new_leftmost, new_fpu);
1282 Editor::add_location_from_selection ()
1284 if (selection->time.empty()) {
1288 if (session == 0 || clicked_trackview == 0) {
1292 jack_nframes_t start = selection->time[clicked_selection].start;
1293 jack_nframes_t end = selection->time[clicked_selection].end;
1295 Location *location = new Location (start, end, "selection");
1297 session->begin_reversible_command (_("add marker"));
1298 XMLNode &before = session->locations()->get_state();
1299 session->locations()->add (location, true);
1300 XMLNode &after = session->locations()->get_state();
1301 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1302 session->commit_reversible_command ();
1306 Editor::add_location_from_playhead_cursor ()
1308 jack_nframes_t where = session->audible_frame();
1310 Location *location = new Location (where, where, "mark", Location::IsMark);
1311 session->begin_reversible_command (_("add marker"));
1312 XMLNode &before = session->locations()->get_state();
1313 session->locations()->add (location, true);
1314 XMLNode &after = session->locations()->get_state();
1315 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1316 session->commit_reversible_command ();
1320 Editor::add_location_from_audio_region ()
1322 if (selection->audio_regions.empty()) {
1326 AudioRegionView* rv = *(selection->audio_regions.begin());
1327 Region& region = rv->region;
1329 Location *location = new Location (region.position(), region.last_frame(), region.name());
1330 session->begin_reversible_command (_("add marker"));
1331 XMLNode &before = session->locations()->get_state();
1332 session->locations()->add (location, true);
1333 XMLNode &after = session->locations()->get_state();
1334 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1335 session->commit_reversible_command ();
1339 Editor::select_all_in_track (Selection::Operation op)
1341 list<Selectable *> touched;
1343 if (!clicked_trackview) {
1347 clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1350 case Selection::Toggle:
1351 selection->add (touched);
1353 case Selection::Set:
1354 selection->set (touched);
1356 case Selection::Extend:
1357 /* not defined yet */
1363 Editor::select_all (Selection::Operation op)
1365 list<Selectable *> touched;
1367 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1368 if ((*iter)->hidden()) {
1371 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
1373 begin_reversible_command (_("select all"));
1375 case Selection::Toggle:
1376 selection->add (touched);
1378 case Selection::Set:
1379 selection->set (touched);
1381 case Selection::Extend:
1382 /* not defined yet */
1385 commit_reversible_command ();
1389 Editor::invert_selection_in_track ()
1391 list<Selectable *> touched;
1393 if (!clicked_trackview) {
1397 clicked_trackview->get_inverted_selectables (*selection, touched);
1398 selection->set (touched);
1402 Editor::invert_selection ()
1404 list<Selectable *> touched;
1406 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1407 if ((*iter)->hidden()) {
1410 (*iter)->get_inverted_selectables (*selection, touched);
1413 selection->set (touched);
1417 Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, Selection::Operation op)
1419 list<Selectable *> touched;
1421 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1422 if ((*iter)->hidden()) {
1425 (*iter)->get_selectables (start, end, top, bot, touched);
1428 cerr << "select all within found " << touched.size() << endl;
1430 begin_reversible_command (_("select all within"));
1432 case Selection::Toggle:
1434 selection->add (touched);
1436 case Selection::Set:
1438 selection->set (touched);
1440 case Selection::Extend:
1442 /* not defined yet */
1446 cerr << "selection now has " << selection->points.size() << endl;
1448 commit_reversible_command ();
1449 return !touched.empty();
1453 Editor::set_selection_from_audio_region ()
1455 if (selection->audio_regions.empty()) {
1459 AudioRegionView* rv = *(selection->audio_regions.begin());
1460 Region& region = rv->region;
1462 begin_reversible_command (_("set selection from region"));
1463 selection->set (0, region.position(), region.last_frame());
1464 commit_reversible_command ();
1466 set_mouse_mode (Editing::MouseRange, false);
1470 Editor::set_selection_from_punch()
1474 if ((location = session->locations()->auto_punch_location()) == 0) {
1478 set_selection_from_range (*location);
1482 Editor::set_selection_from_loop()
1486 if ((location = session->locations()->auto_loop_location()) == 0) {
1489 set_selection_from_range (*location);
1493 Editor::set_selection_from_range (Location& loc)
1495 begin_reversible_command (_("set selection from range"));
1496 selection->set (0, loc.start(), loc.end());
1497 commit_reversible_command ();
1499 set_mouse_mode (Editing::MouseRange, false);
1503 Editor::select_all_selectables_using_time_selection ()
1505 list<Selectable *> touched;
1507 if (selection->time.empty()) {
1511 jack_nframes_t start = selection->time[clicked_selection].start;
1512 jack_nframes_t end = selection->time[clicked_selection].end;
1514 if (end - start < 1) {
1518 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1519 if ((*iter)->hidden()) {
1522 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1525 begin_reversible_command (_("select all from range"));
1526 selection->set (touched);
1527 commit_reversible_command ();
1532 Editor::select_all_selectables_using_punch()
1534 Location* location = session->locations()->auto_punch_location();
1535 list<Selectable *> touched;
1537 if (location == 0 || (location->end() - location->start() <= 1)) {
1541 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1542 if ((*iter)->hidden()) {
1545 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1547 begin_reversible_command (_("select all from punch"));
1548 selection->set (touched);
1549 commit_reversible_command ();
1554 Editor::select_all_selectables_using_loop()
1556 Location* location = session->locations()->auto_loop_location();
1557 list<Selectable *> touched;
1559 if (location == 0 || (location->end() - location->start() <= 1)) {
1563 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1564 if ((*iter)->hidden()) {
1567 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1569 begin_reversible_command (_("select all from loop"));
1570 selection->set (touched);
1571 commit_reversible_command ();
1576 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1578 jack_nframes_t start;
1580 list<Selectable *> touched;
1583 begin_reversible_command (_("select all after cursor"));
1584 start = cursor->current_frame ;
1585 end = session->current_end_frame();
1587 if (cursor->current_frame > 0) {
1588 begin_reversible_command (_("select all before cursor"));
1590 end = cursor->current_frame - 1;
1596 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1597 if ((*iter)->hidden()) {
1600 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1602 selection->set (touched);
1603 commit_reversible_command ();
1607 Editor::select_all_selectables_between_cursors (Cursor *cursor, Cursor *other_cursor)
1609 jack_nframes_t start;
1611 list<Selectable *> touched;
1612 bool other_cursor_is_first = cursor->current_frame > other_cursor->current_frame;
1614 if (cursor->current_frame == other_cursor->current_frame) {
1618 begin_reversible_command (_("select all between cursors"));
1619 if (other_cursor_is_first) {
1620 start = other_cursor->current_frame;
1621 end = cursor->current_frame - 1;
1624 start = cursor->current_frame;
1625 end = other_cursor->current_frame - 1;
1628 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1629 if ((*iter)->hidden()) {
1632 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1634 selection->set (touched);
1635 commit_reversible_command ();
1639 Editor::amplitude_zoom_step (bool in)
1653 #ifdef FIX_FOR_CANVAS
1654 /* XXX DO SOMETHING */
1663 Editor::delete_sample_forward ()
1668 Editor::delete_sample_backward ()
1673 Editor::delete_screen ()
1680 Editor::search_backwards ()
1686 Editor::search_forwards ()
1694 Editor::jump_forward_to_mark ()
1700 Location *location = session->locations()->first_location_after (playhead_cursor->current_frame);
1703 session->request_locate (location->start(), session->transport_rolling());
1705 session->request_locate (session->current_end_frame());
1710 Editor::jump_backward_to_mark ()
1716 Location *location = session->locations()->first_location_before (playhead_cursor->current_frame);
1719 session->request_locate (location->start(), session->transport_rolling());
1721 session->goto_start ();
1732 if (get_prefix (prefix, was_floating)) {
1733 pos = session->audible_frame ();
1736 pos = (jack_nframes_t) floor (prefix * session->frame_rate ());
1738 pos = (jack_nframes_t) floor (prefix);
1742 session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true);
1746 Editor::clear_markers ()
1749 session->begin_reversible_command (_("clear markers"));
1750 XMLNode &before = session->locations()->get_state();
1751 session->locations()->clear_markers ();
1752 XMLNode &after = session->locations()->get_state();
1753 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1754 session->commit_reversible_command ();
1759 Editor::clear_ranges ()
1762 session->begin_reversible_command (_("clear ranges"));
1763 XMLNode &before = session->locations()->get_state();
1765 Location * looploc = session->locations()->auto_loop_location();
1766 Location * punchloc = session->locations()->auto_punch_location();
1768 session->locations()->clear_ranges ();
1770 if (looploc) session->locations()->add (looploc);
1771 if (punchloc) session->locations()->add (punchloc);
1773 XMLNode &after = session->locations()->get_state();
1774 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1775 session->commit_reversible_command ();
1780 Editor::clear_locations ()
1782 session->begin_reversible_command (_("clear locations"));
1783 XMLNode &before = session->locations()->get_state();
1784 session->locations()->clear ();
1785 XMLNode &after = session->locations()->get_state();
1786 session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
1787 session->commit_reversible_command ();
1788 session->locations()->clear ();
1791 /* INSERT/REPLACE */
1794 Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
1799 jack_nframes_t where;
1800 AudioTimeAxisView *atv = 0;
1803 track_canvas.window_to_world (x, y, wx, wy);
1804 wx += horizontal_adjustment.get_value();
1805 wy += vertical_adjustment.get_value();
1808 event.type = GDK_BUTTON_RELEASE;
1809 event.button.x = wx;
1810 event.button.y = wy;
1812 where = event_frame (&event, &cx, &cy);
1814 if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) {
1815 /* clearly outside canvas area */
1819 if ((tv = trackview_by_y_position (cy)) == 0) {
1823 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) == 0) {
1827 if ((playlist = atv->playlist()) == 0) {
1833 begin_reversible_command (_("insert dragged region"));
1834 XMLNode &before = playlist->get_state();
1835 playlist->add_region (*(new AudioRegion (region)), where, 1.0);
1836 session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
1837 commit_reversible_command ();
1841 Editor::insert_region_list_selection (float times)
1843 AudioTimeAxisView *tv = 0;
1846 if (clicked_audio_trackview != 0) {
1847 tv = clicked_audio_trackview;
1848 } else if (!selection->tracks.empty()) {
1849 if ((tv = dynamic_cast<AudioTimeAxisView*>(selection->tracks.front())) == 0) {
1856 if ((playlist = tv->playlist()) == 0) {
1860 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
1862 if (selected->count_selected_rows() != 1) {
1866 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
1867 Region* region = (*i)[region_list_columns.region];
1869 begin_reversible_command (_("insert region"));
1870 XMLNode &before = playlist->get_state();
1871 playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
1872 session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
1873 commit_reversible_command ();
1877 /* BUILT-IN EFFECTS */
1880 Editor::reverse_selection ()
1885 /* GAIN ENVELOPE EDITING */
1888 Editor::edit_envelope ()
1895 Editor::toggle_playback (bool with_abort)
1901 switch (session->slave_source()) {
1906 /* transport controlled by the master */
1910 if (session->is_auditioning()) {
1911 session->cancel_audition ();
1915 if (session->transport_rolling()) {
1916 session->request_stop (with_abort);
1917 if (session->get_auto_loop()) {
1918 session->request_auto_loop (false);
1921 session->request_transport_speed (1.0f);
1926 Editor::play_from_start ()
1928 session->request_locate (session->current_start_frame(), true);
1932 Editor::play_selection ()
1934 if (selection->time.empty()) {
1938 session->request_play_range (true);
1942 Editor::play_selected_region ()
1944 if (!selection->audio_regions.empty()) {
1945 AudioRegionView *rv = *(selection->audio_regions.begin());
1947 session->request_bounded_roll (rv->region.position(), rv->region.last_frame());
1952 Editor::loop_selected_region ()
1954 if (!selection->audio_regions.empty()) {
1955 AudioRegionView *rv = *(selection->audio_regions.begin());
1958 if ((tll = transport_loop_location()) != 0) {
1960 tll->set (rv->region.position(), rv->region.last_frame());
1962 // enable looping, reposition and start rolling
1964 session->request_auto_loop (true);
1965 session->request_locate (tll->start(), false);
1966 session->request_transport_speed (1.0f);
1972 Editor::play_location (Location& location)
1974 if (location.start() <= location.end()) {
1978 session->request_bounded_roll (location.start(), location.end());
1982 Editor::loop_location (Location& location)
1984 if (location.start() <= location.end()) {
1990 if ((tll = transport_loop_location()) != 0) {
1991 tll->set (location.start(), location.end());
1993 // enable looping, reposition and start rolling
1994 session->request_auto_loop (true);
1995 session->request_locate (tll->start(), true);
2000 Editor::toggle_region_mute ()
2002 if (clicked_regionview) {
2003 clicked_regionview->region.set_muted (!clicked_regionview->region.muted());
2004 } else if (!selection->audio_regions.empty()) {
2005 bool yn = ! (*selection->audio_regions.begin())->region.muted();
2006 selection->foreach_audio_region (&AudioRegion::set_muted, yn);
2011 Editor::toggle_region_opaque ()
2013 if (clicked_regionview) {
2014 clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque());
2015 } else if (!selection->audio_regions.empty()) {
2016 bool yn = ! (*selection->audio_regions.begin())->region.opaque();
2017 selection->foreach_audio_region (&Region::set_opaque, yn);
2022 Editor::raise_region ()
2024 selection->foreach_audio_region (&Region::raise);
2028 Editor::raise_region_to_top ()
2030 selection->foreach_audio_region (&Region::raise_to_top);
2034 Editor::lower_region ()
2036 selection->foreach_audio_region (&Region::lower);
2040 Editor::lower_region_to_bottom ()
2042 selection->foreach_audio_region (&Region::lower_to_bottom);
2046 Editor::edit_region ()
2048 if (clicked_regionview == 0) {
2052 clicked_regionview->show_region_editor ();
2056 Editor::rename_region ()
2060 Button ok_button (_("OK"));
2061 Button cancel_button (_("Cancel"));
2063 if (selection->audio_regions.empty()) {
2067 dialog.set_title (_("ardour: rename region"));
2068 dialog.set_name ("RegionRenameWindow");
2069 dialog.set_size_request (300, -1);
2070 dialog.set_position (Gtk::WIN_POS_MOUSE);
2071 dialog.set_modal (true);
2073 dialog.get_vbox()->set_border_width (10);
2074 dialog.get_vbox()->pack_start (entry);
2075 dialog.get_action_area()->pack_start (ok_button);
2076 dialog.get_action_area()->pack_start (cancel_button);
2078 entry.set_name ("RegionNameDisplay");
2079 ok_button.set_name ("EditorGTKButton");
2080 cancel_button.set_name ("EditorGTKButton");
2082 region_renamed = false;
2084 entry.signal_activate().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2085 ok_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), true));
2086 cancel_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::rename_region_finished), false));
2093 if (region_renamed) {
2094 (*selection->audio_regions.begin())->region.set_name (entry.get_text());
2095 redisplay_regions ();
2100 Editor::rename_region_finished (bool status)
2103 region_renamed = status;
2108 Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route)
2110 if (session->is_auditioning()) {
2111 session->cancel_audition ();
2114 // note: some potential for creativity here, because region doesn't
2115 // have to belong to the playlist that Route is handling
2117 // bool was_soloed = route.soloed();
2119 route.set_solo (true, this);
2121 session->request_bounded_roll (region.position(), region.position() + region.length());
2123 /* XXX how to unset the solo state ? */
2127 Editor::audition_selected_region ()
2129 if (!selection->audio_regions.empty()) {
2130 AudioRegionView* rv = *(selection->audio_regions.begin());
2131 session->audition_region (rv->region);
2136 Editor::audition_playlist_region_standalone (AudioRegion& region)
2138 session->audition_region (region);
2142 Editor::build_interthread_progress_window ()
2144 interthread_progress_window = new ArdourDialog (X_("interthread progress"), true);
2146 interthread_progress_bar.set_orientation (Gtk::PROGRESS_LEFT_TO_RIGHT);
2148 interthread_progress_window->get_vbox()->pack_start (interthread_progress_label, false, false);
2149 interthread_progress_window->get_vbox()->pack_start (interthread_progress_bar,false, false);
2151 // GTK2FIX: this button needs a modifiable label
2153 Button* b = interthread_progress_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
2154 b->signal_clicked().connect (mem_fun(*this, &Editor::interthread_cancel_clicked));
2156 interthread_cancel_button.add (interthread_cancel_label);
2158 interthread_progress_window->set_default_size (200, 100);
2162 Editor::interthread_cancel_clicked ()
2164 if (current_interthread_info) {
2165 current_interthread_info->cancel = true;
2170 Editor::region_from_selection ()
2172 if (clicked_trackview == 0) {
2176 if (selection->time.empty()) {
2180 jack_nframes_t start = selection->time[clicked_selection].start;
2181 jack_nframes_t end = selection->time[clicked_selection].end;
2183 jack_nframes_t selection_cnt = end - start + 1;
2185 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2187 AudioRegion *region;
2188 AudioRegion *current;
2192 jack_nframes_t internal_start;
2195 if ((pl = (*i)->playlist()) == 0) {
2199 if ((current_r = pl->top_region_at (start)) == 0) {
2203 if ((current = dynamic_cast<AudioRegion*> (current_r)) != 0) {
2204 internal_start = start - current->position();
2205 session->region_name (new_name, current->name(), true);
2206 region = new AudioRegion (*current, internal_start, selection_cnt, new_name);
2212 Editor::create_region_from_selection (vector<AudioRegion *>& new_regions)
2214 if (selection->time.empty() || selection->tracks.empty()) {
2218 jack_nframes_t start = selection->time[clicked_selection].start;
2219 jack_nframes_t end = selection->time[clicked_selection].end;
2221 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2223 AudioRegion* current;
2226 jack_nframes_t internal_start;
2229 if ((playlist = (*i)->playlist()) == 0) {
2233 if ((current_r = playlist->top_region_at(start)) == 0) {
2237 if ((current = dynamic_cast<AudioRegion*>(current_r)) == 0) {
2241 internal_start = start - current->position();
2242 session->region_name (new_name, current->name(), true);
2244 new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name));
2249 Editor::split_multichannel_region ()
2251 vector<AudioRegion*> v;
2253 if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) {
2257 clicked_regionview->region.separate_by_channel (*session, v);
2259 /* nothing else to do, really */
2263 Editor::new_region_from_selection ()
2265 region_from_selection ();
2266 cancel_selection ();
2270 Editor::separate_region_from_selection ()
2272 bool doing_undo = false;
2274 if (selection->time.empty()) {
2280 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2282 AudioTimeAxisView* atv;
2284 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2286 if (atv->is_audio_track()) {
2288 if ((playlist = atv->playlist()) != 0) {
2290 begin_reversible_command (_("separate"));
2295 before = &(playlist->get_state());
2297 /* XXX need to consider musical time selections here at some point */
2299 double speed = atv->get_diskstream()->speed();
2301 for (list<AudioRange>::iterator t = selection->time.begin(); t != selection->time.end(); ++t) {
2302 playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true);
2306 session->add_command(new MementoCommand<Playlist>(*playlist, *before, playlist->get_state()));
2312 if (doing_undo) commit_reversible_command ();
2316 Editor::separate_regions_using_location (Location& loc)
2318 bool doing_undo = false;
2320 if (loc.is_mark()) {
2326 /* XXX i'm unsure as to whether this should operate on selected tracks only
2327 or the entire enchillada. uncomment the below line to correct the behaviour
2328 (currently set for all tracks)
2331 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
2332 //for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2334 AudioTimeAxisView* atv;
2336 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2338 if (atv->is_audio_track()) {
2340 if ((playlist = atv->playlist()) != 0) {
2343 begin_reversible_command (_("separate"));
2347 before = &(playlist->get_state());
2350 /* XXX need to consider musical time selections here at some point */
2352 double speed = atv->get_diskstream()->speed();
2355 playlist->partition ((jack_nframes_t)(loc.start() * speed), (jack_nframes_t)(loc.end() * speed), true);
2357 session->add_command(new MementoCommand<Playlist>(*playlist, *before, playlist->get_state()));
2363 if (doing_undo) commit_reversible_command ();
2367 Editor::crop_region_to_selection ()
2369 if (selection->time.empty()) {
2373 vector<Playlist*> playlists;
2376 if (clicked_trackview != 0) {
2378 if ((playlist = clicked_trackview->playlist()) == 0) {
2382 playlists.push_back (playlist);
2386 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2388 AudioTimeAxisView* atv;
2390 if ((atv = dynamic_cast<AudioTimeAxisView*> ((*i))) != 0) {
2392 if (atv->is_audio_track()) {
2394 if ((playlist = atv->playlist()) != 0) {
2395 playlists.push_back (playlist);
2402 if (!playlists.empty()) {
2404 jack_nframes_t start;
2408 begin_reversible_command (_("trim to selection"));
2410 for (vector<Playlist*>::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2414 start = selection->time.start();
2416 if ((region = (*i)->top_region_at(start)) == 0) {
2420 /* now adjust lengths to that we do the right thing
2421 if the selection extends beyond the region
2424 start = max (start, region->position());
2425 end = min (selection->time.end_frame(), start + region->length() - 1);
2426 cnt = end - start + 1;
2428 XMLNode &before = (*i)->get_state();
2429 region->trim_to (start, cnt, this);
2430 XMLNode &after = (*i)->get_state();
2431 session->add_command (new MementoCommand<Playlist>(*(*i), before, after));
2434 commit_reversible_command ();
2439 Editor::region_fill_track ()
2443 if (!session || selection->audio_regions.empty()) {
2447 end = session->current_end_frame ();
2449 begin_reversible_command (_("region fill"));
2451 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2453 AudioRegion& region ((*i)->region);
2454 Playlist* pl = region.playlist();
2456 if (end <= region.last_frame()) {
2460 double times = (double) (end - region.last_frame()) / (double) region.length();
2466 XMLNode &before = pl->get_state();
2467 pl->add_region (*(new AudioRegion (region)), region.last_frame(), times);
2468 session->add_command (new MementoCommand<Playlist>(*pl, before, pl->get_state()));
2471 commit_reversible_command ();
2475 Editor::region_fill_selection ()
2477 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2481 if (selection->time.empty()) {
2487 Glib::RefPtr<TreeSelection> selected = region_list_display.get_selection();
2489 if (selected->count_selected_rows() != 1) {
2493 TreeModel::iterator i = region_list_display.get_selection()->get_selected();
2494 region = (*i)[region_list_columns.region];
2496 jack_nframes_t start = selection->time[clicked_selection].start;
2497 jack_nframes_t end = selection->time[clicked_selection].end;
2501 if (selection->tracks.empty()) {
2505 jack_nframes_t selection_length = end - start;
2506 float times = (float)selection_length / region->length();
2508 begin_reversible_command (_("fill selection"));
2510 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
2512 if ((playlist = (*i)->playlist()) == 0) {
2516 XMLNode &before = playlist->get_state();
2517 playlist->add_region (*(createRegion (*region)), start, times);
2518 session->add_command (new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
2521 commit_reversible_command ();
2525 Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
2528 if (!region.covers (position)) {
2529 error << _("Programming error. that region doesn't cover that position") << __FILE__ << " +" << __LINE__ << endmsg;
2532 begin_reversible_command (_("set region sync position"));
2533 XMLNode &before = region.playlist()->get_state();
2534 region.set_sync_position (position);
2535 XMLNode &after = region.playlist()->get_state();
2536 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2537 commit_reversible_command ();
2541 Editor::set_region_sync_from_edit_cursor ()
2543 if (clicked_regionview == 0) {
2547 if (!clicked_regionview->region.covers (edit_cursor->current_frame)) {
2548 error << _("Place the edit cursor at the desired sync point") << endmsg;
2552 Region& region (clicked_regionview->region);
2553 begin_reversible_command (_("set sync from edit cursor"));
2554 XMLNode &before = region.playlist()->get_state();
2555 region.set_sync_position (edit_cursor->current_frame);
2556 XMLNode &after = region.playlist()->get_state();
2557 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2558 commit_reversible_command ();
2562 Editor::remove_region_sync ()
2564 if (clicked_regionview) {
2565 Region& region (clicked_regionview->region);
2566 begin_reversible_command (_("remove sync"));
2567 XMLNode &before = region.playlist()->get_state();
2568 region.clear_sync_position ();
2569 XMLNode &after = region.playlist()->get_state();
2570 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2571 commit_reversible_command ();
2576 Editor::naturalize ()
2578 if (selection->audio_regions.empty()) {
2581 begin_reversible_command (_("naturalize"));
2582 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2583 XMLNode &before = (*i)->region.get_state();
2584 (*i)->region.move_to_natural_position (this);
2585 XMLNode &after = (*i)->region.get_state();
2586 session->add_command (new MementoCommand<AudioRegion>((*i)->region, before, after));
2588 commit_reversible_command ();
2592 Editor::align (RegionPoint what)
2594 align_selection (what, edit_cursor->current_frame);
2598 Editor::align_relative (RegionPoint what)
2600 align_selection_relative (what, edit_cursor->current_frame);
2603 struct RegionSortByTime {
2604 bool operator() (const AudioRegionView* a, const AudioRegionView* b) {
2605 return a->region.position() < b->region.position();
2610 Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
2612 if (selection->audio_regions.empty()) {
2616 jack_nframes_t distance;
2617 jack_nframes_t pos = 0;
2620 list<AudioRegionView*> sorted;
2621 selection->audio_regions.by_position (sorted);
2622 Region& r ((*sorted.begin())->region);
2626 pos = r.first_frame ();
2630 pos = r.last_frame();
2634 pos = r.adjust_to_sync (r.first_frame());
2638 if (pos > position) {
2639 distance = pos - position;
2642 distance = position - pos;
2646 begin_reversible_command (_("align selection (relative)"));
2648 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2650 Region& region ((*i)->region);
2652 XMLNode &before = region.playlist()->get_state();
2655 region.set_position (region.position() + distance, this);
2657 region.set_position (region.position() - distance, this);
2660 XMLNode &after = region.playlist()->get_state();
2661 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2665 commit_reversible_command ();
2669 Editor::align_selection (RegionPoint point, jack_nframes_t position)
2671 if (selection->audio_regions.empty()) {
2675 begin_reversible_command (_("align selection"));
2677 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
2678 align_region_internal ((*i)->region, point, position);
2681 commit_reversible_command ();
2685 Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position)
2687 begin_reversible_command (_("align region"));
2688 align_region_internal (region, point, position);
2689 commit_reversible_command ();
2693 Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position)
2695 XMLNode &before = region.playlist()->get_state();
2699 region.set_position (region.adjust_to_sync (position), this);
2703 if (position > region.length()) {
2704 region.set_position (position - region.length(), this);
2709 region.set_position (position, this);
2713 XMLNode &after = region.playlist()->get_state();
2714 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2718 Editor::trim_region_to_edit_cursor ()
2720 if (clicked_regionview == 0) {
2724 Region& region (clicked_regionview->region);
2727 AudioTimeAxisView *atav;
2729 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2730 if (atav->get_diskstream() != 0) {
2731 speed = atav->get_diskstream()->speed();
2735 begin_reversible_command (_("trim to edit"));
2736 XMLNode &before = region.playlist()->get_state();
2737 region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2738 XMLNode &after = region.playlist()->get_state();
2739 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2740 commit_reversible_command ();
2744 Editor::trim_region_from_edit_cursor ()
2746 if (clicked_regionview == 0) {
2750 Region& region (clicked_regionview->region);
2753 AudioTimeAxisView *atav;
2755 if ( clicked_trackview != 0 && (atav = dynamic_cast<AudioTimeAxisView*>(clicked_trackview)) != 0 ) {
2756 if (atav->get_diskstream() != 0) {
2757 speed = atav->get_diskstream()->speed();
2761 begin_reversible_command (_("trim to edit"));
2762 XMLNode &before = region.playlist()->get_state();
2763 region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
2764 XMLNode &after = region.playlist()->get_state();
2765 session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
2766 commit_reversible_command ();
2770 Editor::unfreeze_route ()
2772 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2776 clicked_audio_trackview->audio_track()->unfreeze ();
2780 Editor::_freeze_thread (void* arg)
2782 PBD::ThreadCreated (pthread_self(), X_("Freeze"));
2783 return static_cast<Editor*>(arg)->freeze_thread ();
2787 Editor::freeze_thread ()
2789 clicked_audio_trackview->audio_track()->freeze (*current_interthread_info);
2794 Editor::freeze_progress_timeout (void *arg)
2796 interthread_progress_bar.set_fraction (current_interthread_info->progress/100);
2797 return !(current_interthread_info->done || current_interthread_info->cancel);
2801 Editor::freeze_route ()
2803 if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) {
2807 InterThreadInfo itt;
2809 if (interthread_progress_window == 0) {
2810 build_interthread_progress_window ();
2813 interthread_progress_window->set_title (_("ardour: freeze"));
2814 interthread_progress_window->set_position (Gtk::WIN_POS_MOUSE);
2815 interthread_progress_window->show_all ();
2816 interthread_progress_bar.set_fraction (0.0f);
2817 interthread_progress_label.set_text ("");
2818 interthread_cancel_label.set_text (_("Cancel Freeze"));
2819 current_interthread_info = &itt;
2821 interthread_progress_connection =
2822 Glib::signal_timeout().connect (bind (mem_fun(*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100);
2826 itt.progress = 0.0f;
2828 pthread_create (&itt.thread, 0, _freeze_thread, this);
2830 track_canvas.get_window()->set_cursor (Gdk::Cursor (Gdk::WATCH));
2832 while (!itt.done && !itt.cancel) {
2833 gtk_main_iteration ();
2836 interthread_progress_connection.disconnect ();
2837 interthread_progress_window->hide_all ();
2838 current_interthread_info = 0;
2839 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
2843 Editor::bounce_range_selection ()
2845 if (selection->time.empty()) {
2849 TrackViewList *views = get_valid_views (selection->time.track, selection->time.group);
2851 jack_nframes_t start = selection->time[clicked_selection].start;
2852 jack_nframes_t end = selection->time[clicked_selection].end;
2853 jack_nframes_t cnt = end - start + 1;
2855 begin_reversible_command (_("bounce range"));
2857 for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) {
2859 AudioTimeAxisView* atv;
2861 if ((atv = dynamic_cast<AudioTimeAxisView*> (*i)) == 0) {
2867 if ((playlist = atv->playlist()) == 0) {
2871 InterThreadInfo itt;
2875 itt.progress = false;
2877 XMLNode &before = playlist->get_state();
2878 atv->audio_track()->bounce_range (start, cnt, itt);
2879 XMLNode &after = playlist->get_state();
2880 session->add_command (new MementoCommand<Playlist> (*playlist, before, after));
2883 commit_reversible_command ();
2901 Editor::cut_copy (CutCopyOp op)
2903 /* only cancel selection if cut/copy is successful.*/
2915 opname = _("clear");
2919 cut_buffer->clear ();
2921 switch (current_mouse_mode()) {
2923 if (!selection->audio_regions.empty() || !selection->points.empty()) {
2925 begin_reversible_command (opname + _(" objects"));
2927 if (!selection->audio_regions.empty()) {
2929 cut_copy_regions (op);
2932 selection->clear_audio_regions ();
2936 if (!selection->points.empty()) {
2937 cut_copy_points (op);
2940 selection->clear_points ();
2944 commit_reversible_command ();
2949 if (!selection->time.empty()) {
2951 begin_reversible_command (opname + _(" range"));
2952 cut_copy_ranges (op);
2953 commit_reversible_command ();
2956 selection->clear_time ();
2968 Editor::cut_copy_points (CutCopyOp op)
2970 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
2972 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
2975 atv->cut_copy_clear_objects (selection->points, op);
2981 Editor::cut_copy_regions (CutCopyOp op)
2983 typedef std::map<AudioPlaylist*,AudioPlaylist*> PlaylistMapping;
2984 PlaylistMapping pmap;
2985 jack_nframes_t first_position = max_frames;
2986 set<Playlist*> freezelist;
2987 pair<set<Playlist*>::iterator,bool> insert_result;
2989 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) {
2990 first_position = min ((*x)->region.position(), first_position);
2992 if (op == Cut || op == Clear) {
2993 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
2995 insert_result = freezelist.insert (pl);
2996 if (insert_result.second) {
2998 session->add_command (new MementoUndoCommand<Playlist>(*pl, pl->get_state()));
3004 for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) {
3006 AudioPlaylist *pl = dynamic_cast<AudioPlaylist*>((*x)->region.playlist());
3008 AudioRegionSelection::iterator tmp;
3015 PlaylistMapping::iterator pi = pmap.find (pl);
3017 if (pi == pmap.end()) {
3018 npl = new AudioPlaylist (*session, "cutlist", true);
3027 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
3028 pl->remove_region (&((*x)->region));
3032 npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position);
3036 pl->remove_region (&((*x)->region));
3044 list<Playlist*> foo;
3046 for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) {
3047 foo.push_back (i->second);
3051 cut_buffer->set (foo);
3054 for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
3056 session->add_command (new MementoRedoCommand<Playlist>(*(*pl), (*pl)->get_state()));
3061 Editor::cut_copy_ranges (CutCopyOp op)
3063 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3064 (*i)->cut_copy_clear (*selection, op);
3069 Editor::paste (float times)
3071 paste_internal (edit_cursor->current_frame, times);
3075 Editor::mouse_paste ()
3080 track_canvas.get_pointer (x, y);
3081 track_canvas.window_to_world (x, y, wx, wy);
3082 wx += horizontal_adjustment.get_value();
3083 wy += vertical_adjustment.get_value();
3086 event.type = GDK_BUTTON_RELEASE;
3087 event.button.x = wx;
3088 event.button.y = wy;
3090 jack_nframes_t where = event_frame (&event, 0, 0);
3092 paste_internal (where, 1);
3096 Editor::paste_internal (jack_nframes_t position, float times)
3098 bool commit = false;
3100 if (cut_buffer->empty() || selection->tracks.empty()) {
3104 if (position == max_frames) {
3105 position = edit_cursor->current_frame;
3108 begin_reversible_command (_("paste"));
3110 TrackSelection::iterator i;
3113 for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) {
3115 /* undo/redo is handled by individual tracks */
3117 if ((*i)->paste (position, times, *cut_buffer, nth)) {
3123 commit_reversible_command ();
3128 Editor::paste_named_selection (float times)
3130 TrackSelection::iterator t;
3132 Glib::RefPtr<TreeSelection> selected = named_selection_display.get_selection();
3134 if (selected->count_selected_rows() != 1 || selection->tracks.empty()) {
3138 TreeModel::iterator i = selected->get_selected();
3139 NamedSelection* ns = (*i)[named_selection_columns.selection];
3141 list<Playlist*>::iterator chunk;
3142 list<Playlist*>::iterator tmp;
3144 chunk = ns->playlists.begin();
3146 begin_reversible_command (_("paste chunk"));
3148 for (t = selection->tracks.begin(); t != selection->tracks.end(); ++t) {
3150 AudioTimeAxisView* atv;
3154 if ((atv = dynamic_cast<AudioTimeAxisView*> (*t)) == 0) {
3158 if ((pl = atv->playlist()) == 0) {
3162 if ((apl = dynamic_cast<AudioPlaylist*> (pl)) == 0) {
3169 XMLNode &before = apl->get_state();
3170 apl->paste (**chunk, edit_cursor->current_frame, times);
3171 session->add_command(new MementoCommand<AudioPlaylist>(*apl, before, apl->get_state()));
3173 if (tmp != ns->playlists.end()) {
3178 commit_reversible_command();
3182 Editor::duplicate_some_regions (AudioRegionSelection& regions, float times)
3185 AudioRegionSelection sel = regions; // clear (below) will clear the argument list
3187 begin_reversible_command (_("duplicate region"));
3189 selection->clear_audio_regions ();
3191 for (AudioRegionSelection::iterator i = sel.begin(); i != sel.end(); ++i) {
3193 Region& r ((*i)->region);
3195 TimeAxisView& tv = (*i)->get_time_axis_view();
3196 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
3197 sigc::connection c = atv->view->AudioRegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view));
3199 playlist = (*i)->region.playlist();
3200 XMLNode &before = playlist->get_state();
3201 playlist->duplicate (r, r.last_frame(), times);
3202 session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
3206 if (latest_regionview) {
3207 selection->add (latest_regionview);
3212 commit_reversible_command ();
3216 Editor::duplicate_selection (float times)
3218 if (selection->time.empty() || selection->tracks.empty()) {
3223 vector<AudioRegion*> new_regions;
3224 vector<AudioRegion*>::iterator ri;
3226 create_region_from_selection (new_regions);
3228 if (new_regions.empty()) {
3232 begin_reversible_command (_("duplicate selection"));
3234 ri = new_regions.begin();
3236 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3237 if ((playlist = (*i)->playlist()) == 0) {
3240 XMLNode &before = playlist->get_state();
3241 playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
3242 XMLNode &after = playlist->get_state();
3243 session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
3246 if (ri == new_regions.end()) {
3251 commit_reversible_command ();
3255 Editor::reset_point_selection ()
3257 /* reset all selected points to the relevant default value */
3259 cerr << "point selection has " << selection->points.size() << " entries\n";
3261 for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) {
3263 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*>(&(*i).track);
3266 atv->reset_objects (selection->points);
3272 Editor::center_playhead ()
3274 float page = canvas_width * frames_per_unit;
3276 center_screen_internal (playhead_cursor->current_frame, page);
3280 Editor::center_edit_cursor ()
3282 float page = canvas_width * frames_per_unit;
3284 center_screen_internal (edit_cursor->current_frame, page);
3288 Editor::clear_playlist (Playlist& playlist)
3290 begin_reversible_command (_("clear playlist"));
3291 XMLNode &before = playlist.get_state();
3293 XMLNode &after = playlist.get_state();
3294 session->add_command (new MementoCommand<Playlist>(playlist, before, after));
3295 commit_reversible_command ();
3299 Editor::nudge_track (bool use_edit_cursor, bool forwards)
3302 jack_nframes_t distance;
3303 jack_nframes_t next_distance;
3304 jack_nframes_t start;
3306 if (use_edit_cursor) {
3307 start = edit_cursor->current_frame;
3312 if ((distance = get_nudge_distance (start, next_distance)) == 0) {
3316 if (selection->tracks.empty()) {
3320 begin_reversible_command (_("nudge track"));
3322 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3324 if ((playlist = (*i)->playlist()) == 0) {
3328 XMLNode &before = playlist->get_state();
3329 playlist->nudge_after (start, distance, forwards);
3330 XMLNode &after = playlist->get_state();
3331 session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
3334 commit_reversible_command ();
3338 Editor::remove_last_capture ()
3340 vector<string> choices;
3347 if (Config->get_verify_remove_last_capture()) {
3348 prompt = _("Do you really want to destroy the last capture?"
3349 "\n(This is destructive and cannot be undone)");
3351 choices.push_back (_("No, do nothing."));
3352 choices.push_back (_("Yes, destroy it."));
3354 Gtkmm2ext::Choice prompter (prompt, choices);
3356 if (prompter.run () == 1) {
3357 session->remove_last_capture ();
3361 session->remove_last_capture();
3366 Editor::normalize_region ()
3372 if (selection->audio_regions.empty()) {
3376 begin_reversible_command (_("normalize"));
3378 track_canvas.get_window()->set_cursor (*wait_cursor);
3381 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3382 XMLNode &before = (*r)->region.get_state();
3383 (*r)->region.normalize_to (0.0f);
3384 XMLNode &after = (*r)->region.get_state();
3385 session->add_command (new MementoCommand<AudioRegion>((*r)->region, before, after));
3388 commit_reversible_command ();
3389 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3394 Editor::denormalize_region ()
3400 if (selection->audio_regions.empty()) {
3404 begin_reversible_command ("denormalize");
3406 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) {
3407 XMLNode &before = (*r)->region.get_state();
3408 (*r)->region.set_scale_amplitude (1.0f);
3409 XMLNode &after = (*r)->region.get_state();
3410 session->add_command (new MementoCommand<AudioRegion>((*r)->region, before, after));
3413 commit_reversible_command ();
3418 Editor::reverse_region ()
3424 Reverse rev (*session);
3425 apply_filter (rev, _("reverse regions"));
3429 Editor::apply_filter (AudioFilter& filter, string command)
3431 if (selection->audio_regions.empty()) {
3435 begin_reversible_command (command);
3437 track_canvas.get_window()->set_cursor (*wait_cursor);
3440 for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) {
3442 AudioRegion& region ((*r)->region);
3443 Playlist* playlist = region.playlist();
3445 AudioRegionSelection::iterator tmp;
3450 if (region.apply (filter) == 0) {
3452 XMLNode &before = playlist->get_state();
3453 playlist->replace_region (region, *(filter.results.front()), region.position());
3454 XMLNode &after = playlist->get_state();
3455 session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
3463 commit_reversible_command ();
3464 selection->audio_regions.clear ();
3467 track_canvas.get_window()->set_cursor (*current_canvas_cursor);
3471 Editor::region_selection_op (void (Region::*pmf)(void))
3473 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3474 ((*i)->region.*pmf)();
3480 Editor::region_selection_op (void (Region::*pmf)(void*), void *arg)
3482 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3483 ((*i)->region.*pmf)(arg);
3488 Editor::region_selection_op (void (Region::*pmf)(bool), bool yn)
3490 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3491 ((*i)->region.*pmf)(yn);
3496 Editor::external_edit_region ()
3498 if (!clicked_regionview) {
3506 Editor::brush (jack_nframes_t pos)
3508 AudioRegionSelection sel;
3511 if (selection->audio_regions.empty()) {
3512 /* XXX get selection from region list */
3514 sel = selection->audio_regions;
3521 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3522 mouse_brush_insert_region ((*i), pos);
3527 Editor::toggle_gain_envelope_visibility ()
3529 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3530 (*i)->set_envelope_visible (!(*i)->envelope_visible());
3535 Editor::toggle_gain_envelope_active ()
3537 for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) {
3538 AudioRegion* ar = dynamic_cast<AudioRegion*>(&(*i)->region);
3540 ar->set_envelope_active (true);