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>
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"
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 TrackViewList visible_views
;
164 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
165 if ((*i
)->marked_for_display()) {
166 visible_views
.push_back (*i
);
169 selection
->set (visible_views
);
173 Editor::set_selected_track_as_side_effect (bool force
)
175 if (!clicked_trackview
) {
179 if (!selection
->tracks
.empty()) {
181 if (!selection
->selected (clicked_trackview
)) {
182 selection
->add (clicked_trackview
);
186 selection
->set (clicked_trackview
);
191 Editor::set_selected_track (TimeAxisView
& view
, Selection::Operation op
, bool no_remove
)
194 case Selection::Toggle
:
195 if (selection
->selected (&view
)) {
197 selection
->remove (&view
);
200 selection
->add (&view
);
205 if (!selection
->selected (&view
)) {
206 selection
->add (&view
);
211 selection
->set (&view
);
214 case Selection::Extend
:
215 extend_selection_to_track (view
);
221 Editor::set_selected_track_from_click (bool press
, Selection::Operation op
, bool no_remove
)
223 if (!clicked_trackview
) {
231 set_selected_track (*clicked_trackview
, op
, no_remove
);
235 Editor::set_selected_control_point_from_click (Selection::Operation op
, bool no_remove
)
237 if (!clicked_control_point
) {
241 /* select this point and any others that it represents */
246 x1
= pixel_to_frame (clicked_control_point
->get_x() - 10);
247 x2
= pixel_to_frame (clicked_control_point
->get_x() + 10);
248 y1
= clicked_control_point
->get_x() - 10;
249 y2
= clicked_control_point
->get_y() + 10;
251 return select_all_within (x1
, x2
, y1
, y2
, selection
->tracks
, op
);
255 Editor::get_onscreen_tracks (TrackViewList
& tvl
)
257 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
258 if ((*i
)->y_position
< canvas_height
) {
265 Editor::get_relevant_audio_tracks (set
<AudioTimeAxisView
*>& relevant_tracks
)
267 /* step one: get all selected tracks and all tracks in the relevant edit groups */
269 for (TrackSelection::iterator ti
= selection
->tracks
.begin(); ti
!= selection
->tracks
.end(); ++ti
) {
271 AudioTimeAxisView
* atv
= dynamic_cast<AudioTimeAxisView
*>(*ti
);
277 RouteGroup
* group
= atv
->route()->edit_group();
279 if (group
&& group
->is_active()) {
281 /* active group for this track, loop over all tracks and get every member of the group */
283 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
285 AudioTimeAxisView
* tatv
;
287 if ((tatv
= dynamic_cast<AudioTimeAxisView
*> (*i
)) != 0) {
289 if (tatv
->route()->edit_group() == group
) {
290 relevant_tracks
.insert (tatv
);
295 relevant_tracks
.insert (atv
);
302 * Call a slot for a given `basis' track and also for any track that is in the same
304 * @param sl Slot to call.
305 * @param basis Basis track.
309 Editor::mapover_audio_tracks (slot
<void,AudioTimeAxisView
&,uint32_t> sl
, TimeAxisView
* basis
)
311 AudioTimeAxisView
* audio_basis
= dynamic_cast<AudioTimeAxisView
*> (basis
);
312 if (audio_basis
== 0) {
316 /* work out the tracks that we will call the slot for; use
317 a set here as it will disallow possible duplicates of the
319 set
<AudioTimeAxisView
*> tracks
;
321 /* always call for the basis */
322 tracks
.insert (audio_basis
);
324 RouteGroup
* group
= audio_basis
->route()->edit_group();
325 if (group
&& group
->is_active()) {
327 /* the basis is a member of an active edit group; find other members */
328 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
329 AudioTimeAxisView
* v
= dynamic_cast<AudioTimeAxisView
*> (*i
);
330 if (v
&& v
->route()->edit_group() == group
) {
337 uint32_t const sz
= tracks
.size ();
338 for (set
<AudioTimeAxisView
*>::iterator i
= tracks
.begin(); i
!= tracks
.end(); ++i
) {
344 Editor::mapped_get_equivalent_regions (RouteTimeAxisView
& tv
, uint32_t ignored
, RegionView
* basis
, vector
<RegionView
*>* all_equivs
)
346 boost::shared_ptr
<Playlist
> pl
;
347 vector
<boost::shared_ptr
<Region
> > results
;
349 boost::shared_ptr
<Diskstream
> ds
;
351 if ((ds
= tv
.get_diskstream()) == 0) {
356 if (&tv
== &basis
->get_time_axis_view()) {
357 /* looking in same track as the original */
361 if ((pl
= ds
->playlist()) != 0) {
362 pl
->get_equivalent_regions (basis
->region(), results
);
365 for (vector
<boost::shared_ptr
<Region
> >::iterator ir
= results
.begin(); ir
!= results
.end(); ++ir
) {
366 if ((marv
= tv
.view()->find_view (*ir
)) != 0) {
367 all_equivs
->push_back (marv
);
373 Editor::get_equivalent_regions (RegionView
* basis
, vector
<RegionView
*>& equivalent_regions
)
375 mapover_audio_tracks (bind (mem_fun (*this, &Editor::mapped_get_equivalent_regions
), basis
, &equivalent_regions
), &basis
->get_trackview());
377 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
379 equivalent_regions
.push_back (basis
);
383 Editor::set_selected_regionview_from_click (bool press
, Selection::Operation op
, bool no_track_remove
)
385 vector
<RegionView
*> all_equivalent_regions
;
388 if (!clicked_regionview
|| !clicked_audio_trackview
) {
393 button_release_can_deselect
= false;
396 if (op
== Selection::Toggle
|| op
== Selection::Set
) {
400 case Selection::Toggle
:
402 if (selection
->selected (clicked_regionview
)) {
405 /* whatever was clicked was selected already; do nothing here but allow
406 the button release to deselect it
409 button_release_can_deselect
= true;
413 if (button_release_can_deselect
) {
415 /* just remove this one region, but only on a permitted button release */
417 selection
->remove (clicked_regionview
);
420 /* no more deselect action on button release till a new press
421 finds an already selected object.
424 button_release_can_deselect
= false;
432 if (selection
->selected (clicked_audio_trackview
)) {
433 get_equivalent_regions (clicked_regionview
, all_equivalent_regions
);
435 all_equivalent_regions
.push_back (clicked_regionview
);
438 /* add all the equivalent regions, but only on button press */
442 if (!all_equivalent_regions
.empty()) {
446 selection
->add (all_equivalent_regions
);
452 if (!selection
->selected (clicked_regionview
)) {
454 get_equivalent_regions (clicked_regionview
, all_equivalent_regions
);
455 selection
->set (all_equivalent_regions
);
458 /* no commit necessary: clicked on an already selected region */
468 } else if (op
== Selection::Extend
) {
470 list
<Selectable
*> results
;
471 nframes64_t last_frame
;
472 nframes64_t first_frame
;
473 bool same_track
= false;
475 /* 1. find the last selected regionview in the track that was clicked in */
478 first_frame
= max_frames
;
480 for (RegionSelection::iterator x
= selection
->regions
.begin(); x
!= selection
->regions
.end(); ++x
) {
481 if (&(*x
)->get_time_axis_view() == &clicked_regionview
->get_time_axis_view()) {
483 if ((*x
)->region()->last_frame() > last_frame
) {
484 last_frame
= (*x
)->region()->last_frame();
487 if ((*x
)->region()->first_frame() < first_frame
) {
488 first_frame
= (*x
)->region()->first_frame();
497 /* 2. figure out the boundaries for our search for new objects */
499 switch (clicked_regionview
->region()->coverage (first_frame
, last_frame
)) {
501 if (last_frame
< clicked_regionview
->region()->first_frame()) {
502 first_frame
= last_frame
;
503 last_frame
= clicked_regionview
->region()->last_frame();
505 last_frame
= first_frame
;
506 first_frame
= clicked_regionview
->region()->first_frame();
510 case OverlapExternal
:
511 if (last_frame
< clicked_regionview
->region()->first_frame()) {
512 first_frame
= last_frame
;
513 last_frame
= clicked_regionview
->region()->last_frame();
515 last_frame
= first_frame
;
516 first_frame
= clicked_regionview
->region()->first_frame();
520 case OverlapInternal
:
521 if (last_frame
< clicked_regionview
->region()->first_frame()) {
522 first_frame
= last_frame
;
523 last_frame
= clicked_regionview
->region()->last_frame();
525 last_frame
= first_frame
;
526 first_frame
= clicked_regionview
->region()->first_frame();
532 /* nothing to do except add clicked region to selection, since it
533 overlaps with the existing selection in this track.
540 /* click in a track that has no regions selected, so extend vertically
541 to pick out all regions that are defined by the existing selection
546 first_frame
= entered_regionview
->region()->position();
547 last_frame
= entered_regionview
->region()->last_frame();
549 for (RegionSelection::iterator i
= selection
->regions
.begin(); i
!= selection
->regions
.end(); ++i
) {
550 if ((*i
)->region()->position() < first_frame
) {
551 first_frame
= (*i
)->region()->position();
553 if ((*i
)->region()->last_frame() + 1 > last_frame
) {
554 last_frame
= (*i
)->region()->last_frame();
559 /* 2. find all the tracks we should select in */
561 set
<AudioTimeAxisView
*> relevant_tracks
;
562 set
<AudioTimeAxisView
*> already_in_selection
;
564 get_relevant_audio_tracks (relevant_tracks
);
566 if (relevant_tracks
.empty()) {
568 /* no relevant tracks -> no tracks selected .. thus .. if
569 the regionview we're in isn't selected (i.e. we're
570 about to extend to it), then find all tracks between
571 the this one and any selected ones.
574 if (!selection
->selected (entered_regionview
)) {
576 AudioTimeAxisView
* atv
= dynamic_cast<AudioTimeAxisView
*> (&entered_regionview
->get_time_axis_view());
580 /* add this track to the ones we will search */
582 relevant_tracks
.insert (atv
);
584 /* find the track closest to this one that
585 already a selected region.
588 AudioTimeAxisView
* closest
= 0;
589 int distance
= INT_MAX
;
590 int key
= atv
->route()->order_key ("editor");
592 for (RegionSelection::iterator x
= selection
->regions
.begin(); x
!= selection
->regions
.end(); ++x
) {
594 AudioTimeAxisView
* aatv
= dynamic_cast<AudioTimeAxisView
*>(&(*x
)->get_time_axis_view());
596 if (aatv
&& aatv
!= atv
) {
598 pair
<set
<AudioTimeAxisView
*>::iterator
,bool> result
;
600 result
= already_in_selection
.insert (aatv
);
603 /* newly added to already_in_selection */
606 int d
= aatv
->route()->order_key ("editor");
610 if (abs (d
) < distance
) {
620 /* now add all tracks between that one and this one */
622 int okey
= closest
->route()->order_key ("editor");
628 for (TrackViewList::iterator x
= track_views
.begin(); x
!= track_views
.end(); ++x
) {
629 AudioTimeAxisView
* aatv
= dynamic_cast<AudioTimeAxisView
*>(*x
);
630 if (aatv
&& aatv
!= atv
) {
632 int k
= aatv
->route()->order_key ("editor");
634 if (k
>= okey
&& k
<= key
) {
636 /* in range but don't add it if
637 it already has tracks selected.
638 this avoids odd selection
639 behaviour that feels wrong.
642 if (find (already_in_selection
.begin(),
643 already_in_selection
.end(),
644 aatv
) == already_in_selection
.end()) {
646 relevant_tracks
.insert (aatv
);
656 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
657 one that was clicked.
660 for (set
<AudioTimeAxisView
*>::iterator t
= relevant_tracks
.begin(); t
!= relevant_tracks
.end(); ++t
) {
661 (*t
)->get_selectables (first_frame
, last_frame
, -1.0, -1.0, results
);
664 /* 4. convert to a vector of audio regions */
666 vector
<RegionView
*> regions
;
668 for (list
<Selectable
*>::iterator x
= results
.begin(); x
!= results
.end(); ++x
) {
671 if ((arv
= dynamic_cast<RegionView
*>(*x
)) != 0) {
672 regions
.push_back (arv
);
676 if (!regions
.empty()) {
677 selection
->add (regions
);
688 Editor::set_selected_regionview_from_region_list (boost::shared_ptr
<Region
> region
, Selection::Operation op
)
690 vector
<RegionView
*> all_equivalent_regions
;
692 get_regions_corresponding_to (region
, all_equivalent_regions
);
694 if (all_equivalent_regions
.empty()) {
699 case Selection::Toggle
:
700 /* XXX this is not correct */
701 selection
->toggle (all_equivalent_regions
);
704 selection
->set (all_equivalent_regions
);
706 case Selection::Extend
:
707 selection
->add (all_equivalent_regions
);
710 selection
->add (all_equivalent_regions
);
716 Editor::set_selected_regionview_from_map_event (GdkEventAny
* ev
, StreamView
* sv
, boost::weak_ptr
<Region
> weak_r
)
719 boost::shared_ptr
<Region
> r (weak_r
.lock());
725 boost::shared_ptr
<AudioRegion
> ar
;
727 if ((ar
= boost::dynamic_pointer_cast
<AudioRegion
> (r
)) == 0) {
731 if ((rv
= sv
->find_view (ar
)) == 0) {
735 /* don't reset the selection if its something other than
736 a single other region.
739 if (selection
->regions
.size() > 1) {
743 begin_reversible_command (_("set selected regions"));
747 commit_reversible_command () ;
753 Editor::track_selection_changed ()
755 switch (selection
->tracks
.size()){
759 set_selected_mixer_strip (*(selection
->tracks
.front()));
763 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
764 if (find (selection
->tracks
.begin(), selection
->tracks
.end(), *i
) != selection
->tracks
.end()) {
765 (*i
)->set_selected (true);
767 (*i
)->set_selected (false);
771 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions
, !selection
->tracks
.empty());
775 Editor::time_selection_changed ()
777 if (Profile
->get_sae()) {
781 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
782 (*i
)->hide_selection ();
785 if (selection
->tracks
.empty()) {
786 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
787 (*i
)->show_selection (selection
->time
);
790 for (TrackSelection::iterator i
= selection
->tracks
.begin(); i
!= selection
->tracks
.end(); ++i
) {
791 (*i
)->show_selection (selection
->time
);
795 if (selection
->time
.empty()) {
796 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions
, false);
798 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions
, true);
804 Editor::sensitize_the_right_region_actions (bool have_selected_regions
)
806 for (vector
<Glib::RefPtr
<Action
> >::iterator x
= ActionManager::region_selection_sensitive_actions
.begin();
807 x
!= ActionManager::region_selection_sensitive_actions
.end(); ++x
) {
809 string accel_path
= (*x
)->get_accel_path ();
812 /* if there is an accelerator, it should always be sensitive
813 to allow for keyboard ops on entered regions.
816 bool known
= ActionManager::lookup_entry (accel_path
, key
);
818 if (known
&& ((key
.get_key() != GDK_VoidSymbol
) && (key
.get_key() != 0))) {
819 (*x
)->set_sensitive (true);
821 (*x
)->set_sensitive (have_selected_regions
);
828 Editor::region_selection_changed ()
830 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
831 (*i
)->set_selected_regionviews (selection
->regions
);
834 sensitize_the_right_region_actions (!selection
->regions
.empty());
838 Editor::point_selection_changed ()
840 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
841 (*i
)->set_selected_points (selection
->points
);
846 Editor::select_all_in_track (Selection::Operation op
)
848 list
<Selectable
*> touched
;
850 if (!clicked_trackview
) {
854 clicked_trackview
->get_selectables (0, max_frames
, 0, DBL_MAX
, touched
);
857 case Selection::Toggle
:
858 selection
->add (touched
);
861 selection
->set (touched
);
863 case Selection::Extend
:
864 /* meaningless, because we're selecting everything */
867 selection
->add (touched
);
873 Editor::select_all (Selection::Operation op
)
875 list
<Selectable
*> touched
;
877 for (TrackViewList::iterator iter
= track_views
.begin(); iter
!= track_views
.end(); ++iter
) {
878 if ((*iter
)->hidden()) {
881 (*iter
)->get_selectables (0, max_frames
, 0, DBL_MAX
, touched
);
883 begin_reversible_command (_("select all"));
886 selection
->add (touched
);
888 case Selection::Toggle
:
889 selection
->add (touched
);
892 selection
->set (touched
);
894 case Selection::Extend
:
895 /* meaningless, because we're selecting everything */
898 commit_reversible_command ();
902 Editor::invert_selection_in_track ()
904 list
<Selectable
*> touched
;
906 if (!clicked_trackview
) {
910 clicked_trackview
->get_inverted_selectables (*selection
, touched
);
911 selection
->set (touched
);
915 Editor::invert_selection ()
917 list
<Selectable
*> touched
;
919 for (TrackViewList::iterator iter
= track_views
.begin(); iter
!= track_views
.end(); ++iter
) {
920 if ((*iter
)->hidden()) {
923 (*iter
)->get_inverted_selectables (*selection
, touched
);
926 selection
->set (touched
);
930 Editor::select_all_within (nframes64_t start
, nframes64_t end
, double top
, double bot
, const TrackViewList
& tracklist
, Selection::Operation op
)
932 list
<Selectable
*> touched
;
933 list
<Selectable
*>::size_type n
= 0;
934 TrackViewList touched_tracks
;
936 for (TrackViewList::const_iterator iter
= tracklist
.begin(); iter
!= tracklist
.end(); ++iter
) {
937 if ((*iter
)->hidden()) {
943 (*iter
)->get_selectables (start
, end
, top
, bot
, touched
);
945 if (n
!= touched
.size()) {
946 touched_tracks
.push_back (*iter
);
950 if (touched
.empty()) {
954 if (!touched_tracks
.empty()) {
958 selection
->add (touched_tracks
);
960 case Selection::Toggle
:
961 selection
->toggle (touched_tracks
);
964 selection
->set (touched_tracks
);
966 case Selection::Extend
:
967 /* not defined yet */
972 begin_reversible_command (_("select all within"));
975 selection
->add (touched
);
977 case Selection::Toggle
:
978 selection
->toggle (touched
);
981 selection
->set (touched
);
983 case Selection::Extend
:
984 /* not defined yet */
988 commit_reversible_command ();
990 return !touched
.empty();
994 Editor::set_selection_from_audio_region ()
996 if (selection
->regions
.empty()) {
1000 selection
->set (0, selection
->regions
.start(), selection
->regions
.end_frame());
1001 if (!Profile
->get_sae()) {
1002 set_mouse_mode (Editing::MouseRange
, false);
1007 Editor::set_selection_from_punch()
1011 if ((location
= session
->locations()->auto_punch_location()) == 0) {
1015 set_selection_from_range (*location
);
1019 Editor::set_selection_from_loop()
1023 if ((location
= session
->locations()->auto_loop_location()) == 0) {
1026 set_selection_from_range (*location
);
1030 Editor::set_selection_from_range (Location
& loc
)
1032 begin_reversible_command (_("set selection from range"));
1033 selection
->set (0, loc
.start(), loc
.end());
1034 commit_reversible_command ();
1036 if (!Profile
->get_sae()) {
1037 set_mouse_mode (Editing::MouseRange
, false);
1042 Editor::select_all_selectables_using_time_selection ()
1044 list
<Selectable
*> touched
;
1046 if (selection
->time
.empty()) {
1050 nframes64_t start
= selection
->time
[clicked_selection
].start
;
1051 nframes64_t end
= selection
->time
[clicked_selection
].end
;
1053 if (end
- start
< 1) {
1059 if (selection
->tracks
.empty()) {
1062 ts
= &selection
->tracks
;
1065 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1066 if ((*iter
)->hidden()) {
1069 (*iter
)->get_selectables (start
, end
- 1, 0, DBL_MAX
, touched
);
1072 begin_reversible_command (_("select all from range"));
1073 selection
->set (touched
);
1074 commit_reversible_command ();
1079 Editor::select_all_selectables_using_punch()
1081 Location
* location
= session
->locations()->auto_punch_location();
1082 list
<Selectable
*> touched
;
1084 if (location
== 0 || (location
->end() - location
->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 (location
->start(), location
->end() - 1, 0, DBL_MAX
, touched
);
1103 begin_reversible_command (_("select all from punch"));
1104 selection
->set (touched
);
1105 commit_reversible_command ();
1110 Editor::select_all_selectables_using_loop()
1112 Location
* location
= session
->locations()->auto_loop_location();
1113 list
<Selectable
*> touched
;
1115 if (location
== 0 || (location
->end() - location
->start() <= 1)) {
1122 if (selection
->tracks
.empty()) {
1125 ts
= &selection
->tracks
;
1128 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1129 if ((*iter
)->hidden()) {
1132 (*iter
)->get_selectables (location
->start(), location
->end() - 1, 0, DBL_MAX
, touched
);
1134 begin_reversible_command (_("select all from loop"));
1135 selection
->set (touched
);
1136 commit_reversible_command ();
1141 Editor::select_all_selectables_using_cursor (Cursor
*cursor
, bool after
)
1145 list
<Selectable
*> touched
;
1148 begin_reversible_command (_("select all after cursor"));
1149 start
= cursor
->current_frame
;
1150 end
= session
->current_end_frame();
1152 if (cursor
->current_frame
> 0) {
1153 begin_reversible_command (_("select all before cursor"));
1155 end
= cursor
->current_frame
- 1;
1164 if (selection
->tracks
.empty()) {
1167 ts
= &selection
->tracks
;
1170 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1171 if ((*iter
)->hidden()) {
1174 (*iter
)->get_selectables (start
, end
, 0, DBL_MAX
, touched
);
1176 selection
->set (touched
);
1177 commit_reversible_command ();
1181 Editor::select_all_selectables_using_edit (bool after
)
1185 list
<Selectable
*> touched
;
1188 begin_reversible_command (_("select all after edit"));
1189 start
= get_preferred_edit_position();
1190 end
= session
->current_end_frame();
1192 if ((end
= get_preferred_edit_position()) > 1) {
1193 begin_reversible_command (_("select all before edit"));
1204 if (selection
->tracks
.empty()) {
1207 ts
= &selection
->tracks
;
1210 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1211 if ((*iter
)->hidden()) {
1214 (*iter
)->get_selectables (start
, end
, 0, DBL_MAX
, touched
);
1216 selection
->set (touched
);
1217 commit_reversible_command ();
1221 Editor::select_all_selectables_between (bool within
)
1225 list
<Selectable
*> touched
;
1227 if (!get_edit_op_range (start
, end
)) {
1233 if (selection
->tracks
.empty()) {
1236 ts
= &selection
->tracks
;
1239 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1240 if ((*iter
)->hidden()) {
1243 (*iter
)->get_selectables (start
, end
, 0, DBL_MAX
, touched
);
1246 selection
->set (touched
);
1250 Editor::select_range_between ()
1255 if (!get_edit_op_range (start
, end
)) {
1259 set_mouse_mode (MouseRange
);
1260 selection
->set ((TimeAxisView
*) 0, start
, end
);
1264 Editor::get_edit_op_range (nframes64_t
& start
, nframes64_t
& end
) const
1269 /* in range mode, use any existing selection */
1271 if (mouse_mode
== MouseRange
&& !selection
->time
.empty()) {
1272 /* we know that these are ordered */
1273 start
= selection
->time
.start();
1274 end
= selection
->time
.end_frame();
1278 if (!mouse_frame (m
, ignored
)) {
1279 /* mouse is not in a canvas, try playhead+selected marker.
1280 this is probably most true when using menus.
1283 if (selection
->markers
.empty()) {
1287 start
= selection
->markers
.front()->position();
1288 end
= session
->audible_frame();
1292 switch (_edit_point
) {
1293 case EditAtPlayhead
:
1294 if (selection
->markers
.empty()) {
1295 /* use mouse + playhead */
1297 end
= session
->audible_frame();
1299 /* use playhead + selected marker */
1300 start
= session
->audible_frame();
1301 end
= selection
->markers
.front()->position();
1306 /* use mouse + selected marker */
1307 if (selection
->markers
.empty()) {
1309 end
= session
->audible_frame();
1311 start
= selection
->markers
.front()->position();
1316 case EditAtSelectedMarker
:
1317 /* use mouse + selected marker */
1318 if (selection
->markers
.empty()) {
1320 MessageDialog
win (_("No edit range defined"),
1325 win
.set_secondary_text (
1326 _("the edit point is Selected Marker\nbut there is no selected marker."));
1329 win
.set_default_response (RESPONSE_CLOSE
);
1330 win
.set_position (Gtk::WIN_POS_MOUSE
);
1335 return false; // NO RANGE
1337 start
= selection
->markers
.front()->position();
1351 /* turn range into one delimited by start...end,
1361 Editor::deselect_all ()
1363 selection
->clear ();