Go back to player having a playlist and not assuming it uses the film's content.
authorCarl Hetherington <cth@carlh.net>
Mon, 29 Jun 2015 22:19:04 +0000 (23:19 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 1 Jul 2015 16:27:02 +0000 (17:27 +0100)
12 files changed:
src/lib/analyse_audio_job.cc
src/lib/analyse_audio_job.h
src/lib/film.h
src/lib/player.cc
src/lib/player.h
src/lib/transcoder.cc
src/tools/server_test.cc
src/wx/audio_dialog.cc
src/wx/film_viewer.cc
test/audio_analysis_test.cc
test/player_test.cc
test/upmixer_a_test.cc

index 8f9b150..2146b03 100644 (file)
@@ -23,6 +23,7 @@
 #include "compose.hpp"
 #include "film.h"
 #include "player.h"
+#include "playlist.h"
 #include <boost/foreach.hpp>
 
 #include "i18n.h"
@@ -36,8 +37,9 @@ using boost::dynamic_pointer_cast;
 
 int const AnalyseAudioJob::_num_points = 1024;
 
-AnalyseAudioJob::AnalyseAudioJob (shared_ptr<const Film> film)
+AnalyseAudioJob::AnalyseAudioJob (shared_ptr<const Film> film, shared_ptr<const Playlist> playlist)
        : Job (film)
+       , _playlist (playlist)
        , _done (0)
        , _samples_per_point (1)
        , _overall_peak (0)
@@ -61,17 +63,17 @@ AnalyseAudioJob::json_name () const
 void
 AnalyseAudioJob::run ()
 {
-       shared_ptr<Player> player (new Player (_film));
+       shared_ptr<Player> player (new Player (_film, _playlist));
        player->set_ignore_video ();
 
-       int64_t const len = _film->length().frames (_film->audio_frame_rate());
+       int64_t const len = _playlist->length().frames (_film->audio_frame_rate());
        _samples_per_point = max (int64_t (1), len / _num_points);
 
        _current.resize (_film->audio_channels ());
        _analysis.reset (new AudioAnalysis (_film->audio_channels ()));
 
        bool has_any_audio = false;
-       BOOST_FOREACH (shared_ptr<Content> c, _film->content ()) {
+       BOOST_FOREACH (shared_ptr<Content> c, _playlist->content ()) {
                if (dynamic_pointer_cast<AudioContent> (c)) {
                        has_any_audio = true;
                }
@@ -127,4 +129,3 @@ AnalyseAudioJob::analyse (shared_ptr<const AudioBuffers> b)
                ++_done;
        }
 }
-
index 1794ab3..234424b 100644 (file)
@@ -26,6 +26,7 @@
 #include "types.h"
 
 class AudioBuffers;
+class Playlist;
 
 /** @class AnalyseAudioJob
  *  @brief A job to analyse the audio of a film and make a note of its
@@ -37,7 +38,7 @@ class AudioBuffers;
 class AnalyseAudioJob : public Job
 {
 public:
-       AnalyseAudioJob (boost::shared_ptr<const Film>);
+       AnalyseAudioJob (boost::shared_ptr<const Film>, boost::shared_ptr<const Playlist>);
 
        std::string name () const;
        std::string json_name () const;
@@ -46,6 +47,8 @@ public:
 private:
        void analyse (boost::shared_ptr<const AudioBuffers>);
 
+       boost::shared_ptr<const Playlist> _playlist;
+
        int64_t _done;
        int64_t _samples_per_point;
        std::vector<AudioPoint> _current;
@@ -57,4 +60,3 @@ private:
 
        static const int _num_points;
 };
-
index fe1795b..23478c4 100644 (file)
@@ -141,6 +141,10 @@ public:
 
        void repeat_content (ContentList, int);
 
+       boost::shared_ptr<const Playlist> playlist () const {
+               return _playlist;
+       }
+
        /** Identifiers for the parts of our state;
            used for signalling changes.
        */
index 361f41c..2eaf817 100644 (file)
@@ -45,6 +45,7 @@
 #include "dcp_subtitle_content.h"
 #include "dcp_subtitle_decoder.h"
 #include "audio_processor.h"
+#include "playlist.h"
 #include <boost/foreach.hpp>
 #include <stdint.h>
 #include <algorithm>
@@ -68,14 +69,16 @@ using boost::weak_ptr;
 using boost::dynamic_pointer_cast;
 using boost::optional;
 
-Player::Player (shared_ptr<const Film> film)
+Player::Player (shared_ptr<const Film> film, shared_ptr<const Playlist> playlist)
        : _film (film)
+       , _playlist (playlist)
        , _have_valid_pieces (false)
        , _ignore_video (false)
        , _always_burn_subtitles (false)
 {
-       _film_content_changed_connection = _film->ContentChanged.connect (bind (&Player::content_changed, this, _1, _2, _3));
        _film_changed_connection = _film->Changed.connect (bind (&Player::film_changed, this, _1));
+       _playlist_changed_connection = _playlist->ContentChanged.connect (bind (&Player::playlist_changed, this));
+       _playlist_content_changed_connection = _playlist->ContentChanged.connect (bind (&Player::playlist_content_changed, this, _1, _2, _3));
        set_video_container_size (_film->frame_size ());
 
        film_changed (Film::AUDIO_PROCESSOR);
@@ -87,11 +90,9 @@ Player::setup_pieces ()
        list<shared_ptr<Piece> > old_pieces = _pieces;
        _pieces.clear ();
 
-       ContentList content = _film->content ();
+       BOOST_FOREACH (shared_ptr<Content> i, _playlist->content ()) {
 
-       for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
-
-               if (!(*i)->paths_valid ()) {
+               if (!i->paths_valid ()) {
                        continue;
                }
 
@@ -101,13 +102,13 @@ Player::setup_pieces ()
                /* Work out a FrameRateChange for the best overlap video for this content, in case we need it below */
                DCPTime best_overlap_t;
                shared_ptr<VideoContent> best_overlap;
-               for (ContentList::iterator j = content.begin(); j != content.end(); ++j) {
-                       shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (*j);
+               BOOST_FOREACH (shared_ptr<Content> j, _playlist->content ()) {
+                       shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (j);
                        if (!vc) {
                                continue;
                        }
 
-                       DCPTime const overlap = max (vc->position(), (*i)->position()) - min (vc->end(), (*i)->end());
+                       DCPTime const overlap = max (vc->position(), i->position()) - min (vc->end(), i->end());
                        if (overlap > best_overlap_t) {
                                best_overlap = vc;
                                best_overlap_t = overlap;
@@ -123,20 +124,20 @@ Player::setup_pieces ()
                }
 
                /* FFmpeg */
-               shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (*i);
+               shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (i);
                if (fc) {
                        decoder.reset (new FFmpegDecoder (fc, _film->log()));
                        frc = FrameRateChange (fc->video_frame_rate(), _film->video_frame_rate());
                }
 
-               shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (*i);
+               shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (i);
                if (dc) {
                        decoder.reset (new DCPDecoder (dc));
                        frc = FrameRateChange (dc->video_frame_rate(), _film->video_frame_rate());
                }
 
                /* ImageContent */
-               shared_ptr<const ImageContent> ic = dynamic_pointer_cast<const ImageContent> (*i);
+               shared_ptr<const ImageContent> ic = dynamic_pointer_cast<const ImageContent> (i);
                if (ic) {
                        /* See if we can re-use an old ImageDecoder */
                        for (list<shared_ptr<Piece> >::const_iterator j = old_pieces.begin(); j != old_pieces.end(); ++j) {
@@ -154,21 +155,21 @@ Player::setup_pieces ()
                }
 
                /* SndfileContent */
-               shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (*i);
+               shared_ptr<const SndfileContent> sc = dynamic_pointer_cast<const SndfileContent> (i);
                if (sc) {
                        decoder.reset (new SndfileDecoder (sc));
                        frc = best_overlap_frc;
                }
 
                /* SubRipContent */
-               shared_ptr<const SubRipContent> rc = dynamic_pointer_cast<const SubRipContent> (*i);
+               shared_ptr<const SubRipContent> rc = dynamic_pointer_cast<const SubRipContent> (i);
                if (rc) {
                        decoder.reset (new SubRipDecoder (rc));
                        frc = best_overlap_frc;
                }
 
                /* DCPSubtitleContent */
-               shared_ptr<const DCPSubtitleContent> dsc = dynamic_pointer_cast<const DCPSubtitleContent> (*i);
+               shared_ptr<const DCPSubtitleContent> dsc = dynamic_pointer_cast<const DCPSubtitleContent> (i);
                if (dsc) {
                        decoder.reset (new DCPSubtitleDecoder (dsc));
                        frc = best_overlap_frc;
@@ -179,14 +180,14 @@ Player::setup_pieces ()
                        vd->set_ignore_video ();
                }
 
-               _pieces.push_back (shared_ptr<Piece> (new Piece (*i, decoder, frc.get ())));
+               _pieces.push_back (shared_ptr<Piece> (new Piece (i, decoder, frc.get ())));
        }
 
        _have_valid_pieces = true;
 }
 
 void
-Player::content_changed (weak_ptr<Content> w, int property, bool frequent)
+Player::playlist_content_changed (weak_ptr<Content> w, int property, bool frequent)
 {
        shared_ptr<Content> c = w.lock ();
        if (!c) {
@@ -232,6 +233,13 @@ Player::set_video_container_size (dcp::Size s)
        _black_image->make_black ();
 }
 
+void
+Player::playlist_changed ()
+{
+       _have_valid_pieces = false;
+       Changed (false);
+}
+
 void
 Player::film_changed (Film::Property p)
 {
@@ -240,10 +248,7 @@ Player::film_changed (Film::Property p)
           last time we were run.
        */
 
-       if (p == Film::CONTENT) {
-               _have_valid_pieces = false;
-               Changed (false);
-       } else if (p == Film::CONTAINER || p == Film::VIDEO_FRAME_RATE) {
+       if (p == Film::CONTAINER || p == Film::VIDEO_FRAME_RATE) {
                Changed (false);
        } else if (p == Film::AUDIO_PROCESSOR) {
                if (_film->audio_processor ()) {
index 6edfa49..0abb02d 100644 (file)
@@ -78,12 +78,12 @@ public:
 };
 
 /** @class Player
- *  @brief A class which can `play' a Film.
+ *  @brief A class which can `play' a Playlist.
  */
 class Player : public boost::enable_shared_from_this<Player>, public boost::noncopyable
 {
 public:
-       Player (boost::shared_ptr<const Film>);
+       Player (boost::shared_ptr<const Film>, boost::shared_ptr<const Playlist> playlist);
 
        std::list<boost::shared_ptr<PlayerVideo> > get_video (DCPTime time, bool accurate);
        boost::shared_ptr<AudioBuffers> get_audio (DCPTime time, DCPTime length, bool accurate);
@@ -111,9 +111,10 @@ private:
        friend struct player_overlaps_test;
 
        void setup_pieces ();
-       void content_changed (boost::weak_ptr<Content>, int, bool);
        void flush ();
        void film_changed (Film::Property);
+       void playlist_changed ();
+       void playlist_content_changed (boost::weak_ptr<Content>, int, bool);
        std::list<PositionImage> transform_image_subtitles (std::list<ImageSubtitle>) const;
        void update_subtitle_from_text ();
        Frame dcp_to_content_video (boost::shared_ptr<const Piece> piece, DCPTime t) const;
@@ -146,6 +147,7 @@ private:
        }
 
        boost::shared_ptr<const Film> _film;
+       boost::shared_ptr<const Playlist> _playlist;
 
        /** Our pieces are ready to go; if this is false the pieces must be (re-)created before they are used */
        bool _have_valid_pieces;
@@ -166,8 +168,9 @@ private:
 
        PlayerStatistics _statistics;
 
-       boost::signals2::scoped_connection _film_content_changed_connection;
        boost::signals2::scoped_connection _film_changed_connection;
+       boost::signals2::scoped_connection _playlist_changed_connection;
+       boost::signals2::scoped_connection _playlist_content_changed_connection;
 };
 
 #endif
index fd216c1..e0af2c5 100644 (file)
@@ -50,7 +50,7 @@ using boost::dynamic_pointer_cast;
  */
 Transcoder::Transcoder (shared_ptr<const Film> film, shared_ptr<Job> j)
        : _film (film)
-       , _player (new Player (film))
+       , _player (new Player (film, film->playlist ()))
        , _writer (new Writer (film, j))
        , _encoder (new Encoder (film, j, _writer))
        , _finishing (false)
@@ -112,4 +112,3 @@ Transcoder::video_frames_out () const
 {
        return _encoder->video_frames_out ();
 }
-
index b7e48a3..19b5133 100644 (file)
@@ -142,7 +142,7 @@ main (int argc, char* argv[])
                film.reset (new Film (film_dir));
                film->read_metadata ();
 
-               shared_ptr<Player> player (new Player (film));
+               shared_ptr<Player> player (new Player (film, film->playlist ()));
 
                DCPTime const frame = DCPTime::from_frames (1, film->video_frame_rate ());
                for (DCPTime t; t < film->length(); t += frame) {
index fd523aa..70046f5 100644 (file)
@@ -126,7 +126,7 @@ AudioDialog::try_to_load_analysis ()
        if (!boost::filesystem::exists (path)) {
                _plot->set_analysis (shared_ptr<AudioAnalysis> ());
                _analysis.reset ();
-               shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film));
+               shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, film->playlist ()));
                _analysis_finished_connection = job->Finished.connect (bind (&AudioDialog::analysis_finished, this));
                JobManager::instance()->add (job);
                return;
@@ -136,7 +136,7 @@ AudioDialog::try_to_load_analysis ()
                _analysis.reset (new AudioAnalysis (path));
        } catch (xmlpp::exception& e) {
                /* Probably an old-style analysis file: recreate it */
-               shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film));
+               shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, film->playlist ()));
                _analysis_finished_connection = job->Finished.connect (bind (&AudioDialog::analysis_finished, this));
                JobManager::instance()->add (job);
                return;
@@ -265,5 +265,3 @@ AudioDialog::Show (bool show)
        try_to_load_analysis ();
        return r;
 }
-
-
index 7a306de..6f29bcc 100644 (file)
@@ -138,7 +138,7 @@ FilmViewer::set_film (shared_ptr<Film> film)
        }
 
        try {
-               _player.reset (new Player (_film));
+               _player.reset (new Player (_film, _film->playlist ()));
        } catch (bad_alloc) {
                error_dialog (this, _("There is not enough free memory to do that."));
                _film.reset ();
index 94ad96a..7cbe283 100644 (file)
@@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE (audio_analysis_test)
        film->examine_and_add_content (c);
        wait_for_jobs ();
 
-       shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film));
+       shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, film->playlist ()));
        job->Finished.connect (boost::bind (&finished));
        JobManager::instance()->add (job);
        wait_for_jobs ();
@@ -115,7 +115,7 @@ BOOST_AUTO_TEST_CASE (audio_analysis_negative_delay_test)
        film->examine_and_add_content (c);
        wait_for_jobs ();
 
-       shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film));
+       shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, film->playlist ()));
        job->Finished.connect (boost::bind (&finished));
        JobManager::instance()->add (job);
        wait_for_jobs ();
@@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE (audio_analysis_test2)
        film->examine_and_add_content (c);
        wait_for_jobs ();
 
-       shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film));
+       shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, film->playlist ()));
        job->Finished.connect (boost::bind (&finished));
        JobManager::instance()->add (job);
        wait_for_jobs ();
index 87e7fda..12e928a 100644 (file)
@@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE (player_overlaps_test)
        B->set_position (DCPTime::from_seconds (10));
        C->set_position (DCPTime::from_seconds (20));
 
-       shared_ptr<Player> player (new Player (film));
+       shared_ptr<Player> player (new Player (film, film->playlist ()));
 
        list<shared_ptr<Piece> > o = player->overlaps<FFmpegContent> (DCPTime::from_seconds (0), DCPTime::from_seconds (5));
        BOOST_CHECK_EQUAL (o.size(), 1U);
@@ -92,7 +92,7 @@ BOOST_AUTO_TEST_CASE (player_silence_padding_test)
        film->examine_and_add_content (c);
        wait_for_jobs ();
 
-       shared_ptr<Player> player (new Player (film));
+       shared_ptr<Player> player (new Player (film, film->playlist ()));
        shared_ptr<AudioBuffers> test = player->get_audio (DCPTime (0), DCPTime::from_seconds (1), true);
        BOOST_CHECK_EQUAL (test->frames(), 48000);
        BOOST_CHECK_EQUAL (test->channels(), film->audio_channels ());
@@ -103,4 +103,3 @@ BOOST_AUTO_TEST_CASE (player_silence_padding_test)
                }
        }
 }
-
index 9bdcfd7..5b7cff7 100644 (file)
@@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE (upmixer_a_test)
        SNDFILE* Ls = sf_open ("build/test/upmixer_a_test/Ls.wav", SFM_WRITE, &info);
        SNDFILE* Rs = sf_open ("build/test/upmixer_a_test/Rs.wav", SFM_WRITE, &info);
 
-       shared_ptr<Player> player (new Player (film));
+       shared_ptr<Player> player (new Player (film, film->playlist ()));
        for (DCPTime t; t < film->length(); t += DCPTime::from_seconds (1)) {
                shared_ptr<AudioBuffers> b = player->get_audio (t, DCPTime::from_seconds (1), true);
                sf_write_float (L, b->data(0), b->frames());