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/session.h"
26 #include "ardour/playlist.h"
27 #include "ardour/route_group.h"
28 #include "ardour/profile.h"
32 #include "audio_time_axis.h"
33 #include "audio_region_view.h"
34 #include "audio_streamview.h"
35 #include "automation_line.h"
36 #include "control_point.h"
37 #include "editor_regions.h"
42 using namespace ARDOUR;
46 using namespace Gtkmm2ext;
47 using namespace Editing;
49 struct TrackViewByPositionSorter
51 bool operator() (const TimeAxisView* a, const TimeAxisView *b) {
52 return a->y_position() < b->y_position();
57 Editor::extend_selection_to_track (TimeAxisView& view)
59 if (selection->selected (&view)) {
60 /* already selected, do nothing */
64 if (selection->tracks.empty()) {
66 if (!selection->selected (&view)) {
67 selection->set (&view);
74 /* something is already selected, so figure out which range of things to add */
76 TrackViewList to_be_added;
77 TrackViewList sorted = track_views;
78 TrackViewByPositionSorter cmp;
79 bool passed_clicked = false;
84 if (!selection->selected (&view)) {
85 to_be_added.push_back (&view);
88 /* figure out if we should go forward or backwards */
90 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
93 passed_clicked = true;
96 if (selection->selected (*i)) {
106 passed_clicked = false;
110 for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
113 passed_clicked = true;
117 if (passed_clicked) {
118 if ((*i)->hidden()) {
121 if (selection->selected (*i)) {
123 } else if (!(*i)->hidden()) {
124 to_be_added.push_back (*i);
131 for (TrackViewList::reverse_iterator r = sorted.rbegin(); r != sorted.rend(); ++r) {
134 passed_clicked = true;
138 if (passed_clicked) {
140 if ((*r)->hidden()) {
144 if (selection->selected (*r)) {
146 } else if (!(*r)->hidden()) {
147 to_be_added.push_back (*r);
153 if (!to_be_added.empty()) {
154 selection->add (to_be_added);
162 Editor::select_all_tracks ()
164 TrackViewList visible_views;
165 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
166 if ((*i)->marked_for_display()) {
167 visible_views.push_back (*i);
170 selection->set (visible_views);
173 /** Select clicked_axisview, unless there are no currently selected
174 * tracks, in which case nothing will happen unless `force' is true.
177 Editor::set_selected_track_as_side_effect (Selection::Operation op, bool /*force*/)
179 if (!clicked_axisview) {
184 if (!clicked_routeview) {
188 bool had_tracks = !selection->tracks.empty();
189 RouteGroup* group = clicked_routeview->route()->route_group();
190 RouteGroup& arg (_session->all_route_group());
193 case Selection::Toggle:
194 if (selection->selected (clicked_axisview)) {
195 if (arg.is_select() && arg.is_active()) {
196 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
197 selection->remove(*i);
199 } else if (group && group->is_active()) {
200 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
201 if ((*i)->route_group() == group)
202 selection->remove(*i);
205 selection->remove (clicked_axisview);
208 if (arg.is_select() && arg.is_active()) {
209 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
212 } else if (group && group->is_active()) {
213 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
214 if ( (*i)->route_group() == group)
218 selection->add (clicked_axisview);
224 if (!had_tracks && arg.is_select() && arg.is_active()) {
225 /* nothing was selected already, and all group is active etc. so use
228 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
231 } else if (group && group->is_active()) {
232 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
233 if ((*i)->route_group() == group)
237 selection->add (clicked_axisview);
243 if (!had_tracks && arg.is_select() && arg.is_active()) {
244 /* nothing was selected already, and all group is active etc. so use
247 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
250 } else if (group && group->is_active()) {
251 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
252 if ((*i)->route_group() == group)
256 selection->set (clicked_axisview);
260 case Selection::Extend:
262 cerr << ("Editor::set_selected_track_as_side_effect case Selection::Add not yet implemented\n");
266 #else // the older version
268 if (!selection->tracks.empty()) {
269 if (!selection->selected (clicked_axisview)) {
270 selection->add (clicked_axisview);
274 selection->set (clicked_axisview);
280 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
283 case Selection::Toggle:
284 if (selection->selected (&view)) {
286 selection->remove (&view);
289 selection->add (&view);
294 if (!selection->selected (&view)) {
295 selection->add (&view);
300 selection->set (&view);
303 case Selection::Extend:
304 extend_selection_to_track (view);
310 Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool no_remove)
312 if (!clicked_routeview) {
320 set_selected_track (*clicked_routeview, op, no_remove);
324 Editor::set_selected_control_point_from_click (Selection::Operation op, bool /*no_remove*/)
326 if (!clicked_control_point) {
332 selection->set (clicked_control_point);
335 selection->add (clicked_control_point);
337 case Selection::Toggle:
338 selection->toggle (clicked_control_point);
340 case Selection::Extend:
349 Editor::get_onscreen_tracks (TrackViewList& tvl)
351 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
352 if ((*i)->y_position() < _canvas_height) {
358 /** Call a slot for a given `basis' track and also for any track that is in the same
359 * active route group with a particular set of properties.
361 * @param sl Slot to call.
362 * @param basis Basis track.
363 * @param prop Properties that active edit groups must share to be included in the map.
367 Editor::mapover_tracks (sigc::slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis, PBD::PropertyID prop) const
369 RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
371 if (route_basis == 0) {
375 set<RouteTimeAxisView*> tracks;
376 tracks.insert (route_basis);
378 RouteGroup* group = route_basis->route()->route_group();
380 if (group && group->enabled_property(prop) && group->enabled_property (Properties::active.property_id) ) {
382 /* the basis is a member of an active route group, with the appropriate
383 properties; find other members */
385 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
386 RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
387 if (v && v->route()->route_group() == group) {
394 uint32_t const sz = tracks.size ();
396 for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
402 Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t, RegionView * basis, vector<RegionView*>* all_equivs) const
404 boost::shared_ptr<Playlist> pl;
405 vector<boost::shared_ptr<Region> > results;
407 boost::shared_ptr<Track> tr;
409 if ((tr = tv.track()) == 0) {
414 if (&tv == &basis->get_time_axis_view()) {
415 /* looking in same track as the original */
419 if ((pl = tr->playlist()) != 0) {
420 pl->get_equivalent_regions (basis->region(), results);
423 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
424 if ((marv = tv.view()->find_view (*ir)) != 0) {
425 all_equivs->push_back (marv);
431 Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions, PBD::PropertyID property) const
433 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_time_axis_view(), property);
435 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
437 equivalent_regions.push_back (basis);
441 Editor::get_equivalent_regions (RegionSelection & basis, PBD::PropertyID prop) const
443 RegionSelection equivalent;
445 for (RegionSelection::const_iterator i = basis.begin(); i != basis.end(); ++i) {
447 vector<RegionView*> eq;
450 sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), *i, &eq),
451 &(*i)->get_time_axis_view(), prop
454 for (vector<RegionView*>::iterator j = eq.begin(); j != eq.end(); ++j) {
466 Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
468 int region_count = 0;
470 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
472 RouteTimeAxisView* tatv;
474 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
476 boost::shared_ptr<Playlist> pl;
477 vector<boost::shared_ptr<Region> > results;
479 boost::shared_ptr<Track> tr;
481 if ((tr = tatv->track()) == 0) {
486 if ((pl = (tr->playlist())) != 0) {
487 pl->get_region_list_equivalent_regions (region, results);
490 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
491 if ((marv = tatv->view()->find_view (*ir)) != 0) {
504 Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool /*no_track_remove*/)
506 vector<RegionView*> all_equivalent_regions;
509 if (!clicked_regionview || !clicked_routeview) {
514 button_release_can_deselect = false;
517 if (op == Selection::Toggle || op == Selection::Set) {
521 case Selection::Toggle:
523 if (selection->selected (clicked_regionview)) {
526 /* whatever was clicked was selected already; do nothing here but allow
527 the button release to deselect it
530 button_release_can_deselect = true;
534 if (button_release_can_deselect) {
536 /* just remove this one region, but only on a permitted button release */
538 selection->remove (clicked_regionview);
541 /* no more deselect action on button release till a new press
542 finds an already selected object.
545 button_release_can_deselect = false;
553 if (selection->selected (clicked_routeview)) {
554 get_equivalent_regions (clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
556 all_equivalent_regions.push_back (clicked_regionview);
559 /* add all the equivalent regions, but only on button press */
561 if (!all_equivalent_regions.empty()) {
565 selection->add (all_equivalent_regions);
571 if (!selection->selected (clicked_regionview)) {
572 get_equivalent_regions (clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
573 selection->set (all_equivalent_regions);
576 /* no commit necessary: clicked on an already selected region */
586 } else if (op == Selection::Extend) {
588 list<Selectable*> results;
589 framepos_t last_frame;
590 framepos_t first_frame;
591 bool same_track = false;
593 /* 1. find the last selected regionview in the track that was clicked in */
596 first_frame = max_framepos;
598 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
599 if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
601 if ((*x)->region()->last_frame() > last_frame) {
602 last_frame = (*x)->region()->last_frame();
605 if ((*x)->region()->first_frame() < first_frame) {
606 first_frame = (*x)->region()->first_frame();
615 /* 2. figure out the boundaries for our search for new objects */
617 switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
619 if (last_frame < clicked_regionview->region()->first_frame()) {
620 first_frame = last_frame;
621 last_frame = clicked_regionview->region()->last_frame();
623 last_frame = first_frame;
624 first_frame = clicked_regionview->region()->first_frame();
628 case OverlapExternal:
629 if (last_frame < clicked_regionview->region()->first_frame()) {
630 first_frame = last_frame;
631 last_frame = clicked_regionview->region()->last_frame();
633 last_frame = first_frame;
634 first_frame = clicked_regionview->region()->first_frame();
638 case OverlapInternal:
639 if (last_frame < clicked_regionview->region()->first_frame()) {
640 first_frame = last_frame;
641 last_frame = clicked_regionview->region()->last_frame();
643 last_frame = first_frame;
644 first_frame = clicked_regionview->region()->first_frame();
650 /* nothing to do except add clicked region to selection, since it
651 overlaps with the existing selection in this track.
658 /* click in a track that has no regions selected, so extend vertically
659 to pick out all regions that are defined by the existing selection
664 first_frame = entered_regionview->region()->position();
665 last_frame = entered_regionview->region()->last_frame();
667 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
668 if ((*i)->region()->position() < first_frame) {
669 first_frame = (*i)->region()->position();
671 if ((*i)->region()->last_frame() + 1 > last_frame) {
672 last_frame = (*i)->region()->last_frame();
677 /* 2. find all the tracks we should select in */
679 set<RouteTimeAxisView*> relevant_tracks;
681 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
682 RouteTimeAxisView* r = dynamic_cast<RouteTimeAxisView*> (*i);
684 relevant_tracks.insert (r);
688 set<RouteTimeAxisView*> already_in_selection;
690 if (relevant_tracks.empty()) {
692 /* no tracks selected .. thus .. if the
693 regionview we're in isn't selected
694 (i.e. we're about to extend to it), then
695 find all tracks between the this one and
699 if (!selection->selected (entered_regionview)) {
701 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&entered_regionview->get_time_axis_view());
705 /* add this track to the ones we will search */
707 relevant_tracks.insert (rtv);
709 /* find the track closest to this one that
710 already a selected region.
713 RouteTimeAxisView* closest = 0;
714 int distance = INT_MAX;
715 int key = rtv->route()->order_key ("editor");
717 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
719 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(&(*x)->get_time_axis_view());
721 if (artv && artv != rtv) {
723 pair<set<RouteTimeAxisView*>::iterator,bool> result;
725 result = already_in_selection.insert (artv);
728 /* newly added to already_in_selection */
730 int d = artv->route()->order_key ("editor");
734 if (abs (d) < distance) {
744 /* now add all tracks between that one and this one */
746 int okey = closest->route()->order_key ("editor");
752 for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
753 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
754 if (artv && artv != rtv) {
756 int k = artv->route()->order_key ("editor");
758 if (k >= okey && k <= key) {
760 /* in range but don't add it if
761 it already has tracks selected.
762 this avoids odd selection
763 behaviour that feels wrong.
766 if (find (already_in_selection.begin(),
767 already_in_selection.end(),
768 artv) == already_in_selection.end()) {
770 relevant_tracks.insert (artv);
780 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
781 one that was clicked.
784 for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
785 (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
788 /* 4. convert to a vector of regions */
790 vector<RegionView*> regions;
792 for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
795 if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
796 regions.push_back (arv);
800 if (!regions.empty()) {
801 selection->add (regions);
812 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
814 vector<RegionView*> all_equivalent_regions;
816 get_regions_corresponding_to (region, all_equivalent_regions);
818 if (all_equivalent_regions.empty()) {
822 begin_reversible_command (_("set selected regions"));
825 case Selection::Toggle:
826 /* XXX this is not correct */
827 selection->toggle (all_equivalent_regions);
830 selection->set (all_equivalent_regions);
832 case Selection::Extend:
833 selection->add (all_equivalent_regions);
836 selection->add (all_equivalent_regions);
840 commit_reversible_command () ;
844 Editor::set_selected_regionview_from_map_event (GdkEventAny* /*ev*/, StreamView* sv, boost::weak_ptr<Region> weak_r)
847 boost::shared_ptr<Region> r (weak_r.lock());
853 if ((rv = sv->find_view (r)) == 0) {
857 /* don't reset the selection if its something other than
858 a single other region.
861 if (selection->regions.size() > 1) {
865 begin_reversible_command (_("set selected regions"));
869 commit_reversible_command () ;
875 Editor::track_selection_changed ()
877 switch (selection->tracks.size()) {
881 set_selected_mixer_strip (*(selection->tracks.front()));
885 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
887 bool yn = (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end());
889 (*i)->set_selected (yn);
891 TimeAxisView::Children c = (*i)->get_child_list ();
892 for (TimeAxisView::Children::iterator j = c.begin(); j != c.end(); ++j) {
893 (*j)->set_selected (find (selection->tracks.begin(), selection->tracks.end(), j->get()) != selection->tracks.end());
897 ((mouse_mode == MouseRange) ||
898 ((mouse_mode == MouseObject) && (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT)))) {
899 (*i)->reshow_selection (selection->time);
901 (*i)->hide_selection ();
905 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
909 Editor::time_selection_changed ()
911 if (Profile->get_sae()) {
915 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
916 (*i)->hide_selection ();
919 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
920 (*i)->show_selection (selection->time);
923 if (selection->time.empty()) {
924 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
926 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
931 Editor::sensitize_the_right_region_actions (bool have_selected_regions)
933 for (vector<Glib::RefPtr<Action> >::iterator x = ActionManager::region_selection_sensitive_actions.begin();
934 x != ActionManager::region_selection_sensitive_actions.end(); ++x) {
936 string accel_path = (*x)->get_accel_path ();
939 /* if there is an accelerator, it should always be sensitive
940 to allow for keyboard ops on entered regions.
943 bool known = ActionManager::lookup_entry (accel_path, key);
945 if (known && ((key.get_key() != GDK_VoidSymbol) && (key.get_key() != 0))) {
946 (*x)->set_sensitive (true);
948 (*x)->set_sensitive (have_selected_regions);
955 Editor::region_selection_changed ()
957 _regions->block_change_connection (true);
958 editor_regions_selection_changed_connection.block(true);
960 _regions->unselect_all ();
962 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
963 (*i)->set_selected_regionviews (selection->regions);
966 _regions->set_selected (selection->regions);
968 sensitize_the_right_region_actions (!selection->regions.empty());
970 _regions->block_change_connection (false);
971 editor_regions_selection_changed_connection.block(false);
975 Editor::point_selection_changed ()
977 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
978 (*i)->set_selected_points (selection->points);
983 Editor::select_all_in_track (Selection::Operation op)
985 list<Selectable *> touched;
987 if (!clicked_routeview) {
991 clicked_routeview->get_selectables (0, max_framepos, 0, DBL_MAX, touched);
994 case Selection::Toggle:
995 selection->add (touched);
998 selection->set (touched);
1000 case Selection::Extend:
1001 /* meaningless, because we're selecting everything */
1003 case Selection::Add:
1004 selection->add (touched);
1010 Editor::select_all (Selection::Operation op)
1012 list<Selectable *> touched;
1014 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1015 if ((*iter)->hidden()) {
1018 (*iter)->get_selectables (0, max_framepos, 0, DBL_MAX, touched);
1020 begin_reversible_command (_("select all"));
1022 case Selection::Add:
1023 selection->add (touched);
1025 case Selection::Toggle:
1026 selection->add (touched);
1028 case Selection::Set:
1029 selection->set (touched);
1031 case Selection::Extend:
1032 /* meaningless, because we're selecting everything */
1035 commit_reversible_command ();
1038 Editor::invert_selection_in_track ()
1040 list<Selectable *> touched;
1042 if (!clicked_routeview) {
1046 clicked_routeview->get_inverted_selectables (*selection, touched);
1047 selection->set (touched);
1051 Editor::invert_selection ()
1053 list<Selectable *> touched;
1055 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
1056 if ((*iter)->hidden()) {
1059 (*iter)->get_inverted_selectables (*selection, touched);
1062 selection->set (touched);
1065 /** @param start Start time in session frames.
1066 * @param end End time in session frames.
1067 * @param top Top (lower) y limit in trackview coordinates (ie 0 at the top of the track view)
1068 * @param bottom Bottom (higher) y limit in trackview coordinates (ie 0 at the top of the track view)
1069 * @param preserve_if_selected true to leave the current selection alone if we're adding to the selection and all of the selectables
1070 * within the region are already selected.
1073 Editor::select_all_within (
1074 framepos_t start, framepos_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op, bool preserve_if_selected
1077 list<Selectable*> found;
1079 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
1081 if ((*iter)->hidden()) {
1085 (*iter)->get_selectables (start, end, top, bot, found);
1088 if (found.empty()) {
1092 if (preserve_if_selected && op != Selection::Toggle) {
1093 list<Selectable*>::iterator i = found.begin();
1094 while (i != found.end() && (*i)->get_selected()) {
1098 if (i == found.end()) {
1103 begin_reversible_command (_("select all within"));
1105 case Selection::Add:
1106 selection->add (found);
1108 case Selection::Toggle:
1109 selection->toggle (found);
1111 case Selection::Set:
1112 selection->set (found);
1114 case Selection::Extend:
1115 /* not defined yet */
1119 commit_reversible_command ();
1121 return !found.empty();
1125 Editor::set_selection_from_region ()
1127 if (selection->regions.empty()) {
1131 selection->set (selection->regions.start(), selection->regions.end_frame());
1132 if (!Profile->get_sae()) {
1133 set_mouse_mode (Editing::MouseRange, false);
1138 Editor::set_selection_from_punch()
1142 if ((location = _session->locations()->auto_punch_location()) == 0) {
1146 set_selection_from_range (*location);
1150 Editor::set_selection_from_loop()
1154 if ((location = _session->locations()->auto_loop_location()) == 0) {
1157 set_selection_from_range (*location);
1161 Editor::set_selection_from_range (Location& loc)
1163 begin_reversible_command (_("set selection from range"));
1164 selection->set (loc.start(), loc.end());
1165 commit_reversible_command ();
1167 if (!Profile->get_sae()) {
1168 set_mouse_mode (Editing::MouseRange, false);
1173 Editor::select_all_selectables_using_time_selection ()
1175 list<Selectable *> touched;
1177 if (selection->time.empty()) {
1181 nframes64_t start = selection->time[clicked_selection].start;
1182 nframes64_t end = selection->time[clicked_selection].end;
1184 if (end - start < 1) {
1190 if (selection->tracks.empty()) {
1193 ts = &selection->tracks;
1196 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1197 if ((*iter)->hidden()) {
1200 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1203 begin_reversible_command (_("select all from range"));
1204 selection->set (touched);
1205 commit_reversible_command ();
1210 Editor::select_all_selectables_using_punch()
1212 Location* location = _session->locations()->auto_punch_location();
1213 list<Selectable *> touched;
1215 if (location == 0 || (location->end() - location->start() <= 1)) {
1222 if (selection->tracks.empty()) {
1225 ts = &selection->tracks;
1228 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1229 if ((*iter)->hidden()) {
1232 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1234 begin_reversible_command (_("select all from punch"));
1235 selection->set (touched);
1236 commit_reversible_command ();
1241 Editor::select_all_selectables_using_loop()
1243 Location* location = _session->locations()->auto_loop_location();
1244 list<Selectable *> touched;
1246 if (location == 0 || (location->end() - location->start() <= 1)) {
1253 if (selection->tracks.empty()) {
1256 ts = &selection->tracks;
1259 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1260 if ((*iter)->hidden()) {
1263 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1265 begin_reversible_command (_("select all from loop"));
1266 selection->set (touched);
1267 commit_reversible_command ();
1272 Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
1276 list<Selectable *> touched;
1279 begin_reversible_command (_("select all after cursor"));
1280 start = cursor->current_frame ;
1281 end = _session->current_end_frame();
1283 if (cursor->current_frame > 0) {
1284 begin_reversible_command (_("select all before cursor"));
1286 end = cursor->current_frame - 1;
1295 if (selection->tracks.empty()) {
1298 ts = &selection->tracks;
1301 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1302 if ((*iter)->hidden()) {
1305 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1307 selection->set (touched);
1308 commit_reversible_command ();
1312 Editor::select_all_selectables_using_edit (bool after)
1316 list<Selectable *> touched;
1319 begin_reversible_command (_("select all after edit"));
1320 start = get_preferred_edit_position();
1321 end = _session->current_end_frame();
1323 if ((end = get_preferred_edit_position()) > 1) {
1324 begin_reversible_command (_("select all before edit"));
1335 if (selection->tracks.empty()) {
1338 ts = &selection->tracks;
1341 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1342 if ((*iter)->hidden()) {
1345 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1347 selection->set (touched);
1348 commit_reversible_command ();
1352 Editor::select_all_selectables_between (bool /*within*/)
1356 list<Selectable *> touched;
1358 if (!get_edit_op_range (start, end)) {
1364 if (selection->tracks.empty()) {
1367 ts = &selection->tracks;
1370 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1371 if ((*iter)->hidden()) {
1374 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1377 selection->set (touched);
1381 Editor::select_range_between ()
1386 if (mouse_mode == MouseRange && !selection->time.empty()) {
1387 selection->clear_time ();
1390 if (!get_edit_op_range (start, end)) {
1394 set_mouse_mode (MouseRange);
1395 selection->set (start, end);
1399 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1404 /* in range mode, use any existing selection */
1406 if (mouse_mode == MouseRange && !selection->time.empty()) {
1407 /* we know that these are ordered */
1408 start = selection->time.start();
1409 end = selection->time.end_frame();
1413 if (!mouse_frame (m, ignored)) {
1414 /* mouse is not in a canvas, try playhead+selected marker.
1415 this is probably most true when using menus.
1418 if (selection->markers.empty()) {
1422 start = selection->markers.front()->position();
1423 end = _session->audible_frame();
1427 switch (_edit_point) {
1428 case EditAtPlayhead:
1429 if (selection->markers.empty()) {
1430 /* use mouse + playhead */
1432 end = _session->audible_frame();
1434 /* use playhead + selected marker */
1435 start = _session->audible_frame();
1436 end = selection->markers.front()->position();
1441 /* use mouse + selected marker */
1442 if (selection->markers.empty()) {
1444 end = _session->audible_frame();
1446 start = selection->markers.front()->position();
1451 case EditAtSelectedMarker:
1452 /* use mouse + selected marker */
1453 if (selection->markers.empty()) {
1455 MessageDialog win (_("No edit range defined"),
1460 win.set_secondary_text (
1461 _("the edit point is Selected Marker\nbut there is no selected marker."));
1464 win.set_default_response (RESPONSE_CLOSE);
1465 win.set_position (Gtk::WIN_POS_MOUSE);
1470 return false; // NO RANGE
1472 start = selection->markers.front()->position();
1486 /* turn range into one delimited by start...end,
1496 Editor::deselect_all ()
1498 selection->clear ();
1502 Editor::select_range_around_region (RegionView* rv)
1506 selection->set (&rv->get_time_axis_view());
1508 selection->time.clear ();
1509 boost::shared_ptr<Region> r = rv->region ();
1510 return selection->set (r->position(), r->position() + r->length());