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"
40 using namespace ARDOUR;
44 using namespace Gtkmm2ext;
45 using namespace Editing;
47 struct TrackViewByPositionSorter
49 bool operator() (const TimeAxisView* a, const TimeAxisView *b) {
50 return a->y_position < b->y_position;
55 Editor::extend_selection_to_track (TimeAxisView& view)
57 if (selection->selected (&view)) {
58 /* already selected, do nothing */
62 if (selection->tracks.empty()) {
64 if (!selection->selected (&view)) {
65 selection->set (&view);
72 /* something is already selected, so figure out which range of things to add */
74 TrackViewList to_be_added;
75 TrackViewList sorted = track_views;
76 TrackViewByPositionSorter cmp;
77 bool passed_clicked = false;
82 if (!selection->selected (&view)) {
83 to_be_added.push_back (&view);
86 /* figure out if we should go forward or backwards */
88 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
91 passed_clicked = true;
94 if (selection->selected (*i)) {
104 passed_clicked = false;
108 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
111 passed_clicked = true;
115 if (passed_clicked) {
116 if ((*i)->hidden()) {
119 if (selection->selected (*i)) {
121 } else if (!(*i)->hidden()) {
122 to_be_added.push_back (*i);
129 for (TrackViewList::reverse_iterator r = sorted.rbegin(); r != sorted.rend(); ++r) {
132 passed_clicked = true;
136 if (passed_clicked) {
138 if ((*r)->hidden()) {
142 if (selection->selected (*r)) {
144 } else if (!(*r)->hidden()) {
145 to_be_added.push_back (*r);
151 if (!to_be_added.empty()) {
152 selection->add (to_be_added);
160 Editor::select_all_tracks ()
162 selection->set (track_views);
166 Editor::set_selected_track_as_side_effect (bool force)
168 if (!clicked_trackview) {
172 if (!selection->tracks.empty()) {
173 if (!selection->selected (clicked_trackview)) {
174 selection->add (clicked_trackview);
178 selection->set (clicked_trackview);
183 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
187 case Selection::Toggle:
188 if (selection->selected (&view)) {
190 selection->remove (&view);
193 selection->add (&view);
198 if (!selection->selected (&view)) {
199 selection->add (&view);
204 if (selection->selected (&view) && selection->tracks.size() > 1) {
206 /* reset track selection if there is only 1 other track
207 selected OR if no_remove is not set (its there to
208 prevent deselecting a multi-track selection
209 when clicking on an already selected track
213 if (selection->tracks.empty()) {
214 selection->set (&view);
215 } else if (selection->tracks.size() == 1 || !no_remove) {
216 selection->set (&view);
221 case Selection::Extend:
222 extend_selection_to_track (view);
228 Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool no_remove)
230 if (!clicked_trackview) {
238 set_selected_track (*clicked_trackview, op, no_remove);
242 Editor::set_selected_control_point_from_click (Selection::Operation op, bool no_remove)
244 if (!clicked_control_point) {
248 /* select this point and any others that it represents */
253 x1 = pixel_to_frame (clicked_control_point->get_x() - 10);
254 x2 = pixel_to_frame (clicked_control_point->get_x() + 10);
255 y1 = clicked_control_point->get_x() - 10;
256 y2 = clicked_control_point->get_y() + 10;
258 return select_all_within (x1, x2, y1, y2, selection->tracks, op);
262 Editor::get_relevant_audio_tracks (set<AudioTimeAxisView*>& relevant_tracks)
264 /* step one: get all selected tracks and all tracks in the relevant edit groups */
266 for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) {
268 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*ti);
274 RouteGroup* group = atv->route()->edit_group();
276 if (group && group->is_active()) {
278 /* active group for this track, loop over all tracks and get every member of the group */
280 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
282 AudioTimeAxisView* tatv;
284 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
286 if (tatv->route()->edit_group() == group) {
287 relevant_tracks.insert (tatv);
292 relevant_tracks.insert (atv);
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_audio_tracks (slot<void,AudioTimeAxisView&,uint32_t> sl, TimeAxisView* basis)
308 AudioTimeAxisView* audio_basis = dynamic_cast<AudioTimeAxisView*> (basis);
309 if (audio_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<AudioTimeAxisView*> tracks;
318 /* always call for the basis */
319 tracks.insert (audio_basis);
321 RouteGroup* group = audio_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::iterator i = track_views.begin(); i != track_views.end(); ++i) {
326 AudioTimeAxisView* v = dynamic_cast<AudioTimeAxisView*> (*i);
327 if (v && v->route()->edit_group() == group) {
334 uint32_t const sz = tracks.size ();
335 for (set<AudioTimeAxisView*>::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)
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)
372 mapover_audio_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_audio_trackview) {
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_audio_trackview)) {
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)) {
451 get_equivalent_regions (clicked_regionview, all_equivalent_regions);
452 selection->set (all_equivalent_regions);
455 /* no commit necessary: clicked on an already selected region */
465 } else if (op == Selection::Extend) {
467 list<Selectable*> results;
468 nframes_t last_frame;
469 nframes_t first_frame;
470 bool same_track = false;
472 /* 1. find the last selected regionview in the track that was clicked in */
475 first_frame = max_frames;
477 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
478 if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
480 if ((*x)->region()->last_frame() > last_frame) {
481 last_frame = (*x)->region()->last_frame();
484 if ((*x)->region()->first_frame() < first_frame) {
485 first_frame = (*x)->region()->first_frame();
494 /* 2. figure out the boundaries for our search for new objects */
496 switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
498 if (last_frame < clicked_regionview->region()->first_frame()) {
499 first_frame = last_frame;
500 last_frame = clicked_regionview->region()->last_frame();
502 last_frame = first_frame;
503 first_frame = clicked_regionview->region()->first_frame();
507 case OverlapExternal:
508 if (last_frame < clicked_regionview->region()->first_frame()) {
509 first_frame = last_frame;
510 last_frame = clicked_regionview->region()->last_frame();
512 last_frame = first_frame;
513 first_frame = clicked_regionview->region()->first_frame();
517 case OverlapInternal:
518 if (last_frame < clicked_regionview->region()->first_frame()) {
519 first_frame = last_frame;
520 last_frame = clicked_regionview->region()->last_frame();
522 last_frame = first_frame;
523 first_frame = clicked_regionview->region()->first_frame();
529 /* nothing to do except add clicked region to selection, since it
530 overlaps with the existing selection in this track.
537 /* click in a track that has no regions selected, so extend vertically
538 to pick out all regions that are defined by the existing selection
543 first_frame = entered_regionview->region()->position();
544 last_frame = entered_regionview->region()->last_frame();
546 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
547 if ((*i)->region()->position() < first_frame) {
548 first_frame = (*i)->region()->position();
550 if ((*i)->region()->last_frame() + 1 > last_frame) {
551 last_frame = (*i)->region()->last_frame();
556 /* 2. find all the tracks we should select in */
558 set<AudioTimeAxisView*> relevant_tracks;
559 set<AudioTimeAxisView*> already_in_selection;
561 get_relevant_audio_tracks (relevant_tracks);
563 if (relevant_tracks.empty()) {
565 /* no relevant tracks -> no tracks selected .. thus .. if
566 the regionview we're in isn't selected (i.e. we're
567 about to extend to it), then find all tracks between
568 the this one and any selected ones.
571 if (!selection->selected (entered_regionview)) {
573 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&entered_regionview->get_time_axis_view());
577 /* add this track to the ones we will search */
579 relevant_tracks.insert (atv);
581 /* find the track closest to this one that
582 already a selected region.
585 AudioTimeAxisView* closest = 0;
586 int distance = INT_MAX;
587 int key = atv->route()->order_key ("editor");
589 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
591 AudioTimeAxisView* aatv = dynamic_cast<AudioTimeAxisView*>(&(*x)->get_time_axis_view());
593 if (aatv && aatv != atv) {
595 pair<set<AudioTimeAxisView*>::iterator,bool> result;
597 result = already_in_selection.insert (aatv);
600 /* newly added to already_in_selection */
603 int d = aatv->route()->order_key ("editor");
607 if (abs (d) < distance) {
617 /* now add all tracks between that one and this one */
619 int okey = closest->route()->order_key ("editor");
625 for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
626 AudioTimeAxisView* aatv = dynamic_cast<AudioTimeAxisView*>(*x);
627 if (aatv && aatv != atv) {
629 int k = aatv->route()->order_key ("editor");
631 if (k >= okey && k <= key) {
633 /* in range but don't add it if
634 it already has tracks selected.
635 this avoids odd selection
636 behaviour that feels wrong.
639 if (find (already_in_selection.begin(),
640 already_in_selection.end(),
641 aatv) == already_in_selection.end()) {
643 relevant_tracks.insert (aatv);
653 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
654 one that was clicked.
657 for (set<AudioTimeAxisView*>::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 audio 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()) {
696 case Selection::Toggle:
697 /* XXX this is not correct */
698 selection->toggle (all_equivalent_regions);
701 selection->set (all_equivalent_regions);
703 case Selection::Extend:
704 selection->add (all_equivalent_regions);
707 selection->add (all_equivalent_regions);
713 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, boost::weak_ptr<Region> weak_r)
716 boost::shared_ptr<Region> r (weak_r.lock());
722 boost::shared_ptr<AudioRegion> ar;
724 if ((ar = boost::dynamic_pointer_cast<AudioRegion> (r)) == 0) {
728 if ((rv = sv->find_view (ar)) == 0) {
732 /* don't reset the selection if its something other than
733 a single other region.
736 if (selection->regions.size() > 1) {
740 begin_reversible_command (_("set selected regions"));
744 commit_reversible_command () ;
750 Editor::track_selection_changed ()
752 switch (selection->tracks.size()){
756 set_selected_mixer_strip (*(selection->tracks.front()));
760 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
761 if (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end()) {
762 (*i)->set_selected (true);
764 (*i)->set_selected (false);
770 Editor::time_selection_changed ()
772 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
773 (*i)->hide_selection ();
776 if (selection->tracks.empty()) {
777 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
778 (*i)->show_selection (selection->time);
781 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
782 (*i)->show_selection (selection->time);
786 if (selection->time.empty()) {
787 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
789 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
795 Editor::region_selection_changed ()
797 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
798 (*i)->set_selected_regionviews (selection->regions);
801 zoomed_to_region = false;
805 Editor::point_selection_changed ()
807 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
808 (*i)->set_selected_points (selection->points);
813 Editor::select_all_in_track (Selection::Operation op)
815 list<Selectable *> touched;
817 if (!clicked_trackview) {
821 clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
824 case Selection::Toggle:
825 selection->add (touched);
828 selection->set (touched);
830 case Selection::Extend:
831 /* meaningless, because we're selecting everything */
834 selection->add (touched);
840 Editor::select_all (Selection::Operation op)
842 list<Selectable *> touched;
844 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
845 if ((*iter)->hidden()) {
848 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
850 begin_reversible_command (_("select all"));
853 selection->add (touched);
855 case Selection::Toggle:
856 selection->add (touched);
859 selection->set (touched);
861 case Selection::Extend:
862 /* meaningless, because we're selecting everything */
865 commit_reversible_command ();
869 Editor::invert_selection_in_track ()
871 list<Selectable *> touched;
873 if (!clicked_trackview) {
877 clicked_trackview->get_inverted_selectables (*selection, touched);
878 selection->set (touched);
882 Editor::invert_selection ()
884 list<Selectable *> touched;
886 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
887 if ((*iter)->hidden()) {
890 (*iter)->get_inverted_selectables (*selection, touched);
893 selection->set (touched);
897 Editor::select_all_within (nframes_t start, nframes_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op)
899 list<Selectable*> touched;
900 list<Selectable*>::size_type n = 0;
901 TrackViewList touched_tracks;
903 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
904 if ((*iter)->hidden()) {
910 (*iter)->get_selectables (start, end, top, bot, touched);
912 if (n != touched.size()) {
913 touched_tracks.push_back (*iter);
917 if (touched.empty()) {
921 if (!touched_tracks.empty()) {
925 selection->add (touched_tracks);
927 case Selection::Toggle:
928 selection->toggle (touched_tracks);
931 selection->set (touched_tracks);
933 case Selection::Extend:
934 /* not defined yet */
939 begin_reversible_command (_("select all within"));
942 selection->add (touched);
944 case Selection::Toggle:
945 selection->toggle (touched);
948 selection->set (touched);
950 case Selection::Extend:
951 /* not defined yet */
955 commit_reversible_command ();
957 return !touched.empty();
961 Editor::set_selection_from_audio_region ()
963 if (selection->regions.empty()) {
967 RegionView* rv = *(selection->regions.begin());
968 boost::shared_ptr<Region> region = rv->region();
970 begin_reversible_command (_("set selection from region"));
971 selection->set (0, region->position(), region->last_frame());
972 commit_reversible_command ();
974 set_mouse_mode (Editing::MouseRange, false);
978 Editor::set_selection_from_punch()
982 if ((location = session->locations()->auto_punch_location()) == 0) {
986 set_selection_from_range (*location);
990 Editor::set_selection_from_loop()
994 if ((location = session->locations()->auto_loop_location()) == 0) {
997 set_selection_from_range (*location);
1001 Editor::set_selection_from_range (Location& loc)
1003 begin_reversible_command (_("set selection from range"));
1004 selection->set (0, loc.start(), loc.end());
1005 commit_reversible_command ();
1007 set_mouse_mode (Editing::MouseRange, false);
1011 Editor::select_all_selectables_using_time_selection ()
1013 list<Selectable *> touched;
1015 if (selection->time.empty()) {
1019 nframes_t start = selection->time[clicked_selection].start;
1020 nframes_t end = selection->time[clicked_selection].end;
1022 if (end - start < 1) {
1026 for (TrackViewList::iterator iter = selection->tracks.begin(); iter != selection->tracks.end(); ++iter) {
1027 if ((*iter)->hidden()) {
1030 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1033 begin_reversible_command (_("select all from range"));
1034 selection->set (touched);
1035 commit_reversible_command ();
1040 Editor::select_all_selectables_using_punch()
1042 Location* location = session->locations()->auto_punch_location();
1043 list<Selectable *> touched;
1045 if (location == 0 || (location->end() - location->start() <= 1)) {
1049 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1050 if ((*iter)->hidden()) {
1053 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1055 begin_reversible_command (_("select all from punch"));
1056 selection->set (touched);
1057 commit_reversible_command ();
1062 Editor::select_all_selectables_using_loop()
1064 Location* location = session->locations()->auto_loop_location();
1065 list<Selectable *> touched;
1067 if (location == 0 || (location->end() - location->start() <= 1)) {
1071 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1072 if ((*iter)->hidden()) {
1075 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1077 begin_reversible_command (_("select all from loop"));
1078 selection->set (touched);
1079 commit_reversible_command ();
1084 Editor::select_all_selectables_using_cursor (Cursor *cursor, bool after)
1088 list<Selectable *> touched;
1091 begin_reversible_command (_("select all after cursor"));
1092 start = cursor->current_frame ;
1093 end = session->current_end_frame();
1095 if (cursor->current_frame > 0) {
1096 begin_reversible_command (_("select all before cursor"));
1098 end = cursor->current_frame - 1;
1104 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1105 if ((*iter)->hidden()) {
1108 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1110 selection->set (touched);
1111 commit_reversible_command ();
1115 Editor::select_all_selectables_using_edit (bool after)
1119 list<Selectable *> touched;
1122 begin_reversible_command (_("select all after edit"));
1123 start = get_preferred_edit_position();
1124 end = session->current_end_frame();
1126 if ((end = get_preferred_edit_position()) > 1) {
1127 begin_reversible_command (_("select all before edit"));
1135 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1136 if ((*iter)->hidden()) {
1139 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1141 selection->set (touched);
1142 commit_reversible_command ();
1146 Editor::select_all_selectables_between (bool within)
1150 list<Selectable *> touched;
1152 if (!get_edit_op_range (start, end)) {
1156 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1157 if ((*iter)->hidden()) {
1160 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1163 selection->set (touched);
1167 Editor::select_range_between ()
1172 if (!get_edit_op_range (start, end)) {
1176 set_mouse_mode (MouseRange);
1177 selection->set ((TimeAxisView*) 0, start, end);
1181 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1186 /* in range mode, use any existing selection */
1188 if (mouse_mode == MouseRange && !selection->time.empty()) {
1189 /* we know that these are ordered */
1190 start = selection->time.start();
1191 end = selection->time.end_frame();
1195 if (!mouse_frame (m, ignored)) {
1196 /* mouse is not in a canvas, try playhead+selected marker.
1197 this is probably most true when using menus.
1200 if (selection->markers.empty()) {
1204 start = selection->markers.front()->position();
1205 end = session->audible_frame();
1209 switch (_edit_point) {
1210 case EditAtPlayhead:
1211 if (selection->markers.empty()) {
1212 /* use mouse + playhead */
1214 end = session->audible_frame();
1216 /* use playhead + selected marker */
1217 start = session->audible_frame();
1218 end = selection->markers.front()->position();
1223 /* use mouse + selected marker */
1224 if (selection->markers.empty()) {
1226 end = session->audible_frame();
1228 start = selection->markers.front()->position();
1233 case EditAtSelectedMarker:
1234 /* use mouse + selected marker */
1235 if (selection->markers.empty()) {
1237 MessageDialog win (_("No edit range defined"),
1242 win.set_secondary_text (
1243 _("the edit point is Selected Marker\nbut there is no selected marker."));
1246 win.set_default_response (RESPONSE_CLOSE);
1247 win.set_position (Gtk::WIN_POS_MOUSE);
1252 return false; // NO RANGE
1254 start = selection->markers.front()->position();
1272 Editor::deselect_all ()
1274 selection->clear ();