Text to player with types.
authorCarl Hetherington <cth@carlh.net>
Thu, 19 Jul 2018 20:23:26 +0000 (21:23 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 19 Jul 2018 22:45:23 +0000 (23:45 +0100)
src/lib/active_subtitles.cc [deleted file]
src/lib/active_subtitles.h [deleted file]
src/lib/active_text.cc [new file with mode: 0644]
src/lib/active_text.h [new file with mode: 0644]
src/lib/content_text.h
src/lib/player.cc
src/lib/player.h
src/lib/text_decoder.cc
src/lib/text_decoder.h
src/lib/types.h
src/lib/wscript

diff --git a/src/lib/active_subtitles.cc b/src/lib/active_subtitles.cc
deleted file mode 100644 (file)
index f309ba1..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
-    Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    DCP-o-matic is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include "active_subtitles.h"
-#include "piece.h"
-#include "text_content.h"
-#include <boost/shared_ptr.hpp>
-#include <boost/weak_ptr.hpp>
-
-using std::list;
-using std::pair;
-using std::make_pair;
-using boost::weak_ptr;
-using boost::shared_ptr;
-using boost::optional;
-
-/** Get the subtitles that should be burnt into a given period.
- *  @param period Period of interest.
- *  @param always_burn_subtitles Always burn subtitles even if their content is not set to burn.
- */
-list<PlayerText>
-ActiveSubtitles::get_burnt (DCPTimePeriod period, bool always_burn_subtitles) const
-{
-       list<PlayerText> ps;
-
-       for (Map::const_iterator i = _data.begin(); i != _data.end(); ++i) {
-
-               shared_ptr<Piece> piece = i->first.lock ();
-               if (!piece) {
-                       continue;
-               }
-
-               if (!piece->content->subtitle->use() || (!always_burn_subtitles && !piece->content->subtitle->burn())) {
-                       /* Not burning this piece */
-                       continue;
-               }
-
-               BOOST_FOREACH (Period j, i->second) {
-                       DCPTimePeriod test (j.from, j.to.get_value_or(DCPTime::max()));
-                       optional<DCPTimePeriod> overlap = period.overlap (test);
-                       if (overlap && overlap->duration() > DCPTime(period.duration().get() / 2)) {
-                               ps.push_back (j.subs);
-                       }
-               }
-       }
-
-       return ps;
-}
-
-/** Remove subtitles that finish before a given time from our list.
- *  @param time Time to remove before.
- */
-void
-ActiveSubtitles::clear_before (DCPTime time)
-{
-       Map updated;
-       for (Map::const_iterator i = _data.begin(); i != _data.end(); ++i) {
-               list<Period> as;
-               BOOST_FOREACH (Period j, i->second) {
-                       if (!j.to || j.to.get() >= time) {
-                               as.push_back (j);
-                       }
-               }
-               if (!as.empty ()) {
-                       updated[i->first] = as;
-               }
-       }
-       _data = updated;
-}
-
-/** Add a new subtitle with a from time.
- *  @param piece Piece that the subtitle is from.
- *  @param ps Subtitles.
- *  @param from From time for these subtitles.
- */
-void
-ActiveSubtitles::add_from (weak_ptr<Piece> piece, PlayerText ps, DCPTime from)
-{
-       if (_data.find(piece) == _data.end()) {
-               _data[piece] = list<Period>();
-       }
-       _data[piece].push_back (Period (ps, from));
-}
-
-/** Add the to time for the last subtitle added from a piece.
- *  @param piece Piece that the subtitle is from.
- *  @param to To time for the last subtitle submitted to add_from for this piece.
- *  @return Return the corresponding subtitles and their from time.
- */
-pair<PlayerText, DCPTime>
-ActiveSubtitles::add_to (weak_ptr<Piece> piece, DCPTime to)
-{
-       DCPOMATIC_ASSERT (_data.find(piece) != _data.end());
-
-       _data[piece].back().to = to;
-
-       BOOST_FOREACH (PlainText& i, _data[piece].back().subs.text) {
-               i.set_out (dcp::Time(to.seconds(), 1000));
-       }
-
-       return make_pair (_data[piece].back().subs, _data[piece].back().from);
-}
-
-/** @param piece A piece.
- *  @return true if we have any active subtitles from this piece.
- */
-bool
-ActiveSubtitles::have (weak_ptr<Piece> piece) const
-{
-       Map::const_iterator i = _data.find(piece);
-       if (i == _data.end()) {
-               return false;
-       }
-
-       return !i->second.empty();
-}
-
-void
-ActiveSubtitles::clear ()
-{
-       _data.clear ();
-}
diff --git a/src/lib/active_subtitles.h b/src/lib/active_subtitles.h
deleted file mode 100644 (file)
index 2dd0a4b..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-    Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
-
-    This file is part of DCP-o-matic.
-
-    DCP-o-matic is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    DCP-o-matic is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-/** @file  src/lib/active_subtitles.h
- *  @brief ActiveSubtitles class.
- */
-
-#include "dcpomatic_time.h"
-#include "player_text.h"
-#include <boost/noncopyable.hpp>
-#include <list>
-#include <map>
-
-class Piece;
-
-/** @class ActiveSubtitles
- *  @brief A class to maintain information on active subtitles for Player.
- */
-class ActiveSubtitles : public boost::noncopyable
-{
-public:
-       std::list<PlayerText> get_burnt (DCPTimePeriod period, bool always_burn_subtitles) const;
-       void clear_before (DCPTime time);
-       void clear ();
-       void add_from (boost::weak_ptr<Piece> piece, PlayerText ps, DCPTime from);
-       std::pair<PlayerText, DCPTime> add_to (boost::weak_ptr<Piece> piece, DCPTime to);
-       bool have (boost::weak_ptr<Piece> piece) const;
-
-private:
-       class Period
-       {
-       public:
-               Period () {}
-
-               Period (PlayerText s, DCPTime f)
-                       : subs (s)
-                       , from (f)
-               {}
-
-               PlayerText subs;
-               DCPTime from;
-               boost::optional<DCPTime> to;
-       };
-
-       typedef std::map<boost::weak_ptr<Piece>, std::list<Period> > Map;
-
-       Map _data;
-};
diff --git a/src/lib/active_text.cc b/src/lib/active_text.cc
new file mode 100644 (file)
index 0000000..885aa03
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+    Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    DCP-o-matic is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "active_text.h"
+#include "piece.h"
+#include "text_content.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+
+using std::list;
+using std::pair;
+using std::make_pair;
+using boost::weak_ptr;
+using boost::shared_ptr;
+using boost::optional;
+
+/** Get the subtitles that should be burnt into a given period.
+ *  @param period Period of interest.
+ *  @param always_burn_subtitles Always burn subtitles even if their content is not set to burn.
+ */
+list<PlayerText>
+ActiveText::get_burnt (DCPTimePeriod period, bool always_burn_subtitles) const
+{
+       list<PlayerText> ps;
+
+       for (Map::const_iterator i = _data.begin(); i != _data.end(); ++i) {
+
+               shared_ptr<Piece> piece = i->first.lock ();
+               if (!piece) {
+                       continue;
+               }
+
+               if (!piece->content->subtitle->use() || (!always_burn_subtitles && !piece->content->subtitle->burn())) {
+                       /* Not burning this piece */
+                       continue;
+               }
+
+               BOOST_FOREACH (Period j, i->second) {
+                       DCPTimePeriod test (j.from, j.to.get_value_or(DCPTime::max()));
+                       optional<DCPTimePeriod> overlap = period.overlap (test);
+                       if (overlap && overlap->duration() > DCPTime(period.duration().get() / 2)) {
+                               ps.push_back (j.subs);
+                       }
+               }
+       }
+
+       return ps;
+}
+
+/** Remove subtitles that finish before a given time from our list.
+ *  @param time Time to remove before.
+ */
+void
+ActiveText::clear_before (DCPTime time)
+{
+       Map updated;
+       for (Map::const_iterator i = _data.begin(); i != _data.end(); ++i) {
+               list<Period> as;
+               BOOST_FOREACH (Period j, i->second) {
+                       if (!j.to || j.to.get() >= time) {
+                               as.push_back (j);
+                       }
+               }
+               if (!as.empty ()) {
+                       updated[i->first] = as;
+               }
+       }
+       _data = updated;
+}
+
+/** Add a new subtitle with a from time.
+ *  @param piece Piece that the subtitle is from.
+ *  @param ps Subtitles.
+ *  @param from From time for these subtitles.
+ */
+void
+ActiveText::add_from (weak_ptr<Piece> piece, PlayerText ps, DCPTime from)
+{
+       if (_data.find(piece) == _data.end()) {
+               _data[piece] = list<Period>();
+       }
+       _data[piece].push_back (Period (ps, from));
+}
+
+/** Add the to time for the last subtitle added from a piece.
+ *  @param piece Piece that the subtitle is from.
+ *  @param to To time for the last subtitle submitted to add_from for this piece.
+ *  @return Return the corresponding subtitles and their from time.
+ */
+pair<PlayerText, DCPTime>
+ActiveText::add_to (weak_ptr<Piece> piece, DCPTime to)
+{
+       DCPOMATIC_ASSERT (_data.find(piece) != _data.end());
+
+       _data[piece].back().to = to;
+
+       BOOST_FOREACH (PlainText& i, _data[piece].back().subs.text) {
+               i.set_out (dcp::Time(to.seconds(), 1000));
+       }
+
+       return make_pair (_data[piece].back().subs, _data[piece].back().from);
+}
+
+/** @param piece A piece.
+ *  @return true if we have any active subtitles from this piece.
+ */
+bool
+ActiveText::have (weak_ptr<Piece> piece) const
+{
+       Map::const_iterator i = _data.find(piece);
+       if (i == _data.end()) {
+               return false;
+       }
+
+       return !i->second.empty();
+}
+
+void
+ActiveText::clear ()
+{
+       _data.clear ();
+}
diff --git a/src/lib/active_text.h b/src/lib/active_text.h
new file mode 100644 (file)
index 0000000..09ef1cd
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+    Copyright (C) 2017-2018 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    DCP-o-matic is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+/** @file  src/lib/active_text.h
+ *  @brief ActiveText class.
+ */
+
+#include "dcpomatic_time.h"
+#include "player_text.h"
+#include <boost/noncopyable.hpp>
+#include <list>
+#include <map>
+
+class Piece;
+
+/** @class ActiveText
+ *  @brief A class to maintain information on active subtitles for Player.
+ */
+class ActiveText : public boost::noncopyable
+{
+public:
+       std::list<PlayerText> get_burnt (DCPTimePeriod period, bool always_burn_subtitles) const;
+       void clear_before (DCPTime time);
+       void clear ();
+       void add_from (boost::weak_ptr<Piece> piece, PlayerText ps, DCPTime from);
+       std::pair<PlayerText, DCPTime> add_to (boost::weak_ptr<Piece> piece, DCPTime to);
+       bool have (boost::weak_ptr<Piece> piece) const;
+
+private:
+       class Period
+       {
+       public:
+               Period () {}
+
+               Period (PlayerText s, DCPTime f)
+                       : subs (s)
+                       , from (f)
+               {}
+
+               PlayerText subs;
+               DCPTime from;
+               boost::optional<DCPTime> to;
+       };
+
+       typedef std::map<boost::weak_ptr<Piece>, std::list<Period> > Map;
+
+       Map _data;
+};
index 17ec579dfb93685d3195414878bdb2f20485871b..eaba64ecfcb97d8a6f1ba3171aa192bb7bd4b2b1 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "dcpomatic_time.h"
 #include "rect.h"
+#include "types.h"
 #include "bitmap_text.h"
 #include <dcp/subtitle_string.h>
 #include <list>
@@ -32,23 +33,29 @@ class Image;
 class ContentText
 {
 public:
-       explicit ContentText (ContentTime f)
+       explicit ContentText (ContentTime f, TextType t)
                : _from (f)
+               , _type (t)
        {}
 
        ContentTime from () const {
                return _from;
        }
 
+       TextType type () const {
+               return _type;
+       }
+
 private:
        ContentTime _from;
+       TextType _type;
 };
 
 class ContentBitmapText : public ContentText
 {
 public:
-       ContentBitmapText (ContentTime f, boost::shared_ptr<Image> im, dcpomatic::Rect<double> r)
-               : ContentText (f)
+       ContentBitmapText (ContentTime f, TextType type, boost::shared_ptr<Image> im, dcpomatic::Rect<double> r)
+               : ContentText (f, type)
                , sub (im, r)
        {}
 
@@ -56,15 +63,15 @@ public:
        BitmapText sub;
 };
 
-/** A text subtitle.  We store the time period separately (as well as in the dcp::SubtitleStrings)
+/** A text caption.  We store the time period separately (as well as in the dcp::SubtitleStrings)
  *  as the dcp::SubtitleString timings are sometimes quite heavily quantised and this causes problems
  *  when we want to compare the quantised periods to the unquantised ones.
  */
 class ContentPlainText : public ContentText
 {
 public:
-       ContentPlainText (ContentTime f, std::list<dcp::SubtitleString> s)
-               : ContentText (f)
+       ContentPlainText (ContentTime f, TextType type, std::list<dcp::SubtitleString> s)
+               : ContentText (f, type)
                , subs (s)
        {}
 
index 35047c3aebd5cc699920a259a30a161dcfc31179..36ffd186839b4d2a287128bae228be02fb904f58 100644 (file)
@@ -168,7 +168,7 @@ Player::setup_pieces ()
                if (decoder->subtitle) {
                        decoder->subtitle->BitmapStart.connect (bind (&Player::bitmap_text_start, this, weak_ptr<Piece> (piece), _1));
                        decoder->subtitle->PlainStart.connect (bind (&Player::plain_text_start, this, weak_ptr<Piece> (piece), _1));
-                       decoder->subtitle->Stop.connect (bind (&Player::subtitle_stop, this, weak_ptr<Piece> (piece), _1));
+                       decoder->subtitle->Stop.connect (bind (&Player::subtitle_stop, this, weak_ptr<Piece> (piece), _1, _2));
                }
        }
 
@@ -663,7 +663,7 @@ Player::subtitles_for_frame (DCPTime time) const
 
        int const vfr = _film->video_frame_rate();
 
-       BOOST_FOREACH (PlayerText i, _active_subtitles.get_burnt (DCPTimePeriod(time, time + DCPTime::from_frames(1, vfr)), _always_burn_subtitles)) {
+       BOOST_FOREACH (PlayerText i, _active_text[TEXT_SUBTITLE].get_burnt (DCPTimePeriod(time, time + DCPTime::from_frames(1, vfr)), _always_burn_subtitles)) {
 
                /* Image subtitles */
                list<PositionImage> c = transform_bitmap_texts (i.image);
@@ -862,7 +862,7 @@ Player::bitmap_text_start (weak_ptr<Piece> wp, ContentBitmapText subtitle)
        ps.image.push_back (subtitle.sub);
        DCPTime from (content_time_to_dcp (piece, subtitle.from()));
 
-       _active_subtitles.add_from (wp, ps, from);
+       _active_text[subtitle.type()].add_from (wp, ps, from);
 }
 
 void
@@ -905,13 +905,13 @@ Player::plain_text_start (weak_ptr<Piece> wp, ContentPlainText subtitle)
                ps.add_fonts (piece->content->subtitle->fonts ());
        }
 
-       _active_subtitles.add_from (wp, ps, from);
+       _active_text[subtitle.type()].add_from (wp, ps, from);
 }
 
 void
-Player::subtitle_stop (weak_ptr<Piece> wp, ContentTime to)
+Player::subtitle_stop (weak_ptr<Piece> wp, ContentTime to, TextType type)
 {
-       if (!_active_subtitles.have (wp)) {
+       if (!_active_text[type].have (wp)) {
                return;
        }
 
@@ -926,7 +926,7 @@ Player::subtitle_stop (weak_ptr<Piece> wp, ContentTime to)
                return;
        }
 
-       pair<PlayerText, DCPTime> from = _active_subtitles.add_to (wp, dcp_to);
+       pair<PlayerText, DCPTime> from = _active_text[type].add_to (wp, dcp_to);
 
        if (piece->content->subtitle->use() && !_always_burn_subtitles && !piece->content->subtitle->burn()) {
                Subtitle (from.first, DCPTimePeriod (from.second, dcp_to));
@@ -951,7 +951,9 @@ Player::seek (DCPTime time, bool accurate)
        }
 
        _audio_merger.clear ();
-       _active_subtitles.clear ();
+       for (int i = 0; i < TEXT_COUNT; ++i) {
+               _active_text[i].clear ();
+       }
 
        BOOST_FOREACH (shared_ptr<Piece> i, _pieces) {
                if (time < i->content->position()) {
@@ -1010,7 +1012,9 @@ void
 Player::do_emit_video (shared_ptr<PlayerVideo> pv, DCPTime time)
 {
        if (pv->eyes() == EYES_BOTH || pv->eyes() == EYES_RIGHT) {
-               _active_subtitles.clear_before (time);
+               for (int i = 0; i < TEXT_COUNT; ++i) {
+                       _active_text[i].clear_before (time);
+               }
        }
 
        optional<PositionImage> subtitles = subtitles_for_frame (time);
index 2f1baa53c1659e296af43da5c5522114869b50db..a4170f83e7dd5b4e23e7e54b340c79973e98aff7 100644 (file)
@@ -22,7 +22,7 @@
 #define DCPOMATIC_PLAYER_H
 
 #include "player_text.h"
-#include "active_subtitles.h"
+#include "active_text.h"
 #include "content_text.h"
 #include "film.h"
 #include "content.h"
@@ -128,7 +128,7 @@ private:
        void audio (boost::weak_ptr<Piece>, AudioStreamPtr, ContentAudio);
        void bitmap_text_start (boost::weak_ptr<Piece>, ContentBitmapText);
        void plain_text_start (boost::weak_ptr<Piece>, ContentPlainText);
-       void subtitle_stop (boost::weak_ptr<Piece>, ContentTime);
+       void subtitle_stop (boost::weak_ptr<Piece>, ContentTime, TextType);
        DCPTime one_video_frame () const;
        void fill_audio (DCPTimePeriod period);
        std::pair<boost::shared_ptr<AudioBuffers>, DCPTime> discard_audio (
@@ -196,7 +196,7 @@ private:
        Empty _black;
        Empty _silent;
 
-       ActiveSubtitles _active_subtitles;
+       ActiveText _active_text[TEXT_COUNT];
        boost::shared_ptr<AudioProcessor> _audio_processor;
 
        boost::signals2::scoped_connection _film_changed_connection;
index a7271601df19e19f83c58b490c4209e8294bb283..2423fc73864fd1bcdde8af7f49648814ce18ed09 100644 (file)
@@ -60,7 +60,7 @@ TextDecoder::TextDecoder (
 void
 TextDecoder::emit_bitmap_start (ContentTime from, shared_ptr<Image> image, dcpomatic::Rect<double> rect)
 {
-       BitmapStart (ContentBitmapText (from, image, rect));
+       BitmapStart (ContentBitmapText (from, _content->type(), image, rect));
        _position = from;
 }
 
@@ -94,7 +94,7 @@ TextDecoder::emit_plain_start (ContentTime from, list<dcp::SubtitleString> s)
                }
        }
 
-       PlainStart (ContentPlainText (from, s));
+       PlainStart (ContentPlainText (from, _content->type(), s));
        _position = from;
 }
 
@@ -233,7 +233,7 @@ TextDecoder::emit_plain_start (ContentTime from, sub::Subtitle const & subtitle)
 void
 TextDecoder::emit_stop (ContentTime to)
 {
-       Stop (to);
+       Stop (to, _content->type());
 }
 
 void
index f9d021b3f22581f79b5a921abf06358d06e0db44..96eba80e2ca527442357ec87921f36f1ae3b4812 100644 (file)
@@ -64,7 +64,7 @@ public:
 
        boost::signals2::signal<void (ContentBitmapText)> BitmapStart;
        boost::signals2::signal<void (ContentPlainText)> PlainStart;
-       boost::signals2::signal<void (ContentTime)> Stop;
+       boost::signals2::signal<void (ContentTime, TextType)> Stop;
 
 private:
        boost::shared_ptr<const TextContent> _content;
index 5707cf5cef0ca822c21f70895e2713ee06ff6b23..e52daca00f0751e7c84b7671e77ea01d2fa2e2d4 100644 (file)
@@ -132,7 +132,8 @@ enum ReelType
 enum TextType
 {
        TEXT_SUBTITLE,
-       TEXT_CLOSED_CAPTION
+       TEXT_CLOSED_CAPTION,
+       TEXT_COUNT
 };
 
 extern std::string text_type_to_string (TextType t);
index ee5a583ac11e3e9eb0cc29994e4ab45df0bf78fe..ddbc1d4ff33a88c0d0a118b8d9dbf44e09e717d9 100644 (file)
@@ -21,7 +21,7 @@ import os
 import i18n
 
 sources = """
-          active_subtitles.cc
+          active_text.cc
           analyse_audio_job.cc
           atmos_mxf_content.cc
           audio_analysis.cc