X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fplaylist.cc;h=e4494acb052b74f6ef545dcf8568a290a1918137;hb=a6d892268ccdf8e50194c0168491c8a360bbb687;hp=aea6c5f413deaae0f6c95e2a702a596f6e7010ae;hpb=a8b5ac47b89927eb2495dba71393a8a073967560;p=dcpomatic.git diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc index aea6c5f41..e4494acb0 100644 --- a/src/lib/playlist.cc +++ b/src/lib/playlist.cc @@ -28,6 +28,7 @@ #include "ffmpeg_content.h" #include "imagemagick_decoder.h" #include "imagemagick_content.h" +#include "content_factory.h" #include "job.h" #include "config.h" #include "util.h" @@ -41,6 +42,7 @@ using std::min; using std::max; using std::string; using std::stringstream; +using std::pair; using boost::optional; using boost::shared_ptr; using boost::weak_ptr; @@ -48,21 +50,12 @@ using boost::dynamic_pointer_cast; using boost::lexical_cast; Playlist::Playlist () - : _loop (1) - , _sequence_video (true) + : _sequence_video (true) , _sequencing_video (false) { } -Playlist::Playlist (shared_ptr other) - : _loop (other->_loop) -{ - for (ContentList::const_iterator i = other->_content.begin(); i != other->_content.end(); ++i) { - _content.push_back ((*i)->clone ()); - } -} - Playlist::~Playlist () { _content.clear (); @@ -70,15 +63,16 @@ Playlist::~Playlist () } void -Playlist::content_changed (weak_ptr c, int p) +Playlist::content_changed (weak_ptr content, int property, bool frequent) { - if (p == ContentProperty::LENGTH) { + if (property == ContentProperty::LENGTH) { maybe_sequence_video (); } - ContentChanged (c, p); + ContentChanged (content, property, frequent); } + void Playlist::maybe_sequence_video () { @@ -115,8 +109,6 @@ Playlist::video_identifier () const } } - t += lexical_cast (_loop); - return md5_digest (t.c_str(), t.length()); } @@ -126,23 +118,10 @@ Playlist::set_from_xml (shared_ptr film, shared_ptr > c = node->node_children ("Content"); for (list >::iterator i = c.begin(); i != c.end(); ++i) { - string const type = (*i)->string_child ("Type"); - - boost::shared_ptr content; - - if (type == "FFmpeg") { - content.reset (new FFmpegContent (film, *i)); - } else if (type == "ImageMagick") { - content.reset (new ImageMagickContent (film, *i)); - } else if (type == "Sndfile") { - content.reset (new SndfileContent (film, *i)); - } - - _content.push_back (content); + _content.push_back (content_factory (film, *i)); } reconnect (); - _loop = node->number_child ("Loop"); _sequence_video = node->bool_child ("SequenceVideo"); } @@ -154,7 +133,6 @@ Playlist::as_xml (xmlpp::Node* node) (*i)->as_xml (node->add_child ("Content")); } - node->add_child("Loop")->add_child_text(lexical_cast (_loop)); node->add_child("SequenceVideo")->add_child_text(_sequence_video ? "1" : "0"); } @@ -180,13 +158,6 @@ Playlist::remove (shared_ptr c) } } -void -Playlist::set_loop (int l) -{ - _loop = l; - Changed (); -} - bool Playlist::has_subtitles () const { @@ -231,7 +202,7 @@ Playlist::best_dcp_frame_rate () const candidates.push_back (FrameRateCandidate (float (*i) * 2, *i)); } - /* Pick the best one, bailing early if we hit an exact match */ + /* Pick the best one */ float error = std::numeric_limits::max (); optional best; list::iterator i = candidates.begin(); @@ -244,7 +215,8 @@ Playlist::best_dcp_frame_rate () const continue; } - this_error += fabs (i->source - vc->video_frame_rate ()); + /* Use the largest difference between DCP and source as the "error" */ + this_error = max (this_error, float (fabs (i->source - vc->video_frame_rate ()))); } if (this_error < error) { @@ -283,7 +255,7 @@ Playlist::reconnect () _content_connections.clear (); for (ContentList::iterator i = _content.begin(); i != _content.end(); ++i) { - _content_connections.push_back ((*i)->Changed.connect (bind (&Playlist::content_changed, this, _1, _2))); + _content_connections.push_back ((*i)->Changed.connect (bind (&Playlist::content_changed, this, _1, _2, _3))); } } @@ -311,3 +283,35 @@ ContentSorter::operator() (shared_ptr a, shared_ptr b) { return a->start() < b->start(); } + +/** @return content in an undefined order */ +Playlist::ContentList +Playlist::content () const +{ + return _content; +} + +void +Playlist::repeat (list > c, int n) +{ + pair range (TIME_MAX, 0); + for (list >::iterator i = c.begin(); i != c.end(); ++i) { + range.first = min (range.first, (*i)->start ()); + range.second = max (range.second, (*i)->start ()); + range.first = min (range.first, (*i)->end ()); + range.second = max (range.second, (*i)->end ()); + } + + Time pos = range.second; + for (int i = 0; i < n; ++i) { + for (list >::iterator i = c.begin(); i != c.end(); ++i) { + shared_ptr copy = (*i)->clone (); + copy->set_start (pos + copy->start() - range.first); + _content.push_back (copy); + } + pos += range.second - range.first; + } + + reconnect (); + Changed (); +}