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/diskstream.h"
27 #include "ardour/playlist.h"
28 #include "ardour/route_group.h"
29 #include "ardour/profile.h"
33 #include "audio_time_axis.h"
34 #include "audio_region_view.h"
35 #include "audio_streamview.h"
36 #include "automation_line.h"
37 #include "control_point.h"
38 #include "editor_regions.h"
43 using namespace ARDOUR
;
47 using namespace Gtkmm2ext
;
48 using namespace Editing
;
50 struct TrackViewByPositionSorter
52 bool operator() (const TimeAxisView
* a
, const TimeAxisView
*b
) {
53 return a
->y_position() < b
->y_position();
58 Editor::extend_selection_to_track (TimeAxisView
& view
)
60 if (selection
->selected (&view
)) {
61 /* already selected, do nothing */
65 if (selection
->tracks
.empty()) {
67 if (!selection
->selected (&view
)) {
68 selection
->set (&view
);
75 /* something is already selected, so figure out which range of things to add */
77 TrackViewList to_be_added
;
78 TrackViewList sorted
= track_views
;
79 TrackViewByPositionSorter cmp
;
80 bool passed_clicked
= false;
85 if (!selection
->selected (&view
)) {
86 to_be_added
.push_back (&view
);
89 /* figure out if we should go forward or backwards */
91 for (TrackViewList::iterator i
= sorted
.begin(); i
!= sorted
.end(); ++i
) {
94 passed_clicked
= true;
97 if (selection
->selected (*i
)) {
107 passed_clicked
= false;
111 for (TrackViewList::iterator i
= sorted
.begin(); i
!= sorted
.end(); ++i
) {
114 passed_clicked
= true;
118 if (passed_clicked
) {
119 if ((*i
)->hidden()) {
122 if (selection
->selected (*i
)) {
124 } else if (!(*i
)->hidden()) {
125 to_be_added
.push_back (*i
);
132 for (TrackViewList::reverse_iterator r
= sorted
.rbegin(); r
!= sorted
.rend(); ++r
) {
135 passed_clicked
= true;
139 if (passed_clicked
) {
141 if ((*r
)->hidden()) {
145 if (selection
->selected (*r
)) {
147 } else if (!(*r
)->hidden()) {
148 to_be_added
.push_back (*r
);
154 if (!to_be_added
.empty()) {
155 selection
->add (to_be_added
);
163 Editor::select_all_tracks ()
165 TrackViewList visible_views
;
166 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
167 if ((*i
)->marked_for_display()) {
168 visible_views
.push_back (*i
);
171 selection
->set (visible_views
);
174 /** Select clicked_routeview, unless there are no currently selected
175 * tracks, in which case nothing will happen unless `force' is true.
178 Editor::set_selected_track_as_side_effect (bool force
)
180 if (!clicked_routeview
) {
184 if (!selection
->tracks
.empty()) {
185 if (!selection
->selected (clicked_routeview
)) {
186 selection
->add (clicked_routeview
);
190 selection
->set (clicked_routeview
);
195 Editor::set_selected_track (TimeAxisView
& view
, Selection::Operation op
, bool no_remove
)
198 case Selection::Toggle
:
199 if (selection
->selected (&view
)) {
201 selection
->remove (&view
);
204 selection
->add (&view
);
209 if (!selection
->selected (&view
)) {
210 selection
->add (&view
);
215 selection
->set (&view
);
218 case Selection::Extend
:
219 extend_selection_to_track (view
);
225 Editor::set_selected_track_from_click (bool press
, Selection::Operation op
, bool no_remove
)
227 if (!clicked_routeview
) {
235 set_selected_track (*clicked_routeview
, op
, no_remove
);
239 Editor::set_selected_control_point_from_click (Selection::Operation op
, bool /*no_remove*/)
241 if (!clicked_control_point
) {
245 if (clicked_control_point
->selected()) {
246 /* the clicked control point is already selected; others may be as well, so
247 don't change the selection.
252 /* We know the ControlPoint that was clicked, but (as discussed in automation_selectable.h)
253 * selected automation data are described by areas on the AutomationLine. A ControlPoint
254 * represents any model points in the space that it takes up, so the AutomationSelectable
255 * needs to be the size of the ControlPoint.
258 double const size
= clicked_control_point
->size ();
260 nframes64_t
const x1
= pixel_to_frame (clicked_control_point
->get_x() - size
/ 2);
261 nframes64_t
const x2
= pixel_to_frame (clicked_control_point
->get_x() + size
/ 2);
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
, Selection::Set
);
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
);
298 if (route_basis
== 0) {
302 set
<RouteTimeAxisView
*> tracks
;
303 tracks
.insert (route_basis
);
305 RouteGroup
* group
= route_basis
->route()->route_group();
306 if (group
&& group
->enabled_property (prop
)) {
308 /* the basis is a member of an active route group, with the appropriate
309 properties; find other members */
311 for (TrackViewList::const_iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
312 RouteTimeAxisView
* v
= dynamic_cast<RouteTimeAxisView
*> (*i
);
313 if (v
&& v
->route()->route_group() == group
) {
320 uint32_t const sz
= tracks
.size ();
321 for (set
<RouteTimeAxisView
*>::iterator i
= tracks
.begin(); i
!= tracks
.end(); ++i
) {
327 Editor::mapped_get_equivalent_regions (RouteTimeAxisView
& tv
, uint32_t, RegionView
* basis
, vector
<RegionView
*>* all_equivs
) const
329 boost::shared_ptr
<Playlist
> pl
;
330 vector
<boost::shared_ptr
<Region
> > results
;
332 boost::shared_ptr
<Diskstream
> ds
;
334 if ((ds
= tv
.get_diskstream()) == 0) {
339 if (&tv
== &basis
->get_time_axis_view()) {
340 /* looking in same track as the original */
344 if ((pl
= ds
->playlist()) != 0) {
345 pl
->get_equivalent_regions (basis
->region(), results
);
348 for (vector
<boost::shared_ptr
<Region
> >::iterator ir
= results
.begin(); ir
!= results
.end(); ++ir
) {
349 if ((marv
= tv
.view()->find_view (*ir
)) != 0) {
350 all_equivs
->push_back (marv
);
356 Editor::get_equivalent_regions (RegionView
* basis
, vector
<RegionView
*>& equivalent_regions
, PBD::PropertyID property
) const
358 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions
), basis
, &equivalent_regions
), &basis
->get_trackview(), property
);
360 /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
362 equivalent_regions
.push_back (basis
);
366 Editor::get_equivalent_regions (RegionSelection
& basis
, PBD::PropertyID prop
) const
368 RegionSelection equivalent
;
370 for (RegionSelection::const_iterator i
= basis
.begin(); i
!= basis
.end(); ++i
) {
372 vector
<RegionView
*> eq
;
375 sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions
), *i
, &eq
),
376 &(*i
)->get_trackview(), prop
379 for (vector
<RegionView
*>::iterator j
= eq
.begin(); j
!= eq
.end(); ++j
) {
391 Editor::get_regionview_count_from_region_list (boost::shared_ptr
<Region
> region
)
393 int region_count
= 0;
395 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
397 RouteTimeAxisView
* tatv
;
399 if ((tatv
= dynamic_cast<RouteTimeAxisView
*> (*i
)) != 0) {
401 boost::shared_ptr
<Playlist
> pl
;
402 vector
<boost::shared_ptr
<Region
> > results
;
404 boost::shared_ptr
<Diskstream
> ds
;
406 if ((ds
= tatv
->get_diskstream()) == 0) {
411 if ((pl
= (ds
->playlist())) != 0) {
412 pl
->get_region_list_equivalent_regions (region
, results
);
415 for (vector
<boost::shared_ptr
<Region
> >::iterator ir
= results
.begin(); ir
!= results
.end(); ++ir
) {
416 if ((marv
= tatv
->view()->find_view (*ir
)) != 0) {
429 Editor::set_selected_regionview_from_click (bool press
, Selection::Operation op
, bool /*no_track_remove*/)
431 vector
<RegionView
*> all_equivalent_regions
;
434 if (!clicked_regionview
|| !clicked_routeview
) {
439 button_release_can_deselect
= false;
442 if (op
== Selection::Toggle
|| op
== Selection::Set
) {
446 case Selection::Toggle
:
448 if (selection
->selected (clicked_regionview
)) {
451 /* whatever was clicked was selected already; do nothing here but allow
452 the button release to deselect it
455 button_release_can_deselect
= true;
459 if (button_release_can_deselect
) {
461 /* just remove this one region, but only on a permitted button release */
463 selection
->remove (clicked_regionview
);
466 /* no more deselect action on button release till a new press
467 finds an already selected object.
470 button_release_can_deselect
= false;
478 if (selection
->selected (clicked_routeview
)) {
479 get_equivalent_regions (clicked_regionview
, all_equivalent_regions
, ARDOUR::Properties::select
.property_id
);
481 all_equivalent_regions
.push_back (clicked_regionview
);
484 /* add all the equivalent regions, but only on button press */
486 if (!all_equivalent_regions
.empty()) {
490 selection
->add (all_equivalent_regions
);
496 if (!selection
->selected (clicked_regionview
)) {
497 get_equivalent_regions (clicked_regionview
, all_equivalent_regions
, ARDOUR::Properties::select
.property_id
);
498 selection
->set (all_equivalent_regions
);
501 /* no commit necessary: clicked on an already selected region */
511 } else if (op
== Selection::Extend
) {
513 list
<Selectable
*> results
;
514 nframes64_t last_frame
;
515 nframes64_t first_frame
;
516 bool same_track
= false;
518 /* 1. find the last selected regionview in the track that was clicked in */
521 first_frame
= max_frames
;
523 for (RegionSelection::iterator x
= selection
->regions
.begin(); x
!= selection
->regions
.end(); ++x
) {
524 if (&(*x
)->get_time_axis_view() == &clicked_regionview
->get_time_axis_view()) {
526 if ((*x
)->region()->last_frame() > last_frame
) {
527 last_frame
= (*x
)->region()->last_frame();
530 if ((*x
)->region()->first_frame() < first_frame
) {
531 first_frame
= (*x
)->region()->first_frame();
540 /* 2. figure out the boundaries for our search for new objects */
542 switch (clicked_regionview
->region()->coverage (first_frame
, last_frame
)) {
544 if (last_frame
< clicked_regionview
->region()->first_frame()) {
545 first_frame
= last_frame
;
546 last_frame
= clicked_regionview
->region()->last_frame();
548 last_frame
= first_frame
;
549 first_frame
= clicked_regionview
->region()->first_frame();
553 case OverlapExternal
:
554 if (last_frame
< clicked_regionview
->region()->first_frame()) {
555 first_frame
= last_frame
;
556 last_frame
= clicked_regionview
->region()->last_frame();
558 last_frame
= first_frame
;
559 first_frame
= clicked_regionview
->region()->first_frame();
563 case OverlapInternal
:
564 if (last_frame
< clicked_regionview
->region()->first_frame()) {
565 first_frame
= last_frame
;
566 last_frame
= clicked_regionview
->region()->last_frame();
568 last_frame
= first_frame
;
569 first_frame
= clicked_regionview
->region()->first_frame();
575 /* nothing to do except add clicked region to selection, since it
576 overlaps with the existing selection in this track.
583 /* click in a track that has no regions selected, so extend vertically
584 to pick out all regions that are defined by the existing selection
589 first_frame
= entered_regionview
->region()->position();
590 last_frame
= entered_regionview
->region()->last_frame();
592 for (RegionSelection::iterator i
= selection
->regions
.begin(); i
!= selection
->regions
.end(); ++i
) {
593 if ((*i
)->region()->position() < first_frame
) {
594 first_frame
= (*i
)->region()->position();
596 if ((*i
)->region()->last_frame() + 1 > last_frame
) {
597 last_frame
= (*i
)->region()->last_frame();
602 /* 2. find all the tracks we should select in */
604 set
<RouteTimeAxisView
*> relevant_tracks
;
606 for (TrackSelection::iterator i
= selection
->tracks
.begin(); i
!= selection
->tracks
.end(); ++i
) {
607 RouteTimeAxisView
* r
= dynamic_cast<RouteTimeAxisView
*> (*i
);
609 relevant_tracks
.insert (r
);
613 set
<RouteTimeAxisView
*> already_in_selection
;
615 if (relevant_tracks
.empty()) {
617 /* no tracks selected .. thus .. if the
618 regionview we're in isn't selected
619 (i.e. we're about to extend to it), then
620 find all tracks between the this one and
624 if (!selection
->selected (entered_regionview
)) {
626 RouteTimeAxisView
* rtv
= dynamic_cast<RouteTimeAxisView
*> (&entered_regionview
->get_time_axis_view());
630 /* add this track to the ones we will search */
632 relevant_tracks
.insert (rtv
);
634 /* find the track closest to this one that
635 already a selected region.
638 RouteTimeAxisView
* closest
= 0;
639 int distance
= INT_MAX
;
640 int key
= rtv
->route()->order_key ("editor");
642 for (RegionSelection::iterator x
= selection
->regions
.begin(); x
!= selection
->regions
.end(); ++x
) {
644 RouteTimeAxisView
* artv
= dynamic_cast<RouteTimeAxisView
*>(&(*x
)->get_time_axis_view());
646 if (artv
&& artv
!= rtv
) {
648 pair
<set
<RouteTimeAxisView
*>::iterator
,bool> result
;
650 result
= already_in_selection
.insert (artv
);
653 /* newly added to already_in_selection */
655 int d
= artv
->route()->order_key ("editor");
659 if (abs (d
) < distance
) {
669 /* now add all tracks between that one and this one */
671 int okey
= closest
->route()->order_key ("editor");
677 for (TrackViewList::iterator x
= track_views
.begin(); x
!= track_views
.end(); ++x
) {
678 RouteTimeAxisView
* artv
= dynamic_cast<RouteTimeAxisView
*>(*x
);
679 if (artv
&& artv
!= rtv
) {
681 int k
= artv
->route()->order_key ("editor");
683 if (k
>= okey
&& k
<= key
) {
685 /* in range but don't add it if
686 it already has tracks selected.
687 this avoids odd selection
688 behaviour that feels wrong.
691 if (find (already_in_selection
.begin(),
692 already_in_selection
.end(),
693 artv
) == already_in_selection
.end()) {
695 relevant_tracks
.insert (artv
);
705 /* 3. find all selectable objects (regionviews in this case) between that one and the end of the
706 one that was clicked.
709 for (set
<RouteTimeAxisView
*>::iterator t
= relevant_tracks
.begin(); t
!= relevant_tracks
.end(); ++t
) {
710 (*t
)->get_selectables (first_frame
, last_frame
, -1.0, -1.0, results
);
713 /* 4. convert to a vector of regions */
715 vector
<RegionView
*> regions
;
717 for (list
<Selectable
*>::iterator x
= results
.begin(); x
!= results
.end(); ++x
) {
720 if ((arv
= dynamic_cast<RegionView
*>(*x
)) != 0) {
721 regions
.push_back (arv
);
725 if (!regions
.empty()) {
726 selection
->add (regions
);
737 Editor::set_selected_regionview_from_region_list (boost::shared_ptr
<Region
> region
, Selection::Operation op
)
739 vector
<RegionView
*> all_equivalent_regions
;
741 get_regions_corresponding_to (region
, all_equivalent_regions
);
743 if (all_equivalent_regions
.empty()) {
747 begin_reversible_command (_("set selected regions"));
750 case Selection::Toggle
:
751 /* XXX this is not correct */
752 selection
->toggle (all_equivalent_regions
);
755 selection
->set (all_equivalent_regions
);
757 case Selection::Extend
:
758 selection
->add (all_equivalent_regions
);
761 selection
->add (all_equivalent_regions
);
765 commit_reversible_command () ;
769 Editor::set_selected_regionview_from_map_event (GdkEventAny
* /*ev*/, StreamView
* sv
, boost::weak_ptr
<Region
> weak_r
)
772 boost::shared_ptr
<Region
> r (weak_r
.lock());
778 if ((rv
= sv
->find_view (r
)) == 0) {
782 /* don't reset the selection if its something other than
783 a single other region.
786 if (selection
->regions
.size() > 1) {
790 begin_reversible_command (_("set selected regions"));
794 commit_reversible_command () ;
800 Editor::track_selection_changed ()
802 switch (selection
->tracks
.size()){
806 set_selected_mixer_strip (*(selection
->tracks
.front()));
810 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
811 if (find (selection
->tracks
.begin(), selection
->tracks
.end(), *i
) != selection
->tracks
.end()) {
812 (*i
)->set_selected (true);
814 (*i
)->set_selected (false);
818 ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions
, !selection
->tracks
.empty());
822 Editor::time_selection_changed ()
824 if (Profile
->get_sae()) {
828 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
829 (*i
)->hide_selection ();
832 for (TrackSelection::iterator i
= selection
->tracks
.begin(); i
!= selection
->tracks
.end(); ++i
) {
833 (*i
)->show_selection (selection
->time
);
836 if (selection
->time
.empty()) {
837 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions
, false);
839 ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions
, true);
844 Editor::sensitize_the_right_region_actions (bool have_selected_regions
)
846 for (vector
<Glib::RefPtr
<Action
> >::iterator x
= ActionManager::region_selection_sensitive_actions
.begin();
847 x
!= ActionManager::region_selection_sensitive_actions
.end(); ++x
) {
849 string accel_path
= (*x
)->get_accel_path ();
852 /* if there is an accelerator, it should always be sensitive
853 to allow for keyboard ops on entered regions.
856 bool known
= ActionManager::lookup_entry (accel_path
, key
);
858 if (known
&& ((key
.get_key() != GDK_VoidSymbol
) && (key
.get_key() != 0))) {
859 (*x
)->set_sensitive (true);
861 (*x
)->set_sensitive (have_selected_regions
);
868 Editor::region_selection_changed ()
870 _regions
->block_change_connection (true);
871 editor_regions_selection_changed_connection
.block(true);
873 _regions
->unselect_all ();
875 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
876 (*i
)->set_selected_regionviews (selection
->regions
);
879 _regions
->set_selected (selection
->regions
);
881 sensitize_the_right_region_actions (!selection
->regions
.empty());
883 _regions
->block_change_connection (false);
884 editor_regions_selection_changed_connection
.block(false);
888 Editor::point_selection_changed ()
890 for (TrackViewList::iterator i
= track_views
.begin(); i
!= track_views
.end(); ++i
) {
891 (*i
)->set_selected_points (selection
->points
);
896 Editor::select_all_in_track (Selection::Operation op
)
898 list
<Selectable
*> touched
;
900 if (!clicked_routeview
) {
904 clicked_routeview
->get_selectables (0, max_frames
, 0, DBL_MAX
, touched
);
907 case Selection::Toggle
:
908 selection
->add (touched
);
911 selection
->set (touched
);
913 case Selection::Extend
:
914 /* meaningless, because we're selecting everything */
917 selection
->add (touched
);
923 Editor::select_all (Selection::Operation op
)
925 list
<Selectable
*> touched
;
927 for (TrackViewList::iterator iter
= track_views
.begin(); iter
!= track_views
.end(); ++iter
) {
928 if ((*iter
)->hidden()) {
931 (*iter
)->get_selectables (0, max_frames
, 0, DBL_MAX
, touched
);
933 begin_reversible_command (_("select all"));
936 selection
->add (touched
);
938 case Selection::Toggle
:
939 selection
->add (touched
);
942 selection
->set (touched
);
944 case Selection::Extend
:
945 /* meaningless, because we're selecting everything */
948 commit_reversible_command ();
951 Editor::invert_selection_in_track ()
953 list
<Selectable
*> touched
;
955 if (!clicked_routeview
) {
959 clicked_routeview
->get_inverted_selectables (*selection
, touched
);
960 selection
->set (touched
);
964 Editor::invert_selection ()
966 list
<Selectable
*> touched
;
968 for (TrackViewList::iterator iter
= track_views
.begin(); iter
!= track_views
.end(); ++iter
) {
969 if ((*iter
)->hidden()) {
972 (*iter
)->get_inverted_selectables (*selection
, touched
);
975 selection
->set (touched
);
978 /** @param top Top (lower) y limit in trackview coordinates.
979 * @param bottom Bottom (higher) y limit in trackview coordinates.
982 Editor::select_all_within (
983 nframes64_t start
, nframes64_t end
, double top
, double bot
, const TrackViewList
& tracklist
, Selection::Operation op
986 list
<Selectable
*> found
;
987 TrackViewList tracks
;
989 for (TrackViewList::const_iterator iter
= tracklist
.begin(); iter
!= tracklist
.end(); ++iter
) {
991 if ((*iter
)->hidden()) {
995 list
<Selectable
*>::size_type
const n
= found
.size ();
997 (*iter
)->get_selectables (start
, end
, top
, bot
, found
);
999 if (n
!= found
.size()) {
1000 tracks
.push_back (*iter
);
1004 if (found
.empty()) {
1008 if (!tracks
.empty()) {
1011 case Selection::Add
:
1012 selection
->add (tracks
);
1014 case Selection::Toggle
:
1015 selection
->toggle (tracks
);
1017 case Selection::Set
:
1018 selection
->set (tracks
);
1020 case Selection::Extend
:
1021 /* not defined yet */
1026 begin_reversible_command (_("select all within"));
1028 case Selection::Add
:
1029 selection
->add (found
);
1031 case Selection::Toggle
:
1032 selection
->toggle (found
);
1034 case Selection::Set
:
1035 selection
->set (found
);
1037 case Selection::Extend
:
1038 /* not defined yet */
1042 commit_reversible_command ();
1044 return !found
.empty();
1048 Editor::set_selection_from_region ()
1050 if (selection
->regions
.empty()) {
1054 selection
->set (selection
->regions
.start(), selection
->regions
.end_frame());
1055 if (!Profile
->get_sae()) {
1056 set_mouse_mode (Editing::MouseRange
, false);
1061 Editor::set_selection_from_punch()
1065 if ((location
= _session
->locations()->auto_punch_location()) == 0) {
1069 set_selection_from_range (*location
);
1073 Editor::set_selection_from_loop()
1077 if ((location
= _session
->locations()->auto_loop_location()) == 0) {
1080 set_selection_from_range (*location
);
1084 Editor::set_selection_from_range (Location
& loc
)
1086 begin_reversible_command (_("set selection from range"));
1087 selection
->set (loc
.start(), loc
.end());
1088 commit_reversible_command ();
1090 if (!Profile
->get_sae()) {
1091 set_mouse_mode (Editing::MouseRange
, false);
1096 Editor::select_all_selectables_using_time_selection ()
1098 list
<Selectable
*> touched
;
1100 if (selection
->time
.empty()) {
1104 nframes64_t start
= selection
->time
[clicked_selection
].start
;
1105 nframes64_t end
= selection
->time
[clicked_selection
].end
;
1107 if (end
- start
< 1) {
1113 if (selection
->tracks
.empty()) {
1116 ts
= &selection
->tracks
;
1119 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1120 if ((*iter
)->hidden()) {
1123 (*iter
)->get_selectables (start
, end
- 1, 0, DBL_MAX
, touched
);
1126 begin_reversible_command (_("select all from range"));
1127 selection
->set (touched
);
1128 commit_reversible_command ();
1133 Editor::select_all_selectables_using_punch()
1135 Location
* location
= _session
->locations()->auto_punch_location();
1136 list
<Selectable
*> touched
;
1138 if (location
== 0 || (location
->end() - location
->start() <= 1)) {
1145 if (selection
->tracks
.empty()) {
1148 ts
= &selection
->tracks
;
1151 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1152 if ((*iter
)->hidden()) {
1155 (*iter
)->get_selectables (location
->start(), location
->end() - 1, 0, DBL_MAX
, touched
);
1157 begin_reversible_command (_("select all from punch"));
1158 selection
->set (touched
);
1159 commit_reversible_command ();
1164 Editor::select_all_selectables_using_loop()
1166 Location
* location
= _session
->locations()->auto_loop_location();
1167 list
<Selectable
*> touched
;
1169 if (location
== 0 || (location
->end() - location
->start() <= 1)) {
1176 if (selection
->tracks
.empty()) {
1179 ts
= &selection
->tracks
;
1182 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1183 if ((*iter
)->hidden()) {
1186 (*iter
)->get_selectables (location
->start(), location
->end() - 1, 0, DBL_MAX
, touched
);
1188 begin_reversible_command (_("select all from loop"));
1189 selection
->set (touched
);
1190 commit_reversible_command ();
1195 Editor::select_all_selectables_using_cursor (EditorCursor
*cursor
, bool after
)
1199 list
<Selectable
*> touched
;
1202 begin_reversible_command (_("select all after cursor"));
1203 start
= cursor
->current_frame
;
1204 end
= _session
->current_end_frame();
1206 if (cursor
->current_frame
> 0) {
1207 begin_reversible_command (_("select all before cursor"));
1209 end
= cursor
->current_frame
- 1;
1218 if (selection
->tracks
.empty()) {
1221 ts
= &selection
->tracks
;
1224 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1225 if ((*iter
)->hidden()) {
1228 (*iter
)->get_selectables (start
, end
, 0, DBL_MAX
, touched
);
1230 selection
->set (touched
);
1231 commit_reversible_command ();
1235 Editor::select_all_selectables_using_edit (bool after
)
1239 list
<Selectable
*> touched
;
1242 begin_reversible_command (_("select all after edit"));
1243 start
= get_preferred_edit_position();
1244 end
= _session
->current_end_frame();
1246 if ((end
= get_preferred_edit_position()) > 1) {
1247 begin_reversible_command (_("select all before edit"));
1258 if (selection
->tracks
.empty()) {
1261 ts
= &selection
->tracks
;
1264 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1265 if ((*iter
)->hidden()) {
1268 (*iter
)->get_selectables (start
, end
, 0, DBL_MAX
, touched
);
1270 selection
->set (touched
);
1271 commit_reversible_command ();
1275 Editor::select_all_selectables_between (bool /*within*/)
1279 list
<Selectable
*> touched
;
1281 if (!get_edit_op_range (start
, end
)) {
1287 if (selection
->tracks
.empty()) {
1290 ts
= &selection
->tracks
;
1293 for (TrackViewList::iterator iter
= ts
->begin(); iter
!= ts
->end(); ++iter
) {
1294 if ((*iter
)->hidden()) {
1297 (*iter
)->get_selectables (start
, end
, 0, DBL_MAX
, touched
);
1300 selection
->set (touched
);
1304 Editor::select_range_between ()
1309 if (!get_edit_op_range (start
, end
)) {
1313 set_mouse_mode (MouseRange
);
1314 selection
->set (start
, end
);
1318 Editor::get_edit_op_range (nframes64_t
& start
, nframes64_t
& end
) const
1323 /* in range mode, use any existing selection */
1325 if (mouse_mode
== MouseRange
&& !selection
->time
.empty()) {
1326 /* we know that these are ordered */
1327 start
= selection
->time
.start();
1328 end
= selection
->time
.end_frame();
1332 if (!mouse_frame (m
, ignored
)) {
1333 /* mouse is not in a canvas, try playhead+selected marker.
1334 this is probably most true when using menus.
1337 if (selection
->markers
.empty()) {
1341 start
= selection
->markers
.front()->position();
1342 end
= _session
->audible_frame();
1346 switch (_edit_point
) {
1347 case EditAtPlayhead
:
1348 if (selection
->markers
.empty()) {
1349 /* use mouse + playhead */
1351 end
= _session
->audible_frame();
1353 /* use playhead + selected marker */
1354 start
= _session
->audible_frame();
1355 end
= selection
->markers
.front()->position();
1360 /* use mouse + selected marker */
1361 if (selection
->markers
.empty()) {
1363 end
= _session
->audible_frame();
1365 start
= selection
->markers
.front()->position();
1370 case EditAtSelectedMarker
:
1371 /* use mouse + selected marker */
1372 if (selection
->markers
.empty()) {
1374 MessageDialog
win (_("No edit range defined"),
1379 win
.set_secondary_text (
1380 _("the edit point is Selected Marker\nbut there is no selected marker."));
1383 win
.set_default_response (RESPONSE_CLOSE
);
1384 win
.set_position (Gtk::WIN_POS_MOUSE
);
1389 return false; // NO RANGE
1391 start
= selection
->markers
.front()->position();
1405 /* turn range into one delimited by start...end,
1415 Editor::deselect_all ()
1417 selection
->clear ();
1421 Editor::select_range_around_region (RegionView
* rv
)
1425 selection
->set (&rv
->get_time_axis_view());
1427 selection
->time
.clear ();
1428 boost::shared_ptr
<Region
> r
= rv
->region ();
1429 return selection
->set (r
->position(), r
->position() + r
->length());