using boost::shared_ptr;
using boost::weak_ptr;
using boost::dynamic_pointer_cast;
+using namespace dcpomatic;
Playlist::Playlist ()
: _sequence (true)
Playlist::~Playlist ()
{
+ boost::mutex::scoped_lock lm (_mutex);
_content.clear ();
disconnect ();
}
property == ContentProperty::TRIM_START ||
property == ContentProperty::TRIM_END) {
- ContentList old = _content;
- sort (_content.begin(), _content.end(), ContentSorter ());
- if (_content != old) {
- OrderChanged ();
+ bool changed = false;
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ ContentList old = _content;
+ sort (_content.begin(), _content.end(), ContentSorter ());
+ changed = _content != old;
+ }
+
+ if (changed) {
+ OrderChange ();
}
+
+ /* The length might have changed, and that's good enough for this signal */
+ LengthChange ();
}
}
_sequencing = true;
+ ContentList cont = content ();
+
/* Keep track of the content that we've set the position of so that we don't
do it twice.
*/
DCPTime next_left;
DCPTime next_right;
- BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<Content> i, cont) {
if (!i->video) {
continue;
}
/* Captions */
DCPTime next;
- BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<Content> i, cont) {
if (i->text.empty() || find (placed.begin(), placed.end(), i) != placed.end()) {
continue;
}
{
string t;
- BOOST_FOREACH (shared_ptr<const Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<const Content> i, content()) {
bool burn = false;
BOOST_FOREACH (shared_ptr<TextContent> j, i->text) {
if (j->burn()) {
void
Playlist::set_from_xml (shared_ptr<const Film> film, cxml::ConstNodePtr node, int version, list<string>& notes)
{
+ boost::mutex::scoped_lock lm (_mutex);
+
BOOST_FOREACH (cxml::NodePtr i, node->node_children ("Content")) {
shared_ptr<Content> content = content_factory (i, version, notes);
void
Playlist::as_xml (xmlpp::Node* node, bool with_content_paths)
{
- BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<Content> i, content()) {
i->as_xml (node->add_child ("Content"), with_content_paths);
}
}
Playlist::add (shared_ptr<const Film> film, shared_ptr<Content> c)
{
Change (CHANGE_TYPE_PENDING);
- _content.push_back (c);
- sort (_content.begin(), _content.end(), ContentSorter ());
- reconnect (film);
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ _content.push_back (c);
+ sort (_content.begin(), _content.end(), ContentSorter ());
+ reconnect (film);
+ }
+
Change (CHANGE_TYPE_DONE);
+
+ LengthChange ();
}
void
{
Change (CHANGE_TYPE_PENDING);
- ContentList::iterator i = _content.begin ();
- while (i != _content.end() && *i != c) {
- ++i;
+ bool cancelled = false;
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ ContentList::iterator i = _content.begin ();
+ while (i != _content.end() && *i != c) {
+ ++i;
+ }
+
+ if (i != _content.end()) {
+ _content.erase (i);
+ } else {
+ cancelled = true;
+ }
}
- if (i != _content.end ()) {
- _content.erase (i);
- Change (CHANGE_TYPE_DONE);
- } else {
+ if (cancelled) {
Change (CHANGE_TYPE_CANCELLED);
+ } else {
+ Change (CHANGE_TYPE_DONE);
}
/* This won't change order, so it does not need a sort */
+
+ LengthChange ();
}
void
{
Change (CHANGE_TYPE_PENDING);
- BOOST_FOREACH (shared_ptr<Content> i, c) {
- ContentList::iterator j = _content.begin ();
- while (j != _content.end() && *j != i) {
- ++j;
- }
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ BOOST_FOREACH (shared_ptr<Content> i, c) {
+ ContentList::iterator j = _content.begin ();
+ while (j != _content.end() && *j != i) {
+ ++j;
+ }
- if (j != _content.end ()) {
- _content.erase (j);
+ if (j != _content.end ()) {
+ _content.erase (j);
+ }
}
}
+ Change (CHANGE_TYPE_DONE);
+
/* This won't change order, so it does not need a sort */
- Change (CHANGE_TYPE_DONE);
+ LengthChange ();
}
class FrameRateCandidate
while (i != candidates.end()) {
float this_error = 0;
- BOOST_FOREACH (shared_ptr<Content> j, _content) {
+ BOOST_FOREACH (shared_ptr<Content> j, content()) {
if (!j->video || !j->video_frame_rate()) {
continue;
}
Playlist::length (shared_ptr<const Film> film) const
{
DCPTime len;
- BOOST_FOREACH (shared_ptr<const Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<const Content> i, content()) {
len = max (len, i->end(film));
}
optional<DCPTime>
Playlist::start () const
{
- if (_content.empty ()) {
+ ContentList cont = content ();
+ if (cont.empty()) {
return optional<DCPTime> ();
}
DCPTime start = DCPTime::max ();
- BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<Content> i, cont) {
start = min (start, i->position ());
}
return start;
}
+/** Must be called with a lock held on _mutex */
void
Playlist::disconnect ()
{
- for (list<boost::signals2::connection>::iterator i = _content_connections.begin(); i != _content_connections.end(); ++i) {
- i->disconnect ();
+ BOOST_FOREACH (boost::signals2::connection& i, _content_connections) {
+ i.disconnect ();
}
_content_connections.clear ();
}
+/** Must be called with a lock held on _mutex */
void
Playlist::reconnect (shared_ptr<const Film> film)
{
Playlist::video_end (shared_ptr<const Film> film) const
{
DCPTime end;
- BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<Content> i, content()) {
if (i->video) {
end = max (end, i->end(film));
}
Playlist::text_end (shared_ptr<const Film> film) const
{
DCPTime end;
- BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<Content> i, content()) {
if (!i->text.empty ()) {
end = max (end, i->end(film));
}
FrameRateChange
Playlist::active_frame_rate_change (DCPTime t, int dcp_video_frame_rate) const
{
- for (ContentList::const_reverse_iterator i = _content.rbegin(); i != _content.rend(); ++i) {
+ ContentList cont = content ();
+ for (ContentList::const_reverse_iterator i = cont.rbegin(); i != cont.rend(); ++i) {
if (!(*i)->video) {
continue;
}
ContentList
Playlist::content () const
{
+ boost::mutex::scoped_lock lm (_mutex);
return _content;
}
Change (CHANGE_TYPE_PENDING);
- DCPTime pos = range.second;
- for (int i = 0; i < n; ++i) {
- BOOST_FOREACH (shared_ptr<Content> j, c) {
- shared_ptr<Content> copy = j->clone ();
- copy->set_position (film, pos + copy->position() - range.first);
- _content.push_back (copy);
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ DCPTime pos = range.second;
+ for (int i = 0; i < n; ++i) {
+ BOOST_FOREACH (shared_ptr<Content> j, c) {
+ shared_ptr<Content> copy = j->clone ();
+ copy->set_position (film, pos + copy->position() - range.first);
+ _content.push_back (copy);
+ }
+ pos += range.second - range.first;
}
- pos += range.second - range.first;
- }
- sort (_content.begin(), _content.end(), ContentSorter ());
+ sort (_content.begin(), _content.end(), ContentSorter ());
+ reconnect (film);
+ }
- reconnect (film);
Change (CHANGE_TYPE_DONE);
}
void
Playlist::move_earlier (shared_ptr<const Film> film, shared_ptr<Content> c)
{
- ContentList::iterator previous = _content.end ();
- ContentList::iterator i = _content.begin();
- while (i != _content.end() && *i != c) {
+ ContentList cont = content ();
+ ContentList::iterator previous = cont.end();
+ ContentList::iterator i = cont.begin();
+ while (i != cont.end() && *i != c) {
previous = i;
++i;
}
- DCPOMATIC_ASSERT (i != _content.end ());
- if (previous == _content.end ()) {
+ DCPOMATIC_ASSERT (i != cont.end());
+ if (previous == cont.end()) {
return;
}
void
Playlist::move_later (shared_ptr<const Film> film, shared_ptr<Content> c)
{
- ContentList::iterator i = _content.begin();
- while (i != _content.end() && *i != c) {
+ ContentList cont = content ();
+ ContentList::iterator i = cont.begin();
+ while (i != cont.end() && *i != c) {
++i;
}
- DCPOMATIC_ASSERT (i != _content.end ());
+ DCPOMATIC_ASSERT (i != cont.end());
ContentList::iterator next = i;
++next;
- if (next == _content.end ()) {
+ if (next == cont.end()) {
return;
}
int64_t video = uint64_t (j2k_bandwidth / 8) * length(film).seconds();
int64_t audio = uint64_t (audio_channels * audio_frame_rate * 3) * length(film).seconds();
- BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<Content> i, content()) {
shared_ptr<DCPContent> d = dynamic_pointer_cast<DCPContent> (i);
if (d) {
if (d->reference_video()) {
{
string best_summary;
int best_score = -1;
- BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<Content> i, content()) {
int score = 0;
optional<DCPTimePeriod> const o = DCPTimePeriod(i->position(), i->end(film)).overlap (period);
if (o) {
{
pair<double, double> range (DBL_MAX, -DBL_MAX);
- BOOST_FOREACH (shared_ptr<Content> i, _content) {
+ BOOST_FOREACH (shared_ptr<Content> i, content()) {
if (!i->video) {
continue;
}