1 #include <msp/strings/utils.h>
4 #include "trackchain.h"
8 TrackChain::TrackChain(Layout &l):
11 layout.signal_object_removed.connect(sigc::mem_fun(this, &TrackChain::object_removed));
14 void TrackChain::add_track(Track &track)
16 if(tracks.count(&track))
19 Validity valid = check_validity(track);
21 throw_bad_chain(valid);
23 tracks.insert(&track);
25 on_track_added(track);
26 signal_track_added.emit(track);
29 void TrackChain::add_tracks(const TrackSet &trks)
32 for(TrackSet::const_iterator i=trks.begin(); i!=trks.end(); ++i)
36 while(!pending.empty())
38 Validity valid = UNLINKED;
39 for(TrackSet::iterator i=pending.begin(); i!=pending.end(); ++i)
40 if((valid=check_validity(**i))==VALID)
47 signal_track_added.emit(*t);
52 throw_bad_chain(valid);
56 TrackChain::Validity TrackChain::check_validity(Track &track) const
65 return ends[0]->get_link_slot(track)>=0 ? VALID : UNLINKED;
68 Validity result = UNLINKED;
69 for(unsigned i=0; i<2; ++i)
71 int j = ends[i]->get_link_slot(track);
74 const TrackType::Endpoint &ep1 = ends[i].endpoint();
75 const TrackType::Endpoint &ep2 = ends[i]->get_type().get_endpoint(j);
76 if(!ep1.has_common_paths(ep2))
86 void TrackChain::throw_bad_chain(Validity v)
89 throw bad_chain("unlinked");
91 throw bad_chain("bad path");
92 else if(v==INCOMPATIBLE)
93 throw bad_chain("incompatible");
96 void TrackChain::update_ends(Track &track)
99 // We don't really know the proper endpoint yet; just pick something
100 ends[0] = TrackIter(&track, 0);
103 // We're adding the second track; determine endpoints for both
104 ends[0] = TrackIter(&*ends[0], ends[0]->get_link_slot(track));
105 ends[1] = TrackIter(&track, track.get_link_slot(*ends[0]));
110 for(unsigned i=0; i<2; ++i)
111 if(ends[i]->get_link_slot(track)>=0)
116 // Closed loop; clear the ends
117 ends[0] = TrackIter();
118 ends[1] = TrackIter();
121 ends[linked-1] = TrackIter(&track, track.get_link_slot(*ends[linked-1]));
125 bool TrackChain::has_track(Track &t) const
127 return tracks.count(&t);
130 void TrackChain::object_removed(Object &obj)
132 if(Track *track = dynamic_cast<Track *>(&obj))
135 /* TODO If the track was in the middle of the chain, keep only the
137 signal_track_removed.emit(*track);