Emit no audio from DCPs if none is mapped
[dcpomatic.git] / src / lib / player.cc
index 0796fbceb118323890583014fbbbb104e412dab1..27c89a2fa2f63a1235c7982076bfb8c8a62b94db 100644 (file)
@@ -251,7 +251,7 @@ have_video (shared_ptr<const Content> content)
 bool
 have_audio (shared_ptr<const Content> content)
 {
-       return static_cast<bool>(content->audio) && content->can_be_played();
+       return static_cast<bool>(content->audio) && !content->audio->mapping().mapped_output_channels().empty() && content->can_be_played();
 }
 
 
@@ -688,6 +688,39 @@ Player::set_play_referenced ()
 }
 
 
+pair<shared_ptr<Piece>, optional<DCPTime>>
+Player::earliest_piece_and_time() const
+{
+       auto film = _film.lock();
+       DCPOMATIC_ASSERT(film);
+
+       shared_ptr<Piece> earliest_content;
+       optional<DCPTime> earliest_time;
+
+       for (auto const& piece: _pieces) {
+               if (piece->done) {
+                       continue;
+               }
+
+               auto const t = content_time_to_dcp(piece, max(piece->decoder->position(), piece->content->trim_start()));
+               if (t > piece->content->end(film)) {
+                       piece->done = true;
+               } else {
+
+                       /* Given two choices at the same time, pick the one with texts so we see it before
+                          the video.
+                       */
+                       if (!earliest_time || t < *earliest_time || (t == *earliest_time && !piece->decoder->text.empty())) {
+                               earliest_time = t;
+                               earliest_content = piece;
+                       }
+               }
+       }
+
+       return { earliest_content, earliest_time };
+}
+
+
 bool
 Player::pass ()
 {
@@ -711,26 +744,7 @@ Player::pass ()
 
        shared_ptr<Piece> earliest_content;
        optional<DCPTime> earliest_time;
-
-       for (auto i: _pieces) {
-               if (i->done) {
-                       continue;
-               }
-
-               auto const t = content_time_to_dcp (i, max(i->decoder->position(), i->content->trim_start()));
-               if (t > i->content->end(film)) {
-                       i->done = true;
-               } else {
-
-                       /* Given two choices at the same time, pick the one with texts so we see it before
-                          the video.
-                       */
-                       if (!earliest_time || t < *earliest_time || (t == *earliest_time && !i->decoder->text.empty())) {
-                               earliest_time = t;
-                               earliest_content = i;
-                       }
-               }
-       }
+       std::tie(earliest_content, earliest_time) = earliest_piece_and_time();
 
        bool done = false;
 
@@ -1094,13 +1108,16 @@ Player::video (weak_ptr<Piece> weak_piece, ContentVideo video)
 
        auto const content_video = piece->content->video;
 
+       auto scaled_size = content_video->scaled_size(film->frame_size());
+       DCPOMATIC_ASSERT(scaled_size);
+
        for (auto eyes: eyes_to_emit) {
                _last_video[weak_piece] = std::make_shared<PlayerVideo>(
                        video.image,
                        content_video->actual_crop(),
                        content_video->fade(film, video.frame),
                        scale_for_display(
-                               content_video->scaled_size(film->frame_size()),
+                               *scaled_size,
                                _video_container_size,
                                film->frame_size(),
                                content_video->pixel_quanta()
@@ -1641,3 +1658,30 @@ Player::set_disable_audio_processor()
        _disable_audio_processor = true;
 }
 
+
+Frame
+Player::frames_done() const
+{
+       auto film = _film.lock();
+       DCPOMATIC_ASSERT(film);
+
+       shared_ptr<Piece> earliest_content;
+       optional<DCPTime> earliest_time;
+       std::tie(earliest_content, earliest_time) = earliest_piece_and_time();
+
+       return earliest_time.get_value_or({}).frames_round(film->video_frame_rate());
+}
+
+
+float
+Player::progress() const
+{
+       auto film = _film.lock();
+       DCPOMATIC_ASSERT(film);
+
+       shared_ptr<Piece> earliest_content;
+       optional<DCPTime> earliest_time;
+       std::tie(earliest_content, earliest_time) = earliest_piece_and_time();
+
+       return static_cast<float>(earliest_time.get_value_or({}).get()) / film->length().get();
+}