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) {
994 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
995 if ((*iter)->hidden()) {
998 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1001 begin_reversible_command (_("select all from range"));
1002 selection->set (touched);
1003 commit_reversible_command ();
1008 Editor::select_all_selectables_using_punch()
1010 Location* location = session->locations()->auto_punch_location();
1011 list<Selectable *> touched;
1013 if (location == 0 || (location->end() - location->start() <= 1)) {
1017 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1018 if ((*iter)->hidden()) {
1021 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1023 begin_reversible_command (_("select all from punch"));
1024 selection->set (touched);
1025 commit_reversible_command ();
1030 Editor::select_all_selectables_using_loop()
1032 Location* location = session->locations()->auto_loop_location();
1033 list<Selectable *> touched;
1035 if (location == 0 || (location->end() - location->start() <= 1)) {
1039 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1040 if ((*iter)->hidden()) {
1043 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1045 begin_reversible_command (_("select all from loop"));
1046 selection->set (touched);
1047 commit_reversible_command ();
1052 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1056 list<Selectable *> touched;
1059 begin_reversible_command (_("select all after cursor"));
1060 start = cursor->current_frame ;
1061 end = session->current_end_frame();
1063 if (cursor->current_frame > 0) {
1064 begin_reversible_command (_("select all before cursor"));
1066 end = cursor->current_frame - 1;
1072 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1073 if ((*iter)->hidden()) {
1076 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1078 selection->set (touched);
1079 commit_reversible_command ();
1083 Editor::select_all_selectables_using_edit (bool after)
1087 list<Selectable *> touched;
1090 begin_reversible_command (_("select all after edit"));
1091 start = get_preferred_edit_position();
1092 end = session->current_end_frame();
1094 if ((end = get_preferred_edit_position()) > 1) {
1095 begin_reversible_command (_("select all before edit"));
1103 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1104 if ((*iter)->hidden()) {
1107 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1109 selection->set (touched);
1110 commit_reversible_command ();
1114 Editor::select_all_selectables_between (bool within)
1118 list<Selectable *> touched;
1120 if (!get_edit_op_range (start, end)) {
1124 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1125 if ((*iter)->hidden()) {
1128 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1131 selection->set (touched);
1135 Editor::select_range_between ()
1140 if (!get_edit_op_range (start, end)) {
1144 set_mouse_mode (MouseRange);
1145 selection->set ((TimeAxisView*) 0, start, end);
1149 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1154 /* in range mode, use any existing selection */
1156 if (mouse_mode == MouseRange && !selection->time.empty()) {
1157 /* we know that these are ordered */
1158 start = selection->time.start();
1159 end = selection->time.end_frame();
1163 if (!mouse_frame (m, ignored)) {
1164 /* mouse is not in a canvas, try playhead+selected marker.
1165 this is probably most true when using menus.
1168 if (selection->markers.empty()) {
1172 start = selection->markers.front()->position();
1173 end = session->audible_frame();
1177 switch (_edit_point) {
1178 case EditAtPlayhead:
1179 if (selection->markers.empty()) {
1180 /* use mouse + playhead */
1182 end = session->audible_frame();
1184 /* use playhead + selected marker */
1185 start = session->audible_frame();
1186 end = selection->markers.front()->position();
1191 /* use mouse + selected marker */
1192 if (selection->markers.empty()) {
1194 end = session->audible_frame();
1196 start = selection->markers.front()->position();
1201 case EditAtSelectedMarker:
1202 /* use mouse + selected marker */
1203 if (selection->markers.empty()) {
1205 MessageDialog win (_("No edit range defined"),
1210 win.set_secondary_text (
1211 _("the edit point is Selected Marker\nbut there is no selected marker."));
1214 win.set_default_response (RESPONSE_CLOSE);
1215 win.set_position (Gtk::WIN_POS_MOUSE);
1220 return false; // NO RANGE
1222 start = selection->markers.front()->position();
1240 Editor::deselect_all ()
1242 selection->clear ();