2 Copyright (C) 2002 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.
21 #include <sigc++/bind.h>
23 #include "pbd/error.h"
24 #include "pbd/stacktrace.h"
26 #include "ardour/playlist.h"
27 #include "ardour/rc_configuration.h"
29 #include "gui_thread.h"
30 #include "midi_cut_buffer.h"
31 #include "region_view.h"
32 #include "selection.h"
33 #include "selection_templates.h"
34 #include "time_axis_view.h"
35 #include "automation_time_axis.h"
36 #include "public_editor.h"
37 #include "control_point.h"
42 using namespace ARDOUR;
45 struct AudioRangeComparator {
46 bool operator()(AudioRange a, AudioRange b) {
47 return a.start < b.start;
51 Selection::Selection (const PublicEditor* e)
55 , _no_tracks_changed (false)
59 /* we have disambiguate which remove() for the compiler */
61 void (Selection::*track_remove)(TimeAxisView*) = &Selection::remove;
62 TimeAxisView::CatchDeletion.connect (*this, MISSING_INVALIDATOR, boost::bind (track_remove, this, _1), gui_context());
64 void (Selection::*marker_remove)(Marker*) = &Selection::remove;
65 Marker::CatchDeletion.connect (*this, MISSING_INVALIDATOR, boost::bind (marker_remove, this, _1), gui_context());
67 void (Selection::*point_remove)(ControlPoint*) = &Selection::remove;
68 ControlPoint::CatchDeletion.connect (*this, MISSING_INVALIDATOR, boost::bind (point_remove, this, _1), gui_context());
73 Selection::operator= (const Selection& other)
76 regions = other.regions;
77 tracks = other.tracks;
80 midi_regions = other.midi_regions;
81 midi_notes = other.midi_notes;
88 operator== (const Selection& a, const Selection& b)
90 return a.regions == b.regions &&
91 a.tracks == b.tracks &&
94 a.playlists == b.playlists &&
95 a.midi_notes == b.midi_notes &&
96 a.midi_regions == b.midi_regions;
99 /** Clear everything from the Selection */
110 clear_midi_regions ();
115 Selection::clear_objects ()
122 clear_midi_regions ();
126 Selection::clear_tracks ()
128 if (!tracks.empty()) {
129 for (TrackViewList::iterator x = tracks.begin(); x != tracks.end(); ++x) {
130 (*x)->set_selected (false);
133 if (!_no_tracks_changed) {
140 Selection::clear_time ()
148 Selection::dump_region_layers()
150 cerr << "region selection layer dump" << endl;
151 for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) {
152 cerr << "layer: " << (int)(*i)->region()->layer() << endl;
158 Selection::clear_regions ()
160 if (!regions.empty()) {
161 regions.clear_all ();
167 Selection::clear_midi_notes ()
169 if (!midi_notes.empty()) {
170 for (MidiNoteSelection::iterator x = midi_notes.begin(); x != midi_notes.end(); ++x) {
177 /* The note selection is actually stored in MidiRegionView, emit signal to
178 tell them to clear their selection. */
179 ClearMidiNoteSelection(); /* EMIT SIGNAL */
183 Selection::clear_midi_regions ()
185 if (!midi_regions.empty()) {
186 midi_regions.clear ();
187 MidiRegionsChanged ();
192 Selection::clear_playlists ()
194 /* Selections own their playlists */
196 for (PlaylistSelection::iterator i = playlists.begin(); i != playlists.end(); ++i) {
197 /* selections own their own regions, which are copies of the "originals". make them go away */
198 (*i)->drop_regions ();
202 if (!playlists.empty()) {
209 Selection::clear_lines ()
211 if (!lines.empty()) {
218 Selection::clear_markers ()
220 if (!markers.empty()) {
227 Selection::toggle (boost::shared_ptr<Playlist> pl)
229 clear_time(); //enforce object/range exclusivity
230 clear_tracks(); //enforce object/track exclusivity
232 PlaylistSelection::iterator i;
234 if ((i = find (playlists.begin(), playlists.end(), pl)) == playlists.end()) {
236 playlists.push_back(pl);
245 Selection::toggle (const TrackViewList& track_list)
247 for (TrackViewList::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
253 Selection::toggle (TimeAxisView* track)
255 TrackSelection::iterator i;
257 if ((i = find (tracks.begin(), tracks.end(), track)) == tracks.end()) {
258 track->set_selected (true);
259 tracks.push_back (track);
261 track->set_selected (false);
265 if (!_no_tracks_changed) {
271 Selection::toggle (const MidiNoteSelection& midi_note_list)
273 clear_time(); //enforce object/range exclusivity
274 clear_tracks(); //enforce object/track exclusivity
276 for (MidiNoteSelection::const_iterator i = midi_note_list.begin(); i != midi_note_list.end(); ++i) {
282 Selection::toggle (MidiCutBuffer* midi)
284 MidiNoteSelection::iterator i;
286 if ((i = find (midi_notes.begin(), midi_notes.end(), midi)) == midi_notes.end()) {
287 midi_notes.push_back (midi);
289 /* remember that we own the MCB */
291 midi_notes.erase (i);
299 Selection::toggle (RegionView* r)
301 clear_time(); //enforce object/range exclusivity
302 clear_tracks(); //enforce object/track exclusivity
304 RegionSelection::iterator i;
306 if ((i = find (regions.begin(), regions.end(), r)) == regions.end()) {
316 Selection::toggle (MidiRegionView* mrv)
318 clear_time(); //enforce object/range exclusivity
319 clear_tracks(); //enforce object/track exclusivity
321 MidiRegionSelection::iterator i;
323 if ((i = find (midi_regions.begin(), midi_regions.end(), mrv)) == midi_regions.end()) {
326 midi_regions.erase (i);
329 MidiRegionsChanged ();
333 Selection::toggle (vector<RegionView*>& r)
335 clear_time(); //enforce object/range exclusivity
336 clear_tracks(); //enforce object/track exclusivity
338 RegionSelection::iterator i;
340 for (vector<RegionView*>::iterator x = r.begin(); x != r.end(); ++x) {
341 if ((i = find (regions.begin(), regions.end(), (*x))) == regions.end()) {
352 Selection::toggle (framepos_t start, framepos_t end)
354 clear_objects(); //enforce object/range exclusivity
356 AudioRangeComparator cmp;
358 /* XXX this implementation is incorrect */
360 time.push_back (AudioRange (start, end, ++next_time_id));
370 Selection::add (boost::shared_ptr<Playlist> pl)
372 clear_time(); //enforce object/range exclusivity
373 clear_tracks(); //enforce object/track exclusivity
375 if (find (playlists.begin(), playlists.end(), pl) == playlists.end()) {
377 playlists.push_back(pl);
383 Selection::add (const list<boost::shared_ptr<Playlist> >& pllist)
385 clear_time(); //enforce object/range exclusivity
386 clear_tracks(); //enforce object/track exclusivity
388 bool changed = false;
390 for (list<boost::shared_ptr<Playlist> >::const_iterator i = pllist.begin(); i != pllist.end(); ++i) {
391 if (find (playlists.begin(), playlists.end(), (*i)) == playlists.end()) {
393 playlists.push_back (*i);
404 Selection::add (const TrackViewList& track_list)
406 clear_objects(); //enforce object/range exclusivity
408 TrackViewList added = tracks.add (track_list);
410 if (!added.empty()) {
411 for (TrackViewList::iterator x = added.begin(); x != added.end(); ++x) {
412 (*x)->set_selected (true);
414 if (!_no_tracks_changed) {
421 Selection::add (TimeAxisView* track)
423 clear_objects(); //enforce object/range exclusivity
426 track->set_selected (true);
427 tr.push_back (track);
432 Selection::add (const MidiNoteSelection& midi_list)
434 clear_time(); //enforce object/range exclusivity
435 clear_tracks(); //enforce object/track exclusivity
437 const MidiNoteSelection::const_iterator b = midi_list.begin();
438 const MidiNoteSelection::const_iterator e = midi_list.end();
440 if (!midi_list.empty()) {
441 midi_notes.insert (midi_notes.end(), b, e);
447 Selection::add (MidiCutBuffer* midi)
449 /* we take ownership of the MCB */
451 if (find (midi_notes.begin(), midi_notes.end(), midi) == midi_notes.end()) {
452 midi_notes.push_back (midi);
458 Selection::add (vector<RegionView*>& v)
460 clear_time(); //enforce object/range exclusivity
461 clear_tracks(); //enforce object/track exclusivity
463 /* XXX This method or the add (const RegionSelection&) needs to go
466 bool changed = false;
468 for (vector<RegionView*>::iterator i = v.begin(); i != v.end(); ++i) {
469 if (find (regions.begin(), regions.end(), (*i)) == regions.end()) {
470 changed = regions.add ((*i));
480 Selection::add (const RegionSelection& rs)
482 clear_time(); //enforce object/range exclusivity
483 clear_tracks(); //enforce object/track exclusivity
485 /* XXX This method or the add (const vector<RegionView*>&) needs to go
488 bool changed = false;
490 for (RegionSelection::const_iterator i = rs.begin(); i != rs.end(); ++i) {
491 if (find (regions.begin(), regions.end(), (*i)) == regions.end()) {
492 changed = regions.add ((*i));
502 Selection::add (RegionView* r)
504 clear_time(); //enforce object/range exclusivity
505 clear_tracks(); //enforce object/track exclusivity
507 if (find (regions.begin(), regions.end(), r) == regions.end()) {
508 bool changed = regions.add (r);
516 Selection::add (MidiRegionView* mrv)
518 clear_time(); //enforce object/range exclusivity
519 clear_tracks(); //enforce object/track exclusivity
521 if (find (midi_regions.begin(), midi_regions.end(), mrv) == midi_regions.end()) {
522 midi_regions.push_back (mrv);
523 /* XXX should we do this? */
524 MidiRegionsChanged ();
529 Selection::add (framepos_t start, framepos_t end)
531 clear_objects(); //enforce object/range exclusivity
533 AudioRangeComparator cmp;
535 /* XXX this implementation is incorrect */
537 time.push_back (AudioRange (start, end, ++next_time_id));
547 Selection::move_time (framecnt_t distance)
553 for (list<AudioRange>::iterator i = time.begin(); i != time.end(); ++i) {
554 (*i).start += distance;
555 (*i).end += distance;
562 Selection::replace (uint32_t sid, framepos_t start, framepos_t end)
564 clear_objects(); //enforce object/range exclusivity
566 for (list<AudioRange>::iterator i = time.begin(); i != time.end(); ++i) {
567 if ((*i).id == sid) {
569 time.push_back (AudioRange(start,end, sid));
571 /* don't consolidate here */
574 AudioRangeComparator cmp;
584 Selection::add (boost::shared_ptr<Evoral::ControlList> cl)
586 clear_time(); //enforce object/range exclusivity
587 clear_tracks(); //enforce object/track exclusivity
589 boost::shared_ptr<ARDOUR::AutomationList> al
590 = boost::dynamic_pointer_cast<ARDOUR::AutomationList>(cl);
592 warning << "Programming error: Selected list is not an ARDOUR::AutomationList" << endmsg;
595 if (find (lines.begin(), lines.end(), al) == lines.end()) {
596 lines.push_back (al);
602 Selection::remove (TimeAxisView* track)
604 list<TimeAxisView*>::iterator i;
605 if ((i = find (tracks.begin(), tracks.end(), track)) != tracks.end()) {
606 track->set_selected (false);
608 if (!_no_tracks_changed) {
615 Selection::remove (const TrackViewList& track_list)
617 bool changed = false;
619 for (TrackViewList::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
621 TrackViewList::iterator x = find (tracks.begin(), tracks.end(), *i);
622 if (x != tracks.end()) {
623 (*i)->set_selected (false);
630 if (!_no_tracks_changed) {
637 Selection::remove (ControlPoint* p)
639 PointSelection::iterator i = find (points.begin(), points.end(), p);
640 if (i != points.end ()) {
646 Selection::remove (const MidiNoteSelection& midi_list)
648 bool changed = false;
650 for (MidiNoteSelection::const_iterator i = midi_list.begin(); i != midi_list.end(); ++i) {
652 MidiNoteSelection::iterator x;
654 if ((x = find (midi_notes.begin(), midi_notes.end(), (*i))) != midi_notes.end()) {
655 midi_notes.erase (x);
666 Selection::remove (MidiCutBuffer* midi)
668 MidiNoteSelection::iterator x;
670 if ((x = find (midi_notes.begin(), midi_notes.end(), midi)) != midi_notes.end()) {
671 /* remember that we own the MCB */
673 midi_notes.erase (x);
679 Selection::remove (boost::shared_ptr<Playlist> track)
681 list<boost::shared_ptr<Playlist> >::iterator i;
682 if ((i = find (playlists.begin(), playlists.end(), track)) != playlists.end()) {
689 Selection::remove (const list<boost::shared_ptr<Playlist> >& pllist)
691 bool changed = false;
693 for (list<boost::shared_ptr<Playlist> >::const_iterator i = pllist.begin(); i != pllist.end(); ++i) {
695 list<boost::shared_ptr<Playlist> >::iterator x;
697 if ((x = find (playlists.begin(), playlists.end(), (*i))) != playlists.end()) {
709 Selection::remove (RegionView* r)
711 if (regions.remove (r)) {
717 Selection::remove (MidiRegionView* mrv)
719 MidiRegionSelection::iterator x;
721 if ((x = find (midi_regions.begin(), midi_regions.end(), mrv)) != midi_regions.end()) {
722 midi_regions.erase (x);
723 MidiRegionsChanged ();
729 Selection::remove (uint32_t selection_id)
735 for (list<AudioRange>::iterator i = time.begin(); i != time.end(); ++i) {
736 if ((*i).id == selection_id) {
746 Selection::remove (framepos_t /*start*/, framepos_t /*end*/)
751 Selection::remove (boost::shared_ptr<ARDOUR::AutomationList> ac)
753 AutomationSelection::iterator i;
754 if ((i = find (lines.begin(), lines.end(), ac)) != lines.end()) {
761 Selection::set (TimeAxisView* track)
763 clear_objects(); //enforce object/range exclusivity
769 Selection::set (const TrackViewList& track_list)
771 clear_objects(); //enforce object/range exclusivity
777 Selection::set (const MidiNoteSelection& midi_list)
779 clear_time (); //enforce region/object exclusivity
780 clear_tracks(); //enforce object/track exclusivity
786 Selection::set (boost::shared_ptr<Playlist> playlist)
788 clear_time (); //enforce region/object exclusivity
789 clear_tracks(); //enforce object/track exclusivity
795 Selection::set (const list<boost::shared_ptr<Playlist> >& pllist)
797 clear_time(); //enforce region/object exclusivity
803 Selection::set (const RegionSelection& rs)
805 clear_time(); //enforce region/object exclusivity
806 clear_tracks(); //enforce object/track exclusivity
809 RegionsChanged(); /* EMIT SIGNAL */
813 Selection::set (MidiRegionView* mrv)
815 clear_time(); //enforce region/object exclusivity
816 clear_tracks(); //enforce object/track exclusivity
822 Selection::set (RegionView* r, bool /*also_clear_tracks*/)
824 clear_time(); //enforce region/object exclusivity
825 clear_tracks(); //enforce object/track exclusivity
831 Selection::set (vector<RegionView*>& v)
833 clear_time(); //enforce region/object exclusivity
834 clear_tracks(); //enforce object/track exclusivity
840 /** Set the start and end time of the time selection, without changing
841 * the list of tracks it applies to.
844 Selection::set (framepos_t start, framepos_t end)
846 clear_objects(); //enforce region/object exclusivity
849 if ((start == 0 && end == 0) || end < start) {
854 time.push_back (AudioRange (start, end, ++next_time_id));
856 /* reuse the first entry, and remove all the rest */
858 while (time.size() > 1) {
861 time.front().start = start;
862 time.front().end = end;
869 return time.front().id;
872 /** Set the start and end of the range selection. If more than one range
873 * is currently selected, the start of the earliest range and the end of the
874 * latest range are set. If no range is currently selected, this method
875 * selects a single range from start to end.
877 * @param start New start time.
878 * @param end New end time.
881 Selection::set_preserving_all_ranges (framepos_t start, framepos_t end)
883 clear_objects(); //enforce region/object exclusivity
885 if ((start == 0 && end == 0) || (end < start)) {
890 time.push_back (AudioRange (start, end, ++next_time_id));
892 time.sort (AudioRangeComparator ());
893 time.front().start = start;
894 time.back().end = end;
903 Selection::set (boost::shared_ptr<Evoral::ControlList> ac)
905 clear_time(); //enforce region/object exclusivity
906 clear_tracks(); //enforce object/track exclusivity
913 Selection::selected (Marker* m)
915 return find (markers.begin(), markers.end(), m) != markers.end();
919 Selection::selected (TimeAxisView* tv)
921 return tv->get_selected ();
925 Selection::selected (RegionView* rv)
927 return find (regions.begin(), regions.end(), rv) != regions.end();
931 Selection::selected (ControlPoint* cp)
933 return find (points.begin(), points.end(), cp) != points.end();
937 Selection::empty (bool internal_selection)
939 bool object_level_empty = regions.empty () &&
942 playlists.empty () &&
945 playlists.empty () &&
950 if (!internal_selection) {
951 return object_level_empty;
954 /* this is intended to really only apply when using a Selection
958 return object_level_empty && midi_notes.empty() && points.empty();
962 Selection::toggle (ControlPoint* cp)
964 clear_time(); //enforce region/object exclusivity
965 clear_tracks(); //enforce object/track exclusivity
967 cp->set_selected (!cp->get_selected ());
968 PointSelection::iterator i = find (points.begin(), points.end(), cp);
969 if (i == points.end()) {
970 points.push_back (cp);
975 PointsChanged (); /* EMIT SIGNAL */
979 Selection::toggle (vector<ControlPoint*> const & cps)
981 clear_time(); //enforce region/object exclusivity
982 clear_tracks(); //enforce object/track exclusivity
984 for (vector<ControlPoint*>::const_iterator i = cps.begin(); i != cps.end(); ++i) {
990 Selection::toggle (list<Selectable*> const & selectables)
992 clear_time(); //enforce region/object exclusivity
993 clear_tracks(); //enforce object/track exclusivity
997 vector<RegionView*> rvs;
998 vector<ControlPoint*> cps;
1000 for (std::list<Selectable*>::const_iterator i = selectables.begin(); i != selectables.end(); ++i) {
1001 if ((rv = dynamic_cast<RegionView*> (*i)) != 0) {
1003 } else if ((cp = dynamic_cast<ControlPoint*> (*i)) != 0) {
1006 fatal << _("programming error: ")
1007 << X_("unknown selectable type passed to Selection::toggle()")
1009 abort(); /*NOTREACHED*/
1023 Selection::set (list<Selectable*> const & selectables)
1025 clear_time (); //enforce region/object exclusivity
1026 clear_tracks(); //enforce object/track exclusivity
1033 Selection::add (PointSelection const & s)
1035 clear_time (); //enforce region/object exclusivity
1036 clear_tracks(); //enforce object/track exclusivity
1038 for (PointSelection::const_iterator i = s.begin(); i != s.end(); ++i) {
1039 points.push_back (*i);
1044 Selection::add (list<Selectable*> const & selectables)
1046 clear_time (); //enforce region/object exclusivity
1047 clear_tracks(); //enforce object/track exclusivity
1051 vector<RegionView*> rvs;
1052 vector<ControlPoint*> cps;
1054 for (std::list<Selectable*>::const_iterator i = selectables.begin(); i != selectables.end(); ++i) {
1055 if ((rv = dynamic_cast<RegionView*> (*i)) != 0) {
1057 } else if ((cp = dynamic_cast<ControlPoint*> (*i)) != 0) {
1060 fatal << _("programming error: ")
1061 << X_("unknown selectable type passed to Selection::add()")
1063 abort(); /*NOTREACHED*/
1077 Selection::clear_points ()
1079 if (!points.empty()) {
1086 Selection::add (ControlPoint* cp)
1088 clear_time (); //enforce region/object exclusivity
1089 clear_tracks(); //enforce object/track exclusivity
1091 cp->set_selected (true);
1092 points.push_back (cp);
1093 PointsChanged (); /* EMIT SIGNAL */
1097 Selection::add (vector<ControlPoint*> const & cps)
1099 clear_time (); //enforce region/object exclusivity
1100 clear_tracks(); //enforce object/track exclusivity
1102 for (vector<ControlPoint*>::const_iterator i = cps.begin(); i != cps.end(); ++i) {
1103 (*i)->set_selected (true);
1104 points.push_back (*i);
1106 PointsChanged (); /* EMIT SIGNAL */
1110 Selection::set (ControlPoint* cp)
1112 clear_time (); //enforce region/object exclusivity
1113 clear_tracks(); //enforce object/track exclusivity
1115 if (cp->get_selected()) {
1119 for (uint32_t i = 0; i < cp->line().npoints(); ++i) {
1120 cp->line().nth (i)->set_selected (false);
1128 Selection::set (Marker* m)
1130 clear_time (); //enforce region/object exclusivity
1131 clear_tracks(); //enforce object/track exclusivity
1138 Selection::toggle (Marker* m)
1140 MarkerSelection::iterator i;
1142 if ((i = find (markers.begin(), markers.end(), m)) == markers.end()) {
1150 Selection::remove (Marker* m)
1152 MarkerSelection::iterator i;
1154 if ((i = find (markers.begin(), markers.end(), m)) != markers.end()) {
1161 Selection::add (Marker* m)
1163 clear_time (); //enforce region/object exclusivity
1164 clear_tracks(); //enforce object/track exclusivity
1166 if (find (markers.begin(), markers.end(), m) == markers.end()) {
1167 markers.push_back (m);
1173 Selection::add (const list<Marker*>& m)
1175 clear_time (); //enforce region/object exclusivity
1176 clear_tracks(); //enforce object/track exclusivity
1178 markers.insert (markers.end(), m.begin(), m.end());
1186 MarkerSelection::range (framepos_t& s, framepos_t& e)
1191 for (MarkerSelection::iterator i = begin(); i != end(); ++i) {
1193 if ((*i)->position() < s) {
1194 s = (*i)->position();
1197 if ((*i)->position() > e) {
1198 e = (*i)->position();
1202 s = std::min (s, e);
1203 e = std::max (s, e);
1207 Selection::get_state () const
1209 /* XXX: not complete; just sufficient to get track selection state
1210 so that re-opening plugin windows for editor mixer strips works
1214 XMLNode* node = new XMLNode (X_("Selection"));
1216 for (TrackSelection::const_iterator i = tracks.begin(); i != tracks.end(); ++i) {
1217 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
1218 AutomationTimeAxisView* atv = dynamic_cast<AutomationTimeAxisView*> (*i);
1220 XMLNode* t = node->add_child (X_("RouteView"));
1221 t->add_property (X_("id"), atoi (rtv->route()->id().to_s().c_str()));
1223 XMLNode* t = node->add_child (X_("AutomationView"));
1224 t->add_property (X_("id"), atoi (atv->parent_route()->id().to_s().c_str()));
1225 t->add_property (X_("parameter"), EventTypeMap::instance().to_symbol (atv->parameter ()));
1229 for (RegionSelection::const_iterator i = regions.begin(); i != regions.end(); ++i) {
1230 XMLNode* r = node->add_child (X_("Region"));
1231 r->add_property (X_("id"), atoi ((*i)->region ()->id ().to_s ().c_str()));
1235 for (TimeSelection::const_iterator i = time.begin(); i != time.end(); ++i) {
1236 XMLNode* t = node->add_child (X_("AudioRange"));
1237 snprintf(buf, sizeof(buf), "%" PRId64, (*i).start);
1238 t->add_property (X_("start"), string(buf));
1239 snprintf(buf, sizeof(buf), "%" PRId64, (*i).end);
1240 t->add_property (X_("end"), string(buf));
1243 for (MarkerSelection::const_iterator i = markers.begin(); i != markers.end(); ++i) {
1244 XMLNode* t = node->add_child (X_("Marker"));
1247 Location* loc = editor->find_location_from_marker (*i, is_start);
1249 t->add_property (X_("id"), atoi (loc->id().to_s().c_str()));
1250 t->add_property (X_("start"), is_start ? X_("yes") : X_("no"));
1257 Selection::set_state (XMLNode const & node, int)
1259 if (node.name() != X_("Selection")) {
1268 XMLNodeList children = node.children ();
1269 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
1270 if ((*i)->name() == X_("RouteView")) {
1272 XMLProperty* prop_id = (*i)->property (X_("id"));
1274 PBD::ID id (prop_id->value ());
1275 RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (id);
1280 } else if ((*i)->name() == X_("Region")) {
1281 XMLProperty* prop_id = (*i)->property (X_("id"));
1283 PBD::ID id (prop_id->value ());
1286 editor->get_regionviews_by_id (id, rs);
1292 regionviews are being constructed - stash the region IDs
1293 so we can identify them in Editor::region_view_added ()
1295 regions.pending.push_back (id);
1298 } else if ((*i)->name() == X_("AudioRange")) {
1299 XMLProperty* prop_start = (*i)->property (X_("start"));
1300 XMLProperty* prop_end = (*i)->property (X_("end"));
1302 assert (prop_start);
1305 framepos_t s (atol (prop_start->value ().c_str()));
1306 framepos_t e (atol (prop_end->value ().c_str()));
1308 set_preserving_all_ranges (s, e);
1310 } else if ((*i)->name() == X_("AutomationView")) {
1312 XMLProperty* prop_id = (*i)->property (X_("id"));
1313 XMLProperty* prop_parameter = (*i)->property (X_("parameter"));
1316 assert (prop_parameter);
1318 PBD::ID id (prop_id->value ());
1319 RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (id);
1322 boost::shared_ptr<AutomationTimeAxisView> atv = rtv->automation_child (EventTypeMap::instance().from_symbol (prop_parameter->value ()));
1324 /* the automation could be for an entity that was never saved
1325 in the session file. Don't freak out if we can't find
1334 } else if ((*i)->name() == X_("Marker")) {
1336 XMLProperty* prop_id = (*i)->property (X_("id"));
1337 XMLProperty* prop_start = (*i)->property (X_("start"));
1339 assert (prop_start);
1341 PBD::ID id (prop_id->value ());
1342 Marker* m = editor->find_marker_from_location_id (id, string_is_affirmative (prop_start->value ()));
1355 Selection::remove_regions (TimeAxisView* t)
1357 RegionSelection::iterator i = regions.begin();
1358 while (i != regions.end ()) {
1359 RegionSelection::iterator tmp = i;
1362 if (&(*i)->get_time_axis_view() == t) {
1371 Selection::block_tracks_changed (bool yn)
1373 _no_tracks_changed = yn;