1 #include <msp/strings/utils.h>
4 #include "trackchain.h"
10 TrackChain::TrackChain(Layout &l):
13 layout.signal_object_removed.connect(sigc::mem_fun(this, &TrackChain::object_removed));
16 void TrackChain::set_name(const string &n)
19 signal_name_changed.emit(name);
22 void TrackChain::add_track(Track &track)
24 if(tracks.count(&track))
27 Validity valid = check_validity(track);
29 throw_bad_chain(valid);
31 tracks.insert(&track);
33 on_track_added(track);
34 signal_track_added.emit(track);
37 void TrackChain::add_tracks(const TrackSet &trks)
40 for(TrackSet::const_iterator i=trks.begin(); i!=trks.end(); ++i)
44 while(!pending.empty())
46 Validity valid = UNLINKED;
47 for(TrackSet::iterator i=pending.begin(); i!=pending.end(); ++i)
48 if((valid=check_validity(**i))==VALID)
55 signal_track_added.emit(*t);
60 throw_bad_chain(valid);
64 TrackChain::Validity TrackChain::check_validity(Track &track) const
73 return ends[0]->get_link_slot(track)>=0 ? VALID : UNLINKED;
76 Validity result = UNLINKED;
77 for(unsigned i=0; i<2; ++i)
79 int j = ends[i]->get_link_slot(track);
82 const TrackType::Endpoint &ep1 = ends[i].endpoint();
83 const TrackType::Endpoint &ep2 = ends[i]->get_type().get_endpoint(j);
84 if(!ep1.has_common_paths(ep2))
94 void TrackChain::throw_bad_chain(Validity v)
97 throw bad_chain("unlinked");
99 throw bad_chain("bad path");
100 else if(v==INCOMPATIBLE)
101 throw bad_chain("incompatible");
104 void TrackChain::update_ends(Track &track)
107 // We don't really know the proper endpoint yet; just pick something
108 ends[0] = TrackIter(&track, 0);
111 // We're adding the second track; determine endpoints for both
112 ends[0] = TrackIter(&*ends[0], ends[0]->get_link_slot(track));
113 ends[1] = TrackIter(&track, track.get_link_slot(*ends[0]));
118 for(unsigned i=0; i<2; ++i)
119 if(ends[i]->get_link_slot(track)>=0)
124 // Closed loop; clear the ends
125 ends[0] = TrackIter();
126 ends[1] = TrackIter();
129 ends[linked-1] = TrackIter(&track, track.get_link_slot(*ends[linked-1]));
133 bool TrackChain::has_track(Track &t) const
135 return tracks.count(&t);
138 bool TrackChain::is_loop() const
140 return !tracks.empty() && !ends[0] && !ends[1];
143 void TrackChain::object_removed(Object &obj)
145 if(Track *track = dynamic_cast<Track *>(&obj))
148 /* TODO If the track was in the middle of the chain, keep only the
150 signal_track_removed.emit(*track);