2 Copyright (C) 2000-2006 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.
23 #include <pbd/stacktrace.h>
25 #include <ardour/diskstream.h>
26 #include <ardour/playlist.h>
27 #include <ardour/route_group.h>
31 #include "audio_time_axis.h"
32 #include "audio_region_view.h"
33 #include "audio_streamview.h"
34 #include "automation_line.h"
35 #include "control_point.h"
41 using namespace ARDOUR;
45 using namespace Gtkmm2ext;
46 using namespace Editing;
48 struct TrackViewByPositionSorter
50 bool operator() (const TimeAxisView* a, const TimeAxisView *b) {
51 return a->y_position < b->y_position;
56 Editor::extend_selection_to_track (TimeAxisView& view)
58 if (selection->selected (&view)) {
59 /* already selected, do nothing */
63 if (selection->tracks.empty()) {
65 if (!selection->selected (&view)) {
66 selection->set (&view);
73 /* something is already selected, so figure out which range of things to add */
75 TrackViewList to_be_added;
76 TrackViewList sorted = track_views;
77 TrackViewByPositionSorter cmp;
78 bool passed_clicked = false;
83 if (!selection->selected (&view)) {
84 to_be_added.push_back (&view);
87 /* figure out if we should go forward or backwards */
89 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
92 passed_clicked = true;
95 if (selection->selected (*i)) {
105 passed_clicked = false;
109 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
112 passed_clicked = true;
116 if (passed_clicked) {
117 if ((*i)->hidden()) {
120 if (selection->selected (*i)) {
122 } else if (!(*i)->hidden()) {
123 to_be_added.push_back (*i);
130 for (TrackViewList::reverse_iterator r = sorted.rbegin(); r != sorted.rend(); ++r) {
133 passed_clicked = true;
137 if (passed_clicked) {
139 if ((*r)->hidden()) {
143 if (selection->selected (*r)) {
145 } else if (!(*r)->hidden()) {
146 to_be_added.push_back (*r);
152 if (!to_be_added.empty()) {
153 selection->add (to_be_added);
161 Editor::select_all_tracks ()
163 selection->set (track_views);
167 Editor::set_selected_track_as_side_effect (bool force)
169 if (!clicked_routeview) {
173 if (!selection->tracks.empty()) {
174 if (!selection->selected (clicked_routeview)) {
175 selection->add (clicked_routeview);
179 selection->set (clicked_routeview);
184 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
188 case Selection::Toggle:
189 if (selection->selected (&view)) {
191 selection->remove (&view);
194 selection->add (&view);
199 if (!selection->selected (&view)) {
200 selection->add (&view);
205 if (selection->selected (&view) && selection->tracks.size() > 1) {
207 /* reset track selection if there is only 1 other track
208 selected OR if no_remove is not set (its there to
209 prevent deselecting a multi-track selection
210 when clicking on an already selected track
214 if (selection->tracks.empty()) {
215 selection->set (&view);
216 } else if (selection->tracks.size() == 1 || !no_remove) {
217 selection->set (&view);
222 case Selection::Extend:
223 extend_selection_to_track (view);
229 Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool no_remove)
231 if (!clicked_routeview) {
239 set_selected_track (*clicked_routeview, op, no_remove);
243 Editor::set_selected_control_point_from_click (Selection::Operation op, bool no_remove)
245 if (!clicked_control_point) {
249 /* select this point and any others that it represents */
254 x1 = pixel_to_frame (clicked_control_point->get_x() - 10);
255 x2 = pixel_to_frame (clicked_control_point->get_x() + 10);
256 y1 = clicked_control_point->get_x() - 10;
257 y2 = clicked_control_point->get_y() + 10;
259 return select_all_within (x1, x2, y1, y2, selection->tracks, op);
263 Editor::get_relevant_tracks (set<RouteTimeAxisView*>& relevant_tracks)
265 /* step one: get all selected tracks and all tracks in the relevant edit groups */
267 for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
269 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*ti);
275 RouteGroup* group = rtv->route()->edit_group();
277 if (group && group->is_active()) {
279 /* active group for this track, loop over all tracks and get every member of the group */
281 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
283 RouteTimeAxisView* trtv;
285 if ((trtv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
287 if (trtv->route()->edit_group() == group) {
288 relevant_tracks.insert (trtv);
293 relevant_tracks.insert (rtv);
299 * Call a slot for a given `basis' track and also for any track that is in the same
301 * @param sl Slot to call.
302 * @param basis Basis track.
306 Editor::mapover_tracks (slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis) const
308 RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
309 if (route_basis == 0) {
313 /* work out the tracks that we will call the slot for; use
314 a set here as it will disallow possible duplicates of the
316 set<RouteTimeAxisView*> tracks;
318 /* always call for the basis */
319 tracks.insert (route_basis);
321 RouteGroup* group = route_basis->route()->edit_group();
322 if (group && group->is_active()) {
324 /* the basis is a member of an active edit group; find other members */
325 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
326 RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
327 if (v && v->route()->edit_group() == group) {
334 uint32_t const sz = tracks.size ();
335 for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
341 Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t ignored, RegionView* basis, vector<RegionView*>* all_equivs) const
343 boost::shared_ptr<Playlist> pl;
344 vector<boost::shared_ptr<Region> > results;
346 boost::shared_ptr<Diskstream> ds;
348 if ((ds = tv.get_diskstream()) == 0) {
353 if (&tv == &basis->get_time_axis_view()) {
354 /* looking in same track as the original */
358 if ((pl = ds->playlist()) != 0) {
359 pl->get_equivalent_regions (basis->region(), results);
362 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
363 if ((marv = tv.view()->find_view (*ir)) != 0) {
364 all_equivs->push_back (marv);
370 Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions) const
372 mapover_tracks (bind (mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_trackview());
374 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
376 equivalent_regions.push_back (basis);
380 Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool no_track_remove)
382 vector<RegionView*> all_equivalent_regions;
385 if (!clicked_regionview || !clicked_routeview) {
390 button_release_can_deselect = false;
393 if (op == Selection::Toggle || op == Selection::Set) {
397 case Selection::Toggle:
399 if (selection->selected (clicked_regionview)) {
402 /* whatever was clicked was selected already; do nothing here but allow
403 the button release to deselect it
406 button_release_can_deselect = true;
410 if (button_release_can_deselect) {
412 /* just remove this one region, but only on a permitted button release */
414 selection->remove (clicked_regionview);
417 /* no more deselect action on button release till a new press
418 finds an already selected object.
421 button_release_can_deselect = false;
429 if (selection->selected (clicked_routeview)) {
430 get_equivalent_regions (clicked_regionview, all_equivalent_regions);
432 all_equivalent_regions.push_back (clicked_regionview);
435 /* add all the equivalent regions, but only on button press */
439 if (!all_equivalent_regions.empty()) {
443 selection->add (all_equivalent_regions);
449 if (!selection->selected (clicked_regionview)) {
450 selection->set (clicked_regionview);
453 /* no commit necessary: clicked on an already selected region */
463 } else if (op == Selection::Extend) {
465 list<Selectable*> results;
466 nframes_t last_frame;
467 nframes_t first_frame;
468 bool same_track = false;
470 /* 1. find the last selected regionview in the track that was clicked in */
473 first_frame = max_frames;
475 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
476 if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
478 if ((*x)->region()->last_frame() > last_frame) {
479 last_frame = (*x)->region()->last_frame();
482 if ((*x)->region()->first_frame() < first_frame) {
483 first_frame = (*x)->region()->first_frame();
492 /* 2. figure out the boundaries for our search for new objects */
494 switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
496 if (last_frame < clicked_regionview->region()->first_frame()) {
497 first_frame = last_frame;
498 last_frame = clicked_regionview->region()->last_frame();
500 last_frame = first_frame;
501 first_frame = clicked_regionview->region()->first_frame();
505 case OverlapExternal:
506 if (last_frame < clicked_regionview->region()->first_frame()) {
507 first_frame = last_frame;
508 last_frame = clicked_regionview->region()->last_frame();
510 last_frame = first_frame;
511 first_frame = clicked_regionview->region()->first_frame();
515 case OverlapInternal:
516 if (last_frame < clicked_regionview->region()->first_frame()) {
517 first_frame = last_frame;
518 last_frame = clicked_regionview->region()->last_frame();
520 last_frame = first_frame;
521 first_frame = clicked_regionview->region()->first_frame();
527 /* nothing to do except add clicked region to selection, since it
528 overlaps with the existing selection in this track.
535 /* click in a track that has no regions selected, so extend vertically
536 to pick out all regions that are defined by the existing selection
541 first_frame = entered_regionview->region()->position();
542 last_frame = entered_regionview->region()->last_frame();
544 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
545 if ((*i)->region()->position() < first_frame) {
546 first_frame = (*i)->region()->position();
548 if ((*i)->region()->last_frame() + 1 > last_frame) {
549 last_frame = (*i)->region()->last_frame();
554 /* 2. find all the tracks we should select in */
556 set<RouteTimeAxisView*> relevant_tracks;
557 set<RouteTimeAxisView*> already_in_selection;
559 get_relevant_tracks (relevant_tracks);
561 if (relevant_tracks.empty()) {
563 /* no relevant tracks -> no tracks selected .. thus .. if
564 the regionview we're in isn't selected (i.e. we're
565 about to extend to it), then find all tracks between
566 the this one and any selected ones.
569 if (!selection->selected (entered_regionview)) {
571 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&entered_regionview->get_time_axis_view());
575 /* add this track to the ones we will search */
577 relevant_tracks.insert (rtv);
579 /* find the track closest to this one that
580 already a selected region.
583 RouteTimeAxisView* closest = 0;
584 int distance = INT_MAX;
585 int key = rtv->route()->order_key ("editor");
587 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
589 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(&(*x)->get_time_axis_view());
591 if (artv && artv != rtv) {
593 pair<set<RouteTimeAxisView*>::iterator,bool> result;
595 result = already_in_selection.insert (artv);
598 /* newly added to already_in_selection */
601 int d = artv->route()->order_key ("editor");
605 if (abs (d) < distance) {
615 /* now add all tracks between that one and this one */
617 int okey = closest->route()->order_key ("editor");
623 for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
624 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
625 if (artv && artv != rtv) {
627 int k = artv->route()->order_key ("editor");
629 if (k >= okey && k <= key) {
631 /* in range but don't add it if
632 it already has tracks selected.
633 this avoids odd selection
634 behaviour that feels wrong.
637 if (find (already_in_selection.begin(),
638 already_in_selection.end(),
639 artv) == already_in_selection.end()) {
641 relevant_tracks.insert (artv);
651 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
652 one that was clicked.
655 get_relevant_tracks (relevant_tracks);
657 for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
658 (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
661 /* 4. convert to a vector of regions */
663 vector<RegionView*> regions;
665 for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
668 if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
669 regions.push_back (arv);
673 if (!regions.empty()) {
674 selection->add (regions);
685 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
687 vector<RegionView*> all_equivalent_regions;
689 get_regions_corresponding_to (region, all_equivalent_regions);
691 if (all_equivalent_regions.empty()) {
695 begin_reversible_command (_("set selected regions"));
698 case Selection::Toggle:
699 /* XXX this is not correct */
700 selection->toggle (all_equivalent_regions);
703 selection->set (all_equivalent_regions);
705 case Selection::Extend:
706 selection->add (all_equivalent_regions);
709 selection->add (all_equivalent_regions);
713 commit_reversible_command () ;
717 Editor::track_selection_changed ()
719 switch (selection->tracks.size()){
723 set_selected_mixer_strip (*(selection->tracks.front()));
727 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
728 if (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end()) {
729 (*i)->set_selected (true);
731 (*i)->set_selected (false);
737 Editor::time_selection_changed ()
739 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
740 (*i)->hide_selection ();
743 if (selection->tracks.empty()) {
744 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
745 (*i)->show_selection (selection->time);
748 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
749 (*i)->show_selection (selection->time);
753 if (selection->time.empty()) {
754 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
756 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
762 Editor::region_selection_changed ()
764 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
765 (*i)->set_selected_regionviews (selection->regions);
768 zoomed_to_region = false;
772 Editor::point_selection_changed ()
774 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
775 (*i)->set_selected_points (selection->points);
779 /** Select everything in the selected tracks
780 * @param Selection operation to apply.
783 Editor::select_all_in_selected_tracks (Selection::Operation op)
785 list<Selectable *> touched;
787 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
788 (*i)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
792 case Selection::Toggle:
793 selection->add (touched);
796 selection->set (touched);
798 case Selection::Extend:
799 /* meaningless, because we're selecting everything */
802 selection->add (touched);
808 Editor::select_all (Selection::Operation op)
810 list<Selectable *> touched;
812 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
813 if ((*iter)->hidden()) {
816 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
818 begin_reversible_command (_("select all"));
821 selection->add (touched);
823 case Selection::Toggle:
824 selection->add (touched);
827 selection->set (touched);
829 case Selection::Extend:
830 /* meaningless, because we're selecting everything */
833 commit_reversible_command ();
836 /** Invert the selection in the selected tracks */
838 Editor::invert_selection_in_selected_tracks ()
840 list<Selectable *> touched;
842 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
843 (*i)->get_inverted_selectables (*selection, touched);
846 selection->set (touched);
850 Editor::invert_selection ()
852 list<Selectable *> touched;
854 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
855 if ((*iter)->hidden()) {
858 (*iter)->get_inverted_selectables (*selection, touched);
861 selection->set (touched);
865 Editor::select_all_within (nframes_t start, nframes_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op)
867 list<Selectable*> touched;
868 list<Selectable*>::size_type n = 0;
869 TrackViewList touched_tracks;
871 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
872 if ((*iter)->hidden()) {
878 (*iter)->get_selectables (start, end, top, bot, touched);
880 if (n != touched.size()) {
881 touched_tracks.push_back (*iter);
885 if (touched.empty()) {
889 if (!touched_tracks.empty()) {
893 selection->add (touched_tracks);
895 case Selection::Toggle:
896 selection->toggle (touched_tracks);
899 selection->set (touched_tracks);
901 case Selection::Extend:
902 /* not defined yet */
907 begin_reversible_command (_("select all within"));
910 selection->add (touched);
912 case Selection::Toggle:
913 selection->toggle (touched);
916 selection->set (touched);
918 case Selection::Extend:
919 /* not defined yet */
923 commit_reversible_command ();
925 return !touched.empty();
929 Editor::set_selection_from_audio_region ()
931 if (selection->regions.empty()) {
935 RegionView* rv = *(selection->regions.begin());
936 boost::shared_ptr<Region> region = rv->region();
938 begin_reversible_command (_("set selection from region"));
939 selection->set (0, region->position(), region->last_frame());
940 commit_reversible_command ();
942 set_mouse_mode (Editing::MouseRange, false);
946 Editor::set_selection_from_punch()
950 if ((location = session->locations()->auto_punch_location()) == 0) {
954 set_selection_from_range (*location);
958 Editor::set_selection_from_loop()
962 if ((location = session->locations()->auto_loop_location()) == 0) {
965 set_selection_from_range (*location);
969 Editor::set_selection_from_range (Location& loc)
971 begin_reversible_command (_("set selection from range"));
972 selection->set (0, loc.start(), loc.end());
973 commit_reversible_command ();
975 set_mouse_mode (Editing::MouseRange, false);
979 Editor::select_all_selectables_using_time_selection ()
981 list<Selectable *> touched;
983 if (selection->time.empty()) {
987 nframes_t start = selection->time[clicked_selection].start;
988 nframes_t end = selection->time[clicked_selection].end;
990 if (end - start < 1) {
996 if (selection->tracks.empty()) {
999 ts = &selection->tracks;
1002 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1003 if ((*iter)->hidden()) {
1006 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1009 begin_reversible_command (_("select all from range"));
1010 selection->set (touched);
1011 commit_reversible_command ();
1016 Editor::select_all_selectables_using_punch()
1018 Location* location = session->locations()->auto_punch_location();
1019 list<Selectable *> touched;
1021 if (location == 0 || (location->end() - location->start() <= 1)) {
1028 if (selection->tracks.empty()) {
1031 ts = &selection->tracks;
1034 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1035 if ((*iter)->hidden()) {
1038 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1040 begin_reversible_command (_("select all from punch"));
1041 selection->set (touched);
1042 commit_reversible_command ();
1047 Editor::select_all_selectables_using_loop()
1049 Location* location = session->locations()->auto_loop_location();
1050 list<Selectable *> touched;
1052 if (location == 0 || (location->end() - location->start() <= 1)) {
1059 if (selection->tracks.empty()) {
1062 ts = &selection->tracks;
1065 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1066 if ((*iter)->hidden()) {
1069 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1071 begin_reversible_command (_("select all from loop"));
1072 selection->set (touched);
1073 commit_reversible_command ();
1078 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1082 list<Selectable *> touched;
1085 begin_reversible_command (_("select all after cursor"));
1086 start = cursor->current_frame ;
1087 end = session->current_end_frame();
1089 if (cursor->current_frame > 0) {
1090 begin_reversible_command (_("select all before cursor"));
1092 end = cursor->current_frame - 1;
1101 if (selection->tracks.empty()) {
1104 ts = &selection->tracks;
1107 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1108 if ((*iter)->hidden()) {
1111 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1113 selection->set (touched);
1114 commit_reversible_command ();
1118 Editor::select_all_selectables_using_edit (bool after)
1122 list<Selectable *> touched;
1125 begin_reversible_command (_("select all after edit"));
1126 start = get_preferred_edit_position();
1127 end = session->current_end_frame();
1129 if ((end = get_preferred_edit_position()) > 1) {
1130 begin_reversible_command (_("select all before edit"));
1141 if (selection->tracks.empty()) {
1144 ts = &selection->tracks;
1147 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1148 if ((*iter)->hidden()) {
1151 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1153 selection->set (touched);
1154 commit_reversible_command ();
1158 Editor::select_all_selectables_between (bool within)
1162 list<Selectable *> touched;
1164 if (!get_edit_op_range (start, end)) {
1170 if (selection->tracks.empty()) {
1173 ts = &selection->tracks;
1176 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1177 if ((*iter)->hidden()) {
1180 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1183 selection->set (touched);
1187 Editor::select_range_between ()
1192 if (!get_edit_op_range (start, end)) {
1196 set_mouse_mode (MouseRange);
1197 selection->set ((TimeAxisView*) 0, start, end);
1201 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1206 /* in range mode, use any existing selection */
1208 if (mouse_mode == MouseRange && !selection->time.empty()) {
1209 /* we know that these are ordered */
1210 start = selection->time.start();
1211 end = selection->time.end_frame();
1215 if (!mouse_frame (m, ignored)) {
1216 /* mouse is not in a canvas, try playhead+selected marker.
1217 this is probably most true when using menus.
1220 if (selection->markers.empty()) {
1224 start = selection->markers.front()->position();
1225 end = session->audible_frame();
1229 switch (_edit_point) {
1230 case EditAtPlayhead:
1231 if (selection->markers.empty()) {
1232 /* use mouse + playhead */
1234 end = session->audible_frame();
1236 /* use playhead + selected marker */
1237 start = session->audible_frame();
1238 end = selection->markers.front()->position();
1243 /* use mouse + selected marker */
1244 if (selection->markers.empty()) {
1246 end = session->audible_frame();
1248 start = selection->markers.front()->position();
1253 case EditAtSelectedMarker:
1254 /* use mouse + selected marker */
1255 if (selection->markers.empty()) {
1257 MessageDialog win (_("No edit range defined"),
1262 win.set_secondary_text (
1263 _("the edit point is Selected Marker\nbut there is no selected marker."));
1266 win.set_default_response (RESPONSE_CLOSE);
1267 win.set_position (Gtk::WIN_POS_MOUSE);
1272 return false; // NO RANGE
1274 start = selection->markers.front()->position();
1292 Editor::deselect_all ()
1294 selection->clear ();
1297 Editor::ExclusiveRegionSelection::ExclusiveRegionSelection (Editor& ed, RegionView* rv)
1302 if (!rv || ed.current_mouse_mode() != Editing::MouseObject) {
1306 if (ed.get_selection().regions.empty() && !ed.get_selection().selected (rv)) {
1307 ed.get_selection().set (rv, false);
1314 Editor::ExclusiveRegionSelection::~ExclusiveRegionSelection ()
1317 editor.get_selection().remove (regionview);