*/
-#include <libcxml/cxml.h>
-#include <boost/shared_ptr.hpp>
#include "playlist.h"
#include "sndfile_content.h"
#include "sndfile_decoder.h"
#include "config.h"
#include "util.h"
#include "md5_digester.h"
+#include <libcxml/cxml.h>
+#include <libxml++/libxml++.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/foreach.hpp>
+#include <iostream>
#include "i18n.h"
DCPTime next_left;
DCPTime next_right;
- for (ContentList::iterator i = _content.begin(); i != _content.end(); ++i) {
- shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*i);
+ BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (i);
if (!vc) {
continue;
}
{
string t;
- for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
- shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (*i);
- shared_ptr<const SubtitleContent> sc = dynamic_pointer_cast<const SubtitleContent> (*i);
+ BOOST_FOREACH (shared_ptr<const Content> i, _content) {
+ shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (i);
+ shared_ptr<const SubtitleContent> sc = dynamic_pointer_cast<const SubtitleContent> (i);
if (vc) {
t += vc->identifier ();
} else if (sc && sc->burn_subtitles ()) {
void
Playlist::set_from_xml (shared_ptr<const Film> film, cxml::ConstNodePtr node, int version, list<string>& notes)
{
- list<cxml::NodePtr> c = node->node_children ("Content");
- for (list<cxml::NodePtr>::iterator i = c.begin(); i != c.end(); ++i) {
- _content.push_back (content_factory (film, *i, version, notes));
+ BOOST_FOREACH (cxml::NodePtr i, node->node_children ("Content")) {
+ _content.push_back (content_factory (film, i, version, notes));
}
sort (_content.begin(), _content.end(), ContentSorter ());
void
Playlist::as_xml (xmlpp::Node* node)
{
- for (ContentList::iterator i = _content.begin(); i != _content.end(); ++i) {
- (*i)->as_xml (node->add_child ("Content"));
+ BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ i->as_xml (node->add_child ("Content"));
}
}
void
Playlist::remove (ContentList c)
{
- for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
+ BOOST_FOREACH (shared_ptr<Content> i, c) {
ContentList::iterator j = _content.begin ();
- while (j != _content.end() && *j != *i) {
+ while (j != _content.end() && *j != i) {
++j;
}
while (i != candidates.end()) {
float this_error = 0;
- for (ContentList::const_iterator j = _content.begin(); j != _content.end(); ++j) {
- shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*j);
+ BOOST_FOREACH (shared_ptr<Content> j, _content) {
+ shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (j);
if (!vc) {
continue;
}
+ /* Best error for this content; we could use the content as-is or double its rate */
+ float best_error = min (
+ float (fabs (i->source - vc->video_frame_rate ())),
+ float (fabs (i->source - vc->video_frame_rate () * 2))
+ );
+
/* Use the largest difference between DCP and source as the "error" */
- this_error = max (this_error, float (fabs (i->source - vc->video_frame_rate ())));
+ this_error = max (this_error, best_error);
}
if (this_error < error) {
return best->dcp;
}
+/** @return length of the playlist from time 0 to the last thing on the playlist */
DCPTime
Playlist::length () const
{
DCPTime len;
- for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
- len = max (len, (*i)->end());
+ BOOST_FOREACH (shared_ptr<const Content> i, _content) {
+ len = max (len, i->end());
}
return len;
}
+/** @return position of the first thing on the playlist, if it's not empty */
+optional<DCPTime>
+Playlist::start () const
+{
+ if (_content.empty ()) {
+ return optional<DCPTime> ();
+ }
+
+ DCPTime start = DCPTime::max ();
+ BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ start = min (start, i->position ());
+ }
+
+ return start;
+}
+
void
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, _3)));
+ BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ _content_connections.push_back (i->Changed.connect (bind (&Playlist::content_changed, this, _1, _2, _3)));
}
}
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 ());
+ BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ if (dynamic_pointer_cast<const VideoContent> (i)) {
+ end = max (end, i->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) {
+ for (ContentList::const_reverse_iterator i = _content.rbegin(); i != _content.rend(); ++i) {
shared_ptr<const VideoContent> vc = dynamic_pointer_cast<const VideoContent> (*i);
if (!vc) {
continue;
}
- if (vc->position() >= t && t < vc->end()) {
+ if (vc->position() <= t) {
+ /* This is the first piece of content (going backwards...) that starts before t,
+ so it's the active one.
+ */
return FrameRateChange (vc->video_frame_rate(), dcp_video_frame_rate);
}
}
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 ());
+ BOOST_FOREACH (shared_ptr<Content> i, c) {
+ 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 ();
+ BOOST_FOREACH (shared_ptr<Content> j, c) {
+ shared_ptr<Content> copy = j->clone ();
copy->set_position (pos + copy->position() - range.first);
_content.push_back (copy);
}