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::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, boost::weak_ptr<Region> weak_r)
720 boost::shared_ptr<Region> r (weak_r.lock());
726 if ((rv = sv->find_view (r)) == 0) {
730 /* don't reset the selection if its something other than
731 a single other region.
734 if (selection->regions.size() > 1) {
738 begin_reversible_command (_("set selected regions"));
742 commit_reversible_command () ;
748 Editor::track_selection_changed ()
750 switch (selection->tracks.size()){
754 set_selected_mixer_strip (*(selection->tracks.front()));
758 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
759 if (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end()) {
760 (*i)->set_selected (true);
762 (*i)->set_selected (false);
768 Editor::time_selection_changed ()
770 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
771 (*i)->hide_selection ();
774 if (selection->tracks.empty()) {
775 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
776 (*i)->show_selection (selection->time);
779 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
780 (*i)->show_selection (selection->time);
784 if (selection->time.empty()) {
785 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
787 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
793 Editor::region_selection_changed ()
795 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
796 (*i)->set_selected_regionviews (selection->regions);
799 zoomed_to_region = false;
803 Editor::point_selection_changed ()
805 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
806 (*i)->set_selected_points (selection->points);
811 Editor::select_all_in_track (Selection::Operation op)
813 list<Selectable *> touched;
815 if (!clicked_routeview) {
819 clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
822 case Selection::Toggle:
823 selection->add (touched);
826 selection->set (touched);
828 case Selection::Extend:
829 /* meaningless, because we're selecting everything */
832 selection->add (touched);
838 Editor::select_all (Selection::Operation op)
840 list<Selectable *> touched;
842 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
843 if ((*iter)->hidden()) {
846 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
848 begin_reversible_command (_("select all"));
851 selection->add (touched);
853 case Selection::Toggle:
854 selection->add (touched);
857 selection->set (touched);
859 case Selection::Extend:
860 /* meaningless, because we're selecting everything */
863 commit_reversible_command ();
866 Editor::invert_selection_in_track ()
868 list<Selectable *> touched;
870 if (!clicked_routeview) {
874 clicked_routeview->get_inverted_selectables (*selection, touched);
875 selection->set (touched);
879 Editor::invert_selection ()
881 list<Selectable *> touched;
883 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
884 if ((*iter)->hidden()) {
887 (*iter)->get_inverted_selectables (*selection, touched);
890 selection->set (touched);
894 Editor::select_all_within (nframes_t start, nframes_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op)
896 list<Selectable*> touched;
897 list<Selectable*>::size_type n = 0;
898 TrackViewList touched_tracks;
900 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
901 if ((*iter)->hidden()) {
907 (*iter)->get_selectables (start, end, top, bot, touched);
909 if (n != touched.size()) {
910 touched_tracks.push_back (*iter);
914 if (touched.empty()) {
918 if (!touched_tracks.empty()) {
922 selection->add (touched_tracks);
924 case Selection::Toggle:
925 selection->toggle (touched_tracks);
928 selection->set (touched_tracks);
930 case Selection::Extend:
931 /* not defined yet */
936 begin_reversible_command (_("select all within"));
939 selection->add (touched);
941 case Selection::Toggle:
942 selection->toggle (touched);
945 selection->set (touched);
947 case Selection::Extend:
948 /* not defined yet */
952 commit_reversible_command ();
954 return !touched.empty();
958 Editor::set_selection_from_region ()
960 if (selection->regions.empty()) {
964 RegionView* rv = *(selection->regions.begin());
965 boost::shared_ptr<Region> region = rv->region();
967 begin_reversible_command (_("set selection from region"));
968 selection->set (0, region->position(), region->last_frame());
969 commit_reversible_command ();
971 set_mouse_mode (Editing::MouseRange, false);
975 Editor::set_selection_from_punch()
979 if ((location = session->locations()->auto_punch_location()) == 0) {
983 set_selection_from_range (*location);
987 Editor::set_selection_from_loop()
991 if ((location = session->locations()->auto_loop_location()) == 0) {
994 set_selection_from_range (*location);
998 Editor::set_selection_from_range (Location& loc)
1000 begin_reversible_command (_("set selection from range"));
1001 selection->set (0, loc.start(), loc.end());
1002 commit_reversible_command ();
1004 set_mouse_mode (Editing::MouseRange, false);
1008 Editor::select_all_selectables_using_time_selection ()
1010 list<Selectable *> touched;
1012 if (selection->time.empty()) {
1016 nframes_t start = selection->time[clicked_selection].start;
1017 nframes_t end = selection->time[clicked_selection].end;
1019 if (end - start < 1) {
1025 if (selection->tracks.empty()) {
1028 ts = &selection->tracks;
1031 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1032 if ((*iter)->hidden()) {
1035 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1038 begin_reversible_command (_("select all from range"));
1039 selection->set (touched);
1040 commit_reversible_command ();
1045 Editor::select_all_selectables_using_punch()
1047 Location* location = session->locations()->auto_punch_location();
1048 list<Selectable *> touched;
1050 if (location == 0 || (location->end() - location->start() <= 1)) {
1057 if (selection->tracks.empty()) {
1060 ts = &selection->tracks;
1063 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1064 if ((*iter)->hidden()) {
1067 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1069 begin_reversible_command (_("select all from punch"));
1070 selection->set (touched);
1071 commit_reversible_command ();
1076 Editor::select_all_selectables_using_loop()
1078 Location* location = session->locations()->auto_loop_location();
1079 list<Selectable *> touched;
1081 if (location == 0 || (location->end() - location->start() <= 1)) {
1088 if (selection->tracks.empty()) {
1091 ts = &selection->tracks;
1094 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1095 if ((*iter)->hidden()) {
1098 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1100 begin_reversible_command (_("select all from loop"));
1101 selection->set (touched);
1102 commit_reversible_command ();
1107 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1111 list<Selectable *> touched;
1114 begin_reversible_command (_("select all after cursor"));
1115 start = cursor->current_frame ;
1116 end = session->current_end_frame();
1118 if (cursor->current_frame > 0) {
1119 begin_reversible_command (_("select all before cursor"));
1121 end = cursor->current_frame - 1;
1130 if (selection->tracks.empty()) {
1133 ts = &selection->tracks;
1136 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1137 if ((*iter)->hidden()) {
1140 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1142 selection->set (touched);
1143 commit_reversible_command ();
1147 Editor::select_all_selectables_using_edit (bool after)
1151 list<Selectable *> touched;
1154 begin_reversible_command (_("select all after edit"));
1155 start = get_preferred_edit_position();
1156 end = session->current_end_frame();
1158 if ((end = get_preferred_edit_position()) > 1) {
1159 begin_reversible_command (_("select all before edit"));
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);
1182 selection->set (touched);
1183 commit_reversible_command ();
1187 Editor::select_all_selectables_between (bool within)
1191 list<Selectable *> touched;
1193 if (!get_edit_op_range (start, end)) {
1199 if (selection->tracks.empty()) {
1202 ts = &selection->tracks;
1205 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1206 if ((*iter)->hidden()) {
1209 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1212 selection->set (touched);
1216 Editor::select_range_between ()
1221 if (!get_edit_op_range (start, end)) {
1225 set_mouse_mode (MouseRange);
1226 selection->set ((TimeAxisView*) 0, start, end);
1230 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1235 /* in range mode, use any existing selection */
1237 if (mouse_mode == MouseRange && !selection->time.empty()) {
1238 /* we know that these are ordered */
1239 start = selection->time.start();
1240 end = selection->time.end_frame();
1244 if (!mouse_frame (m, ignored)) {
1245 /* mouse is not in a canvas, try playhead+selected marker.
1246 this is probably most true when using menus.
1249 if (selection->markers.empty()) {
1253 start = selection->markers.front()->position();
1254 end = session->audible_frame();
1258 switch (_edit_point) {
1259 case EditAtPlayhead:
1260 if (selection->markers.empty()) {
1261 /* use mouse + playhead */
1263 end = session->audible_frame();
1265 /* use playhead + selected marker */
1266 start = session->audible_frame();
1267 end = selection->markers.front()->position();
1272 /* use mouse + selected marker */
1273 if (selection->markers.empty()) {
1275 end = session->audible_frame();
1277 start = selection->markers.front()->position();
1282 case EditAtSelectedMarker:
1283 /* use mouse + selected marker */
1284 if (selection->markers.empty()) {
1286 MessageDialog win (_("No edit range defined"),
1291 win.set_secondary_text (
1292 _("the edit point is Selected Marker\nbut there is no selected marker."));
1295 win.set_default_response (RESPONSE_CLOSE);
1296 win.set_position (Gtk::WIN_POS_MOUSE);
1301 return false; // NO RANGE
1303 start = selection->markers.front()->position();
1321 Editor::deselect_all ()
1323 selection->clear ();
1326 Editor::ExclusiveRegionSelection::ExclusiveRegionSelection (Editor& ed, RegionView* rv)
1331 if (!rv || ed.current_mouse_mode() != Editing::MouseObject) {
1335 if (ed.get_selection().regions.empty() && !ed.get_selection().selected (rv)) {
1336 ed.get_selection().set (rv, false);
1343 Editor::ExclusiveRegionSelection::~ExclusiveRegionSelection ()
1346 editor.get_selection().remove (regionview);