summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-10-06 13:31:45 +0100
committerCarl Hetherington <cth@carlh.net>2014-10-06 13:31:45 +0100
commit630a56ad9e7ecfb42b1d761098820f9e492f9c4e (patch)
tree18080ecfc5b716d22ae041908356b11350c87e0b /src/lib
parent152b14ab5509678f3d68b52a1ed275cfdc38191b (diff)
Use libsub for subrip decoding; improve default position of srt subs.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/subrip.cc189
-rw-r--r--src/lib/subrip.h14
-rw-r--r--src/lib/subrip_decoder.cc58
-rw-r--r--src/lib/wscript2
4 files changed, 41 insertions, 222 deletions
diff --git a/src/lib/subrip.cc b/src/lib/subrip.cc
index 6c9cef916..8a7423698 100644
--- a/src/lib/subrip.cc
+++ b/src/lib/subrip.cc
@@ -17,23 +17,17 @@
*/
-#include <boost/algorithm/string.hpp>
-#include <boost/lexical_cast.hpp>
#include "subrip.h"
-#include "subrip_content.h"
-#include "subrip_subtitle.h"
#include "cross.h"
#include "exceptions.h"
+#include "subrip_content.h"
+#include <libsub/subrip_reader.h>
+#include <libsub/collect.h>
#include "i18n.h"
-using std::string;
-using std::list;
using std::vector;
-using std::cout;
using boost::shared_ptr;
-using boost::lexical_cast;
-using boost::algorithm::trim;
SubRip::SubRip (shared_ptr<const SubRipContent> content)
{
@@ -42,179 +36,8 @@ SubRip::SubRip (shared_ptr<const SubRipContent> content)
throw OpenFileError (content->path (0));
}
- enum {
- COUNTER,
- METADATA,
- CONTENT
- } state = COUNTER;
-
- char buffer[256];
-
- boost::optional<SubRipSubtitle> current;
- list<string> lines;
-
- while (!feof (f)) {
- fgets (buffer, sizeof (buffer), f);
- if (feof (f)) {
- break;
- }
-
- string line (buffer);
- trim_right_if (line, boost::is_any_of ("\n\r"));
-
- switch (state) {
- case COUNTER:
- {
- if (line.empty ()) {
- /* a blank line at the start is ok */
- break;
- }
-
- state = METADATA;
- current = SubRipSubtitle ();
- }
- break;
- case METADATA:
- {
- vector<string> p;
- boost::algorithm::split (p, line, boost::algorithm::is_any_of (" "));
- if (p.size() != 3 && p.size() != 7) {
- throw SubRipError (line, _("a time/position line"), content->path (0));
- }
-
- current->period = ContentTimePeriod (convert_time (p[0]), convert_time (p[2]));
-
- if (p.size() > 3) {
- current->x1 = convert_coordinate (p[3]);
- current->x2 = convert_coordinate (p[4]);
- current->y1 = convert_coordinate (p[5]);
- current->y2 = convert_coordinate (p[6]);
- }
- state = CONTENT;
- break;
- }
- case CONTENT:
- if (line.empty ()) {
- state = COUNTER;
- current->pieces = convert_content (lines);
- _subtitles.push_back (current.get ());
- current.reset ();
- lines.clear ();
- } else {
- lines.push_back (line);
- }
- break;
- }
- }
-
- if (state == CONTENT) {
- current->pieces = convert_content (lines);
- _subtitles.push_back (current.get ());
- }
-
- fclose (f);
-}
-
-ContentTime
-SubRip::convert_time (string t)
-{
- ContentTime r;
-
- vector<string> a;
- boost::algorithm::split (a, t, boost::is_any_of (":"));
- assert (a.size() == 3);
- r += ContentTime::from_seconds (lexical_cast<int> (a[0]) * 60 * 60);
- r += ContentTime::from_seconds (lexical_cast<int> (a[1]) * 60);
-
- vector<string> b;
- boost::algorithm::split (b, a[2], boost::is_any_of (","));
- r += ContentTime::from_seconds (lexical_cast<int> (b[0]));
- r += ContentTime::from_seconds (lexical_cast<double> (b[1]) / 1000);
-
- return r;
-}
-
-int
-SubRip::convert_coordinate (string t)
-{
- vector<string> a;
- boost::algorithm::split (a, t, boost::is_any_of (":"));
- assert (a.size() == 2);
- return lexical_cast<int> (a[1]);
-}
-
-void
-SubRip::maybe_content (list<SubRipSubtitlePiece>& pieces, SubRipSubtitlePiece& p)
-{
- if (!p.text.empty ()) {
- pieces.push_back (p);
- p.text.clear ();
- }
-}
-
-list<SubRipSubtitlePiece>
-SubRip::convert_content (list<string> t)
-{
- list<SubRipSubtitlePiece> pieces;
-
- SubRipSubtitlePiece p;
-
- enum {
- TEXT,
- TAG
- } state = TEXT;
-
- string tag;
-
- /* XXX: missing <font> support */
- /* XXX: nesting of tags e.g. <b>foo<i>bar<b>baz</b>fred</i>jim</b> might
- not work, I think.
- */
-
- for (list<string>::const_iterator i = t.begin(); i != t.end(); ++i) {
- for (size_t j = 0; j < i->size(); ++j) {
- switch (state) {
- case TEXT:
- if ((*i)[j] == '<' || (*i)[j] == '{') {
- state = TAG;
- } else {
- p.text += (*i)[j];
- }
- break;
- case TAG:
- if ((*i)[j] == '>' || (*i)[j] == '}') {
- if (tag == "b") {
- maybe_content (pieces, p);
- p.bold = true;
- } else if (tag == "/b") {
- maybe_content (pieces, p);
- p.bold = false;
- } else if (tag == "i") {
- maybe_content (pieces, p);
- p.italic = true;
- } else if (tag == "/i") {
- maybe_content (pieces, p);
- p.italic = false;
- } else if (tag == "u") {
- maybe_content (pieces, p);
- p.underline = true;
- } else if (tag == "/u") {
- maybe_content (pieces, p);
- p.underline = false;
- }
- tag.clear ();
- state = TEXT;
- } else {
- tag += (*i)[j];
- }
- break;
- }
- }
- }
-
- maybe_content (pieces, p);
-
- return pieces;
+ sub::SubripReader reader (f);
+ _subtitles = sub::collect<vector<sub::Subtitle> > (reader.subtitles ());
}
ContentTime
@@ -224,5 +47,5 @@ SubRip::length () const
return ContentTime ();
}
- return _subtitles.back().period.to;
+ return ContentTime::from_seconds (_subtitles.back().to.metric().get().all_as_seconds ());
}
diff --git a/src/lib/subrip.h b/src/lib/subrip.h
index 7603a101d..14bc360c0 100644
--- a/src/lib/subrip.h
+++ b/src/lib/subrip.h
@@ -21,6 +21,7 @@
#define DCPOMATIC_SUBRIP_H
#include "subrip_subtitle.h"
+#include <libsub/subtitle.h>
class SubRipContent;
class subrip_time_test;
@@ -36,18 +37,7 @@ public:
ContentTime length () const;
protected:
- std::vector<SubRipSubtitle> _subtitles;
-
-private:
- friend struct subrip_time_test;
- friend struct subrip_coordinate_test;
- friend struct subrip_content_test;
- friend struct subrip_parse_test;
-
- static ContentTime convert_time (std::string);
- static int convert_coordinate (std::string);
- static std::list<SubRipSubtitlePiece> convert_content (std::list<std::string>);
- static void maybe_content (std::list<SubRipSubtitlePiece> &, SubRipSubtitlePiece &);
+ std::vector<sub::Subtitle> _subtitles;
};
#endif
diff --git a/src/lib/subrip_decoder.cc b/src/lib/subrip_decoder.cc
index 2ae285b5e..411e7542d 100644
--- a/src/lib/subrip_decoder.cc
+++ b/src/lib/subrip_decoder.cc
@@ -39,11 +39,9 @@ SubRipDecoder::seek (ContentTime time, bool accurate)
SubtitleDecoder::seek (time, accurate);
_next = 0;
- list<SubRipSubtitlePiece>::const_iterator i = _subtitles[_next].pieces.begin();
- while (i != _subtitles[_next].pieces.end() && _subtitles[_next].period.from < time) {
- ++i;
+ while (_next < _subtitles.size() && ContentTime::from_seconds (_subtitles[_next].from.metric().get().all_as_seconds ()) < time) {
+ ++_next;
}
-
}
bool
@@ -56,25 +54,27 @@ SubRipDecoder::pass ()
/* XXX: we are ignoring positioning specified in the file */
list<dcp::SubtitleString> out;
- for (list<SubRipSubtitlePiece>::const_iterator i = _subtitles[_next].pieces.begin(); i != _subtitles[_next].pieces.end(); ++i) {
- out.push_back (
- dcp::SubtitleString (
- "Arial",
- i->italic,
- dcp::Color (255, 255, 255),
- /* .srt files don't specify size, so this is an arbitrary value */
- 48,
- dcp::Time (rint (_subtitles[_next].period.from.seconds() * 250)),
- dcp::Time (rint (_subtitles[_next].period.to.seconds() * 250)),
- 0.2,
- dcp::BOTTOM,
- i->text,
- dcp::NONE,
- dcp::Color (255, 255, 255),
- 0,
- 0
- )
- );
+ for (list<sub::Line>::const_iterator i = _subtitles[_next].lines.begin(); i != _subtitles[_next].lines.end(); ++i) {
+ for (list<sub::Block>::const_iterator j = i->blocks.begin(); j != i->blocks.end(); ++j) {
+ out.push_back (
+ dcp::SubtitleString (
+ "Arial",
+ j->italic,
+ dcp::Color (255, 255, 255),
+ /* .srt files don't specify size, so this is an arbitrary value */
+ 48,
+ dcp::Time (rint (_subtitles[_next].from.metric().get().all_as_milliseconds() / 4)),
+ dcp::Time (rint (_subtitles[_next].to.metric().get().all_as_milliseconds() / 4)),
+ i->vertical_position.line.get() * (1.5 / 22) + 0.8,
+ dcp::TOP,
+ j->text,
+ dcp::NONE,
+ dcp::Color (255, 255, 255),
+ 0,
+ 0
+ )
+ );
+ }
}
text_subtitle (out);
@@ -89,9 +89,15 @@ SubRipDecoder::subtitles_during (ContentTimePeriod p, bool starting) const
list<ContentTimePeriod> d;
- for (vector<SubRipSubtitle>::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
- if ((starting && p.contains (i->period.from)) || (!starting && p.overlaps (i->period))) {
- d.push_back (i->period);
+ for (vector<sub::Subtitle>::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
+
+ ContentTimePeriod t (
+ ContentTime::from_seconds (i->from.metric().get().all_as_seconds()),
+ ContentTime::from_seconds (i->to.metric().get().all_as_seconds())
+ );
+
+ if ((starting && p.contains (t.from)) || (!starting && p.overlaps (t))) {
+ d.push_back (t);
}
}
diff --git a/src/lib/wscript b/src/lib/wscript
index 4e62206f1..d62c22bae 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -106,7 +106,7 @@ def build(bld):
AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE
BOOST_FILESYSTEM BOOST_THREAD BOOST_DATETIME BOOST_SIGNALS2
SNDFILE OPENJPEG POSTPROC TIFF MAGICK SSH DCP CXML GLIB LZMA XML++
- CURL ZIP QUICKMAIL PANGOMM CAIROMM XMLSEC
+ CURL ZIP QUICKMAIL PANGOMM CAIROMM XMLSEC SUB
"""
if bld.env.TARGET_OSX: