From: Carl Hetherington Date: Mon, 29 Mar 2021 23:25:31 +0000 (+0200) Subject: Add burnt subtitle language to video content. X-Git-Tag: v2.15.138~21 X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=2791e094c143e0704ce8935fe5a19508429cf062 Add burnt subtitle language to video content. --- diff --git a/src/lib/film.cc b/src/lib/film.cc index 763af8f8a..945559a49 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -766,6 +766,9 @@ Film::subtitle_languages () const } } } + if (i->video && i->video->burnt_subtitle_language()) { + result.first = i->video->burnt_subtitle_language(); + } } std::sort (result.second.begin(), result.second.end()); diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc index fed28b5e4..5686a0a6f 100644 --- a/src/lib/video_content.cc +++ b/src/lib/video_content.cc @@ -50,6 +50,7 @@ int const VideoContentProperty::FADE_OUT = 7; int const VideoContentProperty::RANGE = 8; int const VideoContentProperty::CUSTOM_RATIO = 9; int const VideoContentProperty::CUSTOM_SIZE = 10; +int const VideoContentProperty::BURNT_SUBTITLE_LANGUAGE = 11; using std::string; using std::setprecision; @@ -183,8 +184,15 @@ VideoContent::VideoContent (Content* parent, cxml::ConstNodePtr node, int versio if (node->optional_string_child("Range").get_value_or("full") == "video") { _range = VideoRange::VIDEO; } + + auto burnt = node->optional_string_child("BurntSubtitleLanguage"); + if (burnt) { + _burnt_subtitle_language = dcp::LanguageTag (*burnt); + } + } + VideoContent::VideoContent (Content* parent, vector > c) : ContentPart (parent) , _length (0) @@ -227,6 +235,10 @@ VideoContent::VideoContent (Content* parent, vector > c) throw JoinError (_("Content to be joined must have the same fades.")); } + if (c[i]->video->burnt_subtitle_language() != ref->burnt_subtitle_language()) { + throw JoinError (_("Content to be joined must have the same burnt subtitle language.")); + } + _length += c[i]->video->length (); if (c[i]->video->yuv ()) { @@ -243,8 +255,10 @@ VideoContent::VideoContent (Content* parent, vector > c) _fade_in = ref->fade_in (); _fade_out = ref->fade_out (); _range = ref->range (); + _burnt_subtitle_language = ref->burnt_subtitle_language (); } + void VideoContent::as_xml (xmlpp::Node* node) const { @@ -272,6 +286,9 @@ VideoContent::as_xml (xmlpp::Node* node) const node->add_child("FadeIn")->add_child_text (raw_convert (_fade_in)); node->add_child("FadeOut")->add_child_text (raw_convert (_fade_out)); node->add_child("Range")->add_child_text(_range == VideoRange::FULL ? "full" : "video"); + if (_burnt_subtitle_language) { + node->add_child("BurntSubtitleLanguage")->add_child_text(_burnt_subtitle_language->to_string()); + } } void @@ -556,6 +573,14 @@ VideoContent::set_use (bool u) maybe_set (_use, u, VideoContentProperty::USE); } + +void +VideoContent::set_burnt_subtitle_language (boost::optional language) +{ + maybe_set (_burnt_subtitle_language, language, VideoContentProperty::BURNT_SUBTITLE_LANGUAGE); +} + + void VideoContent::take_settings_from (shared_ptr c) { @@ -574,8 +599,10 @@ VideoContent::take_settings_from (shared_ptr c) set_custom_size (c->_custom_size); set_fade_in (c->_fade_in); set_fade_out (c->_fade_out); + set_burnt_subtitle_language (c->_burnt_subtitle_language); } + void VideoContent::modify_position (shared_ptr film, DCPTime& pos) const { diff --git a/src/lib/video_content.h b/src/lib/video_content.h index 22a6090e7..4e9e5815f 100644 --- a/src/lib/video_content.h +++ b/src/lib/video_content.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2020 Carl Hetherington + Copyright (C) 2013-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,21 +18,26 @@ */ + #ifndef DCPOMATIC_VIDEO_CONTENT_H #define DCPOMATIC_VIDEO_CONTENT_H + #include "colour_conversion.h" +#include "content_part.h" #include "dcpomatic_time.h" -#include "user_property.h" #include "types.h" -#include "content_part.h" +#include "user_property.h" +#include #include + class VideoExaminer; class Ratio; class Film; class Content; + class VideoContentProperty { public: @@ -47,8 +52,10 @@ public: static int const RANGE; static int const CUSTOM_RATIO; static int const CUSTOM_SIZE; + static int const BURNT_SUBTITLE_LANGUAGE; }; + class VideoContent : public ContentPart, public std::enable_shared_from_this { public: @@ -99,6 +106,8 @@ public: void set_range (VideoRange); void set_use (bool); + void set_burnt_subtitle_language (boost::optional language); + VideoFrameType frame_type () const { boost::mutex::scoped_lock lm (_mutex); return _frame_type; @@ -177,6 +186,12 @@ public: return _use; } + boost::optional burnt_subtitle_language () const { + boost::mutex::scoped_lock lm (_mutex); + return _burnt_subtitle_language; + } + + /* XXX: names for these? */ dcp::Size size_after_3d_split () const; dcp::Size size_after_crop () const; @@ -231,6 +246,7 @@ private: /** fade out time in content frames */ Frame _fade_out; VideoRange _range; + boost::optional _burnt_subtitle_language; }; #endif diff --git a/src/wx/content_advanced_dialog.cc b/src/wx/content_advanced_dialog.cc index a33ffed90..5b4650141 100644 --- a/src/wx/content_advanced_dialog.cc +++ b/src/wx/content_advanced_dialog.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2020 Carl Hetherington + Copyright (C) 2020-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -22,6 +22,7 @@ #include "content_advanced_dialog.h" #include "dcpomatic_button.h" #include "filter_dialog.h" +#include "language_tag_widget.h" #include "static_text.h" #include "wx_util.h" #include "lib/content.h" @@ -56,12 +57,12 @@ ContentAdvancedDialog::ContentAdvancedDialog (wxWindow* parent, shared_ptrAdd (_filters, 1, wxALL | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP); filters->Add (_filters_button, 0, wxALL, DCPOMATIC_SIZER_GAP); sizer->Add (filters, wxGBPosition(r, 1), wxGBSpan(1, 2)); @@ -89,13 +90,21 @@ ContentAdvancedDialog::ContentAdvancedDialog (wxWindow* parent, shared_ptrAdd (_set_video_frame_rate, wxGBPosition(r, 2)); ++r; - wxCheckBox* ignore_video = new wxCheckBox (this, wxID_ANY, _("Ignore this content's video and use only audio, subtitles and closed captions")); + /// TRANSLATORS: next to this control is a language selector, so together they will read, for example + /// "Video has burnt-in subtitles in the language fr-FR" + _burnt_subtitle = new wxCheckBox (this, wxID_ANY, _("Video has burnt-in subtitles in the language")); + sizer->Add (_burnt_subtitle, wxGBPosition(r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); + _burnt_subtitle_language = new LanguageTagWidget (this, _("Language of burnt-in subtitles in this content"), content->video ? content->video->burnt_subtitle_language() : boost::none); + sizer->Add (_burnt_subtitle_language->sizer(), wxGBPosition(r, 1), wxGBSpan(1, 2), wxEXPAND); + ++r; + + auto ignore_video = new wxCheckBox (this, wxID_ANY, _("Ignore this content's video and use only audio, subtitles and closed captions")); sizer->Add (ignore_video, wxGBPosition(r, 0), wxGBSpan(1, 3)); ++r; - wxSizer* overall = new wxBoxSizer (wxVERTICAL); + auto overall = new wxBoxSizer (wxVERTICAL); overall->Add (sizer, 1, wxALL, DCPOMATIC_DIALOG_BORDER); - wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL); + auto buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL); if (buttons) { overall->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); } @@ -110,15 +119,22 @@ ContentAdvancedDialog::ContentAdvancedDialog (wxWindow* parent, shared_ptrEnable (!single_frame_image_content); _video_frame_rate->Enable (!single_frame_image_content); - optional vfr = _content->video_frame_rate (); + auto vfr = _content->video_frame_rate (); if (vfr) { _video_frame_rate->SetValue (std_to_wx(locale_convert(*vfr))); } + _burnt_subtitle->SetValue (_content->video && static_cast(_content->video->burnt_subtitle_language())); + _burnt_subtitle_language->set (_content->video ? _content->video->burnt_subtitle_language() : boost::none); + ignore_video->Bind (wxEVT_CHECKBOX, bind(&ContentAdvancedDialog::ignore_video_changed, this, _1)); _filters_button->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::edit_filters, this)); _set_video_frame_rate->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::set_video_frame_rate, this)); _video_frame_rate->Bind (wxEVT_TEXT, boost::bind(&ContentAdvancedDialog::video_frame_rate_changed, this)); + _burnt_subtitle->Bind (wxEVT_CHECKBOX, boost::bind(&ContentAdvancedDialog::burnt_subtitle_changed, this)); + _burnt_subtitle_language->Changed.connect (boost::bind(&ContentAdvancedDialog::burnt_subtitle_language_changed, this)); + + setup_sensitivity (); } @@ -134,7 +150,7 @@ ContentAdvancedDialog::ignore_video_changed (wxCommandEvent& ev) void ContentAdvancedDialog::setup_filters () { - shared_ptr fcs = dynamic_pointer_cast(_content); + auto fcs = dynamic_pointer_cast(_content); if (!fcs) { checked_set (_filters, _("None")); _filters->Enable (false); @@ -142,7 +158,7 @@ ContentAdvancedDialog::setup_filters () return; } - string p = Filter::ffmpeg_string (fcs->filters()); + auto p = Filter::ffmpeg_string (fcs->filters()); if (p.empty()) { checked_set (_filters, _("None")); } else { @@ -157,12 +173,12 @@ ContentAdvancedDialog::setup_filters () void ContentAdvancedDialog::edit_filters () { - shared_ptr fcs = dynamic_pointer_cast(_content); + auto fcs = dynamic_pointer_cast(_content); if (!fcs) { return; } - FilterDialog* d = new FilterDialog (this, fcs->filters()); + auto d = new FilterDialog (this, fcs->filters()); d->ActiveChanged.connect (bind(&ContentAdvancedDialog::filters_changed, this, _1)); d->ShowModal (); d->Destroy (); @@ -172,7 +188,7 @@ ContentAdvancedDialog::edit_filters () void ContentAdvancedDialog::filters_changed (vector filters) { - shared_ptr fcs = dynamic_pointer_cast(_content); + auto fcs = dynamic_pointer_cast(_content); if (!fcs) { return; } @@ -209,3 +225,26 @@ ContentAdvancedDialog::video_frame_rate_changed () _set_video_frame_rate->Enable (enable); } + +void +ContentAdvancedDialog::setup_sensitivity () +{ + _burnt_subtitle->Enable (static_cast(_content->video)); + _burnt_subtitle_language->enable (_content->video && _burnt_subtitle->GetValue()); +} + + +void +ContentAdvancedDialog::burnt_subtitle_changed () +{ + setup_sensitivity (); +} + + +void +ContentAdvancedDialog::burnt_subtitle_language_changed () +{ + DCPOMATIC_ASSERT (_content->video); + _content->video->set_burnt_subtitle_language (_burnt_subtitle_language->get()); +} + diff --git a/src/wx/content_advanced_dialog.h b/src/wx/content_advanced_dialog.h index 6eaaa2e2d..84ad4afac 100644 --- a/src/wx/content_advanced_dialog.h +++ b/src/wx/content_advanced_dialog.h @@ -29,6 +29,7 @@ DCPOMATIC_ENABLE_WARNINGS class Content; class Filter; +class LanguageTagWidget; class ContentAdvancedDialog : public wxDialog @@ -43,6 +44,9 @@ private: void setup_filters (); void set_video_frame_rate (); void video_frame_rate_changed (); + void setup_sensitivity (); + void burnt_subtitle_changed (); + void burnt_subtitle_language_changed (); std::shared_ptr _content; @@ -50,5 +54,7 @@ private: wxButton* _filters_button; wxTextCtrl* _video_frame_rate; wxButton* _set_video_frame_rate; + wxCheckBox* _burnt_subtitle; + LanguageTagWidget* _burnt_subtitle_language; }; diff --git a/src/wx/dcp_panel.cc b/src/wx/dcp_panel.cc index 3304f4d3c..d098c5c95 100644 --- a/src/wx/dcp_panel.cc +++ b/src/wx/dcp_panel.cc @@ -459,6 +459,7 @@ DCPPanel::film_content_changed (int property) property == TextContentProperty::LANGUAGE || property == TextContentProperty::LANGUAGE_IS_ADDITIONAL || property == VideoContentProperty::SCALE || + property == VideoContentProperty::BURNT_SUBTITLE_LANGUAGE || property == DCPContentProperty::REFERENCE_VIDEO || property == DCPContentProperty::REFERENCE_AUDIO || property == DCPContentProperty::REFERENCE_TEXT) {