summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-05-21 17:32:28 +0100
committerCarl Hetherington <cth@carlh.net>2013-05-21 17:32:28 +0100
commit2255aedd15f985796d2e6f7fcc7fb412a5d98812 (patch)
tree744d52adfdd226ce5b0220d62612710873fa77f4 /src/lib
parent2de990b0155fcb5c3dac821ef8c2659e903d2f6e (diff)
Various more hacks; basically trying to remove Regions as an unnecessary complexity.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/audio_content.h2
-rw-r--r--src/lib/content.cc7
-rw-r--r--src/lib/content.h6
-rw-r--r--src/lib/ffmpeg_content.cc47
-rw-r--r--src/lib/ffmpeg_content.h23
-rw-r--r--src/lib/ffmpeg_decoder.cc6
-rw-r--r--src/lib/ffmpeg_decoder.h10
-rw-r--r--src/lib/film.cc16
-rw-r--r--src/lib/film.h2
-rw-r--r--src/lib/player.cc54
-rw-r--r--src/lib/player.h12
-rw-r--r--src/lib/playlist.cc118
-rw-r--r--src/lib/playlist.h32
-rw-r--r--src/lib/sndfile_content.h6
14 files changed, 189 insertions, 152 deletions
diff --git a/src/lib/audio_content.h b/src/lib/audio_content.h
index 36c36992e..51f05efb0 100644
--- a/src/lib/audio_content.h
+++ b/src/lib/audio_content.h
@@ -23,6 +23,7 @@
#define DCPOMATIC_AUDIO_CONTENT_H
#include "content.h"
+#include "audio_mapping.h"
namespace cxml {
class Node;
@@ -49,6 +50,7 @@ public:
virtual ContentAudioFrame audio_length () const = 0;
virtual int content_audio_frame_rate () const = 0;
virtual int output_audio_frame_rate (boost::shared_ptr<const Film>) const = 0;
+ virtual AudioMapping audio_mapping () const = 0;
};
#endif
diff --git a/src/lib/content.cc b/src/lib/content.cc
index 9c3bcd39d..578dafd67 100644
--- a/src/lib/content.cc
+++ b/src/lib/content.cc
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
/*
Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
@@ -25,9 +27,11 @@
using std::string;
using boost::shared_ptr;
+using boost::lexical_cast;
Content::Content (boost::filesystem::path f)
: _file (f)
+ , _time (0)
{
}
@@ -36,12 +40,14 @@ Content::Content (shared_ptr<const cxml::Node> node)
{
_file = node->string_child ("File");
_digest = node->string_child ("Digest");
+ _time = node->number_child<Time> ("Time");
}
Content::Content (Content const & o)
: boost::enable_shared_from_this<Content> (o)
, _file (o._file)
, _digest (o._digest)
+ , _time (o._time)
{
}
@@ -52,6 +58,7 @@ Content::as_xml (xmlpp::Node* node) const
boost::mutex::scoped_lock lm (_mutex);
node->add_child("File")->add_child_text (_file.string());
node->add_child("Digest")->add_child_text (_digest);
+ node->add_child("Time")->add_child_text (lexical_cast<string> (_time));
}
void
diff --git a/src/lib/content.h b/src/lib/content.h
index 8db35891a..fd6288acc 100644
--- a/src/lib/content.h
+++ b/src/lib/content.h
@@ -60,6 +60,11 @@ public:
return _digest;
}
+ Time time () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _time;
+ }
+
boost::signals2::signal<void (boost::weak_ptr<Content>, int)> Changed;
protected:
@@ -70,6 +75,7 @@ protected:
private:
boost::filesystem::path _file;
std::string _digest;
+ Time _time;
};
#endif
diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc
index e898c02d0..fcc775f0a 100644
--- a/src/lib/ffmpeg_content.cc
+++ b/src/lib/ffmpeg_content.cc
@@ -57,7 +57,7 @@ FFmpegContent::FFmpegContent (shared_ptr<const cxml::Node> node)
{
list<shared_ptr<cxml::Node> > c = node->node_children ("SubtitleStream");
for (list<shared_ptr<cxml::Node> >::const_iterator i = c.begin(); i != c.end(); ++i) {
- _subtitle_streams.push_back (FFmpegSubtitleStream (*i));
+ _subtitle_streams.push_back (shared_ptr<FFmpegSubtitleStream> (new FFmpegSubtitleStream (*i)));
if ((*i)->optional_number_child<int> ("Selected")) {
_subtitle_stream = _subtitle_streams.back ();
}
@@ -65,7 +65,7 @@ FFmpegContent::FFmpegContent (shared_ptr<const cxml::Node> node)
c = node->node_children ("AudioStream");
for (list<shared_ptr<cxml::Node> >::const_iterator i = c.begin(); i != c.end(); ++i) {
- _audio_streams.push_back (FFmpegAudioStream (*i));
+ _audio_streams.push_back (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream (*i)));
if ((*i)->optional_number_child<int> ("Selected")) {
_audio_stream = _audio_streams.back ();
}
@@ -94,20 +94,20 @@ FFmpegContent::as_xml (xmlpp::Node* node) const
boost::mutex::scoped_lock lm (_mutex);
- for (vector<FFmpegSubtitleStream>::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) {
+ for (vector<shared_ptr<FFmpegSubtitleStream> >::const_iterator i = _subtitle_streams.begin(); i != _subtitle_streams.end(); ++i) {
xmlpp::Node* t = node->add_child("SubtitleStream");
- if (_subtitle_stream && *i == _subtitle_stream.get()) {
+ if (_subtitle_stream && *i == _subtitle_stream) {
t->add_child("Selected")->add_child_text("1");
}
- i->as_xml (t);
+ (*i)->as_xml (t);
}
- for (vector<FFmpegAudioStream>::const_iterator i = _audio_streams.begin(); i != _audio_streams.end(); ++i) {
+ for (vector<shared_ptr<FFmpegAudioStream> >::const_iterator i = _audio_streams.begin(); i != _audio_streams.end(); ++i) {
xmlpp::Node* t = node->add_child("AudioStream");
- if (_audio_stream && *i == _audio_stream.get()) {
+ if (_audio_stream && *i == _audio_stream) {
t->add_child("Selected")->add_child_text("1");
}
- i->as_xml (t);
+ (*i)->as_xml (t);
}
}
@@ -181,7 +181,7 @@ FFmpegContent::information () const
}
void
-FFmpegContent::set_subtitle_stream (FFmpegSubtitleStream s)
+FFmpegContent::set_subtitle_stream (shared_ptr<FFmpegSubtitleStream> s)
{
{
boost::mutex::scoped_lock lm (_mutex);
@@ -192,7 +192,7 @@ FFmpegContent::set_subtitle_stream (FFmpegSubtitleStream s)
}
void
-FFmpegContent::set_audio_stream (FFmpegAudioStream s)
+FFmpegContent::set_audio_stream (shared_ptr<FFmpegAudioStream> s)
{
{
boost::mutex::scoped_lock lm (_mutex);
@@ -205,16 +205,23 @@ FFmpegContent::set_audio_stream (FFmpegAudioStream s)
ContentAudioFrame
FFmpegContent::audio_length () const
{
+ int const cafr = content_audio_frame_rate ();
+ int const vfr = video_frame_rate ();
+ ContentVideoFrame const vl = video_length ();
+
+ boost::mutex::scoped_lock lm (_mutex);
if (!_audio_stream) {
return 0;
}
- return video_frames_to_audio_frames (_video_length, content_audio_frame_rate(), video_frame_rate());
+ return video_frames_to_audio_frames (vl, cafr, vfr);
}
int
FFmpegContent::audio_channels () const
{
+ boost::mutex::scoped_lock lm (_mutex);
+
if (!_audio_stream) {
return 0;
}
@@ -225,6 +232,8 @@ FFmpegContent::audio_channels () const
int
FFmpegContent::content_audio_frame_rate () const
{
+ boost::mutex::scoped_lock lm (_mutex);
+
if (!_audio_stream) {
return 0;
}
@@ -271,6 +280,7 @@ FFmpegAudioStream::FFmpegAudioStream (shared_ptr<const cxml::Node> node)
id = node->number_child<int> ("Id");
frame_rate = node->number_child<int> ("FrameRate");
channels = node->number_child<int64_t> ("Channels");
+ mapping = AudioMapping (node->node_child ("Mapping"));
}
void
@@ -280,6 +290,7 @@ FFmpegAudioStream::as_xml (xmlpp::Node* root) const
root->add_child("Id")->add_child_text (lexical_cast<string> (id));
root->add_child("FrameRate")->add_child_text (lexical_cast<string> (frame_rate));
root->add_child("Channels")->add_child_text (lexical_cast<string> (channels));
+ mapping.as_xml (root->add_child("Mapping"));
}
/** Construct a SubtitleStream from a value returned from to_string().
@@ -311,3 +322,17 @@ FFmpegContent::length (shared_ptr<const Film> film) const
FrameRateConversion frc (video_frame_rate (), film->dcp_video_frame_rate ());
return video_length() * frc.factor() * TIME_HZ / film->dcp_video_frame_rate ();
}
+
+AudioMapping
+FFmpegContent::audio_mapping () const
+{
+ boost::mutex::scoped_lock lm (_mutex);
+
+ if (!_audio_stream) {
+ return AudioMapping ();
+ }
+
+ cout << "returning am from stream " << _audio_stream.get() << ".\n";
+ return _audio_stream->mapping;
+}
+
diff --git a/src/lib/ffmpeg_content.h b/src/lib/ffmpeg_content.h
index 6c141b6c1..d79e4ec35 100644
--- a/src/lib/ffmpeg_content.h
+++ b/src/lib/ffmpeg_content.h
@@ -34,6 +34,7 @@ public:
, id (i)
, frame_rate (f)
, channels (c)
+ , mapping (c)
{}
FFmpegAudioStream (boost::shared_ptr<const cxml::Node>);
@@ -44,6 +45,7 @@ public:
int id;
int frame_rate;
int channels;
+ AudioMapping mapping;
};
extern bool operator== (FFmpegAudioStream const & a, FFmpegAudioStream const & b);
@@ -98,35 +100,36 @@ public:
ContentAudioFrame audio_length () const;
int content_audio_frame_rate () const;
int output_audio_frame_rate (boost::shared_ptr<const Film>) const;
+ AudioMapping audio_mapping () const;
- std::vector<FFmpegSubtitleStream> subtitle_streams () const {
+ std::vector<boost::shared_ptr<FFmpegSubtitleStream> > subtitle_streams () const {
boost::mutex::scoped_lock lm (_mutex);
return _subtitle_streams;
}
- boost::optional<FFmpegSubtitleStream> subtitle_stream () const {
+ boost::shared_ptr<FFmpegSubtitleStream> subtitle_stream () const {
boost::mutex::scoped_lock lm (_mutex);
return _subtitle_stream;
}
- std::vector<FFmpegAudioStream> audio_streams () const {
+ std::vector<boost::shared_ptr<FFmpegAudioStream> > audio_streams () const {
boost::mutex::scoped_lock lm (_mutex);
return _audio_streams;
}
- boost::optional<FFmpegAudioStream> audio_stream () const {
+ boost::shared_ptr<FFmpegAudioStream> audio_stream () const {
boost::mutex::scoped_lock lm (_mutex);
return _audio_stream;
}
- void set_subtitle_stream (FFmpegSubtitleStream);
- void set_audio_stream (FFmpegAudioStream);
+ void set_subtitle_stream (boost::shared_ptr<FFmpegSubtitleStream>);
+ void set_audio_stream (boost::shared_ptr<FFmpegAudioStream>);
private:
- std::vector<FFmpegSubtitleStream> _subtitle_streams;
- boost::optional<FFmpegSubtitleStream> _subtitle_stream;
- std::vector<FFmpegAudioStream> _audio_streams;
- boost::optional<FFmpegAudioStream> _audio_stream;
+ std::vector<boost::shared_ptr<FFmpegSubtitleStream> > _subtitle_streams;
+ boost::shared_ptr<FFmpegSubtitleStream> _subtitle_stream;
+ std::vector<boost::shared_ptr<FFmpegAudioStream> > _audio_streams;
+ boost::shared_ptr<FFmpegAudioStream> _audio_stream;
};
#endif
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index adf16c940..a637160ae 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -141,11 +141,13 @@ FFmpegDecoder::setup_general ()
}
_audio_streams.push_back (
- FFmpegAudioStream (stream_name (s), i, s->codec->sample_rate, s->codec->channels)
+ shared_ptr<FFmpegAudioStream> (
+ new FFmpegAudioStream (stream_name (s), i, s->codec->sample_rate, s->codec->channels)
+ )
);
} else if (s->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
- _subtitle_streams.push_back (FFmpegSubtitleStream (stream_name (s), i));
+ _subtitle_streams.push_back (shared_ptr<FFmpegSubtitleStream> (new FFmpegSubtitleStream (stream_name (s), i)));
}
}
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index 760fc084d..f3f6b126b 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -1,3 +1,5 @@
+/* -*- c-basic-offset: 8; default-tab-width: 8; -*- */
+
/*
Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
@@ -68,11 +70,11 @@ public:
int sample_aspect_ratio_numerator () const;
int sample_aspect_ratio_denominator () const;
- std::vector<FFmpegSubtitleStream> subtitle_streams () const {
+ std::vector<boost::shared_ptr<FFmpegSubtitleStream> > subtitle_streams () const {
return _subtitle_streams;
}
- std::vector<FFmpegAudioStream> audio_streams () const {
+ std::vector<boost::shared_ptr<FFmpegAudioStream> > audio_streams () const {
return _audio_streams;
}
@@ -126,8 +128,8 @@ private:
std::list<boost::shared_ptr<FilterGraph> > _filter_graphs;
boost::mutex _filter_graphs_mutex;
- std::vector<FFmpegSubtitleStream> _subtitle_streams;
- std::vector<FFmpegAudioStream> _audio_streams;
+ std::vector<boost::shared_ptr<FFmpegSubtitleStream> > _subtitle_streams;
+ std::vector<boost::shared_ptr<FFmpegAudioStream> > _audio_streams;
bool _decode_video;
bool _decode_audio;
diff --git a/src/lib/film.cc b/src/lib/film.cc
index 1b5779f2d..37af4cb20 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -317,7 +317,7 @@ Film::make_dcp ()
throw MissingSettingError (_("format"));
}
- if (_playlist->regions().empty ()) {
+ if (_playlist->content().empty ()) {
throw StringError (_("You must add some content to the DCP before creating it"));
}
@@ -697,11 +697,11 @@ Film::set_trust_content_headers (bool t)
signal_changed (TRUST_CONTENT_HEADERS);
- Playlist::RegionList regions = _playlist->regions ();
- if (!_trust_content_headers && !regions.empty()) {
+ Playlist::ContentList content = _playlist->content ();
+ if (!_trust_content_headers && !content.empty()) {
/* We just said that we don't trust the content's header */
- for (Playlist::RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
- examine_content ((*i)->content);
+ for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
+ examine_content (*i);
}
}
}
@@ -1040,10 +1040,10 @@ Film::playlist () const
return _playlist;
}
-Playlist::RegionList
-Film::regions () const
+Playlist::ContentList
+Film::content () const
{
- return _playlist->regions ();
+ return _playlist->content ();
}
void
diff --git a/src/lib/film.h b/src/lib/film.h
index 03d472cee..c0417382f 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -111,7 +111,7 @@ public:
/* Proxies for some Playlist methods */
- Playlist::RegionList regions () const;
+ Playlist::ContentList content () const;
Time length () const;
bool has_subtitles () const;
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 675fcae5c..5d4635e5a 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -89,12 +89,12 @@ Player::pass ()
*/
Time earliest_pos = TIME_MAX;
- shared_ptr<RegionDecoder> earliest;
+ shared_ptr<DecoderRecord> earliest;
Time next_wait = TIME_MAX;
- for (list<shared_ptr<RegionDecoder> >::iterator i = _decoders.begin(); i != _decoders.end(); ++i) {
- Time const ts = (*i)->region->time;
- Time const te = (*i)->region->time + (*i)->region->content->length (_film);
+ for (list<shared_ptr<DecoderRecord> >::iterator i = _decoders.begin(); i != _decoders.end(); ++i) {
+ Time const ts = (*i)->content->time();
+ Time const te = (*i)->content->time() + (*i)->content->length (_film);
if (ts <= _position && te > _position) {
Time const pos = ts + (*i)->last;
if (pos < earliest_pos) {
@@ -121,24 +121,24 @@ Player::pass ()
}
void
-Player::process_video (shared_ptr<RegionDecoder> rd, shared_ptr<const Image> image, bool same, shared_ptr<Subtitle> sub, Time time)
+Player::process_video (shared_ptr<DecoderRecord> dr, shared_ptr<const Image> image, bool same, shared_ptr<Subtitle> sub, Time time)
{
- shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> (rd->decoder);
+ shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> (dr->decoder);
- Time const global_time = rd->region->time + time;
+ Time const global_time = dr->content->time() + time;
while ((global_time - _last_video) > 1) {
/* Fill in with black */
emit_black_frame ();
}
Video (image, same, sub, global_time);
- rd->last = time;
+ dr->last = time;
_last_video = global_time;
_last_was_black = false;
}
void
-Player::process_audio (shared_ptr<RegionDecoder> rd, shared_ptr<const AudioBuffers> audio, Time time)
+Player::process_audio (shared_ptr<DecoderRecord> dr, shared_ptr<const AudioBuffers> audio, Time time)
{
/* XXX: mapping */
@@ -172,7 +172,7 @@ Player::process_audio (shared_ptr<RegionDecoder> rd, shared_ptr<const AudioBuffe
_audio_buffers.ensure_size (time - _last_audio + audio->frames());
_audio_buffers.accumulate (audio.get(), 0, _film->time_to_audio_frames (time - _last_audio));
- rd->last = time + _film->audio_frames_to_time (audio->frames ());
+ dr->last = time + _film->audio_frames_to_time (audio->frames ());
}
/** @return true on error */
@@ -212,34 +212,34 @@ Player::seek_forward ()
void
Player::setup_decoders ()
{
- list<shared_ptr<RegionDecoder> > old_decoders = _decoders;
+ list<shared_ptr<DecoderRecord> > old_decoders = _decoders;
_decoders.clear ();
- Playlist::RegionList regions = _playlist->regions ();
- for (Playlist::RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
+ Playlist::ContentList content = _playlist->content ();
+ for (Playlist::ContentList::iterator i = content.begin(); i != content.end(); ++i) {
- shared_ptr<RegionDecoder> rd (new RegionDecoder);
- rd->region = *i;
+ shared_ptr<DecoderRecord> dr (new DecoderRecord);
+ dr->content = *i;
/* XXX: into content? */
- shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> ((*i)->content);
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
if (fc) {
shared_ptr<FFmpegDecoder> fd (new FFmpegDecoder (_film, fc, _video, _audio, _subtitles));
- fd->Video.connect (bind (&Player::process_video, this, rd, _1, _2, _3, _4));
- fd->Audio.connect (bind (&Player::process_audio, this, rd, _1, _2));
+ fd->Video.connect (bind (&Player::process_video, this, dr, _1, _2, _3, _4));
+ fd->Audio.connect (bind (&Player::process_audio, this, dr, _1, _2));
- rd->decoder = fd;
+ dr->decoder = fd;
}
- shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> ((*i)->content);
+ shared_ptr<const ImageMagickContent> ic = dynamic_pointer_cast<const ImageMagickContent> (*i);
if (ic) {
shared_ptr<ImageMagickDecoder> id;
/* See if we can re-use an old ImageMagickDecoder */
- for (list<shared_ptr<RegionDecoder> >::const_iterator i = old_decoders.begin(); i != old_decoders.end(); ++i) {
+ for (list<shared_ptr<DecoderRecord> >::const_iterator i = old_decoders.begin(); i != old_decoders.end(); ++i) {
shared_ptr<ImageMagickDecoder> imd = dynamic_pointer_cast<ImageMagickDecoder> ((*i)->decoder);
if (imd && imd->content() == ic) {
id = imd;
@@ -248,21 +248,21 @@ Player::setup_decoders ()
if (!id) {
id.reset (new ImageMagickDecoder (_film, ic));
- id->Video.connect (bind (&Player::process_video, this, rd, _1, _2, _3, _4));
+ id->Video.connect (bind (&Player::process_video, this, dr, _1, _2, _3, _4));
}
- rd->decoder = id;
+ dr->decoder = id;
}
- shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> ((*i)->content);
+ shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
if (sc) {
shared_ptr<AudioDecoder> sd (new SndfileDecoder (_film, sc));
- sd->Audio.connect (bind (&Player::process_audio, this, rd, _1, _2));
+ sd->Audio.connect (bind (&Player::process_audio, this, dr, _1, _2));
- rd->decoder = sd;
+ dr->decoder = sd;
}
- _decoders.push_back (rd);
+ _decoders.push_back (dr);
}
_position = 0;
diff --git a/src/lib/player.h b/src/lib/player.h
index 4979778ed..44b95e076 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -62,19 +62,19 @@ public:
private:
- struct RegionDecoder
+ struct DecoderRecord
{
- RegionDecoder ()
+ DecoderRecord ()
: last (0)
{}
- boost::shared_ptr<Playlist::Region> region;
+ boost::shared_ptr<Content> content;
boost::shared_ptr<Decoder> decoder;
Time last;
};
- void process_video (boost::shared_ptr<RegionDecoder>, boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, Time);
- void process_audio (boost::shared_ptr<RegionDecoder>, boost::shared_ptr<const AudioBuffers>, Time);
+ void process_video (boost::shared_ptr<DecoderRecord>, boost::shared_ptr<const Image>, bool, boost::shared_ptr<Subtitle>, Time);
+ void process_audio (boost::shared_ptr<DecoderRecord>, boost::shared_ptr<const AudioBuffers>, Time);
void setup_decoders ();
void playlist_changed ();
void content_changed (boost::weak_ptr<Content>, int);
@@ -90,7 +90,7 @@ private:
/** Our decoders are ready to go; if this is false the decoders must be (re-)created before they are used */
bool _have_valid_decoders;
- std::list<boost::shared_ptr<RegionDecoder> > _decoders;
+ std::list<boost::shared_ptr<DecoderRecord> > _decoders;
Time _position;
AudioBuffers _audio_buffers;
diff --git a/src/lib/playlist.cc b/src/lib/playlist.cc
index 8db5c5fc2..ad71f87d7 100644
--- a/src/lib/playlist.cc
+++ b/src/lib/playlist.cc
@@ -58,11 +58,17 @@ Playlist::Playlist ()
Playlist::Playlist (shared_ptr<const Playlist> other)
: _loop (other->_loop)
{
- for (RegionList::const_iterator i = other->_regions.begin(); i != other->_regions.end(); ++i) {
- _regions.push_back (shared_ptr<Region> (new Region ((*i)->content->clone(), (*i)->time, this)));
+ for (ContentList::const_iterator i = other->_content.begin(); i != other->_content.end(); ++i) {
+ _content.push_back ((*i)->clone ());
}
}
+Playlist::~Playlist ()
+{
+ _content.clear ();
+ reconnect ();
+}
+
void
Playlist::content_changed (weak_ptr<Content> c, int p)
{
@@ -74,14 +80,14 @@ Playlist::audio_digest () const
{
string t;
- for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) {
- if (!dynamic_pointer_cast<const AudioContent> ((*i)->content)) {
+ for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
+ if (!dynamic_pointer_cast<const AudioContent> (*i)) {
continue;
}
- t += (*i)->content->digest ();
+ t += (*i)->digest ();
- shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> ((*i)->content);
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
if (fc) {
t += lexical_cast<string> (fc->audio_stream()->id);
}
@@ -97,13 +103,13 @@ Playlist::video_digest () const
{
string t;
- for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) {
- if (!dynamic_pointer_cast<const VideoContent> ((*i)->content)) {
+ for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
+ if (!dynamic_pointer_cast<const VideoContent> (*i)) {
continue;
}
- t += (*i)->content->digest ();
- shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> ((*i)->content);
+ t += (*i)->digest ();
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
if (fc && fc->subtitle_stream()) {
t += fc->subtitle_stream()->id;
}
@@ -114,22 +120,34 @@ Playlist::video_digest () const
return md5_digest (t.c_str(), t.length());
}
+/** @param node <Playlist> node */
void
Playlist::set_from_xml (shared_ptr<const cxml::Node> node)
{
- list<shared_ptr<cxml::Node> > c = node->node_children ("Region");
+ list<shared_ptr<cxml::Node> > c = node->node_children ("Content");
for (list<shared_ptr<cxml::Node> >::iterator i = c.begin(); i != c.end(); ++i) {
- _regions.push_back (shared_ptr<Region> (new Region (*i, this)));
+ string const type = (*i)->string_child ("Type");
+
+ boost::shared_ptr<Content> content;
+
+ if (type == "FFmpeg") {
+ content.reset (new FFmpegContent (*i));
+ } else if (type == "ImageMagick") {
+ content.reset (new ImageMagickContent (*i));
+ } else if (type == "Sndfile") {
+ content.reset (new SndfileContent (*i));
+ }
}
_loop = node->number_child<int> ("Loop");
}
+/** @param node <Playlist> node */
void
Playlist::as_xml (xmlpp::Node* node)
{
- for (RegionList::iterator i = _regions.begin(); i != _regions.end(); ++i) {
- (*i)->as_xml (node->add_child ("Region"));
+ for (ContentList::iterator i = _content.begin(); i != _content.end(); ++i) {
+ (*i)->as_xml (node->add_child ("Content"));
}
node->add_child("Loop")->add_child_text(lexical_cast<string> (_loop));
@@ -138,20 +156,21 @@ Playlist::as_xml (xmlpp::Node* node)
void
Playlist::add (shared_ptr<Content> c)
{
- _regions.push_back (shared_ptr<Region> (new Region (c, 0, this)));
+ _content.push_back (c);
+ reconnect ();
Changed ();
}
void
Playlist::remove (shared_ptr<Content> c)
{
- RegionList::iterator i = _regions.begin ();
- while (i != _regions.end() && (*i)->content != c) {
+ ContentList::iterator i = _content.begin ();
+ while (i != _content.end() && *i != c) {
++i;
}
- if (i != _regions.end ()) {
- _regions.erase (i);
+ if (i != _content.end ()) {
+ _content.erase (i);
Changed ();
}
}
@@ -166,8 +185,8 @@ Playlist::set_loop (int l)
bool
Playlist::has_subtitles () const
{
- for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) {
- shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> ((*i)->content);
+ for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
+ shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (*i);
if (fc && !fc->subtitle_streams().empty()) {
return true;
}
@@ -176,40 +195,6 @@ Playlist::has_subtitles () const
return false;
}
-Playlist::Region::Region (shared_ptr<Content> c, Time t, Playlist* p)
- : content (c)
- , time (t)
-{
- connection = c->Changed.connect (bind (&Playlist::content_changed, p, _1, _2));
-}
-
-Playlist::Region::Region (shared_ptr<const cxml::Node> node, Playlist* p)
-{
- shared_ptr<const cxml::Node> content_node = node->node_child ("Content");
- string const type = content_node->string_child ("Type");
-
- if (type == "FFmpeg") {
- content.reset (new FFmpegContent (content_node));
- } else if (type == "ImageMagick") {
- content.reset (new ImageMagickContent (content_node));
- } else if (type == "Sndfile") {
- content.reset (new SndfileContent (content_node));
- }
-
- time = node->number_child<Time> ("Time");
- audio_mapping = AudioMapping (node->node_child ("AudioMapping"));
- connection = content->Changed.connect (bind (&Playlist::content_changed, p, _1, _2));
-}
-
-void
-Playlist::Region::as_xml (xmlpp::Node* node) const
-{
- xmlpp::Node* sub = node->add_child ("Content");
- content->as_xml (sub);
- node->add_child ("Time")->add_child_text (lexical_cast<string> (time));
- audio_mapping.as_xml (node->add_child ("AudioMapping"));
-}
-
class FrameRateCandidate
{
public:
@@ -248,8 +233,8 @@ Playlist::best_dcp_frame_rate () const
while (i != candidates.end()) {
float this_error = std::numeric_limits<float>::max ();
- for (RegionList::const_iterator j = _regions.begin(); j != _regions.end(); ++j) {
- shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> ((*j)->content);
+ for (ContentList::const_iterator j = _content.begin(); j != _content.end(); ++j) {
+ shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*j);
if (!vc) {
continue;
}
@@ -276,10 +261,25 @@ Time
Playlist::length (shared_ptr<const Film> film) const
{
Time len = 0;
- for (RegionList::const_iterator i = _regions.begin(); i != _regions.end(); ++i) {
- Time const t = (*i)->time + (*i)->content->length (film);
+ for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
+ Time const t = (*i)->time() + (*i)->length (film);
len = max (len, t);
}
return len;
}
+
+void
+Playlist::reconnect ()
+{
+ for (list<boost::signals2::connection>::iterator i = _content_connections.begin(); i != _content_connections.end(); ++i) {
+ i->disconnect ();
+ }
+
+ _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)));
+ }
+}
+
diff --git a/src/lib/playlist.h b/src/lib/playlist.h
index f677f0ad7..e8cac0247 100644
--- a/src/lib/playlist.h
+++ b/src/lib/playlist.h
@@ -41,6 +41,7 @@ class SndfileContent;
class SndfileDecoder;
class Job;
class Film;
+class Region;
/** @class Playlist
* @brief A set of content files (video and audio), with knowledge of how they should be arranged into
@@ -57,6 +58,7 @@ class Playlist
public:
Playlist ();
Playlist (boost::shared_ptr<const Playlist>);
+ ~Playlist ();
void as_xml (xmlpp::Node *);
void set_from_xml (boost::shared_ptr<const cxml::Node>);
@@ -66,30 +68,10 @@ public:
bool has_subtitles () const;
- struct Region
- {
- Region ()
- : time (0)
- {}
-
- Region (boost::shared_ptr<Content> c, Time t, Playlist* p);
- Region (boost::shared_ptr<const cxml::Node>, Playlist* p);
-
- void as_xml (xmlpp::Node *) const;
-
- boost::shared_ptr<Content> content;
- Time time;
- /* XXX: obviously not used for video-only; there should
- really by AudioRegion / VideoRegion etc.
- */
- AudioMapping audio_mapping;
- boost::signals2::connection connection;
- };
-
- typedef std::vector<boost::shared_ptr<Region> > RegionList;
+ typedef std::vector<boost::shared_ptr<Content> > ContentList;
- RegionList regions () const {
- return _regions;
+ ContentList content () const {
+ return _content;
}
std::string audio_digest () const;
@@ -109,9 +91,11 @@ public:
private:
void content_changed (boost::weak_ptr<Content>, int);
+ void reconnect ();
- RegionList _regions;
+ ContentList _content;
int _loop;
+ std::list<boost::signals2::connection> _content_connections;
};
#endif
diff --git a/src/lib/sndfile_content.h b/src/lib/sndfile_content.h
index d930d7061..1ef4b3f02 100644
--- a/src/lib/sndfile_content.h
+++ b/src/lib/sndfile_content.h
@@ -62,6 +62,11 @@ public:
}
int output_audio_frame_rate (boost::shared_ptr<const Film>) const;
+
+ AudioMapping audio_mapping () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _audio_mapping;
+ }
static bool valid_file (boost::filesystem::path);
@@ -69,4 +74,5 @@ private:
int _audio_channels;
ContentAudioFrame _audio_length;
int _audio_frame_rate;
+ AudioMapping _audio_mapping;
};