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());
836 zoomed_to_region
= false;
840 Editor::point_selection_changed ()
842 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
843 (*i
)->set_selected_points (selection
->points
);
848 Editor::select_all_in_track (Selection::Operation op
)
850 list
<Selectable
*> touched
;
852 if (!clicked_trackview
) {
856 clicked_trackview
->get_selectables (0, max_frames
, 0, DBL_MAX
, touched
);
859 case Selection::Toggle
:
860 selection
->add (touched
);
863 selection
->set (touched
);
865 case Selection::Extend
:
866 /* meaningless, because we're selecting everything */
869 selection
->add (touched
);
875 Editor::select_all (Selection::Operation op
)
877 list
<Selectable
*> touched
;
879 for (TrackViewList::iterator iter
= track_views
.begin(); iter
!= track_views
.end(); ++iter
) {
880 if ((*iter
)->hidden()) {
883 (*iter
)->get_selectables (0, max_frames
, 0, DBL_MAX
, touched
);
885 begin_reversible_command (_("select all"));
888 selection
->add (touched
);
890 case Selection::Toggle
:
891 selection
->add (touched
);
894 selection
->set (touched
);
896 case Selection::Extend
:
897 /* meaningless, because we're selecting everything */
900 commit_reversible_command ();
904 Editor::invert_selection_in_track ()
906 list
<Selectable
*> touched
;
908 if (!clicked_trackview
) {
912 clicked_trackview
->get_inverted_selectables (*selection
, touched
);
913 selection
->set (touched
);
917 Editor::invert_selection ()
919 list
<Selectable
*> touched
;
921 for (TrackViewList::iterator iter
= track_views
.begin(); iter
!= track_views
.end(); ++iter
) {
922 if ((*iter
)->hidden()) {
925 (*iter
)->get_inverted_selectables (*selection
, touched
);
928 selection
->set (touched
);
932 Editor::select_all_within (nframes64_t start
, nframes64_t end
, double top
, double bot
, const TrackViewList
& tracklist
, Selection::Operation op
)
934 list
<Selectable
*> touched
;
935 list
<Selectable
*>::size_type n
= 0;
936 TrackViewList touched_tracks
;
938 for (TrackViewList::const_iterator iter
= tracklist
.begin(); iter
!= tracklist
.end(); ++iter
) {
939 if ((*iter
)->hidden()) {
945 (*iter
)->get_selectables (start
, end
, top
, bot
, touched
);
947 if (n
!= touched
.size()) {
948 touched_tracks
.push_back (*iter
);
952 if (touched
.empty()) {
956 if (!touched_tracks
.empty()) {
960 selection
->add (touched_tracks
);
962 case Selection::Toggle
:
963 selection
->toggle (touched_tracks
);
966 selection
->set (touched_tracks
);
968 case Selection::Extend
:
969 /* not defined yet */
974 begin_reversible_command (_("select all within"));
977 selection
->add (touched
);
979 case Selection::Toggle
:
980 selection
->toggle (touched
);
983 selection
->set (touched
);
985 case Selection::Extend
:
986 /* not defined yet */
990 commit_reversible_command ();
992 return !touched
.empty();
996 Editor::set_selection_from_audio_region ()
998 if (selection
->regions
.empty()) {
1002 selection
->set (0, selection
->regions
.start(), selection
->regions
.end_frame());
1003 if (!Profile
->get_sae()) {
1004 set_mouse_mode (Editing::MouseRange
, false);
1009 Editor::set_selection_from_punch()
1013 if ((location
= session
->locations()->auto_punch_location()) == 0) {
1017 set_selection_from_range (*location
);
1021 Editor::set_selection_from_loop()
1025 if ((location
= session
->locations()->auto_loop_location()) == 0) {
1028 set_selection_from_range (*location
);
1032 Editor::set_selection_from_range (Location
& loc
)
1034 begin_reversible_command (_("set selection from range"));
1035 selection
->set (0, loc
.start(), loc
.end());
1036 commit_reversible_command ();
1038 if (!Profile
->get_sae()) {
1039 set_mouse_mode (Editing::MouseRange
, false);
1044 Editor::select_all_selectables_using_time_selection ()
1046 list
<Selectable
*> touched
;
1048 if (selection
->time
.empty()) {
1052 nframes64_t start
= selection
->time
[clicked_selection
].start
;
1053 nframes64_t end
= selection
->time
[clicked_selection
].end
;
1055 if (end
- start
< 1) {
1061 if (selection
->tracks
.empty()) {
1064 ts
= &selection
->tracks
;
1067 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1068 if ((*iter
)->hidden()) {
1071 (*iter
)->get_selectables (start
, end
- 1, 0, DBL_MAX
, touched
);
1074 begin_reversible_command (_("select all from range"));
1075 selection
->set (touched
);
1076 commit_reversible_command ();
1081 Editor::select_all_selectables_using_punch()
1083 Location
* location
= session
->locations()->auto_punch_location();
1084 list
<Selectable
*> touched
;
1086 if (location
== 0 || (location
->end() - location
->start() <= 1)) {
1093 if (selection
->tracks
.empty()) {
1096 ts
= &selection
->tracks
;
1099 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1100 if ((*iter
)->hidden()) {
1103 (*iter
)->get_selectables (location
->start(), location
->end() - 1, 0, DBL_MAX
, touched
);
1105 begin_reversible_command (_("select all from punch"));
1106 selection
->set (touched
);
1107 commit_reversible_command ();
1112 Editor::select_all_selectables_using_loop()
1114 Location
* location
= session
->locations()->auto_loop_location();
1115 list
<Selectable
*> touched
;
1117 if (location
== 0 || (location
->end() - location
->start() <= 1)) {
1124 if (selection
->tracks
.empty()) {
1127 ts
= &selection
->tracks
;
1130 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1131 if ((*iter
)->hidden()) {
1134 (*iter
)->get_selectables (location
->start(), location
->end() - 1, 0, DBL_MAX
, touched
);
1136 begin_reversible_command (_("select all from loop"));
1137 selection
->set (touched
);
1138 commit_reversible_command ();
1143 Editor::select_all_selectables_using_cursor (Cursor
*cursor
, bool after
)
1147 list
<Selectable
*> touched
;
1150 begin_reversible_command (_("select all after cursor"));
1151 start
= cursor
->current_frame
;
1152 end
= session
->current_end_frame();
1154 if (cursor
->current_frame
> 0) {
1155 begin_reversible_command (_("select all before cursor"));
1157 end
= cursor
->current_frame
- 1;
1166 if (selection
->tracks
.empty()) {
1169 ts
= &selection
->tracks
;
1172 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1173 if ((*iter
)->hidden()) {
1176 (*iter
)->get_selectables (start
, end
, 0, DBL_MAX
, touched
);
1178 selection
->set (touched
);
1179 commit_reversible_command ();
1183 Editor::select_all_selectables_using_edit (bool after
)
1187 list
<Selectable
*> touched
;
1190 begin_reversible_command (_("select all after edit"));
1191 start
= get_preferred_edit_position();
1192 end
= session
->current_end_frame();
1194 if ((end
= get_preferred_edit_position()) > 1) {
1195 begin_reversible_command (_("select all before edit"));
1206 if (selection
->tracks
.empty()) {
1209 ts
= &selection
->tracks
;
1212 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1213 if ((*iter
)->hidden()) {
1216 (*iter
)->get_selectables (start
, end
, 0, DBL_MAX
, touched
);
1218 selection
->set (touched
);
1219 commit_reversible_command ();
1223 Editor::select_all_selectables_between (bool within
)
1227 list
<Selectable
*> touched
;
1229 if (!get_edit_op_range (start
, end
)) {
1235 if (selection
->tracks
.empty()) {
1238 ts
= &selection
->tracks
;
1241 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1242 if ((*iter
)->hidden()) {
1245 (*iter
)->get_selectables (start
, end
, 0, DBL_MAX
, touched
);
1248 selection
->set (touched
);
1252 Editor::select_range_between ()
1257 if (!get_edit_op_range (start
, end
)) {
1261 set_mouse_mode (MouseRange
);
1262 selection
->set ((TimeAxisView
*) 0, start
, end
);
1266 Editor::get_edit_op_range (nframes64_t
& start
, nframes64_t
& end
) const
1271 /* in range mode, use any existing selection */
1273 if (mouse_mode
== MouseRange
&& !selection
->time
.empty()) {
1274 /* we know that these are ordered */
1275 start
= selection
->time
.start();
1276 end
= selection
->time
.end_frame();
1280 if (!mouse_frame (m
, ignored
)) {
1281 /* mouse is not in a canvas, try playhead+selected marker.
1282 this is probably most true when using menus.
1285 if (selection
->markers
.empty()) {
1289 start
= selection
->markers
.front()->position();
1290 end
= session
->audible_frame();
1294 switch (_edit_point
) {
1295 case EditAtPlayhead
:
1296 if (selection
->markers
.empty()) {
1297 /* use mouse + playhead */
1299 end
= session
->audible_frame();
1301 /* use playhead + selected marker */
1302 start
= session
->audible_frame();
1303 end
= selection
->markers
.front()->position();
1308 /* use mouse + selected marker */
1309 if (selection
->markers
.empty()) {
1311 end
= session
->audible_frame();
1313 start
= selection
->markers
.front()->position();
1318 case EditAtSelectedMarker
:
1319 /* use mouse + selected marker */
1320 if (selection
->markers
.empty()) {
1322 MessageDialog
win (_("No edit range defined"),
1327 win
.set_secondary_text (
1328 _("the edit point is Selected Marker\nbut there is no selected marker."));
1331 win
.set_default_response (RESPONSE_CLOSE
);
1332 win
.set_position (Gtk::WIN_POS_MOUSE
);
1337 return false; // NO RANGE
1339 start
= selection
->markers
.front()->position();
1353 /* turn range into one delimited by start...end,
1363 Editor::deselect_all ()
1365 selection
->clear ();