Add language property to SubtitleContent and use it in output DCP subtitle files.
authorCarl Hetherington <cth@carlh.net>
Thu, 11 Dec 2014 15:20:33 +0000 (15:20 +0000)
committerCarl Hetherington <cth@carlh.net>
Thu, 11 Dec 2014 16:05:58 +0000 (16:05 +0000)
ChangeLog
src/lib/dcp_subtitle_content.cc
src/lib/player.cc
src/lib/player_subtitles.h
src/lib/subtitle_content.cc
src/lib/subtitle_content.h
src/lib/writer.cc
src/lib/writer.h
src/wx/subtitle_panel.cc
src/wx/subtitle_panel.h

index ea124c354bb0256e3fcc2fe2b683a19c9ac655d4..09c77182ca7a63f09801492a07da53bcb03acb6a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2014-12-11  Carl Hetherington  <cth@carlh.net>
+
+       * Add a language property to subtitle content and use it
+       for the DCP subtitle's language specification.
+
 2014-11-24  Carl Hetherington  <cth@carlh.net>
 
        * Version 2.0.22 released.
index 7be96ceeb7d1127b35dfb88a71e35389abffde25..798afbfc39dfc87aca74d50142b9076bd98b9770 100644 (file)
@@ -48,6 +48,7 @@ DCPSubtitleContent::examine (shared_ptr<Job> job, bool calculate_digest)
 {
        Content::examine (job, calculate_digest);
        dcp::SubtitleContent sc (path (0), false);
+       _subtitle_language = sc.language ();
        _length = DCPTime::from_seconds (sc.latest_subtitle_out().to_seconds ());
 }
 
index fabb5b21134b00bf2898237f867f5edbbeaa385d..396dc990684667b93060df953cb767f6e6246335 100644 (file)
@@ -50,6 +50,8 @@
 #include <stdint.h>
 #include <algorithm>
 
+#include "i18n.h"
+
 #define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
 
 using std::list;
@@ -549,6 +551,12 @@ Player::get_subtitles (DCPTime time, DCPTime length, bool starting)
                        continue;
                }
 
+               /* XXX: this will break down if we have multiple subtitle content */
+               ps.language = subtitle_content->subtitle_language();
+               if (ps.language.empty ()) {
+                       ps.language = _("Unknown");
+               }
+
                shared_ptr<SubtitleDecoder> subtitle_decoder = dynamic_pointer_cast<SubtitleDecoder> ((*j)->decoder);
                ContentTime const from = dcp_to_content_subtitle (*j, time);
                /* XXX: this video_frame_rate() should be the rate that the subtitle content has been prepared for */
index d0a3b4f657366b4e06af0a2c54e7441f471b8d91..804c87cb9e22b2fb62c062572d23599a0af8084b 100644 (file)
@@ -36,7 +36,9 @@ public:
 
        /** ImageSubtitles, with their rectangles transformed as specified by their content */
        std::list<ImageSubtitle> image;
-       std::list<dcp::SubtitleString> text; 
+       std::list<dcp::SubtitleString> text;
+
+       std::string language;
 };
 
 #endif
index 5b370847ba08d2f2f156301f5864982f7820efae..df90a4a1a2630056693bad3623de40935088c8ea 100644 (file)
@@ -38,6 +38,7 @@ int const SubtitleContentProperty::SUBTITLE_Y_OFFSET = 501;
 int const SubtitleContentProperty::SUBTITLE_X_SCALE = 502;
 int const SubtitleContentProperty::SUBTITLE_Y_SCALE = 503;
 int const SubtitleContentProperty::USE_SUBTITLES = 504;
+int const SubtitleContentProperty::SUBTITLE_LANGUAGE = 505;
 
 SubtitleContent::SubtitleContent (shared_ptr<const Film> f)
        : Content (f)
@@ -88,6 +89,8 @@ SubtitleContent::SubtitleContent (shared_ptr<const Film> f, cxml::ConstNodePtr n
        } else {
                _subtitle_x_scale = _subtitle_y_scale = node->number_child<float> ("SubtitleScale");
        }
+
+       _subtitle_language = node->optional_string_child ("SubtitleLanguage").get_value_or ("");
 }
 
 SubtitleContent::SubtitleContent (shared_ptr<const Film> f, vector<shared_ptr<Content> > c)
@@ -125,6 +128,7 @@ SubtitleContent::SubtitleContent (shared_ptr<const Film> f, vector<shared_ptr<Co
        _subtitle_y_offset = ref->subtitle_y_offset ();
        _subtitle_x_scale = ref->subtitle_x_scale ();
        _subtitle_y_scale = ref->subtitle_y_scale ();
+       _subtitle_language = ref->subtitle_language ();
 }
 
 void
@@ -135,6 +139,7 @@ SubtitleContent::as_xml (xmlpp::Node* root) const
        root->add_child("SubtitleYOffset")->add_child_text (raw_convert<string> (_subtitle_y_offset));
        root->add_child("SubtitleXScale")->add_child_text (raw_convert<string> (_subtitle_x_scale));
        root->add_child("SubtitleYScale")->add_child_text (raw_convert<string> (_subtitle_y_scale));
+       root->add_child("SubtitleLanguage")->add_child_text (_subtitle_language);
 }
 
 void
@@ -187,6 +192,16 @@ SubtitleContent::set_subtitle_y_scale (double s)
        signal_changed (SubtitleContentProperty::SUBTITLE_Y_SCALE);
 }
 
+void
+SubtitleContent::set_subtitle_language (string language)
+{
+       {
+               boost::mutex::scoped_lock lm (_mutex);
+               _subtitle_language = language;
+       }
+       signal_changed (SubtitleContentProperty::SUBTITLE_LANGUAGE);
+}
+
 string
 SubtitleContent::identifier () const
 {
@@ -197,5 +212,9 @@ SubtitleContent::identifier () const
          << "_" << raw_convert<string> (subtitle_x_offset())
          << "_" << raw_convert<string> (subtitle_y_offset());
 
+       /* The language is for metadata only, and doesn't affect
+          how this content looks.
+       */
+
        return s.str ();
 }
index c3c25232f4893ec59776d42c20f483ec5f72acc1..4cbef657ab5b18da060024ee4bd13f608e53552e 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-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
@@ -30,6 +30,7 @@ public:
        static int const SUBTITLE_X_SCALE;
        static int const SUBTITLE_Y_SCALE;
        static int const USE_SUBTITLES;
+       static int const SUBTITLE_LANGUAGE;
 };
 
 /** @class SubtitleContent
@@ -56,6 +57,7 @@ public:
        void set_subtitle_y_offset (double);
        void set_subtitle_x_scale (double);
        void set_subtitle_y_scale (double);
+       void set_subtitle_language (std::string language);
 
        bool use_subtitles () const {
                boost::mutex::scoped_lock lm (_mutex);
@@ -82,6 +84,14 @@ public:
                return _subtitle_y_scale;
        }
 
+       std::string subtitle_language () const {
+               return _subtitle_language;
+       }
+
+protected:
+       /** subtitle language (e.g. "German") or empty if it is not known */
+       std::string _subtitle_language;
+       
 private:
        friend struct ffmpeg_pts_offset_test;
 
index 11a4f9d0393cd2675c87782bdd30598c5e23a92a..eca0b134a72382303b81cb93e673f8303cf40d02 100644 (file)
@@ -615,9 +615,7 @@ Writer::write (PlayerSubtitles subs)
        }
        
        if (!_subtitle_content) {
-               _subtitle_content.reset (
-                       new dcp::SubtitleContent (_film->name(), _film->isdcf_metadata().subtitle_language)
-                       );
+               _subtitle_content.reset (new dcp::SubtitleContent (_film->name(), subs.language));
        }
        
        for (list<dcp::SubtitleString>::const_iterator i = subs.text.begin(); i != subs.text.end(); ++i) {
index f8aeb8c8302ef89eb497c8076a3c878ec3897209..5efb14e50e39ee9ebf682635dfb2a4f963ee1411 100644 (file)
@@ -94,7 +94,7 @@ public:
        void write (boost::shared_ptr<const EncodedData>, int, Eyes);
        void fake_write (int, Eyes);
        void write (boost::shared_ptr<const AudioBuffers>);
-       void write (PlayerSubtitles);
+       void write (PlayerSubtitles subs);
        void repeat (int f, Eyes);
        void finish ();
 
index 21d6f8e5ba6c46a48a57004fa625e3a584af4641..3198723a5a7806cd5a2be8f6124bff6d9cce27f9 100644 (file)
@@ -83,6 +83,10 @@ SubtitlePanel::SubtitlePanel (ContentPanel* p)
                add_label_to_sizer (s, this, _("%"), false);
                grid->Add (s);
        }
+
+       add_label_to_sizer (grid, this, _("Language"), true);
+       _language = new wxTextCtrl (this, wxID_ANY);
+       grid->Add (_language, 1, wxEXPAND);
        
        add_label_to_sizer (grid, this, _("Stream"), true);
        _stream = new wxChoice (this, wxID_ANY);
@@ -99,8 +103,9 @@ SubtitlePanel::SubtitlePanel (ContentPanel* p)
        _use->Bind         (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&SubtitlePanel::use_toggled, this));
        _x_offset->Bind    (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::x_offset_changed, this));
        _y_offset->Bind    (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::y_offset_changed, this));
-       _x_scale->Bind       (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::x_scale_changed, this));
-       _y_scale->Bind       (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::y_scale_changed, this));
+       _x_scale->Bind     (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::x_scale_changed, this));
+       _y_scale->Bind     (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&SubtitlePanel::y_scale_changed, this));
+       _language->Bind    (wxEVT_COMMAND_TEXT_UPDATED,     boost::bind (&SubtitlePanel::language_changed, this));
        _stream->Bind      (wxEVT_COMMAND_CHOICE_SELECTED,  boost::bind (&SubtitlePanel::stream_changed, this));
        _view_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED,   boost::bind (&SubtitlePanel::view_clicked, this));
 }
@@ -155,6 +160,8 @@ SubtitlePanel::film_content_changed (int property)
                checked_set (_x_scale, scs ? int (rint (scs->subtitle_x_scale() * 100)) : 100);
        } else if (property == SubtitleContentProperty::SUBTITLE_Y_SCALE) {
                checked_set (_y_scale, scs ? int (rint (scs->subtitle_y_scale() * 100)) : 100);
+       } else if (property == SubtitleContentProperty::SUBTITLE_LANGUAGE) {
+               checked_set (_language, scs ? scs->subtitle_language() : "");
        }
 }
 
@@ -198,6 +205,7 @@ SubtitlePanel::setup_sensitivity ()
        _y_offset->Enable (any_subs > 0 && use);
        _x_scale->Enable (any_subs > 0 && use);
        _y_scale->Enable (any_subs > 0 && use);
+       _language->Enable (any_subs > 0 && use);
        _stream->Enable (ffmpeg_subs == 1);
        _view_button->Enable (subrip_or_dcp_subs == 1);
 }
@@ -260,6 +268,15 @@ SubtitlePanel::y_scale_changed ()
        }
 }
 
+void
+SubtitlePanel::language_changed ()
+{
+       SubtitleContentList c = _parent->selected_subtitle ();
+       for (SubtitleContentList::iterator i = c.begin(); i != c.end(); ++i) {
+               (*i)->set_subtitle_language (wx_to_std (_language->GetValue()));
+       }
+}
+
 void
 SubtitlePanel::content_selection_changed ()
 {
@@ -269,6 +286,7 @@ SubtitlePanel::content_selection_changed ()
        film_content_changed (SubtitleContentProperty::SUBTITLE_Y_OFFSET);
        film_content_changed (SubtitleContentProperty::SUBTITLE_X_SCALE);
        film_content_changed (SubtitleContentProperty::SUBTITLE_Y_SCALE);
+       film_content_changed (SubtitleContentProperty::SUBTITLE_LANGUAGE);
 }
 
 void
index bcff995a0029a5ef223d5381113648aaef893fc0..f82fb14e5bfe49ad2a224db55ef35fc59b633a3a 100644 (file)
@@ -38,6 +38,7 @@ private:
        void y_offset_changed ();
        void x_scale_changed ();
        void y_scale_changed ();
+       void language_changed ();
        void stream_changed ();
        void view_clicked ();
 
@@ -48,6 +49,7 @@ private:
        wxSpinCtrl* _y_offset;
        wxSpinCtrl* _x_scale;
        wxSpinCtrl* _y_scale;
+       wxTextCtrl* _language;
        wxChoice* _stream;
        wxButton* _view_button;
        SubtitleView* _view;