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 (bool force)
179 if (!clicked_axisview) {
183 if (!selection->tracks.empty()) {
184 if (!selection->selected (clicked_axisview)) {
185 selection->add (clicked_axisview);
189 selection->set (clicked_axisview);
194 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
197 case Selection::Toggle:
198 if (selection->selected (&view)) {
200 selection->remove (&view);
203 selection->add (&view);
208 if (!selection->selected (&view)) {
209 selection->add (&view);
214 selection->set (&view);
217 case Selection::Extend:
218 extend_selection_to_track (view);
224 Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool no_remove)
226 if (!clicked_routeview) {
234 set_selected_track (*clicked_routeview, op, no_remove);
238 Editor::set_selected_control_point_from_click (Selection::Operation op, bool /*no_remove*/)
240 if (!clicked_control_point) {
244 if (clicked_control_point->selected()) {
245 /* the clicked control point is already selected; others may be as well, so
246 don't change the selection.
251 /* We know the ControlPoint that was clicked, but (as discussed in automation_selectable.h)
252 * selected automation data are described by areas on the AutomationLine. A ControlPoint
253 * represents any model points in the space that it takes up, so the AutomationSelectable
254 * needs to be the size of the ControlPoint.
257 double const size = clicked_control_point->size ();
258 AutomationLine& line = clicked_control_point->line ();
260 nframes64_t const x1 = pixel_to_frame (clicked_control_point->get_x() - size / 2) + line.time_converter().origin_b ();
261 nframes64_t const x2 = pixel_to_frame (clicked_control_point->get_x() + size / 2) + line.time_converter().origin_b ();
262 double y1 = clicked_control_point->get_y() - size / 2;
263 double y2 = clicked_control_point->get_y() + size / 2;
265 /* convert the y values to trackview space */
267 clicked_control_point->line().parent_group().i2w (dummy, y1);
268 clicked_control_point->line().parent_group().i2w (dummy, y2);
269 _trackview_group->w2i (dummy, y1);
270 _trackview_group->w2i (dummy, y2);
272 /* and set up the selection */
273 return select_all_within (x1, x2, y1, y2, selection->tracks, op);
277 Editor::get_onscreen_tracks (TrackViewList& tvl)
279 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
280 if ((*i)->y_position() < _canvas_height) {
286 /** Call a slot for a given `basis' track and also for any track that is in the same
287 * active route group with a particular set of properties.
289 * @param sl Slot to call.
290 * @param basis Basis track.
291 * @param prop Properties that active edit groups must share to be included in the map.
295 Editor::mapover_tracks (sigc::slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis, PBD::PropertyID prop) const
297 RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
299 if (route_basis == 0) {
303 set<RouteTimeAxisView*> tracks;
304 tracks.insert (route_basis);
306 RouteGroup* group = route_basis->route()->route_group();
308 if (group && group->enabled_property(prop) && group->enabled_property (Properties::active.property_id) ) {
310 /* the basis is a member of an active route group, with the appropriate
311 properties; find other members */
313 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
314 RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
315 if (v && v->route()->route_group() == group) {
322 uint32_t const sz = tracks.size ();
324 for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
330 Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t, RegionView * basis, vector<RegionView*>* all_equivs) const
332 boost::shared_ptr<Playlist> pl;
333 vector<boost::shared_ptr<Region> > results;
335 boost::shared_ptr<Track> tr;
337 if ((tr = tv.track()) == 0) {
342 if (&tv == &basis->get_time_axis_view()) {
343 /* looking in same track as the original */
347 if ((pl = tr->playlist()) != 0) {
348 pl->get_equivalent_regions (basis->region(), results);
351 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
352 if ((marv = tv.view()->find_view (*ir)) != 0) {
353 all_equivs->push_back (marv);
359 Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions, PBD::PropertyID property) const
361 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_trackview(), property);
363 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
365 equivalent_regions.push_back (basis);
369 Editor::get_equivalent_regions (RegionSelection & basis, PBD::PropertyID prop) const
371 RegionSelection equivalent;
373 for (RegionSelection::const_iterator i = basis.begin(); i != basis.end(); ++i) {
375 vector<RegionView*> eq;
378 sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), *i, &eq),
379 &(*i)->get_trackview(), prop
382 for (vector<RegionView*>::iterator j = eq.begin(); j != eq.end(); ++j) {
394 Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
396 int region_count = 0;
398 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
400 RouteTimeAxisView* tatv;
402 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
404 boost::shared_ptr<Playlist> pl;
405 vector<boost::shared_ptr<Region> > results;
407 boost::shared_ptr<Track> tr;
409 if ((tr = tatv->track()) == 0) {
414 if ((pl = (tr->playlist())) != 0) {
415 pl->get_region_list_equivalent_regions (region, results);
418 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
419 if ((marv = tatv->view()->find_view (*ir)) != 0) {
432 Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool /*no_track_remove*/)
434 vector<RegionView*> all_equivalent_regions;
437 if (!clicked_regionview || !clicked_routeview) {
442 button_release_can_deselect = false;
445 if (op == Selection::Toggle || op == Selection::Set) {
449 case Selection::Toggle:
451 if (selection->selected (clicked_regionview)) {
454 /* whatever was clicked was selected already; do nothing here but allow
455 the button release to deselect it
458 button_release_can_deselect = true;
462 if (button_release_can_deselect) {
464 /* just remove this one region, but only on a permitted button release */
466 selection->remove (clicked_regionview);
469 /* no more deselect action on button release till a new press
470 finds an already selected object.
473 button_release_can_deselect = false;
481 if (selection->selected (clicked_routeview)) {
482 get_equivalent_regions (clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
484 all_equivalent_regions.push_back (clicked_regionview);
487 /* add all the equivalent regions, but only on button press */
489 if (!all_equivalent_regions.empty()) {
493 selection->add (all_equivalent_regions);
499 if (!selection->selected (clicked_regionview)) {
500 get_equivalent_regions (clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
501 selection->set (all_equivalent_regions);
504 /* no commit necessary: clicked on an already selected region */
514 } else if (op == Selection::Extend) {
516 list<Selectable*> results;
517 nframes64_t last_frame;
518 nframes64_t first_frame;
519 bool same_track = false;
521 /* 1. find the last selected regionview in the track that was clicked in */
524 first_frame = max_frames;
526 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
527 if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
529 if ((*x)->region()->last_frame() > last_frame) {
530 last_frame = (*x)->region()->last_frame();
533 if ((*x)->region()->first_frame() < first_frame) {
534 first_frame = (*x)->region()->first_frame();
543 /* 2. figure out the boundaries for our search for new objects */
545 switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
547 if (last_frame < clicked_regionview->region()->first_frame()) {
548 first_frame = last_frame;
549 last_frame = clicked_regionview->region()->last_frame();
551 last_frame = first_frame;
552 first_frame = clicked_regionview->region()->first_frame();
556 case OverlapExternal:
557 if (last_frame < clicked_regionview->region()->first_frame()) {
558 first_frame = last_frame;
559 last_frame = clicked_regionview->region()->last_frame();
561 last_frame = first_frame;
562 first_frame = clicked_regionview->region()->first_frame();
566 case OverlapInternal:
567 if (last_frame < clicked_regionview->region()->first_frame()) {
568 first_frame = last_frame;
569 last_frame = clicked_regionview->region()->last_frame();
571 last_frame = first_frame;
572 first_frame = clicked_regionview->region()->first_frame();
578 /* nothing to do except add clicked region to selection, since it
579 overlaps with the existing selection in this track.
586 /* click in a track that has no regions selected, so extend vertically
587 to pick out all regions that are defined by the existing selection
592 first_frame = entered_regionview->region()->position();
593 last_frame = entered_regionview->region()->last_frame();
595 for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
596 if ((*i)->region()->position() < first_frame) {
597 first_frame = (*i)->region()->position();
599 if ((*i)->region()->last_frame() + 1 > last_frame) {
600 last_frame = (*i)->region()->last_frame();
605 /* 2. find all the tracks we should select in */
607 set<RouteTimeAxisView*> relevant_tracks;
609 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
610 RouteTimeAxisView* r = dynamic_cast<RouteTimeAxisView*> (*i);
612 relevant_tracks.insert (r);
616 set<RouteTimeAxisView*> already_in_selection;
618 if (relevant_tracks.empty()) {
620 /* no tracks selected .. thus .. if the
621 regionview we're in isn't selected
622 (i.e. we're about to extend to it), then
623 find all tracks between the this one and
627 if (!selection->selected (entered_regionview)) {
629 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&entered_regionview->get_time_axis_view());
633 /* add this track to the ones we will search */
635 relevant_tracks.insert (rtv);
637 /* find the track closest to this one that
638 already a selected region.
641 RouteTimeAxisView* closest = 0;
642 int distance = INT_MAX;
643 int key = rtv->route()->order_key ("editor");
645 for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
647 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(&(*x)->get_time_axis_view());
649 if (artv && artv != rtv) {
651 pair<set<RouteTimeAxisView*>::iterator,bool> result;
653 result = already_in_selection.insert (artv);
656 /* newly added to already_in_selection */
658 int d = artv->route()->order_key ("editor");
662 if (abs (d) < distance) {
672 /* now add all tracks between that one and this one */
674 int okey = closest->route()->order_key ("editor");
680 for (TrackViewList::iterator x = track_views.begin(); x != track_views.end(); ++x) {
681 RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
682 if (artv && artv != rtv) {
684 int k = artv->route()->order_key ("editor");
686 if (k >= okey && k <= key) {
688 /* in range but don't add it if
689 it already has tracks selected.
690 this avoids odd selection
691 behaviour that feels wrong.
694 if (find (already_in_selection.begin(),
695 already_in_selection.end(),
696 artv) == already_in_selection.end()) {
698 relevant_tracks.insert (artv);
708 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
709 one that was clicked.
712 for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
713 (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
716 /* 4. convert to a vector of regions */
718 vector<RegionView*> regions;
720 for (list<Selectable*>::iterator x = results.begin(); x != results.end(); ++x) {
723 if ((arv = dynamic_cast<RegionView*>(*x)) != 0) {
724 regions.push_back (arv);
728 if (!regions.empty()) {
729 selection->add (regions);
740 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
742 vector<RegionView*> all_equivalent_regions;
744 get_regions_corresponding_to (region, all_equivalent_regions);
746 if (all_equivalent_regions.empty()) {
750 begin_reversible_command (_("set selected regions"));
753 case Selection::Toggle:
754 /* XXX this is not correct */
755 selection->toggle (all_equivalent_regions);
758 selection->set (all_equivalent_regions);
760 case Selection::Extend:
761 selection->add (all_equivalent_regions);
764 selection->add (all_equivalent_regions);
768 commit_reversible_command () ;
772 Editor::set_selected_regionview_from_map_event (GdkEventAny* /*ev*/, StreamView* sv, boost::weak_ptr<Region> weak_r)
775 boost::shared_ptr<Region> r (weak_r.lock());
781 if ((rv = sv->find_view (r)) == 0) {
785 /* don't reset the selection if its something other than
786 a single other region.
789 if (selection->regions.size() > 1) {
793 begin_reversible_command (_("set selected regions"));
797 commit_reversible_command () ;
803 Editor::track_selection_changed ()
805 switch (selection->tracks.size()){
809 set_selected_mixer_strip (*(selection->tracks.front()));
813 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
814 if (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end()) {
815 (*i)->set_selected (true);
817 (*i)->set_selected (false);
821 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
825 Editor::time_selection_changed ()
827 if (Profile->get_sae()) {
831 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
832 (*i)->hide_selection ();
835 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
836 (*i)->show_selection (selection->time);
839 if (selection->time.empty()) {
840 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, false);
842 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
847 Editor::sensitize_the_right_region_actions (bool have_selected_regions)
849 for (vector<Glib::RefPtr<Action> >::iterator x = ActionManager::region_selection_sensitive_actions.begin();
850 x != ActionManager::region_selection_sensitive_actions.end(); ++x) {
852 string accel_path = (*x)->get_accel_path ();
855 /* if there is an accelerator, it should always be sensitive
856 to allow for keyboard ops on entered regions.
859 bool known = ActionManager::lookup_entry (accel_path, key);
861 if (known && ((key.get_key() != GDK_VoidSymbol) && (key.get_key() != 0))) {
862 (*x)->set_sensitive (true);
864 (*x)->set_sensitive (have_selected_regions);
871 Editor::region_selection_changed ()
873 _regions->block_change_connection (true);
874 editor_regions_selection_changed_connection.block(true);
876 _regions->unselect_all ();
878 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
879 (*i)->set_selected_regionviews (selection->regions);
882 _regions->set_selected (selection->regions);
884 sensitize_the_right_region_actions (!selection->regions.empty());
886 _regions->block_change_connection (false);
887 editor_regions_selection_changed_connection.block(false);
891 Editor::point_selection_changed ()
893 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
894 (*i)->set_selected_points (selection->points);
899 Editor::select_all_in_track (Selection::Operation op)
901 list<Selectable *> touched;
903 if (!clicked_routeview) {
907 clicked_routeview->get_selectables (0, max_frames, 0, DBL_MAX, touched);
910 case Selection::Toggle:
911 selection->add (touched);
914 selection->set (touched);
916 case Selection::Extend:
917 /* meaningless, because we're selecting everything */
920 selection->add (touched);
926 Editor::select_all (Selection::Operation op)
928 list<Selectable *> touched;
930 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
931 if ((*iter)->hidden()) {
934 (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched);
936 begin_reversible_command (_("select all"));
939 selection->add (touched);
941 case Selection::Toggle:
942 selection->add (touched);
945 selection->set (touched);
947 case Selection::Extend:
948 /* meaningless, because we're selecting everything */
951 commit_reversible_command ();
954 Editor::invert_selection_in_track ()
956 list<Selectable *> touched;
958 if (!clicked_routeview) {
962 clicked_routeview->get_inverted_selectables (*selection, touched);
963 selection->set (touched);
967 Editor::invert_selection ()
969 list<Selectable *> touched;
971 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
972 if ((*iter)->hidden()) {
975 (*iter)->get_inverted_selectables (*selection, touched);
978 selection->set (touched);
981 /** @param start Start time in session frames.
982 * @param end End time in session frames.
983 * @param top Top (lower) y limit in trackview coordinates (ie 0 at the top of the track view)
984 * @param bottom Bottom (higher) y limit in trackview coordinates (ie 0 at the top of the track view)
987 Editor::select_all_within (framepos_t start, framepos_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op)
989 list<Selectable*> found;
991 for (TrackViewList::const_iterator iter = tracklist.begin(); iter != tracklist.end(); ++iter) {
993 if ((*iter)->hidden()) {
997 (*iter)->get_selectables (start, end, top, bot, found);
1000 if (found.empty()) {
1004 begin_reversible_command (_("select all within"));
1006 case Selection::Add:
1007 selection->add (found);
1009 case Selection::Toggle:
1010 selection->toggle (found);
1012 case Selection::Set:
1013 selection->set (found);
1015 case Selection::Extend:
1016 /* not defined yet */
1020 commit_reversible_command ();
1022 return !found.empty();
1026 Editor::set_selection_from_region ()
1028 if (selection->regions.empty()) {
1032 selection->set (selection->regions.start(), selection->regions.end_frame());
1033 if (!Profile->get_sae()) {
1034 set_mouse_mode (Editing::MouseRange, false);
1039 Editor::set_selection_from_punch()
1043 if ((location = _session->locations()->auto_punch_location()) == 0) {
1047 set_selection_from_range (*location);
1051 Editor::set_selection_from_loop()
1055 if ((location = _session->locations()->auto_loop_location()) == 0) {
1058 set_selection_from_range (*location);
1062 Editor::set_selection_from_range (Location& loc)
1064 begin_reversible_command (_("set selection from range"));
1065 selection->set (loc.start(), loc.end());
1066 commit_reversible_command ();
1068 if (!Profile->get_sae()) {
1069 set_mouse_mode (Editing::MouseRange, false);
1074 Editor::select_all_selectables_using_time_selection ()
1076 list<Selectable *> touched;
1078 if (selection->time.empty()) {
1082 nframes64_t start = selection->time[clicked_selection].start;
1083 nframes64_t end = selection->time[clicked_selection].end;
1085 if (end - start < 1) {
1091 if (selection->tracks.empty()) {
1094 ts = &selection->tracks;
1097 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1098 if ((*iter)->hidden()) {
1101 (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
1104 begin_reversible_command (_("select all from range"));
1105 selection->set (touched);
1106 commit_reversible_command ();
1111 Editor::select_all_selectables_using_punch()
1113 Location* location = _session->locations()->auto_punch_location();
1114 list<Selectable *> touched;
1116 if (location == 0 || (location->end() - location->start() <= 1)) {
1123 if (selection->tracks.empty()) {
1126 ts = &selection->tracks;
1129 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1130 if ((*iter)->hidden()) {
1133 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1135 begin_reversible_command (_("select all from punch"));
1136 selection->set (touched);
1137 commit_reversible_command ();
1142 Editor::select_all_selectables_using_loop()
1144 Location* location = _session->locations()->auto_loop_location();
1145 list<Selectable *> touched;
1147 if (location == 0 || (location->end() - location->start() <= 1)) {
1154 if (selection->tracks.empty()) {
1157 ts = &selection->tracks;
1160 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1161 if ((*iter)->hidden()) {
1164 (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
1166 begin_reversible_command (_("select all from loop"));
1167 selection->set (touched);
1168 commit_reversible_command ();
1173 Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
1177 list<Selectable *> touched;
1180 begin_reversible_command (_("select all after cursor"));
1181 start = cursor->current_frame ;
1182 end = _session->current_end_frame();
1184 if (cursor->current_frame > 0) {
1185 begin_reversible_command (_("select all before cursor"));
1187 end = cursor->current_frame - 1;
1196 if (selection->tracks.empty()) {
1199 ts = &selection->tracks;
1202 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1203 if ((*iter)->hidden()) {
1206 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1208 selection->set (touched);
1209 commit_reversible_command ();
1213 Editor::select_all_selectables_using_edit (bool after)
1217 list<Selectable *> touched;
1220 begin_reversible_command (_("select all after edit"));
1221 start = get_preferred_edit_position();
1222 end = _session->current_end_frame();
1224 if ((end = get_preferred_edit_position()) > 1) {
1225 begin_reversible_command (_("select all before edit"));
1236 if (selection->tracks.empty()) {
1239 ts = &selection->tracks;
1242 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1243 if ((*iter)->hidden()) {
1246 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1248 selection->set (touched);
1249 commit_reversible_command ();
1253 Editor::select_all_selectables_between (bool /*within*/)
1257 list<Selectable *> touched;
1259 if (!get_edit_op_range (start, end)) {
1265 if (selection->tracks.empty()) {
1268 ts = &selection->tracks;
1271 for (TrackViewList::iterator iter = ts->begin(); iter != ts->end(); ++iter) {
1272 if ((*iter)->hidden()) {
1275 (*iter)->get_selectables (start, end, 0, DBL_MAX, touched);
1278 selection->set (touched);
1282 Editor::select_range_between ()
1287 if (!get_edit_op_range (start, end)) {
1291 set_mouse_mode (MouseRange);
1292 selection->set (start, end);
1296 Editor::get_edit_op_range (nframes64_t& start, nframes64_t& end) const
1301 /* in range mode, use any existing selection */
1303 if (mouse_mode == MouseRange && !selection->time.empty()) {
1304 /* we know that these are ordered */
1305 start = selection->time.start();
1306 end = selection->time.end_frame();
1310 if (!mouse_frame (m, ignored)) {
1311 /* mouse is not in a canvas, try playhead+selected marker.
1312 this is probably most true when using menus.
1315 if (selection->markers.empty()) {
1319 start = selection->markers.front()->position();
1320 end = _session->audible_frame();
1324 switch (_edit_point) {
1325 case EditAtPlayhead:
1326 if (selection->markers.empty()) {
1327 /* use mouse + playhead */
1329 end = _session->audible_frame();
1331 /* use playhead + selected marker */
1332 start = _session->audible_frame();
1333 end = selection->markers.front()->position();
1338 /* use mouse + selected marker */
1339 if (selection->markers.empty()) {
1341 end = _session->audible_frame();
1343 start = selection->markers.front()->position();
1348 case EditAtSelectedMarker:
1349 /* use mouse + selected marker */
1350 if (selection->markers.empty()) {
1352 MessageDialog win (_("No edit range defined"),
1357 win.set_secondary_text (
1358 _("the edit point is Selected Marker\nbut there is no selected marker."));
1361 win.set_default_response (RESPONSE_CLOSE);
1362 win.set_position (Gtk::WIN_POS_MOUSE);
1367 return false; // NO RANGE
1369 start = selection->markers.front()->position();
1383 /* turn range into one delimited by start...end,
1393 Editor::deselect_all ()
1395 selection->clear ();
1399 Editor::select_range_around_region (RegionView* rv)
1403 selection->set (&rv->get_time_axis_view());
1405 selection->time.clear ();
1406 boost::shared_ptr<Region> r = rv->region ();
1407 return selection->set (r->position(), r->position() + r->length());