2 Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
22 #include "check_box.h"
23 #include "content_advanced_dialog.h"
24 #include "dcpomatic_button.h"
25 #include "filter_dialog.h"
26 #include "language_tag_widget.h"
27 #include "static_text.h"
30 #include "lib/content.h"
31 #include "lib/dcp_content.h"
32 #include "lib/filter.h"
33 #include "lib/ffmpeg_content.h"
34 #include "lib/image_content.h"
35 #include "lib/video_content.h"
36 #include <dcp/warnings.h>
37 LIBDCP_DISABLE_WARNINGS
38 #include <wx/gbsizer.h>
39 #include <wx/propgrid/property.h>
40 #include <wx/propgrid/props.h>
42 LIBDCP_ENABLE_WARNINGS
43 #include <boost/bind/bind.hpp>
46 using std::dynamic_pointer_cast;
47 using std::shared_ptr;
51 using boost::optional;
52 #if BOOST_VERSION >= 106100
53 using namespace boost::placeholders;
55 using dcp::locale_convert;
59 ContentAdvancedDialog::ContentAdvancedDialog (wxWindow* parent, shared_ptr<Content> content)
60 : wxDialog (parent, wxID_ANY, _("Advanced content settings"))
63 auto sizer = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
68 auto size = dc.GetTextExtent (wxT ("A quite long name"));
70 size.SetWidth (size.GetWidth() + 64);
74 add_label_to_sizer (sizer, this, _("Video filters"), true, wxGBPosition(r, 0));
75 _filters = new StaticText (this, _("None"), wxDefaultPosition, size);
76 _filters_button = new Button (this, _("Edit..."));
77 auto filters = new wxBoxSizer (wxHORIZONTAL);
78 filters->Add (_filters, 1, wxALL | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP);
79 filters->Add (_filters_button, 0, wxALL, DCPOMATIC_SIZER_GAP);
80 sizer->Add (filters, wxGBPosition(r, 1), wxGBSpan(1, 2));
83 wxStaticText* video_frame_rate_label;
84 if (_content->video) {
85 video_frame_rate_label = add_label_to_sizer (sizer, this, _("Override detected video frame rate"), true, wxGBPosition(r, 0));
87 video_frame_rate_label = add_label_to_sizer (sizer, this, _("Video frame rate that content was prepared for"), true, wxGBPosition(r, 0));
89 _video_frame_rate = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0, wxNumericPropertyValidator(wxNumericPropertyValidator::Float));
90 sizer->Add (_video_frame_rate, wxGBPosition(r, 1));
91 _set_video_frame_rate = new Button (this, _("Set"));
92 _set_video_frame_rate->Enable (false);
93 sizer->Add (_set_video_frame_rate, wxGBPosition(r, 2));
96 /// TRANSLATORS: next to this control is a language selector, so together they will read, for example
97 /// "Video has burnt-in subtitles in the language fr-FR"
98 _burnt_subtitle = new CheckBox(this, _("Video has burnt-in subtitles in the language"));
99 sizer->Add (_burnt_subtitle, wxGBPosition(r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
100 _burnt_subtitle_language = new LanguageTagWidget (this, _("Language of burnt-in subtitles in this content"), content->video ? content->video->burnt_subtitle_language() : boost::none);
101 sizer->Add (_burnt_subtitle_language->sizer(), wxGBPosition(r, 1), wxGBSpan(1, 2), wxEXPAND);
104 _ignore_video = new CheckBox(this, _("Ignore this content's video and use only audio, subtitles and closed captions"));
105 sizer->Add(_ignore_video, wxGBPosition(r, 0), wxGBSpan(1, 3));
108 auto overall = new wxBoxSizer (wxVERTICAL);
109 overall->Add (sizer, 1, wxALL, DCPOMATIC_DIALOG_BORDER);
110 auto buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);
112 overall->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
115 SetSizerAndFit (overall);
117 _ignore_video->Enable(static_cast<bool>(_content->video));
118 _ignore_video->SetValue(_content->video ? !content->video->use() : false);
120 auto fcs = dynamic_pointer_cast<FFmpegContent>(content);
121 _filters_allowed = static_cast<bool>(fcs);
123 _filters_list = fcs->filters();
127 bool const single_frame_image_content = dynamic_pointer_cast<const ImageContent>(_content) && _content->number_of_paths() == 1;
128 video_frame_rate_label->Enable (!single_frame_image_content);
129 _video_frame_rate->Enable (!single_frame_image_content);
131 auto vfr = _content->video_frame_rate ();
133 _video_frame_rate->SetValue (std_to_wx(locale_convert<string>(*vfr)));
136 _burnt_subtitle->SetValue (_content->video && static_cast<bool>(_content->video->burnt_subtitle_language()));
137 _burnt_subtitle_language->set (_content->video ? _content->video->burnt_subtitle_language() : boost::none);
139 _filters_button->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::edit_filters, this));
140 _set_video_frame_rate->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::set_video_frame_rate, this));
141 _video_frame_rate->Bind (wxEVT_TEXT, boost::bind(&ContentAdvancedDialog::video_frame_rate_changed, this));
142 _burnt_subtitle->bind(&ContentAdvancedDialog::burnt_subtitle_changed, this);
144 setup_sensitivity ();
149 ContentAdvancedDialog::ignore_video() const
151 return _ignore_video->GetValue();
156 ContentAdvancedDialog::setup_filters ()
158 if (!_filters_allowed) {
159 checked_set (_filters, _("None"));
160 _filters->Enable (false);
161 _filters_button->Enable (false);
165 auto p = Filter::ffmpeg_string(_filters_list);
167 checked_set (_filters, _("None"));
169 if (p.length() > 25) {
170 p = p.substr(0, 25) + "...";
172 checked_set (_filters, p);
178 ContentAdvancedDialog::edit_filters ()
180 if (!_filters_allowed) {
184 auto dialog = make_wx<FilterDialog>(this, _filters_list);
185 dialog->ActiveChanged.connect(bind(&ContentAdvancedDialog::filters_changed, this, _1));
191 ContentAdvancedDialog::filters_changed (vector<Filter const *> filters)
193 _filters_list = filters;
199 ContentAdvancedDialog::video_frame_rate() const
201 if (_video_frame_rate->GetValue() == wxT("")) {
205 return locale_convert<double>(wx_to_std(_video_frame_rate->GetValue()));
210 ContentAdvancedDialog::set_video_frame_rate ()
212 _set_video_frame_rate->Enable (false);
217 ContentAdvancedDialog::video_frame_rate_changed ()
220 /* If the user clicks "set" now, with no frame rate entered, it would unset the video
221 frame rate in the selected content. This can't be allowed for some content types.
223 if (_video_frame_rate->GetValue() == wxT("") && (dynamic_pointer_cast<DCPContent>(_content) || dynamic_pointer_cast<FFmpegContent>(_content))) {
227 _set_video_frame_rate->Enable (enable);
232 ContentAdvancedDialog::setup_sensitivity ()
234 _burnt_subtitle->Enable (static_cast<bool>(_content->video));
235 _burnt_subtitle_language->enable (_content->video && _burnt_subtitle->GetValue());
240 ContentAdvancedDialog::burnt_subtitle_changed ()
242 setup_sensitivity ();
246 optional<dcp::LanguageTag>
247 ContentAdvancedDialog::burnt_subtitle_language() const
249 return _burnt_subtitle_language->get();