Start of STL binary reader; start of dumpsubs.
authorCarl Hetherington <cth@carlh.net>
Tue, 27 May 2014 15:56:34 +0000 (16:56 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 27 May 2014 15:56:34 +0000 (16:56 +0100)
13 files changed:
run/dumpsubs [new file with mode: 0755]
src/exceptions.h
src/reader.h
src/reader_factory.cc [new file with mode: 0644]
src/reader_factory.h [new file with mode: 0644]
src/stl_binary_reader.cc [new file with mode: 0644]
src/stl_binary_reader.h [new file with mode: 0644]
src/wscript
test/stl_binary_reader_test.cc [new file with mode: 0644]
test/wscript
tools/dumpsubs.cc [new file with mode: 0644]
tools/wscript [new file with mode: 0644]
wscript

diff --git a/run/dumpsubs b/run/dumpsubs
new file mode 100755 (executable)
index 0000000..e07464a
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash -e
+
+export LD_LIBRARY_PATH=build/src
+build/tools/dumpsubs $*
index 9bab16cf4c0f4afad3cab1683943364f3ce183d5..5e784ee9d28ae2d2c313c2c7766f0c78e5733de8 100644 (file)
@@ -38,4 +38,20 @@ private:
        std::string _message;
 };
        
+class STLError : public std::exception
+{
+public:
+       STLError (std::string const & message) : _message (message) {}
+       ~STLError () throw () {}
+
+       /** @return error message */
+       char const * what () const throw () {
+               return _message.c_str ();
+       }
+
+private:
+       /** error message */
+       std::string _message;
+};
+
 }
index e5f142f94973472f220f5ca036aeac4e5a0ace83..8aa9fd891443ec26dd1d88186da157220062a4f2 100644 (file)
 
 */
 
+#ifndef LIBSUB_READER_H
+#define LIBSUB_READER_H
+
 #include "subtitle.h"
 #include <list>
+#include <map>
+#include <string>
 
 namespace sub {
 
@@ -29,6 +34,10 @@ public:
                return _subs;
        }
 
+       virtual std::map<std::string, std::string> metadata () const {
+               return std::map<std::string, std::string> ();
+       }
+
 protected:
        void warn (std::string) const;
 
@@ -36,3 +45,5 @@ protected:
 };
 
 }
+
+#endif
diff --git a/src/reader_factory.cc b/src/reader_factory.cc
new file mode 100644 (file)
index 0000000..fd19c0f
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <fstream>
+#include <boost/algorithm/string.hpp>
+#include "reader_factory.h"
+#include "dcp_reader.h"
+#include "stl_binary_reader.h"
+#include "stl_text_reader.h"
+
+using std::string;
+using std::ifstream;
+using boost::algorithm::ends_with;
+using boost::shared_ptr;
+using namespace sub;
+
+shared_ptr<Reader>
+sub::reader_factory (string file_name)
+{
+       ifstream f (file_name.c_str ());
+       if (!f.good ()) {
+               return shared_ptr<Reader> ();
+       }
+       
+       if (ends_with (file_name, ".xml") || ends_with (file_name, ".XML")) {
+               return shared_ptr<Reader> (new DCPReader (f));
+       }
+
+       if (ends_with (file_name, ".stl") || ends_with (file_name, ".STL")) {
+               /* Check the start of the DFC */
+               char buffer[11];
+               f.read (buffer, 11);
+               f.seekg (0);
+               if (f.gcount() == 11 && buffer[3] == 'S' && buffer[4] == 'T' && buffer[5] == 'L') {
+                       return shared_ptr<Reader> (new STLBinaryReader (f));
+               } else {
+                       return shared_ptr<Reader> (new STLTextReader (f));
+               }
+       }
+
+       return shared_ptr<Reader> ();
+}
diff --git a/src/reader_factory.h b/src/reader_factory.h
new file mode 100644 (file)
index 0000000..c12a475
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/shared_ptr.hpp>
+
+namespace sub {
+
+class Reader;
+
+extern boost::shared_ptr<Reader>
+reader_factory (std::string);
+
+}
diff --git a/src/stl_binary_reader.cc b/src/stl_binary_reader.cc
new file mode 100644 (file)
index 0000000..3042a93
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/lexical_cast.hpp>
+#include "stl_binary_reader.h"
+#include "exceptions.h"
+#include "compose.hpp"
+
+using std::map;
+using std::cout;
+using std::string;
+using std::istream;
+using boost::lexical_cast;
+using namespace sub;
+
+template <class T>
+T
+string_to_value (string k, map<string, STLCode<T> > m, string name)
+{
+       typename map<string, STLCode<T> >::const_iterator i = m.find (k);
+       if (i == m.end ()) {
+               throw STLError (String::compose ("Unknown %1 %2 in binary STL file", name, k));
+       }
+
+       return i->second.value;
+}
+
+template <class T>
+string
+value_to_description (T v, map<string, STLCode<T> > const & m)
+{
+       for (typename map<string, STLCode<T> >::const_iterator i = m.begin(); i != m.end(); ++i) {
+               if (i->second.value == v) {
+                       return i->second.description;
+               }
+       }
+
+       return "";
+}
+
+template <class T>
+void
+code (map<string, STLCode<T> >& m, string k, T v, string d)
+{
+       m[k] = STLCode<T> (v, d);
+}
+
+
+STLBinaryReader::STLBinaryReader (istream& in)
+       : _buffer (new unsigned char[1024])
+{
+       create_maps ();
+       
+       in.read ((char *) _buffer, 1024);
+       if (in.gcount() != 1024) {
+               throw STLError ("Could not read GSI block from binary STL file");
+       }
+               
+       code_page_number = atoi (fixed_string (0, 3).c_str ());
+       
+       string const dfc = fixed_string (3, 8);
+       if (dfc == "STL24.01") {
+               frame_rate = 24;
+       } else if (dfc == "STL25.01") {
+               frame_rate = 25;
+       } else if (dfc == "STL30.01") {
+               frame_rate = 30;
+       } else {
+               throw STLError (String::compose ("Unknown disk format code %1 in binary STL file", dfc));
+       }
+
+       display_standard = string_to_value (fixed_string (11, 1), _display_standard_map, "display standard code");
+       language_group = string_to_value (fixed_string (12, 2), _language_group_map, "character code");
+       language = string_to_value (fixed_string (14, 2), _language_map, "language code");
+       original_programme_title = fixed_string (16, 32);
+       original_episode_title = fixed_string (48, 32);
+       translated_programme_title = fixed_string (80, 32);
+       translated_episode_title = fixed_string (112, 32);
+       translator_name = fixed_string (144, 32);
+       translator_contact_details = fixed_string (176, 32);
+       subtitle_list_reference_code = fixed_string (208, 32);
+       creation_date = fixed_string (224, 6);
+       revision_date = fixed_string (230, 6);
+       revision_number = fixed_string (236, 2);
+
+       tti_blocks = atoi (fixed_string (238, 6).c_str ());
+       number_of_subtitles = atoi (fixed_string (243, 5).c_str ());
+       subtitle_groups = atoi (fixed_string (248, 3).c_str ());
+       maximum_characters = atoi (fixed_string (251, 2).c_str ());
+       maximum_rows = atoi (fixed_string (253, 2).c_str ());
+       timecode_status = string_to_value (fixed_string (255, 1), _timecode_status_map, "timecode status code");
+       start_of_programme = fixed_string (256, 8);
+       first_in_cue = fixed_string (256, 8);
+       disks = atoi (fixed_string (272, 1).c_str ());
+       disk_sequence_number = atoi (fixed_string (273, 1).c_str ());
+       country_of_origin = fixed_string (274, 3);
+       publisher = fixed_string (277, 32);
+       editor_name = fixed_string (309, 32);
+       editor_contact_details = fixed_string (341, 32);
+}
+
+STLBinaryReader::~STLBinaryReader ()
+{
+       delete[] _buffer;
+}
+
+string
+STLBinaryReader::fixed_string (int offset, int length) const
+{
+       string s;
+       for (int i = 0; i < length; ++i) {
+               s += _buffer[offset + i];
+       }
+
+       return s;
+}
+
+map<string, string>
+STLBinaryReader::metadata () const
+{
+       map<string, string> m;
+
+       m["Code page number"] = lexical_cast<string> (code_page_number);
+       m["Frame rate"] = lexical_cast<string> (frame_rate);
+       m["Display standard"] = value_to_description (display_standard, _display_standard_map);
+       m["Language group"] = value_to_description (language_group, _language_group_map);
+       m["Language"] = value_to_description (language, _language_map);
+       m["Original programme title"] = original_programme_title;
+       m["Original episode title"] = original_episode_title;
+       m["Translated programme title"] = translated_programme_title;
+       m["Translated episode title"] = translated_episode_title;
+       m["Translator name"] = translator_name;
+       m["Translator contact details"] = translator_contact_details;
+       m["Subtitle list reference code"] = subtitle_list_reference_code;
+       m["Creation date"] = creation_date;
+       m["Revision date"] = revision_date;
+       m["Revision number"] = revision_number;
+       m["TTI blocks"] = lexical_cast<string> (tti_blocks);
+       m["Number of subtitles"] = lexical_cast<string> (number_of_subtitles);
+       m["Subtitle groups"] = lexical_cast<string> (subtitle_groups);
+       m["Maximum characters"] = lexical_cast<string> (maximum_characters);
+       m["Maximum rows"] = lexical_cast<string> (maximum_rows);
+       m["Timecode status"] = value_to_description (timecode_status, _timecode_status_map);
+       m["Start of programme"] = start_of_programme;
+       m["First in cue"] = first_in_cue;
+       m["Disks"] = lexical_cast<string> (disks);
+       m["Disk sequence number"] = lexical_cast<string> (disk_sequence_number);
+       m["Country of origin"] = country_of_origin;
+       m["Publisher"] = publisher;
+       m["Editor name"] = editor_name;
+       m["Editor contact details"] = editor_contact_details;
+
+       return m;
+}
+
+void
+STLBinaryReader::create_maps ()
+{
+       code (_display_standard_map, " ", DISPLAY_STANDARD_UNDEFINED, "Undefined");
+       code (_display_standard_map, "0", DISPLAY_STANDARD_OPEN_SUBTITLING, "Open subtitling");
+       code (_display_standard_map, "1", DISPLAY_STANDARD_LEVEL_1_TELETEXT, "Level 1 teletext");
+       code (_display_standard_map, "2", DISPLAY_STANDARD_LEVEL_2_TELETEXT, "Level 2 teletext");
+       
+       code (_language_group_map, "00", LANGUAGE_GROUP_LATIN, "Latin");
+       code (_language_group_map, "01", LANGUAGE_GROUP_LATIN_CYRILLIC, "Latin/Cyrillic");
+       code (_language_group_map, "02", LANGUAGE_GROUP_LATIN_ARABIC, "Latin/Arabic");
+       code (_language_group_map, "03", LANGUAGE_GROUP_LATIN_GREEK, "Latin/Greek");
+       code (_language_group_map, "04", LANGUAGE_GROUP_LATIN_HEBREW, "Latin/Hebrew");
+       
+       code (_language_map, "00", LANGUAGE_UNKNOWN, "Unknown");
+       code (_language_map, "01", LANGUAGE_ALBANIAN, "Albanian");
+       code (_language_map, "02", LANGUAGE_BRETON, "Breton");
+       code (_language_map, "03", LANGUAGE_CATALAN, "Catalan");
+       code (_language_map, "04", LANGUAGE_CROATIAN, "Croatian");
+       code (_language_map, "05", LANGUAGE_WELSH, "Welsh");
+       code (_language_map, "06", LANGUAGE_CZECH, "Czech");
+       code (_language_map, "07", LANGUAGE_DANISH, "Danish");
+       code (_language_map, "08", LANGUAGE_GERMAN, "German");
+       code (_language_map, "09", LANGUAGE_ENGLISH, "English");
+       code (_language_map, "0A", LANGUAGE_SPANISH, "Spanish");
+       code (_language_map, "0B", LANGUAGE_ESPERANTO, "Esperanto");
+       code (_language_map, "0C", LANGUAGE_ESTONIAN, "Estonian");
+       code (_language_map, "0D", LANGUAGE_BASQUE, "Basque");
+       code (_language_map, "0E", LANGUAGE_FAROESE, "Faroese");
+       code (_language_map, "0F", LANGUAGE_FRENCH, "French");
+       code (_language_map, "10", LANGUAGE_FRISIAN, "Frisian");
+       code (_language_map, "11", LANGUAGE_IRISH, "Irish");
+       code (_language_map, "12", LANGUAGE_GAELIC, "Gaelic");
+       code (_language_map, "13", LANGUAGE_GALACIAN, "Galacian");
+       code (_language_map, "14", LANGUAGE_ICELANDIC, "Icelandic");
+       code (_language_map, "15", LANGUAGE_ITALIAN, "Italian");
+       code (_language_map, "16", LANGUAGE_LAPPISH, "Lappish");
+       code (_language_map, "17", LANGUAGE_LATIN, "Latin");
+       code (_language_map, "18", LANGUAGE_LATVIAN, "Latvian");
+       code (_language_map, "19", LANGUAGE_LUXEMBORGIAN, "Luxemborgian");
+       code (_language_map, "1A", LANGUAGE_LITHUANIAN, "Lithuanian");
+       code (_language_map, "1B", LANGUAGE_HUNGARIAN, "Hungarian");
+       code (_language_map, "1C", LANGUAGE_MALTESE, "Maltese");
+       code (_language_map, "1D", LANGUAGE_DUTCH, "Dutch");
+       code (_language_map, "1E", LANGUAGE_NORWEGIAN, "Norwegian");
+       code (_language_map, "1F", LANGUAGE_OCCITAN, "Occitan");
+       code (_language_map, "20", LANGUAGE_POLISH, "Polish");
+       code (_language_map, "21", LANGUAGE_PORTUGESE, "Portugese");
+       code (_language_map, "22", LANGUAGE_ROMANIAN, "Romanian");
+       code (_language_map, "23", LANGUAGE_ROMANSH, "Romansh");
+       code (_language_map, "24", LANGUAGE_SERBIAN, "Serbian");
+       code (_language_map, "25", LANGUAGE_SLOVAK, "Slovak");
+       code (_language_map, "26", LANGUAGE_SLOVENIAN, "Slovenian");
+       code (_language_map, "27", LANGUAGE_FINNISH, "Finnish");
+       code (_language_map, "28", LANGUAGE_SWEDISH, "Swedish");
+       code (_language_map, "29", LANGUAGE_TURKISH, "Turkish");
+       code (_language_map, "2A", LANGUAGE_FLEMISH, "Flemish");
+       code (_language_map, "2B", LANGUAGE_WALLON, "Wallon");
+       code (_language_map, "7F", LANGUAGE_AMHARIC, "Amharic");
+       code (_language_map, "7E", LANGUAGE_ARABIC, "Arabic");
+       code (_language_map, "7D", LANGUAGE_ARMENIAN, "Armenian");
+       code (_language_map, "7C", LANGUAGE_ASSAMESE, "Assamese");
+       code (_language_map, "7B", LANGUAGE_AZERBAIJANI, "Azerbaijani");
+       code (_language_map, "7A", LANGUAGE_BAMBORA, "Bambora");
+       code (_language_map, "79", LANGUAGE_BIELORUSSIAN, "Bielorussian");
+       code (_language_map, "78", LANGUAGE_BENGALI, "Bengali");
+       code (_language_map, "77", LANGUAGE_BULGARIAN, "Bulgarian");
+       code (_language_map, "76", LANGUAGE_BURMESE, "Burmese");
+       code (_language_map, "75", LANGUAGE_CHINESE, "Chinese");
+       code (_language_map, "74", LANGUAGE_CHURASH, "Churash");
+       code (_language_map, "73", LANGUAGE_DARI, "Dari");
+       code (_language_map, "72", LANGUAGE_FULANI, "Fulani");
+       code (_language_map, "71", LANGUAGE_GEORGIAN, "Georgian");
+       code (_language_map, "70", LANGUAGE_GREEK, "Greek");
+       code (_language_map, "6F", LANGUAGE_GUJURATI, "Gujarati");
+       code (_language_map, "6E", LANGUAGE_GURANI, "Gurani");
+       code (_language_map, "6D", LANGUAGE_HAUSA, "Hausa");
+       code (_language_map, "6C", LANGUAGE_HEBREW, "Hebrew");
+       code (_language_map, "6B", LANGUAGE_HINDI, "Hindi");
+       code (_language_map, "6A", LANGUAGE_INDONESIAN, "Indonesian");
+       code (_language_map, "69", LANGUAGE_JAPANESE, "Japanese");
+       code (_language_map, "68", LANGUAGE_KANNADA, "Kannada");
+       code (_language_map, "67", LANGUAGE_KAZAKH, "Kazakh");
+       code (_language_map, "66", LANGUAGE_KHMER, "Khmer");
+       code (_language_map, "65", LANGUAGE_KOREAN, "Korean");
+       code (_language_map, "64", LANGUAGE_LAOTIAN, "Laotian");
+       code (_language_map, "63", LANGUAGE_MACEDONIAN, "Macedonian");
+       code (_language_map, "62", LANGUAGE_MALAGASAY, "Malagasay");
+       code (_language_map, "61", LANGUAGE_MALAYSIAN, "Malaysian");
+       code (_language_map, "60", LANGUAGE_MOLDAVIAN, "Moldavian");
+       code (_language_map, "5F", LANGUAGE_MARATHI, "Marathi");
+       code (_language_map, "5E", LANGUAGE_NDEBELE, "Ndebele");
+       code (_language_map, "5D", LANGUAGE_NEPALI, "Nepali");
+       code (_language_map, "5C", LANGUAGE_ORIYA, "Oriya");
+       code (_language_map, "5B", LANGUAGE_PAPAMIENTO, "Papamiento");
+       code (_language_map, "5A", LANGUAGE_PERSIAN, "Persian");
+       code (_language_map, "59", LANGUAGE_PUNJABI, "Punjabi");
+       code (_language_map, "58", LANGUAGE_PUSHTU, "Pushtu");
+       code (_language_map, "57", LANGUAGE_QUECHUA, "Quechua");
+       code (_language_map, "56", LANGUAGE_RUSSIAN, "Russian");
+       code (_language_map, "55", LANGUAGE_RUTHENIAN, "Ruthenian");
+       code (_language_map, "54", LANGUAGE_SERBO_CROAT, "Serbo Croat");
+       code (_language_map, "53", LANGUAGE_SHONA, "Shona");
+       code (_language_map, "52", LANGUAGE_SINHALESE, "Sinhalese");
+       code (_language_map, "51", LANGUAGE_SOMALI, "Somali");
+       code (_language_map, "50", LANGUAGE_SRANAN_TONGO, "Sranan Tongo");
+       code (_language_map, "4F", LANGUAGE_SWAHILI, "Swahili");
+       code (_language_map, "4E", LANGUAGE_TADZHIK, "Tadzhik");
+       code (_language_map, "4D", LANGUAGE_TAMIL, "Tamil");
+       code (_language_map, "4C", LANGUAGE_TATAR, "Tatar");
+       code (_language_map, "4B", LANGUAGE_TELUGU, "Telugu");
+       code (_language_map, "4A", LANGUAGE_THAI, "Thai");
+       code (_language_map, "49", LANGUAGE_UKRANIAN, "Ukranian");
+       code (_language_map, "48", LANGUAGE_URDU, "Urdu");
+       code (_language_map, "47", LANGUAGE_UZBEK, "Uzbek");
+       code (_language_map, "46", LANGUAGE_VIETNAMESE, "Vietnamese");
+       code (_language_map, "45", LANGUAGE_ZULU, "Zulu");
+
+       code (_timecode_status_map, "0", TIMECODE_STATUS_NOT_INTENDED_FOR_USE, "Not intended for use");
+       code (_timecode_status_map, "1", TIMECODE_STATUS_INTENDED_FOR_USE, "Intended for use");
+}
diff --git a/src/stl_binary_reader.h b/src/stl_binary_reader.h
new file mode 100644 (file)
index 0000000..0491cb8
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <map>
+#include "reader.h"
+
+namespace sub {
+
+template<class T>
+class STLCode
+{
+public:
+       STLCode ()
+               : value ((T) 0)
+       {}
+
+       STLCode (T v, std::string d)
+               : value (v)
+               , description (d)
+       {}
+       
+       T value;
+       std::string description;
+};
+
+class STLBinaryReader : public Reader
+{
+public:
+       STLBinaryReader (std::istream &);
+       ~STLBinaryReader ();
+
+       std::map<std::string, std::string> metadata () const;
+
+       enum DisplayStandard {
+               DISPLAY_STANDARD_UNDEFINED,
+               DISPLAY_STANDARD_OPEN_SUBTITLING,
+               DISPLAY_STANDARD_LEVEL_1_TELETEXT,
+               DISPLAY_STANDARD_LEVEL_2_TELETEXT
+       };
+
+       enum LanguageGroup {
+               LANGUAGE_GROUP_LATIN,
+               LANGUAGE_GROUP_LATIN_CYRILLIC,
+               LANGUAGE_GROUP_LATIN_ARABIC,
+               LANGUAGE_GROUP_LATIN_GREEK,
+               LANGUAGE_GROUP_LATIN_HEBREW
+       };
+
+       enum Language {
+               LANGUAGE_UNKNOWN,
+               LANGUAGE_ALBANIAN,
+               LANGUAGE_BRETON,
+               LANGUAGE_CATALAN,
+               LANGUAGE_CROATIAN,
+               LANGUAGE_WELSH,
+               LANGUAGE_CZECH,
+               LANGUAGE_DANISH,
+               LANGUAGE_GERMAN,
+               LANGUAGE_ENGLISH,
+               LANGUAGE_SPANISH,
+               LANGUAGE_ESPERANTO,
+               LANGUAGE_ESTONIAN,
+               LANGUAGE_BASQUE,
+               LANGUAGE_FAROESE,
+               LANGUAGE_FRENCH,
+               LANGUAGE_FRISIAN,
+               LANGUAGE_IRISH,
+               LANGUAGE_GAELIC,
+               LANGUAGE_GALACIAN,
+               LANGUAGE_ICELANDIC,
+               LANGUAGE_ITALIAN,
+               LANGUAGE_LAPPISH,
+               LANGUAGE_LATIN,
+               LANGUAGE_LATVIAN,
+               LANGUAGE_LUXEMBORGIAN,
+               LANGUAGE_LITHUANIAN,
+               LANGUAGE_HUNGARIAN,
+               LANGUAGE_MALTESE,
+               LANGUAGE_DUTCH,
+               LANGUAGE_NORWEGIAN,
+               LANGUAGE_OCCITAN,
+               LANGUAGE_POLISH,
+               LANGUAGE_PORTUGESE,
+               LANGUAGE_ROMANIAN,
+               LANGUAGE_ROMANSH,
+               LANGUAGE_SERBIAN,
+               LANGUAGE_SLOVAK,
+               LANGUAGE_SLOVENIAN,
+               LANGUAGE_FINNISH,
+               LANGUAGE_SWEDISH,
+               LANGUAGE_TURKISH,
+               LANGUAGE_FLEMISH,
+               LANGUAGE_WALLON,
+               LANGUAGE_AMHARIC,
+               LANGUAGE_ARABIC,
+               LANGUAGE_ARMENIAN,
+               LANGUAGE_ASSAMESE,
+               LANGUAGE_AZERBAIJANI,
+               LANGUAGE_BAMBORA,
+               LANGUAGE_BIELORUSSIAN,
+               LANGUAGE_BENGALI,
+               LANGUAGE_BULGARIAN,
+               LANGUAGE_BURMESE,
+               LANGUAGE_CHINESE,
+               LANGUAGE_CHURASH,
+               LANGUAGE_DARI,
+               LANGUAGE_FULANI,
+               LANGUAGE_GEORGIAN,
+               LANGUAGE_GREEK,
+               LANGUAGE_GUJURATI,
+               LANGUAGE_GURANI,
+               LANGUAGE_HAUSA,
+               LANGUAGE_HEBREW,
+               LANGUAGE_HINDI,
+               LANGUAGE_INDONESIAN,
+               LANGUAGE_JAPANESE,
+               LANGUAGE_KANNADA,
+               LANGUAGE_KAZAKH,
+               LANGUAGE_KHMER,
+               LANGUAGE_KOREAN,
+               LANGUAGE_LAOTIAN,
+               LANGUAGE_MACEDONIAN,
+               LANGUAGE_MALAGASAY,
+               LANGUAGE_MALAYSIAN,
+               LANGUAGE_MOLDAVIAN,
+               LANGUAGE_MARATHI,
+               LANGUAGE_NDEBELE,
+               LANGUAGE_NEPALI,
+               LANGUAGE_ORIYA,
+               LANGUAGE_PAPAMIENTO,
+               LANGUAGE_PERSIAN,
+               LANGUAGE_PUNJABI,
+               LANGUAGE_PUSHTU,
+               LANGUAGE_QUECHUA,
+               LANGUAGE_RUSSIAN,
+               LANGUAGE_RUTHENIAN,
+               LANGUAGE_SERBO_CROAT,
+               LANGUAGE_SHONA,
+               LANGUAGE_SINHALESE,
+               LANGUAGE_SOMALI,
+               LANGUAGE_SRANAN_TONGO,
+               LANGUAGE_SWAHILI,
+               LANGUAGE_TADZHIK,
+               LANGUAGE_TAMIL,
+               LANGUAGE_TATAR,
+               LANGUAGE_TELUGU,
+               LANGUAGE_THAI,
+               LANGUAGE_UKRANIAN,
+               LANGUAGE_URDU,
+               LANGUAGE_UZBEK,
+               LANGUAGE_VIETNAMESE,
+               LANGUAGE_ZULU
+       };
+
+       enum TimecodeStatus {
+               TIMECODE_STATUS_NOT_INTENDED_FOR_USE,
+               TIMECODE_STATUS_INTENDED_FOR_USE
+       };
+
+       int code_page_number;
+       int frame_rate;
+       DisplayStandard display_standard;
+       LanguageGroup language_group;
+       Language language;
+       std::string original_programme_title;
+       std::string original_episode_title;
+       std::string translated_programme_title;
+       std::string translated_episode_title;
+       std::string translator_name;
+       std::string translator_contact_details;
+       std::string subtitle_list_reference_code;
+       std::string creation_date;
+       std::string revision_date;
+       std::string revision_number;
+       int tti_blocks;
+       int number_of_subtitles;
+       int subtitle_groups;
+       int maximum_characters;
+       int maximum_rows;
+       TimecodeStatus timecode_status;
+       std::string start_of_programme;
+       std::string first_in_cue;
+       int disks;
+       int disk_sequence_number;
+       std::string country_of_origin;
+       std::string publisher;
+       std::string editor_name;
+       std::string editor_contact_details;
+
+private:
+       std::string fixed_string (int, int) const;
+       void create_maps ();
+       
+       std::map<std::string, STLCode<DisplayStandard> > _display_standard_map;
+       std::map<std::string, STLCode<LanguageGroup> > _language_group_map;
+       std::map<std::string, STLCode<Language> > _language_map;
+       std::map<std::string, STLCode<TimecodeStatus> > _timecode_status_map;
+
+       unsigned char* _buffer;
+};
+
+}
index 4b54b419ce57c70875f40b8355b4f0732ff13872..f41152b5e538ce35bb1a16ea53b2ec0be19e8a6d 100644 (file)
@@ -18,6 +18,8 @@ def build(bld):
                  frame_time.cc
                  metric_time.cc
                  reader.cc
+                 reader_factory.cc
+                 stl_binary_reader.cc
                  stl_text_reader.cc
                  stl_text_writer.cc
                  subtitle.cc
diff --git a/test/stl_binary_reader_test.cc b/test/stl_binary_reader_test.cc
new file mode 100644 (file)
index 0000000..06b01ed
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/test/unit_test.hpp>
+#include <fstream>
+#include "stl_binary_reader.h"
+#include "subtitle.h"
+#include "test.h"
+
+using std::list;
+using std::cout;
+using std::ifstream;
+
+/* Test reading of a binary STL file */
+BOOST_AUTO_TEST_CASE (stl_binary_reader_test)
+{
+       if (private_test.empty ()) {
+               return;
+       }
+
+       string p = private_test + "/Vampire_Academy_24fps_Reel_6_DE_FR.stl";
+       ifstream f (p.c_str ());
+       sub::STLBinaryReader r (f);
+}
+
index c6abb1dbd411af0ab5b1fcb9e618ec4b368c48e0..630a6a004ad4c58a934dd950c43ae09c39f60bd3 100644 (file)
@@ -18,6 +18,7 @@ def build(bld):
     obj.source = """
                  dcp_reader_test.cc
                  dcp_to_stl_text_test.cc
+                 stl_binary_reader_test.cc
                  stl_text_reader_test.cc
                  stl_text_writer_test.cc
                  time_test.cc
diff --git a/tools/dumpsubs.cc b/tools/dumpsubs.cc
new file mode 100644 (file)
index 0000000..159af25
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <map>
+#include <getopt.h>
+#include "reader_factory.h"
+#include "reader.h"
+
+using std::string;
+using std::cerr;
+using std::cout;
+using std::map;
+using boost::shared_ptr;
+using namespace sub;
+
+static void
+help (string n)
+{
+       cerr << "Syntax: " << n << " <file>\n";
+}
+
+int
+main (int argc, char* argv[])
+{
+       int option_index = 0;
+       while (1) {
+               static struct option long_options[] = {
+                       { "help", no_argument, 0, 'h'},
+                       { 0, 0, 0, 0 }
+               };
+
+               int c = getopt_long (argc, argv, "h", long_options, &option_index);
+
+               if (c == -1) {
+                       break;
+               }
+
+               switch (c) {
+               case 'h':
+                       help (argv[0]);
+                       exit (EXIT_SUCCESS);
+               }
+       }
+
+       if (argc <= optind || argc > (optind + 1)) {
+               help (argv[0]);
+               exit (EXIT_FAILURE);
+       }
+
+       if (access (argv[optind], F_OK) == -1) {
+               cerr << argv[0] << ": file " << argv[optind] << " not found.\n";
+               exit (EXIT_FAILURE);
+       }
+
+       shared_ptr<Reader> reader = reader_factory (argv[optind]);
+       if (!reader) {
+               cerr << argv[0] << ": could not read subtitle file " << argv[optind] << "\n";
+               exit (EXIT_FAILURE);
+       }
+
+       map<string, string> metadata = reader->metadata ();
+       for (map<string, string>::const_iterator i = metadata.begin(); i != metadata.end(); ++i) {
+               cout << i->first << ": " << i->second << "\n";
+       }
+
+       return 0;
+}
diff --git a/tools/wscript b/tools/wscript
new file mode 100644 (file)
index 0000000..3db10b2
--- /dev/null
@@ -0,0 +1,6 @@
+def build(bld):
+    obj = bld(features = 'cxx cxxprogram')
+    obj.use = ['libsub']
+    obj.uselib = 'OPENJPEG CXML'
+    obj.source = 'dumpsubs.cc'
+    obj.target = 'dumpsubs'
diff --git a/wscript b/wscript
index 0d6016f31859c1621d0066c0856cf4ee3dc87260..dadfdaf81611b0e122ba90d3c71a6120024d8b11 100644 (file)
--- a/wscript
+++ b/wscript
@@ -53,6 +53,7 @@ def build(bld):
 
     bld.recurse('src')
     bld.recurse('test')
+    bld.recurse('tools')
 
     bld.add_post_fun(post)