Quell config-save warning when we're only trying to save history.
[dcpomatic.git] / src / lib / player.cc
index 1e543fe1f2f79410d39461937bf20fad1e89b596..a7440cb4ffaef40de59a1ca5d5a68259e340c49c 100644 (file)
@@ -98,7 +98,10 @@ Player::Player (shared_ptr<const Film> film, shared_ptr<const Playlist> playlist
        , _shuffler (0)
 {
        _film_changed_connection = _film->Change.connect (bind (&Player::film_change, this, _1, _2));
-       _playlist_change_connection = _playlist->Change.connect (bind (&Player::playlist_change, this, _1));
+       /* The butler must hear about this first, so since we are proxying this through to the butler we must
+          be first.
+       */
+       _playlist_change_connection = _playlist->Change.connect (bind (&Player::playlist_change, this, _1), boost::signals2::at_front);
        _playlist_content_change_connection = _playlist->ContentChange.connect (bind(&Player::playlist_content_change, this, _1, _3, _4));
        set_video_container_size (_film->frame_size ());
 
@@ -120,6 +123,18 @@ Player::setup_pieces ()
        setup_pieces_unlocked ();
 }
 
+bool
+have_video (shared_ptr<Piece> piece)
+{
+       return piece->decoder && piece->decoder->video;
+}
+
+bool
+have_audio (shared_ptr<Piece> piece)
+{
+       return piece->decoder && piece->decoder->audio;
+}
+
 void
 Player::setup_pieces_unlocked ()
 {
@@ -196,7 +211,7 @@ Player::setup_pieces_unlocked ()
                                bind(&Player::plain_text_start, this, weak_ptr<Piece>(piece), weak_ptr<const TextContent>((*j)->content()), _1)
                                );
                        (*j)->Stop.connect (
-                               bind(&Player::subtitle_stop, this, weak_ptr<Piece>(piece), weak_ptr<const TextContent>((*j)->content()), _1, _2)
+                               bind(&Player::subtitle_stop, this, weak_ptr<Piece>(piece), weak_ptr<const TextContent>((*j)->content()), _1)
                                );
 
                        ++j;
@@ -212,8 +227,8 @@ Player::setup_pieces_unlocked ()
                }
        }
 
-       _black = Empty (_film->content(), _film->length(), bind(&Content::video, _1));
-       _silent = Empty (_film->content(), _film->length(), bind(&Content::audio, _1));
+       _black = Empty (_pieces, _film->length(), bind(&have_video, _1));
+       _silent = Empty (_pieces, _film->length(), bind(&have_audio, _1));
 
        _last_video_time = DCPTime ();
        _last_video_eyes = EYES_BOTH;
@@ -234,6 +249,9 @@ Player::playlist_content_change (ChangeType type, int property, bool frequent)
        } else if (type == CHANGE_TYPE_DONE) {
                /* A change in our content has gone through.  Re-build our pieces. */
                setup_pieces ();
+       } else if (type == CHANGE_TYPE_CANCELLED) {
+               boost::mutex::scoped_lock lm (_mutex);
+               _suspended = false;
        }
 
        Change (type, property, frequent);
@@ -302,39 +320,6 @@ Player::film_change (ChangeType type, Film::Property p)
        }
 }
 
-list<PositionImage>
-Player::transform_bitmap_texts (list<BitmapText> subs) const
-{
-       list<PositionImage> all;
-
-       for (list<BitmapText>::const_iterator i = subs.begin(); i != subs.end(); ++i) {
-               if (!i->image) {
-                       continue;
-               }
-
-               /* We will scale the subtitle up to fit _video_container_size */
-               dcp::Size scaled_size (i->rectangle.width * _video_container_size.width, i->rectangle.height * _video_container_size.height);
-
-               all.push_back (
-                       PositionImage (
-                               i->image->scale (
-                                       scaled_size,
-                                       dcp::YUV_TO_RGB_REC601,
-                                       i->image->pixel_format (),
-                                       true,
-                                       _fast
-                                       ),
-                               Position<int> (
-                                       lrint (_video_container_size.width * i->rectangle.x),
-                                       lrint (_video_container_size.height * i->rectangle.y)
-                                       )
-                               )
-                       );
-       }
-
-       return all;
-}
-
 shared_ptr<PlayerVideo>
 Player::black_player_video_frame (Eyes eyes) const
 {
@@ -709,8 +694,24 @@ Player::open_subtitles_for_frame (DCPTime time) const
                ) {
 
                /* Bitmap subtitles */
-               list<PositionImage> c = transform_bitmap_texts (j.bitmap);
-               copy (c.begin(), c.end(), back_inserter (captions));
+               BOOST_FOREACH (BitmapText i, j.bitmap) {
+                       if (!i.image) {
+                               continue;
+                       }
+
+                       /* i.image will already have been scaled to fit _video_container_size */
+                       dcp::Size scaled_size (i.rectangle.width * _video_container_size.width, i.rectangle.height * _video_container_size.height);
+
+                       captions.push_back (
+                               PositionImage (
+                                       i.image,
+                                       Position<int> (
+                                               lrint (_video_container_size.width * i.rectangle.x),
+                                               lrint (_video_container_size.height * i.rectangle.y)
+                                               )
+                                       )
+                               );
+               }
 
                /* String subtitles (rendered to an image) */
                if (!j.string.empty ()) {
@@ -911,10 +912,13 @@ Player::bitmap_text_start (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, C
        subtitle.sub.rectangle.height *= text->y_scale ();
 
        PlayerText ps;
-       ps.bitmap.push_back (subtitle.sub);
+       shared_ptr<Image> image = subtitle.sub.image;
+       /* We will scale the subtitle up to fit _video_container_size */
+       dcp::Size scaled_size (subtitle.sub.rectangle.width * _video_container_size.width, subtitle.sub.rectangle.height * _video_container_size.height);
+       ps.bitmap.push_back (BitmapText(image->scale(scaled_size, dcp::YUV_TO_RGB_REC601, image->pixel_format(), true, _fast), subtitle.sub.rectangle));
        DCPTime from (content_time_to_dcp (piece, subtitle.from()));
 
-       _active_texts[subtitle.type()].add_from (wc, ps, from);
+       _active_texts[text->type()].add_from (wc, ps, from);
 }
 
 void
@@ -958,19 +962,23 @@ Player::plain_text_start (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, Co
                ps.add_fonts (text->fonts ());
        }
 
-       _active_texts[subtitle.type()].add_from (wc, ps, from);
+       _active_texts[text->type()].add_from (wc, ps, from);
 }
 
 void
-Player::subtitle_stop (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, ContentTime to, TextType type)
+Player::subtitle_stop (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, ContentTime to)
 {
-       if (!_active_texts[type].have (wc)) {
+       shared_ptr<const TextContent> text = wc.lock ();
+       if (!text) {
+               return;
+       }
+
+       if (!_active_texts[text->type()].have(wc)) {
                return;
        }
 
        shared_ptr<Piece> piece = wp.lock ();
-       shared_ptr<const TextContent> text = wc.lock ();
-       if (!piece || !text) {
+       if (!piece) {
                return;
        }
 
@@ -980,11 +988,11 @@ Player::subtitle_stop (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, Conte
                return;
        }
 
-       pair<PlayerText, DCPTime> from = _active_texts[type].add_to (wc, dcp_to);
+       pair<PlayerText, DCPTime> from = _active_texts[text->type()].add_to (wc, dcp_to);
 
-       bool const always = (type == TEXT_OPEN_SUBTITLE && _always_burn_open_subtitles);
+       bool const always = (text->type() == TEXT_OPEN_SUBTITLE && _always_burn_open_subtitles);
        if (text->use() && !always && !text->burn()) {
-               Text (from.first, type, DCPTimePeriod (from.second, dcp_to));
+               Text (from.first, text->type(), text->dcp_track().get_value_or(DCPTextTrack()), DCPTimePeriod (from.second, dcp_to));
        }
 }