Various bits.
authorCarl Hetherington <cth@carlh.net>
Mon, 1 Apr 2013 21:49:31 +0000 (22:49 +0100)
committerCarl Hetherington <cth@carlh.net>
Mon, 1 Apr 2013 21:49:31 +0000 (22:49 +0100)
31 files changed:
src/lib/ab_transcoder.cc
src/lib/ab_transcoder.h
src/lib/analyse_audio_job.cc
src/lib/audio_decoder.cc
src/lib/audio_decoder.h
src/lib/encoder.cc
src/lib/encoder.h
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/film.cc
src/lib/film.h
src/lib/format.cc
src/lib/format.h
src/lib/imagemagick_decoder.cc
src/lib/imagemagick_decoder.h
src/lib/playlist.cc
src/lib/playlist.h
src/lib/sndfile_decoder.cc
src/lib/sndfile_decoder.h
src/lib/transcoder.cc
src/lib/transcoder.h
src/lib/video_decoder.cc
src/lib/video_decoder.h
src/lib/writer.cc
src/lib/writer.h
src/tools/servomatictest.cc
src/wx/audio_dialog.cc
src/wx/audio_dialog.h
src/wx/film_viewer.cc
src/wx/film_viewer.h
wscript

index 6fc438ee8cc04b7d6093d7f9a80e322ce1364a1e..6bf092feed60a0854cce6b2131217d5eb9d38623 100644 (file)
@@ -49,20 +49,20 @@ using boost::dynamic_pointer_cast;
 ABTranscoder::ABTranscoder (shared_ptr<Film> a, shared_ptr<Film> b, shared_ptr<Job> j)
        : _film_a (a)
        , _film_b (b)
 ABTranscoder::ABTranscoder (shared_ptr<Film> a, shared_ptr<Film> b, shared_ptr<Job> j)
        : _film_a (a)
        , _film_b (b)
-       , _playlist_a (_film_a->playlist ())
-       , _playlist_b (_film_b->playlist ())
+       , _player_a (_film_a->player ())
+       , _player_b (_film_b->player ())
        , _job (j)
        , _job (j)
-       , _encoder (new Encoder (_film_a, _playlist_a))
+       , _encoder (new Encoder (_film_a))
        , _combiner (new Combiner (a->log()))
 {
        , _combiner (new Combiner (a->log()))
 {
-       if (_playlist_a->has_audio ()) {
-               _matcher.reset (new Matcher (_film_a->log(), _playlist_a->audio_frame_rate(), _playlist_a->video_frame_rate()));
-               _delay_line.reset (new DelayLine (_film_a->log(), _playlist_a->audio_channels(), _film_a->audio_delay() * _playlist_a->audio_frame_rate() / 1000));
+       if (_film_a->has_audio ()) {
+               _matcher.reset (new Matcher (_film_a->log(), _film_a->audio_frame_rate(), _film_a->video_frame_rate()));
+               _delay_line.reset (new DelayLine (_film_a->log(), _film_a->audio_channels(), _film_a->audio_delay() * _film_a->audio_frame_rate() / 1000));
                _gain.reset (new Gain (_film_a->log(), _film_a->audio_gain()));
        }
 
                _gain.reset (new Gain (_film_a->log(), _film_a->audio_gain()));
        }
 
-       _playlist_a->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3));
-       _playlist_b->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3));
+       _player_a->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3));
+       _player_b->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3));
 
        if (_matcher) {
                _combiner->connect_video (_matcher);
 
        if (_matcher) {
                _combiner->connect_video (_matcher);
@@ -72,7 +72,7 @@ ABTranscoder::ABTranscoder (shared_ptr<Film> a, shared_ptr<Film> b, shared_ptr<J
        }
        
        if (_matcher && _delay_line) {
        }
        
        if (_matcher && _delay_line) {
-               _playlist_a->connect_audio (_delay_line);
+               _player_a->connect_audio (_delay_line);
                _delay_line->connect_audio (_matcher);
                _matcher->connect_audio (_gain);
                _gain->connect_audio (_encoder);
                _delay_line->connect_audio (_matcher);
                _matcher->connect_audio (_gain);
                _gain->connect_audio (_encoder);
@@ -87,11 +87,11 @@ ABTranscoder::go ()
        bool done[2] = { false, false };
        
        while (1) {
        bool done[2] = { false, false };
        
        while (1) {
-               done[0] = _playlist_a->pass ();
-               done[1] = _playlist_b->pass ();
+               done[0] = _player_a->pass ();
+               done[1] = _player_b->pass ();
 
                if (_job) {
 
                if (_job) {
-                       _playlist_a->set_progress (_job);
+                       _player_a->set_progress (_job);
                }
 
                if (done[0] && done[1]) {
                }
 
                if (done[0] && done[1]) {
index 5ce4a03da26873b6b402496581cecdbb559fb23f..b1b01d724f7b4818400122c7347aafe8d9f0bcad 100644 (file)
@@ -35,7 +35,7 @@ class Matcher;
 class DelayLine;
 class Gain;
 class Combiner;
 class DelayLine;
 class Gain;
 class Combiner;
-class Playlist;
+class Player;
 
 /** @class ABTranscoder
  *  @brief A transcoder which uses one Film for the left half of the screen, and a different one
 
 /** @class ABTranscoder
  *  @brief A transcoder which uses one Film for the left half of the screen, and a different one
@@ -55,8 +55,8 @@ public:
 private:
        boost::shared_ptr<Film> _film_a;
        boost::shared_ptr<Film> _film_b;
 private:
        boost::shared_ptr<Film> _film_a;
        boost::shared_ptr<Film> _film_b;
-       boost::shared_ptr<Playlist> _playlist_a;
-       boost::shared_ptr<Playlist> _playlist_b;
+       boost::shared_ptr<Player> _player_a;
+       boost::shared_ptr<Player> _player_b;
        boost::shared_ptr<Job> _job;
        boost::shared_ptr<Encoder> _encoder;
        boost::shared_ptr<Combiner> _combiner;
        boost::shared_ptr<Job> _job;
        boost::shared_ptr<Encoder> _encoder;
        boost::shared_ptr<Combiner> _combiner;
index 6e6dda88634891449b2897be29aa18633583d693..e2c9c5b1854747d5703a7037655c24f050dac211 100644 (file)
@@ -50,18 +50,18 @@ AnalyseAudioJob::name () const
 void
 AnalyseAudioJob::run ()
 {
 void
 AnalyseAudioJob::run ()
 {
-       shared_ptr<Playlist> playlist = _film->playlist ();
-       playlist->disable_video ();
+       shared_ptr<Player> player = _film->player ();
+       player->disable_video ();
        
        
-       playlist->Audio.connect (bind (&AnalyseAudioJob::audio, this, _1));
+       player->Audio.connect (bind (&AnalyseAudioJob::audio, this, _1));
 
 
-       _samples_per_point = max (int64_t (1), playlist->audio_length() / _num_points);
+       _samples_per_point = max (int64_t (1), _film->audio_length() / _num_points);
 
 
-       _current.resize (playlist->audio_channels ());
-       _analysis.reset (new AudioAnalysis (playlist->audio_channels()));
+       _current.resize (_film->audio_channels ());
+       _analysis.reset (new AudioAnalysis (_film->audio_channels()));
                         
                         
-       while (!playlist->pass()) {
-               set_progress (float (_done) / playlist->audio_length ());
+       while (!player->pass()) {
+               set_progress (float (_done) / _film->audio_length ());
        }
 
        _analysis->write (_film->audio_analysis_path ());
        }
 
        _analysis->write (_film->audio_analysis_path ());
index e2006a795d9c31e650f99c64cb3634f18047ca67..df13a984a4b36416fb1120b6512aca4537484f6c 100644 (file)
@@ -22,7 +22,7 @@
 using boost::optional;
 using boost::shared_ptr;
 
 using boost::optional;
 using boost::shared_ptr;
 
-AudioDecoder::AudioDecoder (shared_ptr<const Film> f, shared_ptr<AudioContent> c)
+AudioDecoder::AudioDecoder (shared_ptr<const Film> f)
        : Decoder (f)
 {
 
        : Decoder (f)
 {
 
index cbb84b52d29df63198cf744f0a324767caf6044d..24e2796aeac07badddd987d97074a7c8faf037c5 100644 (file)
@@ -35,7 +35,7 @@ class AudioContent;
 class AudioDecoder : public AudioSource, public virtual Decoder
 {
 public:
 class AudioDecoder : public AudioSource, public virtual Decoder
 {
 public:
-       AudioDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<AudioContent>);
+       AudioDecoder (boost::shared_ptr<const Film>);
 };
 
 #endif
 };
 
 #endif
index 00807f863808e3c952fc52a99ab6cc1833153058..5c3e5670920a0f7dfb6d0efcdd66aae70e05b21d 100644 (file)
@@ -53,9 +53,8 @@ using namespace boost;
 int const Encoder::_history_size = 25;
 
 /** @param f Film that we are encoding */
 int const Encoder::_history_size = 25;
 
 /** @param f Film that we are encoding */
-Encoder::Encoder (shared_ptr<Film> f, shared_ptr<Playlist> p)
+Encoder::Encoder (shared_ptr<Film> f)
        : _film (f)
        : _film (f)
-       , _playlist (p)
        , _video_frames_in (0)
        , _video_frames_out (0)
 #ifdef HAVE_SWRESAMPLE   
        , _video_frames_in (0)
        , _video_frames_out (0)
 #ifdef HAVE_SWRESAMPLE   
@@ -78,22 +77,22 @@ Encoder::~Encoder ()
 void
 Encoder::process_begin ()
 {
 void
 Encoder::process_begin ()
 {
-       if (_playlist->has_audio() && _playlist->audio_frame_rate() != _film->target_audio_sample_rate()) {
+       if (_film->has_audio() && _film->audio_frame_rate() != _film->target_audio_sample_rate()) {
 #ifdef HAVE_SWRESAMPLE
 
                stringstream s;
 #ifdef HAVE_SWRESAMPLE
 
                stringstream s;
-               s << String::compose (N_("Will resample audio from %1 to %2"), _playlist->audio_frame_rate(), _film->target_audio_sample_rate());
+               s << String::compose (N_("Will resample audio from %1 to %2"), _film->audio_frame_rate(), _film->target_audio_sample_rate());
                _film->log()->log (s.str ());
 
                /* We will be using planar float data when we call the resampler */
                _swr_context = swr_alloc_set_opts (
                        0,
                _film->log()->log (s.str ());
 
                /* We will be using planar float data when we call the resampler */
                _swr_context = swr_alloc_set_opts (
                        0,
-                       _playlist->audio_channel_layout(),
+                       _film->audio_channel_layout(),
                        AV_SAMPLE_FMT_FLTP,
                        _film->target_audio_sample_rate(),
                        AV_SAMPLE_FMT_FLTP,
                        _film->target_audio_sample_rate(),
-                       _playlist->audio_channel_layout(),
+                       _film->audio_channel_layout(),
                        AV_SAMPLE_FMT_FLTP,
                        AV_SAMPLE_FMT_FLTP,
-                       _playlist->audio_frame_rate(),
+                       _film->audio_frame_rate(),
                        0, 0
                        );
                
                        0, 0
                        );
                
@@ -119,7 +118,7 @@ Encoder::process_begin ()
                }
        }
 
                }
        }
 
-       _writer.reset (new Writer (_film, _playlist));
+       _writer.reset (new Writer (_film));
 }
 
 
 }
 
 
@@ -127,9 +126,9 @@ void
 Encoder::process_end ()
 {
 #if HAVE_SWRESAMPLE    
 Encoder::process_end ()
 {
 #if HAVE_SWRESAMPLE    
-       if (_playlist->has_audio() && _playlist->audio_channels() && _swr_context) {
+       if (_film->has_audio() && _film->audio_channels() && _swr_context) {
 
 
-               shared_ptr<AudioBuffers> out (new AudioBuffers (_playlist->audio_channels(), 256));
+               shared_ptr<AudioBuffers> out (new AudioBuffers (_film->audio_channels(), 256));
                        
                while (1) {
                        int const frames = swr_convert (_swr_context, (uint8_t **) out->data(), 256, 0, 0);
                        
                while (1) {
                        int const frames = swr_convert (_swr_context, (uint8_t **) out->data(), 256, 0, 0);
@@ -234,7 +233,7 @@ Encoder::frame_done ()
 void
 Encoder::process_video (shared_ptr<Image> image, bool same, boost::shared_ptr<Subtitle> sub)
 {
 void
 Encoder::process_video (shared_ptr<Image> image, bool same, boost::shared_ptr<Subtitle> sub)
 {
-       FrameRateConversion frc (_playlist->video_frame_rate(), _film->dcp_frame_rate());
+       FrameRateConversion frc (_film->video_frame_rate(), _film->dcp_frame_rate());
        
        if (frc.skip && (_video_frames_in % 2)) {
                ++_video_frames_in;
        
        if (frc.skip && (_video_frames_in % 2)) {
                ++_video_frames_in;
@@ -272,7 +271,7 @@ Encoder::process_video (shared_ptr<Image> image, bool same, boost::shared_ptr<Su
                TIMING ("adding to queue of %1", _queue.size ());
                _queue.push_back (boost::shared_ptr<DCPVideoFrame> (
                                          new DCPVideoFrame (
                TIMING ("adding to queue of %1", _queue.size ());
                _queue.push_back (boost::shared_ptr<DCPVideoFrame> (
                                          new DCPVideoFrame (
-                                                 image, sub, _film->format()->dcp_size(), _film->format()->dcp_padding (_playlist),
+                                                 image, sub, _film->format()->dcp_size(), _film->format()->dcp_padding (_film),
                                                  _film->subtitle_offset(), _film->subtitle_scale(),
                                                  _film->scaler(), _video_frames_out, _film->dcp_frame_rate(), s.second,
                                                  _film->colour_lut(), _film->j2k_bandwidth(),
                                                  _film->subtitle_offset(), _film->subtitle_scale(),
                                                  _film->scaler(), _video_frames_out, _film->dcp_frame_rate(), s.second,
                                                  _film->colour_lut(), _film->j2k_bandwidth(),
@@ -302,9 +301,9 @@ Encoder::process_audio (shared_ptr<AudioBuffers> data)
        if (_swr_context) {
 
                /* Compute the resampled frames count and add 32 for luck */
        if (_swr_context) {
 
                /* Compute the resampled frames count and add 32 for luck */
-               int const max_resampled_frames = ceil ((int64_t) data->frames() * _film->target_audio_sample_rate() / _playlist->audio_frame_rate()) + 32;
+               int const max_resampled_frames = ceil ((int64_t) data->frames() * _film->target_audio_sample_rate() / _film->audio_frame_rate()) + 32;
 
 
-               shared_ptr<AudioBuffers> resampled (new AudioBuffers (_playlist->audio_channels(), max_resampled_frames));
+               shared_ptr<AudioBuffers> resampled (new AudioBuffers (_film->audio_channels(), max_resampled_frames));
 
                /* Resample audio */
                int const resampled_frames = swr_convert (
 
                /* Resample audio */
                int const resampled_frames = swr_convert (
@@ -426,8 +425,8 @@ Encoder::encoder_thread (ServerDescription* server)
 void
 Encoder::write_audio (shared_ptr<const AudioBuffers> data)
 {
 void
 Encoder::write_audio (shared_ptr<const AudioBuffers> data)
 {
-       AudioMapping m (_playlist->audio_channels ());
-       if (m.dcp_channels() != _playlist->audio_channels()) {
+       AudioMapping m (_film->audio_channels ());
+       if (m.dcp_channels() != _film->audio_channels()) {
 
                /* Remap (currently just for mono -> 5.1) */
 
 
                /* Remap (currently just for mono -> 5.1) */
 
index c84ee027addcad0eae79e257e42c36cf0a1478f5..86880bc34942561ba12a1488feb00663c2c9d6d8 100644 (file)
@@ -51,7 +51,6 @@ class ServerDescription;
 class DCPVideoFrame;
 class EncodedData;
 class Writer;
 class DCPVideoFrame;
 class EncodedData;
 class Writer;
-class Playlist;
 
 /** @class Encoder
  *  @brief Encoder to J2K and WAV for DCP.
 
 /** @class Encoder
  *  @brief Encoder to J2K and WAV for DCP.
@@ -63,7 +62,7 @@ class Playlist;
 class Encoder : public VideoSink, public AudioSink
 {
 public:
 class Encoder : public VideoSink, public AudioSink
 {
 public:
-       Encoder (boost::shared_ptr<Film> f, boost::shared_ptr<Playlist>);
+       Encoder (boost::shared_ptr<Film> f);
        virtual ~Encoder ();
 
        /** Called to indicate that a processing run is about to begin */
        virtual ~Encoder ();
 
        /** Called to indicate that a processing run is about to begin */
@@ -96,7 +95,6 @@ private:
 
        /** Film that we are encoding */
        boost::shared_ptr<Film> _film;
 
        /** Film that we are encoding */
        boost::shared_ptr<Film> _film;
-       boost::shared_ptr<Playlist> _playlist;
 
        /** Mutex for _time_history and _last_frame */
        mutable boost::mutex _history_mutex;
 
        /** Mutex for _time_history and _last_frame */
        mutable boost::mutex _history_mutex;
index 7b56a59712641cd9de903746f1b9b1a590cf1cea..25ca9bb8882f658385ac677f86a36c685ba5b404 100644 (file)
@@ -61,10 +61,10 @@ using boost::optional;
 using boost::dynamic_pointer_cast;
 using libdcp::Size;
 
 using boost::dynamic_pointer_cast;
 using libdcp::Size;
 
-FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> f, shared_ptr<FFmpegContent> c, bool video, bool audio, bool subtitles, bool video_sync)
+FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> f, shared_ptr<const FFmpegContent> c, bool video, bool audio, bool subtitles, bool video_sync)
        : Decoder (f)
        : Decoder (f)
-       , VideoDecoder (f, c)
-       , AudioDecoder (f, c)
+       , VideoDecoder (f)
+       , AudioDecoder (f)
        , _ffmpeg_content (c)
        , _format_context (0)
        , _video_stream (-1)
        , _ffmpeg_content (c)
        , _format_context (0)
        , _video_stream (-1)
index ef66f09d9d55acfdcc1d1485bac67c5f6cd40d38..71ecf79065384aa1d7c14e23e9915af2971798e3 100644 (file)
@@ -57,7 +57,7 @@ class Log;
 class FFmpegDecoder : public VideoDecoder, public AudioDecoder
 {
 public:
 class FFmpegDecoder : public VideoDecoder, public AudioDecoder
 {
 public:
-       FFmpegDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<FFmpegContent>, bool video, bool audio, bool subtitles, bool video_sync);
+       FFmpegDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const FFmpegContent>, bool video, bool audio, bool subtitles, bool video_sync);
        ~FFmpegDecoder ();
 
        float frames_per_second () const;
        ~FFmpegDecoder ();
 
        float frames_per_second () const;
@@ -105,7 +105,7 @@ private:
 
        std::string stream_name (AVStream* s) const;
 
 
        std::string stream_name (AVStream* s) const;
 
-       boost::shared_ptr<FFmpegContent> _ffmpeg_content;
+       boost::shared_ptr<const FFmpegContent> _ffmpeg_content;
 
        AVFormatContext* _format_context;
        int _video_stream;
 
        AVFormatContext* _format_context;
        int _video_stream;
index f2c7a654aa348ff1ff9b1fea7bda10523141353e..fe16a65fa4faab40f3d6186fc6f35b06abf75f74 100644 (file)
@@ -91,7 +91,8 @@ int const Film::state_version = 4;
  */
 
 Film::Film (string d, bool must_exist)
  */
 
 Film::Film (string d, bool must_exist)
-       : _use_dci_name (true)
+       : _playlist (new Playlist)
+       , _use_dci_name (true)
        , _trust_content_headers (true)
        , _dcp_content_type (0)
        , _format (0)
        , _trust_content_headers (true)
        , _dcp_content_type (0)
        , _format (0)
@@ -151,6 +152,7 @@ Film::Film (Film const & o)
        : boost::enable_shared_from_this<Film> (o)
        /* note: the copied film shares the original's log */
        , _log               (o._log)
        : boost::enable_shared_from_this<Film> (o)
        /* note: the copied film shares the original's log */
        , _log               (o._log)
+       , _playlist          (new Playlist)
        , _directory         (o._directory)
        , _name              (o._name)
        , _use_dci_name      (o._use_dci_name)
        , _directory         (o._directory)
        , _name              (o._name)
        , _use_dci_name      (o._use_dci_name)
@@ -175,7 +177,7 @@ Film::Film (Film const & o)
        , _dcp_frame_rate    (o._dcp_frame_rate)
        , _dirty             (o._dirty)
 {
        , _dcp_frame_rate    (o._dcp_frame_rate)
        , _dirty             (o._dirty)
 {
-       
+       _playlist->setup (_content);
 }
 
 Film::~Film ()
 }
 
 Film::~Film ()
@@ -554,17 +556,14 @@ Film::file (string f) const
 int
 Film::target_audio_sample_rate () const
 {
 int
 Film::target_audio_sample_rate () const
 {
-       /* XXX: how often is this method called? */
-       
-       boost::shared_ptr<Playlist> p = playlist ();
-       if (p->has_audio ()) {
+       if (has_audio ()) {
                return 0;
        }
        
        /* Resample to a DCI-approved sample rate */
                return 0;
        }
        
        /* Resample to a DCI-approved sample rate */
-       double t = dcp_audio_sample_rate (p->audio_frame_rate());
+       double t = dcp_audio_sample_rate (audio_frame_rate());
 
 
-       FrameRateConversion frc (p->video_frame_rate(), dcp_frame_rate());
+       FrameRateConversion frc (video_frame_rate(), dcp_frame_rate());
 
        /* Compensate if the DCP is being run at a different frame rate
           to the source; that is, if the video is run such that it will
 
        /* Compensate if the DCP is being run at a different frame rate
           to the source; that is, if the video is run such that it will
@@ -573,7 +572,7 @@ Film::target_audio_sample_rate () const
        */
 
        if (frc.change_speed) {
        */
 
        if (frc.change_speed) {
-               t *= p->video_frame_rate() * frc.factor() / dcp_frame_rate();
+               t *= video_frame_rate() * frc.factor() / dcp_frame_rate();
        }
 
        return rint (t);
        }
 
        return rint (t);
@@ -1023,11 +1022,11 @@ Film::have_dcp () const
        return true;
 }
 
        return true;
 }
 
-shared_ptr<Playlist>
-Film::playlist () const
+shared_ptr<Player>
+Film::player () const
 {
        boost::mutex::scoped_lock lm (_state_mutex);
 {
        boost::mutex::scoped_lock lm (_state_mutex);
-       return shared_ptr<Playlist> (new Playlist (shared_from_this (), _content));
+       return shared_ptr<Player> (new Player (shared_from_this (), _playlist));
 }
 
 void
 }
 
 void
@@ -1036,9 +1035,59 @@ Film::add_content (shared_ptr<Content> c)
        {
                boost::mutex::scoped_lock lm (_state_mutex);
                _content.push_back (c);
        {
                boost::mutex::scoped_lock lm (_state_mutex);
                _content.push_back (c);
+               _playlist->setup (_content);
        }
 
        signal_changed (CONTENT);
 
        examine_content (c);
 }
        }
 
        signal_changed (CONTENT);
 
        examine_content (c);
 }
+
+ContentAudioFrame
+Film::audio_length () const
+{
+       return _playlist->audio_length ();
+}
+
+int
+Film::audio_channels () const
+{
+       return _playlist->audio_channels ();
+}
+
+int
+Film::audio_frame_rate () const
+{
+       return _playlist->audio_frame_rate ();
+}
+
+int64_t
+Film::audio_channel_layout () const
+{
+       return _playlist->audio_channel_layout ();
+}
+
+bool
+Film::has_audio () const
+{
+       return _playlist->has_audio ();
+}
+
+float
+Film::video_frame_rate () const
+{
+       return _playlist->video_frame_rate ();
+}
+
+libdcp::Size
+Film::video_size () const
+{
+       return _playlist->video_size ();
+}
+
+ContentVideoFrame
+Film::video_length () const
+{
+       return _playlist->video_length ();
+}
+
index f5f9444092d2b634d892af93e452a15d46d21c73..6e097d44e86ee2402961c856d8547e48f97f1647 100644 (file)
@@ -47,6 +47,7 @@ class ExamineContentJob;
 class AnalyseAudioJob;
 class ExternalAudioStream;
 class Content;
 class AnalyseAudioJob;
 class ExternalAudioStream;
 class Content;
+class Player;
 class Playlist;
 
 /** @class Film
 class Playlist;
 
 /** @class Film
@@ -105,7 +106,17 @@ public:
 
        bool have_dcp () const;
 
 
        bool have_dcp () const;
 
-       boost::shared_ptr<Playlist> playlist () const;
+       boost::shared_ptr<Player> player () const;
+
+       ContentAudioFrame audio_length () const;
+       int audio_channels () const;
+       int audio_frame_rate () const;
+       int64_t audio_channel_layout () const;
+       bool has_audio () const;
+       
+       float video_frame_rate () const;
+       libdcp::Size video_size () const;
+       ContentVideoFrame video_length () const;        
 
        /** Identifiers for the parts of our state;
            used for signalling changes.
 
        /** Identifiers for the parts of our state;
            used for signalling changes.
@@ -301,6 +312,8 @@ private:
        void analyse_audio_finished ();
        std::string video_state_identifier () const;
 
        void analyse_audio_finished ();
        std::string video_state_identifier () const;
 
+       boost::shared_ptr<Playlist> _playlist;
+
        /** Complete path to directory containing the film metadata;
         *  must not be relative.
         */
        /** Complete path to directory containing the film metadata;
         *  must not be relative.
         */
index 05b71f2e5c07d0d5798f83c9ac3765f1d426fd5a..538bf7953a216daae781488b962c2ee9f9f9d580 100644 (file)
@@ -207,9 +207,9 @@ FixedFormat::FixedFormat (int r, libdcp::Size dcp, string id, string n, string d
  *  (so there are dcp_padding() pixels on the left and dcp_padding() on the right)
  */
 int
  *  (so there are dcp_padding() pixels on the left and dcp_padding() on the right)
  */
 int
-Format::dcp_padding (shared_ptr<const Playlist> p) const
+Format::dcp_padding (shared_ptr<const Film> f) const
 {
 {
-       int pad = rint ((_dcp_size.width - (_dcp_size.height * ratio_as_integer(p) / 100.0)) / 2.0);
+       int pad = rint ((_dcp_size.width - (_dcp_size.height * ratio_as_integer(f) / 100.0)) / 2.0);
 
        /* This comes out -ve for Scope; bodge it */
        if (pad < 0) {
 
        /* This comes out -ve for Scope; bodge it */
        if (pad < 0) {
@@ -232,15 +232,15 @@ VariableFormat::VariableFormat (libdcp::Size dcp, string id, string n, string d,
 }
 
 int
 }
 
 int
-VariableFormat::ratio_as_integer (shared_ptr<const Playlist> p) const
+VariableFormat::ratio_as_integer (shared_ptr<const Film> f) const
 {
 {
-       return rint (ratio_as_float (p) * 100);
+       return rint (ratio_as_float (f) * 100);
 }
 
 float
 }
 
 float
-VariableFormat::ratio_as_float (shared_ptr<const Playlist> p) const
+VariableFormat::ratio_as_float (shared_ptr<const Film> f) const
 {
 {
-       return float (p->video_size().width) / p->video_size().height;
+       return float (f->video_size().width) / f->video_size().height;
 }
 
 /** @return A name to be presented to the user */
 }
 
 /** @return A name to be presented to the user */
index 94c2253dee88883ea12b418b66cd9edddf4f8185..cc7502893149a800a9ea432bec5ff277c6e54016 100644 (file)
@@ -26,7 +26,7 @@
 #include <vector>
 #include "util.h"
 
 #include <vector>
 #include "util.h"
 
-class Playlist;
+class Film;
 
 class Format
 {
 
 class Format
 {
@@ -42,15 +42,15 @@ public:
        /** @return the aspect ratio multiplied by 100
         *  (e.g. 239 for Cinemascope 2.39:1)
         */
        /** @return the aspect ratio multiplied by 100
         *  (e.g. 239 for Cinemascope 2.39:1)
         */
-       virtual int ratio_as_integer (boost::shared_ptr<const Playlist> f) const = 0;
+       virtual int ratio_as_integer (boost::shared_ptr<const Film> f) const = 0;
 
        /** @return the ratio as a floating point number */
 
        /** @return the ratio as a floating point number */
-       virtual float ratio_as_float (boost::shared_ptr<const Playlist> f) const = 0;
+       virtual float ratio_as_float (boost::shared_ptr<const Film> f) const = 0;
 
        /** @return the ratio of the container (including any padding) as a floating point number */
        float container_ratio_as_float () const;
 
 
        /** @return the ratio of the container (including any padding) as a floating point number */
        float container_ratio_as_float () const;
 
-       int dcp_padding (boost::shared_ptr<const Playlist>) const;
+       int dcp_padding (boost::shared_ptr<const Film>) const;
 
        /** @return size in pixels of the images that we should
         *  put in a DCP for this ratio.  This size will not correspond
 
        /** @return size in pixels of the images that we should
         *  put in a DCP for this ratio.  This size will not correspond
@@ -115,11 +115,11 @@ class FixedFormat : public Format
 public:
        FixedFormat (int, libdcp::Size, std::string, std::string, std::string, std::string);
 
 public:
        FixedFormat (int, libdcp::Size, std::string, std::string, std::string, std::string);
 
-       int ratio_as_integer (boost::shared_ptr<const Playlist>) const {
+       int ratio_as_integer (boost::shared_ptr<const Film>) const {
                return _ratio;
        }
 
                return _ratio;
        }
 
-       float ratio_as_float (boost::shared_ptr<const Playlist>) const {
+       float ratio_as_float (boost::shared_ptr<const Film>) const {
                return _ratio / 100.0;
        }
 
                return _ratio / 100.0;
        }
 
@@ -136,8 +136,8 @@ class VariableFormat : public Format
 public:
        VariableFormat (libdcp::Size, std::string, std::string, std::string, std::string);
 
 public:
        VariableFormat (libdcp::Size, std::string, std::string, std::string, std::string);
 
-       int ratio_as_integer (boost::shared_ptr<const Playlist> f) const;
-       float ratio_as_float (boost::shared_ptr<const Playlist> f) const;
+       int ratio_as_integer (boost::shared_ptr<const Film> f) const;
+       float ratio_as_float (boost::shared_ptr<const Film> f) const;
 
        std::string name () const;
 };
 
        std::string name () const;
 };
index c3723f6106cda578ca24df7ddc75e15c9fd1bc57..279c8bf3290ab36276fa7afb1627e3cfced1b3e3 100644 (file)
@@ -32,9 +32,9 @@ using std::cout;
 using boost::shared_ptr;
 using libdcp::Size;
 
 using boost::shared_ptr;
 using libdcp::Size;
 
-ImageMagickDecoder::ImageMagickDecoder (shared_ptr<const Film> f, shared_ptr<ImageMagickContent> c)
+ImageMagickDecoder::ImageMagickDecoder (shared_ptr<const Film> f, shared_ptr<const ImageMagickContent> c)
        : Decoder (f)
        : Decoder (f)
-       , VideoDecoder (f, c)
+       , VideoDecoder (f)
        , _imagemagick_content (c)
        , _position (0)
 {
        , _imagemagick_content (c)
        , _position (0)
 {
index a26e283c09b92e453f576a282094b78c4e064b68..7ad08df03a2e82f131ebbede586e890e00c34ba6 100644 (file)
@@ -28,7 +28,7 @@ class ImageMagickContent;
 class ImageMagickDecoder : public VideoDecoder
 {
 public:
 class ImageMagickDecoder : public VideoDecoder
 {
 public:
-       ImageMagickDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<ImageMagickContent>);
+       ImageMagickDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const ImageMagickContent>);
 
        float frames_per_second () const {
                /* We don't know */
 
        float frames_per_second () const {
                /* We don't know */
@@ -82,6 +82,6 @@ protected:
 private:
        void film_changed (Film::Property);
 
 private:
        void film_changed (Film::Property);
 
-       boost::shared_ptr<ImageMagickContent> _imagemagick_content;
+       boost::shared_ptr<const ImageMagickContent> _imagemagick_content;
        ContentVideoFrame _position;
 };
        ContentVideoFrame _position;
 };
index fc9edac48c3ec8d3bdb5ec158ca56153f6631798..d9bf8ac363f0460116ede361fa7d956666cd33b6 100644 (file)
@@ -30,15 +30,20 @@ using std::list;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 
-Playlist::Playlist (shared_ptr<const Film> f, list<shared_ptr<Content> > c)
-       : _film (f)
-       , _video_from (VIDEO_NONE)
+Playlist::Playlist ()
+       : _video_from (VIDEO_NONE)
        , _audio_from (AUDIO_NONE)
        , _audio_from (AUDIO_NONE)
-       , _have_setup_decoders (false)
-       , _ffmpeg_decoder_done (false)
-       , _video_sync (true)
 {
 {
-       for (list<shared_ptr<Content> >::const_iterator i = c.begin(); i != c.end(); ++i) {
+
+}
+
+void
+Playlist::setup (list<shared_ptr<Content> > content)
+{
+       _video_from = VIDEO_NONE;
+       _audio_from = AUDIO_NONE;
+       
+       for (list<shared_ptr<Content> >::const_iterator i = content.begin(); i != content.end(); ++i) {
                shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (*i);
                if (fc) {
                        assert (!_ffmpeg);
                shared_ptr<FFmpegContent> fc = dynamic_pointer_cast<FFmpegContent> (*i);
                if (fc) {
                        assert (!_ffmpeg);
@@ -76,7 +81,7 @@ Playlist::audio_length () const
        case AUDIO_SNDFILE:
        {
                ContentAudioFrame l = 0;
        case AUDIO_SNDFILE:
        {
                ContentAudioFrame l = 0;
-               for (list<shared_ptr<SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
+               for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
                        l += (*i)->audio_length ();
                }
                return l;
                        l += (*i)->audio_length ();
                }
                return l;
@@ -97,7 +102,7 @@ Playlist::audio_channels () const
        case AUDIO_SNDFILE:
        {
                int c = 0;
        case AUDIO_SNDFILE:
        {
                int c = 0;
-               for (list<shared_ptr<SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
+               for (list<shared_ptr<const SndfileContent> >::const_iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
                        c += (*i)->audio_channels ();
                }
                return c;
                        c += (*i)->audio_channels ();
                }
                return c;
@@ -180,7 +185,7 @@ Playlist::video_length () const
        case VIDEO_IMAGEMAGICK:
        {
                ContentVideoFrame l = 0;
        case VIDEO_IMAGEMAGICK:
        {
                ContentVideoFrame l = 0;
-               for (list<shared_ptr<ImageMagickContent> >::const_iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) {
+               for (list<shared_ptr<const ImageMagickContent> >::const_iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) {
                        l += (*i)->video_length ();
                }
                return l;
                        l += (*i)->video_length ();
                }
                return l;
@@ -195,27 +200,40 @@ Playlist::has_audio () const
 {
        return _audio_from != AUDIO_NONE;
 }
 {
        return _audio_from != AUDIO_NONE;
 }
+
+Player::Player (boost::shared_ptr<const Film> f, boost::shared_ptr<const Playlist> p)
+       : _film (f)
+       , _playlist (p)
+       , _video (true)
+       , _audio (true)
+       , _subtitles (true)
+       , _have_setup_decoders (false)
+       , _ffmpeg_decoder_done (false)
+       , _video_sync (true)
+{
+
+}
                
 void
                
 void
-Playlist::disable_video ()
+Player::disable_video ()
 {
 {
-       _video_from = VIDEO_NONE;
+       _video = false;
 }
 
 void
 }
 
 void
-Playlist::disable_audio ()
+Player::disable_audio ()
 {
 {
-       _audio_from = AUDIO_NONE;
+       _audio = false;
 }
 
 void
 }
 
 void
-Playlist::disable_subtitles ()
+Player::disable_subtitles ()
 {
 {
-       /* XXX */
+       _subtitles = false;
 }
 
 bool
 }
 
 bool
-Playlist::pass ()
+Player::pass ()
 {
        if (!_have_setup_decoders) {
                setup_decoders ();
 {
        if (!_have_setup_decoders) {
                setup_decoders ();
@@ -224,7 +242,7 @@ Playlist::pass ()
        
        bool done = true;
        
        
        bool done = true;
        
-       if (_video_from == VIDEO_FFMPEG || _audio_from == AUDIO_FFMPEG) {
+       if (_playlist->video_from() == Playlist::VIDEO_FFMPEG || _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
                if (!_ffmpeg_decoder_done) {
                        if (_ffmpeg_decoder->pass ()) {
                                _ffmpeg_decoder_done = true;
                if (!_ffmpeg_decoder_done) {
                        if (_ffmpeg_decoder->pass ()) {
                                _ffmpeg_decoder_done = true;
@@ -234,7 +252,7 @@ Playlist::pass ()
                }
        }
 
                }
        }
 
-       if (_video_from == VIDEO_IMAGEMAGICK) {
+       if (_playlist->video_from() == Playlist::VIDEO_IMAGEMAGICK) {
                if (_imagemagick_decoder != _imagemagick_decoders.end ()) {
                        if ((*_imagemagick_decoder)->pass ()) {
                                _imagemagick_decoder++;
                if (_imagemagick_decoder != _imagemagick_decoders.end ()) {
                        if ((*_imagemagick_decoder)->pass ()) {
                                _imagemagick_decoder++;
@@ -252,37 +270,37 @@ Playlist::pass ()
 }
 
 void
 }
 
 void
-Playlist::set_progress (shared_ptr<Job> job)
+Player::set_progress (shared_ptr<Job> job)
 {
        /* XXX */
 }
 
 void
 {
        /* XXX */
 }
 
 void
-Playlist::process_video (shared_ptr<Image> i, bool same, shared_ptr<Subtitle> s)
+Player::process_video (shared_ptr<Image> i, bool same, shared_ptr<Subtitle> s)
 {
        Video (i, same, s);
 }
 
 void
 {
        Video (i, same, s);
 }
 
 void
-Playlist::process_audio (shared_ptr<AudioBuffers> b)
+Player::process_audio (shared_ptr<AudioBuffers> b)
 {
        Audio (b);
 }
 
 bool
 {
        Audio (b);
 }
 
 bool
-Playlist::seek (double t)
+Player::seek (double t)
 {
        bool r = false;
        
 {
        bool r = false;
        
-       switch (_video_from) {
-       case VIDEO_NONE:
+       switch (_playlist->video_from()) {
+       case Playlist::VIDEO_NONE:
                break;
                break;
-       case VIDEO_FFMPEG:
+       case Playlist::VIDEO_FFMPEG:
                if (_ffmpeg_decoder->seek (t)) {
                        r = true;
                }
                break;
                if (_ffmpeg_decoder->seek (t)) {
                        r = true;
                }
                break;
-       case VIDEO_IMAGEMAGICK:
+       case Playlist::VIDEO_IMAGEMAGICK:
                if ((*_imagemagick_decoder)->seek (t)) {
                        r = true;
                }
                if ((*_imagemagick_decoder)->seek (t)) {
                        r = true;
                }
@@ -295,19 +313,19 @@ Playlist::seek (double t)
 }
 
 bool
 }
 
 bool
-Playlist::seek_to_last ()
+Player::seek_to_last ()
 {
        bool r = false;
        
 {
        bool r = false;
        
-       switch (_video_from) {
-       case VIDEO_NONE:
+       switch (_playlist->video_from ()) {
+       case Playlist::VIDEO_NONE:
                break;
                break;
-       case VIDEO_FFMPEG:
+       case Playlist::VIDEO_FFMPEG:
                if (_ffmpeg_decoder->seek_to_last ()) {
                        r = true;
                }
                break;
                if (_ffmpeg_decoder->seek_to_last ()) {
                        r = true;
                }
                break;
-       case VIDEO_IMAGEMAGICK:
+       case Playlist::VIDEO_IMAGEMAGICK:
                if ((*_imagemagick_decoder)->seek_to_last ()) {
                        r = true;
                }
                if ((*_imagemagick_decoder)->seek_to_last ()) {
                        r = true;
                }
@@ -320,26 +338,32 @@ Playlist::seek_to_last ()
 }
 
 void
 }
 
 void
-Playlist::setup_decoders ()
+Player::setup_decoders ()
 {
 {
-       if (_video_from == VIDEO_FFMPEG || _audio_from == AUDIO_FFMPEG) {
+       if ((_video && _playlist->video_from() == Playlist::VIDEO_FFMPEG) || (_audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG)) {
                _ffmpeg_decoder.reset (
                        new FFmpegDecoder (
                _ffmpeg_decoder.reset (
                        new FFmpegDecoder (
-                               _film, _ffmpeg, _video_from == VIDEO_FFMPEG, _audio_from == AUDIO_FFMPEG, _film->with_subtitles(), _video_sync
+                               _film,
+                               _playlist->ffmpeg(),
+                               _video && _playlist->video_from() == Playlist::VIDEO_FFMPEG,
+                               _audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG,
+                               _subtitles && _film->with_subtitles(),
+                               _video_sync
                                )
                        );
        }
        
                                )
                        );
        }
        
-       if (_video_from == VIDEO_FFMPEG) {
+       if (_video && _playlist->video_from() == Playlist::VIDEO_FFMPEG) {
                _ffmpeg_decoder->connect_video (shared_from_this ());
        }
 
                _ffmpeg_decoder->connect_video (shared_from_this ());
        }
 
-       if (_audio_from == AUDIO_FFMPEG) {
+       if (_audio && _playlist->audio_from() == Playlist::AUDIO_FFMPEG) {
                _ffmpeg_decoder->connect_audio (shared_from_this ());
        }
 
                _ffmpeg_decoder->connect_audio (shared_from_this ());
        }
 
-       if (_video_from == VIDEO_IMAGEMAGICK) {
-               for (list<shared_ptr<ImageMagickContent> >::iterator i = _imagemagick.begin(); i != _imagemagick.end(); ++i) {
+       if (_video && _playlist->video_from() == Playlist::VIDEO_IMAGEMAGICK) {
+               list<shared_ptr<const ImageMagickContent> > ic = _playlist->imagemagick ();
+               for (list<shared_ptr<const ImageMagickContent> >::iterator i = ic.begin(); i != ic.end(); ++i) {
                        shared_ptr<ImageMagickDecoder> d (new ImageMagickDecoder (_film, *i));
                        _imagemagick_decoders.push_back (d);
                        d->connect_video (shared_from_this ());
                        shared_ptr<ImageMagickDecoder> d (new ImageMagickDecoder (_film, *i));
                        _imagemagick_decoders.push_back (d);
                        d->connect_video (shared_from_this ());
@@ -348,8 +372,9 @@ Playlist::setup_decoders ()
                _imagemagick_decoder = _imagemagick_decoders.begin ();
        }
 
                _imagemagick_decoder = _imagemagick_decoders.begin ();
        }
 
-       if (_audio_from == AUDIO_SNDFILE) {
-               for (list<shared_ptr<SndfileContent> >::iterator i = _sndfile.begin(); i != _sndfile.end(); ++i) {
+       if (_audio && _playlist->audio_from() == Playlist::AUDIO_SNDFILE) {
+               list<shared_ptr<const SndfileContent> > sc = _playlist->sndfile ();
+               for (list<shared_ptr<const SndfileContent> >::iterator i = sc.begin(); i != sc.end(); ++i) {
                        shared_ptr<SndfileDecoder> d (new SndfileDecoder (_film, *i));
                        _sndfile_decoders.push_back (d);
                        d->connect_audio (shared_from_this ());
                        shared_ptr<SndfileDecoder> d (new SndfileDecoder (_film, *i));
                        _sndfile_decoders.push_back (d);
                        d->connect_audio (shared_from_this ());
@@ -358,7 +383,22 @@ Playlist::setup_decoders ()
 }
 
 void
 }
 
 void
-Playlist::disable_video_sync ()
+Player::disable_video_sync ()
 {
        _video_sync = false;
 }
 {
        _video_sync = false;
 }
+
+double
+Player::last_video_time () const
+{
+       switch (_playlist->video_from ()) {
+       case Playlist::VIDEO_NONE:
+               return 0;
+       case Playlist::VIDEO_FFMPEG:
+               return _ffmpeg_decoder->last_source_time ();
+       case Playlist::VIDEO_IMAGEMAGICK:
+               return (*_imagemagick_decoder)->last_source_time ();
+       }
+
+       return 0;
+}
index d374dc98c8ec131df3aadaa68c4fe03b1f5f00b1..8278490490fb5f9b515bf8cd9d391a24e2e4107f 100644 (file)
@@ -35,10 +35,12 @@ class SndfileDecoder;
 class Job;
 class Film;
 
 class Job;
 class Film;
 
-class Playlist : public VideoSource, public AudioSource, public VideoSink, public AudioSink, public boost::enable_shared_from_this<Playlist>
+class Playlist
 {
 public:
 {
 public:
-       Playlist (boost::shared_ptr<const Film>, std::list<boost::shared_ptr<Content> >);
+       Playlist ();
+
+       void setup (std::list<boost::shared_ptr<Content> >);
 
        ContentAudioFrame audio_length () const;
        int audio_channels () const;
 
        ContentAudioFrame audio_length () const;
        int audio_channels () const;
@@ -50,6 +52,52 @@ public:
        libdcp::Size video_size () const;
        ContentVideoFrame video_length () const;
 
        libdcp::Size video_size () const;
        ContentVideoFrame video_length () const;
 
+       enum VideoFrom {
+               VIDEO_NONE,
+               VIDEO_FFMPEG,
+               VIDEO_IMAGEMAGICK
+       };
+
+       enum AudioFrom {
+               AUDIO_NONE,
+               AUDIO_FFMPEG,
+               AUDIO_SNDFILE
+       };
+
+       VideoFrom video_from () const {
+               return _video_from;
+       }
+
+       AudioFrom audio_from () const {
+               return _audio_from;
+       }
+
+       boost::shared_ptr<const FFmpegContent> ffmpeg () const {
+               return _ffmpeg;
+       }
+
+       std::list<boost::shared_ptr<const ImageMagickContent> > imagemagick () const {
+               return _imagemagick;
+       }
+
+       std::list<boost::shared_ptr<const SndfileContent> > sndfile () const {
+               return _sndfile;
+       }
+       
+private:
+       VideoFrom _video_from;
+       AudioFrom _audio_from;
+
+       boost::shared_ptr<const FFmpegContent> _ffmpeg;
+       std::list<boost::shared_ptr<const ImageMagickContent> > _imagemagick;
+       std::list<boost::shared_ptr<const SndfileContent> > _sndfile;
+};
+
+class Player : public VideoSource, public AudioSource, public VideoSink, public AudioSink, public boost::enable_shared_from_this<Player>
+{
+public:
+       Player (boost::shared_ptr<const Film>, boost::shared_ptr<const Playlist>);
+
        void disable_video ();
        void disable_audio ();
        void disable_subtitles ();
        void disable_video ();
        void disable_audio ();
        void disable_subtitles ();
@@ -60,29 +108,20 @@ public:
        bool seek (double);
        bool seek_to_last ();
 
        bool seek (double);
        bool seek_to_last ();
 
+       double last_video_time () const;
+
 private:
        void process_video (boost::shared_ptr<Image> i, bool same, boost::shared_ptr<Subtitle> s);
        void process_audio (boost::shared_ptr<AudioBuffers>);
        void setup_decoders ();
 private:
        void process_video (boost::shared_ptr<Image> i, bool same, boost::shared_ptr<Subtitle> s);
        void process_audio (boost::shared_ptr<AudioBuffers>);
        void setup_decoders ();
-       
-       boost::shared_ptr<const Film> _film;
 
 
-       enum {
-               VIDEO_NONE,
-               VIDEO_FFMPEG,
-               VIDEO_IMAGEMAGICK
-       } _video_from;
+       boost::shared_ptr<const Film> _film;
+       boost::shared_ptr<const Playlist> _playlist;
+       
+       bool _video;
+       bool _audio;
+       bool _subtitles;
        
        
-       enum {
-               AUDIO_NONE,
-               AUDIO_FFMPEG,
-               AUDIO_SNDFILE
-       } _audio_from;
-
-       boost::shared_ptr<FFmpegContent> _ffmpeg;
-       std::list<boost::shared_ptr<ImageMagickContent> > _imagemagick;
-       std::list<boost::shared_ptr<SndfileContent> > _sndfile;
-
        bool _have_setup_decoders;
        boost::shared_ptr<FFmpegDecoder> _ffmpeg_decoder;
        bool _ffmpeg_decoder_done;
        bool _have_setup_decoders;
        boost::shared_ptr<FFmpegDecoder> _ffmpeg_decoder;
        bool _ffmpeg_decoder_done;
index daa363c5e8aaef9b8ecfebac5dbe1e1b0e563b53..1f97e5c41d394211824fac7bd4e444abf5a4e990 100644 (file)
@@ -36,9 +36,9 @@ using boost::optional;
 
 /* XXX */
 
 
 /* XXX */
 
-SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<SndfileContent> c)
+SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<const SndfileContent> c)
        : Decoder (f)
        : Decoder (f)
-       , AudioDecoder (f, c)
+       , AudioDecoder (f)
 {
        sf_count_t frames;
        SNDFILE* sf = open_file (frames);
 {
        sf_count_t frames;
        SNDFILE* sf = open_file (frames);
index 9a3ef49b017a3983f698a57c89218089d7e3bfa2..56fc3a9f08bc7811d4a6d7720992874d5a13b393 100644 (file)
@@ -26,7 +26,7 @@ class SndfileContent;
 class SndfileDecoder : public AudioDecoder
 {
 public:
 class SndfileDecoder : public AudioDecoder
 {
 public:
-       SndfileDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<SndfileContent>);
+       SndfileDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const SndfileContent>);
 
        bool pass ();
 
 
        bool pass ();
 
@@ -34,5 +34,5 @@ private:
        SNDFILE* open_file (sf_count_t &);
        void close_file (SNDFILE*);
 
        SNDFILE* open_file (sf_count_t &);
        void close_file (SNDFILE*);
 
-       boost::shared_ptr<SndfileContent> _sndfile_content;
+       boost::shared_ptr<const SndfileContent> _sndfile_content;
 };
 };
index 21944c5fc6ad63aee373b451deac690f49a10bf7..0ee6f523fe7776e57837ad3e7a14419072a3692e 100644 (file)
@@ -47,24 +47,24 @@ using boost::dynamic_pointer_cast;
  */
 Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<Job> j)
        : _job (j)
  */
 Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<Job> j)
        : _job (j)
-       , _playlist (f->playlist ())
-       , _encoder (new Encoder (f, _playlist))
+       , _player (f->player ())
+       , _encoder (new Encoder (f))
 {
 {
-       if (_playlist->has_audio ()) {
-               _matcher.reset (new Matcher (f->log(), _playlist->audio_frame_rate(), _playlist->video_frame_rate()));
-               _delay_line.reset (new DelayLine (f->log(), _playlist->audio_channels(), f->audio_delay() * _playlist->audio_frame_rate() / 1000));
+       if (f->has_audio ()) {
+               _matcher.reset (new Matcher (f->log(), f->audio_frame_rate(), f->video_frame_rate()));
+               _delay_line.reset (new DelayLine (f->log(), f->audio_channels(), f->audio_delay() * f->audio_frame_rate() / 1000));
                _gain.reset (new Gain (f->log(), f->audio_gain()));
        }
 
        if (_matcher) {
                _gain.reset (new Gain (f->log(), f->audio_gain()));
        }
 
        if (_matcher) {
-               _playlist->connect_video (_matcher);
+               _player->connect_video (_matcher);
                _matcher->connect_video (_encoder);
        } else {
                _matcher->connect_video (_encoder);
        } else {
-               _playlist->connect_video (_encoder);
+               _player->connect_video (_encoder);
        }
        
        }
        
-       if (_matcher && _delay_line && _playlist->has_audio ()) {
-               _playlist->connect_audio (_delay_line);
+       if (_matcher && _delay_line && f->has_audio ()) {
+               _player->connect_audio (_delay_line);
                _delay_line->connect_audio (_matcher);
                _matcher->connect_audio (_gain);
                _gain->connect_audio (_encoder);
                _delay_line->connect_audio (_matcher);
                _matcher->connect_audio (_gain);
                _gain->connect_audio (_encoder);
@@ -77,10 +77,10 @@ Transcoder::go ()
        _encoder->process_begin ();
        try {
                while (1) {
        _encoder->process_begin ();
        try {
                while (1) {
-                       if (_playlist->pass ()) {
+                       if (_player->pass ()) {
                                break;
                        }
                                break;
                        }
-                       _playlist->set_progress (_job);
+                       _player->set_progress (_job);
                }
                
        } catch (...) {
                }
                
        } catch (...) {
index 856b10f3af73bc219016858eeb5c0ab34d37f6ef..2d032fcf640538ca06f99780f2be9a97b4fb7004 100644 (file)
@@ -30,7 +30,7 @@ class Matcher;
 class VideoFilter;
 class Gain;
 class DelayLine;
 class VideoFilter;
 class Gain;
 class DelayLine;
-class Playlist;
+class Player;
 
 /** @class Transcoder
  *
 
 /** @class Transcoder
  *
@@ -50,7 +50,7 @@ public:
 protected:
        /** A Job that is running this Transcoder, or 0 */
        boost::shared_ptr<Job> _job;
 protected:
        /** A Job that is running this Transcoder, or 0 */
        boost::shared_ptr<Job> _job;
-       boost::shared_ptr<Playlist> _playlist;
+       boost::shared_ptr<Player> _player;
        boost::shared_ptr<Encoder> _encoder;
        boost::shared_ptr<Matcher> _matcher;
        boost::shared_ptr<DelayLine> _delay_line;
        boost::shared_ptr<Encoder> _encoder;
        boost::shared_ptr<Matcher> _matcher;
        boost::shared_ptr<DelayLine> _delay_line;
index 33dd433eac8e1a6d3484a6ca6be954924727850b..32b06085f21b741e060111cb0bd913fcfcf51d93 100644 (file)
@@ -29,7 +29,7 @@
 using boost::shared_ptr;
 using boost::optional;
 
 using boost::shared_ptr;
 using boost::optional;
 
-VideoDecoder::VideoDecoder (shared_ptr<const Film> f, shared_ptr<VideoContent> c)
+VideoDecoder::VideoDecoder (shared_ptr<const Film> f)
        : Decoder (f)
        , _video_frame (0)
        , _last_source_time (0)
        : Decoder (f)
        , _video_frame (0)
        , _last_source_time (0)
@@ -106,10 +106,7 @@ VideoDecoder::set_progress (Job* j) const
 {
        assert (j);
 
 {
        assert (j);
 
-#if 0
-       XXX
-       if (_film->length()) {
-               j->set_progress (float (_video_frame) / _film->length().get());
+       if (_film->video_length()) {
+               j->set_progress (float (_video_frame) / _film->video_length());
        }
        }
-#endif 
 }
 }
index 03dc4777a6a93a069ae533ecbaf99c787bc14b2c..a2fd5b6510a1fb297c555cf49ce749772e998d21 100644 (file)
@@ -28,7 +28,7 @@ class VideoContent;
 class VideoDecoder : public VideoSource, public virtual Decoder
 {
 public:
 class VideoDecoder : public VideoSource, public virtual Decoder
 {
 public:
-       VideoDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<VideoContent>);
+       VideoDecoder (boost::shared_ptr<const Film>);
 
        /** @return video frames per second, or 0 if unknown */
        virtual float frames_per_second () const = 0;
 
        /** @return video frames per second, or 0 if unknown */
        virtual float frames_per_second () const = 0;
index 5f5dae98f31c24a3181718fdf880d88ad843208e..b08b9caf18a0d7f3f7166f959662c0dd16fbffc9 100644 (file)
@@ -42,9 +42,8 @@ using boost::shared_ptr;
 
 int const Writer::_maximum_frames_in_memory = 8;
 
 
 int const Writer::_maximum_frames_in_memory = 8;
 
-Writer::Writer (shared_ptr<Film> f, shared_ptr<Playlist> p)
+Writer::Writer (shared_ptr<Film> f)
        : _film (f)
        : _film (f)
-       , _playlist (p)
        , _first_nonexistant_frame (0)
        , _thread (0)
        , _finish (false)
        , _first_nonexistant_frame (0)
        , _thread (0)
        , _finish (false)
@@ -76,7 +75,7 @@ Writer::Writer (shared_ptr<Film> f, shared_ptr<Playlist> p)
 
        _picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0);
 
 
        _picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0);
 
-       AudioMapping m (_playlist->audio_channels ());
+       AudioMapping m (_film->audio_channels ());
        
        if (m.dcp_channels() > 0) {
                _sound_asset.reset (
        
        if (m.dcp_channels() > 0) {
                _sound_asset.reset (
@@ -85,7 +84,7 @@ Writer::Writer (shared_ptr<Film> f, shared_ptr<Playlist> p)
                                N_("audio.mxf"),
                                _film->dcp_frame_rate (),
                                m.dcp_channels (),
                                N_("audio.mxf"),
                                _film->dcp_frame_rate (),
                                m.dcp_channels (),
-                               dcp_audio_sample_rate (_playlist->audio_frame_rate())
+                               dcp_audio_sample_rate (_film->audio_frame_rate())
                                )
                        );
 
                                )
                        );
 
index 920f592b647d294458a746d8d6cef1f056c4ab08..beb16c7b9107da1972bcbd5f92a2dc07d3b1b701 100644 (file)
@@ -26,7 +26,6 @@
 class Film;
 class EncodedData;
 class AudioBuffers;
 class Film;
 class EncodedData;
 class AudioBuffers;
-class Playlist;
 
 namespace libdcp {
        class MonoPictureAsset;
 
 namespace libdcp {
        class MonoPictureAsset;
@@ -64,7 +63,7 @@ bool operator== (QueueItem const & a, QueueItem const & b);
 class Writer : public ExceptionStore
 {
 public:
 class Writer : public ExceptionStore
 {
 public:
-       Writer (boost::shared_ptr<Film>, boost::shared_ptr<Playlist>);
+       Writer (boost::shared_ptr<Film>);
 
        bool can_fake_write (int) const;
        
 
        bool can_fake_write (int) const;
        
@@ -81,7 +80,6 @@ private:
 
        /** our Film */
        boost::shared_ptr<Film> _film;
 
        /** our Film */
        boost::shared_ptr<Film> _film;
-       boost::shared_ptr<Playlist> _playlist;
        /** the first frame index that does not already exist in our MXF */
        int _first_nonexistant_frame;
 
        /** the first frame index that does not already exist in our MXF */
        int _first_nonexistant_frame;
 
index 3d847d690f15fa4d2e8230dd3ed0b55ff4344dfc..d7e8bbb0e2ac4ff66d75296aa979fd9081699358 100644 (file)
@@ -150,14 +150,14 @@ main (int argc, char* argv[])
        server = new ServerDescription (server_host, 1);
        shared_ptr<Film> film (new Film (film_dir, true));
 
        server = new ServerDescription (server_host, 1);
        shared_ptr<Film> film (new Film (film_dir, true));
 
-       shared_ptr<Playlist> playlist = film->playlist ();
-       playlist->disable_audio ();
+       shared_ptr<Player> player = film->player ();
+       player->disable_audio ();
 
        try {
 
        try {
-               playlist->Video.connect (boost::bind (process_video, _1, _2, _3));
+               player->Video.connect (boost::bind (process_video, _1, _2, _3));
                bool done = false;
                while (!done) {
                bool done = false;
                while (!done) {
-                       done = playlist->pass ();
+                       done = player->pass ();
                }
        } catch (std::exception& e) {
                cerr << "Error: " << e.what() << "\n";
                }
        } catch (std::exception& e) {
                cerr << "Error: " << e.what() << "\n";
index b7384fd14652528097199b177ed763978aae7068..242d37b1e42728e82c5d6c1c8e80d341fabbc5ea 100644 (file)
@@ -20,7 +20,6 @@
 #include <boost/filesystem.hpp>
 #include "lib/audio_analysis.h"
 #include "lib/film.h"
 #include <boost/filesystem.hpp>
 #include "lib/audio_analysis.h"
 #include "lib/film.h"
-#include "lib/playlist.h"
 #include "audio_dialog.h"
 #include "audio_plot.h"
 #include "wx_util.h"
 #include "audio_dialog.h"
 #include "audio_plot.h"
 #include "wx_util.h"
@@ -91,7 +90,6 @@ AudioDialog::set_film (boost::shared_ptr<Film> f)
        _film_audio_analysis_succeeded_connection.disconnect ();
        
        _film = f;
        _film_audio_analysis_succeeded_connection.disconnect ();
        
        _film = f;
-       _playlist = _film->playlist ();
 
        try_to_load_analysis ();
        setup_channels ();
 
        try_to_load_analysis ();
        setup_channels ();
@@ -106,11 +104,11 @@ AudioDialog::set_film (boost::shared_ptr<Film> f)
 void
 AudioDialog::setup_channels ()
 {
 void
 AudioDialog::setup_channels ()
 {
-       if (!_playlist->has_audio()) {
+       if (!_film->has_audio()) {
                return;
        }
 
                return;
        }
 
-       AudioMapping m (_playlist->audio_channels ());
+       AudioMapping m (_film->audio_channels ());
        
        for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
                if (m.dcp_to_source(static_cast<libdcp::Channel>(i))) {
        
        for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
                if (m.dcp_to_source(static_cast<libdcp::Channel>(i))) {
@@ -136,7 +134,7 @@ AudioDialog::try_to_load_analysis ()
                
        _plot->set_analysis (a);
 
                
        _plot->set_analysis (a);
 
-       AudioMapping m (_playlist->audio_channels ());
+       AudioMapping m (_film->audio_channels ());
        optional<libdcp::Channel> c = m.source_to_dcp (0);
        if (c) {
                _channel_checkbox[c.get()]->SetValue (true);
        optional<libdcp::Channel> c = m.source_to_dcp (0);
        if (c) {
                _channel_checkbox[c.get()]->SetValue (true);
@@ -159,7 +157,7 @@ AudioDialog::channel_clicked (wxCommandEvent& ev)
 
        assert (c < MAX_AUDIO_CHANNELS);
 
 
        assert (c < MAX_AUDIO_CHANNELS);
 
-       AudioMapping m (_playlist->audio_channels ());
+       AudioMapping m (_film->audio_channels ());
        optional<int> s = m.dcp_to_source (static_cast<libdcp::Channel> (c));
        if (s) {
                _plot->set_channel_visible (s.get(), _channel_checkbox[c]->GetValue ());
        optional<int> s = m.dcp_to_source (static_cast<libdcp::Channel> (c));
        if (s) {
                _plot->set_channel_visible (s.get(), _channel_checkbox[c]->GetValue ());
@@ -174,7 +172,6 @@ AudioDialog::film_changed (Film::Property p)
                _plot->set_gain (_film->audio_gain ());
                break;
        case Film::CONTENT:
                _plot->set_gain (_film->audio_gain ());
                break;
        case Film::CONTENT:
-               _playlist = _film->playlist ();
                setup_channels ();
                break;
        default:
                setup_channels ();
                break;
        default:
index 3cb9c1726afcd72833187ebc1c4d9982d2cc21da..514faeea0e952ff83c716392d3aacf5a5514d2ee 100644 (file)
@@ -25,7 +25,6 @@
 
 class AudioPlot;
 class Film;
 
 class AudioPlot;
 class Film;
-class Playlist;
 
 class AudioDialog : public wxDialog
 {
 
 class AudioDialog : public wxDialog
 {
@@ -43,7 +42,6 @@ private:
        void setup_channels ();
 
        boost::shared_ptr<Film> _film;
        void setup_channels ();
 
        boost::shared_ptr<Film> _film;
-       boost::shared_ptr<Playlist> _playlist;
        AudioPlot* _plot;
        wxCheckBox* _channel_checkbox[MAX_AUDIO_CHANNELS];
        wxCheckBox* _type_checkbox[AudioPoint::COUNT];
        AudioPlot* _plot;
        wxCheckBox* _channel_checkbox[MAX_AUDIO_CHANNELS];
        wxCheckBox* _type_checkbox[AudioPoint::COUNT];
index 42af4b3c03790334bd851ba1e515f4088932ef24..79b3d982f64b399d78a57c737a5a6d45d9d26b46 100644 (file)
@@ -97,13 +97,13 @@ FilmViewer::film_changed (Film::Property p)
                break;
        case Film::CONTENT:
        {
                break;
        case Film::CONTENT:
        {
-               _playlist = _film->playlist ();
-               _playlist->disable_audio ();
-               _playlist->disable_subtitles ();
-               _playlist->disable_video_sync ();
+               _player = _film->player ();
+               _player->disable_audio ();
+               _player->disable_subtitles ();
+               _player->disable_video_sync ();
 
 
-               _playlist->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3));
-//             _playlist->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this));
+               _player->Video.connect (bind (&FilmViewer::process_video, this, _1, _2, _3));
+//             _player->OutputChanged.connect (boost::bind (&FilmViewer::decoder_changed, this));
                calculate_sizes ();
                get_frame ();
                _panel->Refresh ();
                calculate_sizes ();
                get_frame ();
                _panel->Refresh ();
@@ -153,7 +153,7 @@ FilmViewer::set_film (shared_ptr<Film> f)
 void
 FilmViewer::decoder_changed ()
 {
 void
 FilmViewer::decoder_changed ()
 {
-       if (!_playlist == 0 || _playlist->seek_to_last ()) {
+       if (!_player || _player->seek_to_last ()) {
                return;
        }
 
                return;
        }
 
@@ -165,7 +165,7 @@ FilmViewer::decoder_changed ()
 void
 FilmViewer::timer (wxTimerEvent &)
 {
 void
 FilmViewer::timer (wxTimerEvent &)
 {
-       if (!_playlist) {
+       if (!_player) {
                return;
        }
        
                return;
        }
        
@@ -174,12 +174,12 @@ FilmViewer::timer (wxTimerEvent &)
 
        get_frame ();
 
 
        get_frame ();
 
-//     if (_playlist->video_length()) {
-//             int const new_slider_position = 4096 * _playlist->last_source_time() / (_film->length().get() / _film->source_frame_rate());
-//             if (new_slider_position != _slider->GetValue()) {
-//                     _slider->SetValue (new_slider_position);
-//             }
-//     }
+       if (_film->video_length()) {
+               int const new_slider_position = 4096 * _player->last_video_time() / (_film->video_length() / _film->video_frame_rate());
+               if (new_slider_position != _slider->GetValue()) {
+                       _slider->SetValue (new_slider_position);
+               }
+       }
 }
 
 
 }
 
 
@@ -220,11 +220,11 @@ FilmViewer::paint_panel (wxPaintEvent &)
 void
 FilmViewer::slider_moved (wxScrollEvent &)
 {
 void
 FilmViewer::slider_moved (wxScrollEvent &)
 {
-       if (!_film || !_playlist) {
+       if (!_film || !_player) {
                return;
        }
        
                return;
        }
        
-       if (_playlist->seek (_slider->GetValue() * _playlist->video_length() / (4096 * _playlist->video_frame_rate()))) {
+       if (_player->seek (_slider->GetValue() * _film->video_length() / (4096 * _film->video_frame_rate()))) {
                return;
        }
        
                return;
        }
        
@@ -308,7 +308,7 @@ FilmViewer::raw_to_display ()
 void
 FilmViewer::calculate_sizes ()
 {
 void
 FilmViewer::calculate_sizes ()
 {
-       if (!_film || !_playlist) {
+       if (!_film || !_player) {
                return;
        }
 
                return;
        }
 
@@ -332,7 +332,7 @@ FilmViewer::calculate_sizes ()
        */
        _display_frame_x = 0;
        if (format) {
        */
        _display_frame_x = 0;
        if (format) {
-               _display_frame_x = static_cast<float> (format->dcp_padding (_playlist)) * _out_size.width / format->dcp_size().width;
+               _display_frame_x = static_cast<float> (format->dcp_padding (_film)) * _out_size.width / format->dcp_size().width;
        }
 
        _film_size = _out_size;
        }
 
        _film_size = _out_size;
@@ -381,7 +381,7 @@ FilmViewer::get_frame ()
        /* Clear our raw frame in case we don't get a new one */
        _raw_frame.reset ();
 
        /* Clear our raw frame in case we don't get a new one */
        _raw_frame.reset ();
 
-       if (!_playlist) {
+       if (!_player) {
                _display_frame.reset ();
                return;
        }
                _display_frame.reset ();
                return;
        }
@@ -389,7 +389,7 @@ FilmViewer::get_frame ()
        try {
                _got_frame = false;
                while (!_got_frame) {
        try {
                _got_frame = false;
                while (!_got_frame) {
-                       if (_playlist->pass ()) {
+                       if (_player->pass ()) {
                                /* We didn't get a frame before the decoder gave up,
                                   so clear our display frame.
                                */
                                /* We didn't get a frame before the decoder gave up,
                                   so clear our display frame.
                                */
index 74ab9798c8e64d023885ba03f34d01fe0000c88d..1e75045ac35c75fcb90962fafb36c5d1030d1ccf 100644 (file)
@@ -57,7 +57,7 @@ private:
        void active_jobs_changed (bool);
 
        boost::shared_ptr<Film> _film;
        void active_jobs_changed (bool);
 
        boost::shared_ptr<Film> _film;
-       boost::shared_ptr<Playlist> _playlist;
+       boost::shared_ptr<Player> _player;
 
        wxSizer* _v_sizer;
        wxPanel* _panel;
 
        wxSizer* _v_sizer;
        wxPanel* _panel;
diff --git a/wscript b/wscript
index fb728ec40844697df0b7681c3d09331f22ecd4ba..9040738fb87227a045705ec9abc93e9dd3f8bab9 100644 (file)
--- a/wscript
+++ b/wscript
@@ -55,6 +55,7 @@ def configure(conf):
 
     if not conf.options.static:
         conf.check_cfg(package = 'libdcp', atleast_version = '0.41', args = '--cflags --libs', uselib_store = 'DCP', mandatory = True)
 
     if not conf.options.static:
         conf.check_cfg(package = 'libdcp', atleast_version = '0.41', args = '--cflags --libs', uselib_store = 'DCP', mandatory = True)
+        conf.check_cfg(package = 'libcxml', atleast_version = '0.01', args = '--cflags --libs', uselib_store = 'CXML', mandatory = True)
         conf.check_cfg(package = 'libavformat', args = '--cflags --libs', uselib_store = 'AVFORMAT', mandatory = True)
         conf.check_cfg(package = 'libavfilter', args = '--cflags --libs', uselib_store = 'AVFILTER', mandatory = True)
         conf.check_cfg(package = 'libavcodec', args = '--cflags --libs', uselib_store = 'AVCODEC', mandatory = True)
         conf.check_cfg(package = 'libavformat', args = '--cflags --libs', uselib_store = 'AVFORMAT', mandatory = True)
         conf.check_cfg(package = 'libavfilter', args = '--cflags --libs', uselib_store = 'AVFILTER', mandatory = True)
         conf.check_cfg(package = 'libavcodec', args = '--cflags --libs', uselib_store = 'AVCODEC', mandatory = True)
@@ -71,6 +72,8 @@ def configure(conf):
         conf.env.HAVE_DCP = 1
         conf.env.STLIB_DCP = ['dcp', 'asdcp-libdcp', 'kumu-libdcp']
         conf.env.LIB_DCP = ['glibmm-2.4', 'xml++-2.6', 'ssl', 'crypto', 'bz2']
         conf.env.HAVE_DCP = 1
         conf.env.STLIB_DCP = ['dcp', 'asdcp-libdcp', 'kumu-libdcp']
         conf.env.LIB_DCP = ['glibmm-2.4', 'xml++-2.6', 'ssl', 'crypto', 'bz2']
+        conf.env.HAVE_CXML = 1
+        conf.env.STLIB_CXML = ['cxml']
         conf.env.HAVE_AVFORMAT = 1
         conf.env.STLIB_AVFORMAT = ['avformat']
         conf.env.HAVE_AVFILTER = 1
         conf.env.HAVE_AVFORMAT = 1
         conf.env.STLIB_AVFORMAT = ['avformat']
         conf.env.HAVE_AVFILTER = 1