+ _content_connections.push_back ((*i)->Changed.connect (bind (&Playlist::content_changed, this, _1, _2, _3)));
+ }
+}
+
+DCPTime
+Playlist::video_end () const
+{
+ DCPTime end;
+ for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
+ if (dynamic_pointer_cast<const VideoContent> (*i)) {
+ end = max (end, (*i)->end ());
+ }
+ }
+
+ return end;
+}
+
+FrameRateChange
+Playlist::active_frame_rate_change (DCPTime t, int dcp_video_frame_rate) const
+{
+ for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
+ shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (*i);
+ if (!vc) {
+ break;
+ }
+
+ if (vc->position() >= t && t < vc->end()) {
+ return FrameRateChange (vc->video_frame_rate(), dcp_video_frame_rate);
+ }
+ }
+
+ return FrameRateChange (dcp_video_frame_rate, dcp_video_frame_rate);
+}
+
+void
+Playlist::set_sequence_video (bool s)
+{
+ _sequence_video = s;
+}
+
+bool
+ContentSorter::operator() (shared_ptr<Content> a, shared_ptr<Content> b)
+{
+ return a->position() < b->position();
+}
+
+/** @return content in an undefined order */
+ContentList
+Playlist::content () const
+{
+ return _content;
+}
+
+void
+Playlist::repeat (ContentList c, int n)
+{
+ pair<DCPTime, DCPTime> range (DCPTime::max (), DCPTime ());
+ for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
+ range.first = min (range.first, (*i)->position ());
+ range.second = max (range.second, (*i)->position ());
+ range.first = min (range.first, (*i)->end ());
+ range.second = max (range.second, (*i)->end ());
+ }
+
+ DCPTime pos = range.second;
+ for (int i = 0; i < n; ++i) {
+ for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
+ shared_ptr<Content> copy = (*i)->clone ();
+ copy->set_position (pos + copy->position() - range.first);
+ _content.push_back (copy);
+ }
+ pos += range.second - range.first;
+ }
+
+ sort (_content.begin(), _content.end(), ContentSorter ());
+
+ reconnect ();
+ Changed ();
+}
+
+void
+Playlist::move_earlier (shared_ptr<Content> c)
+{
+ sort (_content.begin(), _content.end(), ContentSorter ());
+
+ ContentList::iterator previous = _content.end ();
+ ContentList::iterator i = _content.begin();
+ while (i != _content.end() && *i != c) {
+ previous = i;
+ ++i;