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"
29 #include "lib/content.h"
30 #include "lib/dcp_content.h"
31 #include "lib/filter.h"
32 #include "lib/ffmpeg_content.h"
33 #include "lib/image_content.h"
34 #include "lib/video_content.h"
35 #include <dcp/warnings.h>
36 LIBDCP_DISABLE_WARNINGS
37 #include <wx/gbsizer.h>
38 #include <wx/propgrid/property.h>
39 #include <wx/propgrid/props.h>
41 LIBDCP_ENABLE_WARNINGS
42 #include <boost/bind/bind.hpp>
45 using std::dynamic_pointer_cast;
46 using std::shared_ptr;
50 using boost::optional;
51 #if BOOST_VERSION >= 106100
52 using namespace boost::placeholders;
54 using dcp::locale_convert;
58 ContentAdvancedDialog::ContentAdvancedDialog (wxWindow* parent, shared_ptr<Content> content)
59 : wxDialog (parent, wxID_ANY, _("Advanced content settings"))
62 auto sizer = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
67 auto size = dc.GetTextExtent (wxT ("A quite long name"));
69 size.SetWidth (size.GetWidth() + 64);
73 add_label_to_sizer (sizer, this, _("Video filters"), true, wxGBPosition(r, 0));
74 _filters = new StaticText (this, _("None"), wxDefaultPosition, size);
75 _filters_button = new Button (this, _("Edit..."));
76 auto filters = new wxBoxSizer (wxHORIZONTAL);
77 filters->Add (_filters, 1, wxALL | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP);
78 filters->Add (_filters_button, 0, wxALL, DCPOMATIC_SIZER_GAP);
79 sizer->Add (filters, wxGBPosition(r, 1), wxGBSpan(1, 2));
82 wxStaticText* video_frame_rate_label;
83 if (_content->video) {
84 video_frame_rate_label = add_label_to_sizer (sizer, this, _("Override detected video frame rate"), true, wxGBPosition(r, 0));
86 video_frame_rate_label = add_label_to_sizer (sizer, this, _("Video frame rate that content was prepared for"), true, wxGBPosition(r, 0));
88 _video_frame_rate = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0, wxNumericPropertyValidator(wxNumericPropertyValidator::Float));
89 sizer->Add (_video_frame_rate, wxGBPosition(r, 1));
90 _set_video_frame_rate = new Button (this, _("Set"));
91 _set_video_frame_rate->Enable (false);
92 sizer->Add (_set_video_frame_rate, wxGBPosition(r, 2));
95 /// TRANSLATORS: next to this control is a language selector, so together they will read, for example
96 /// "Video has burnt-in subtitles in the language fr-FR"
97 _burnt_subtitle = new CheckBox(this, _("Video has burnt-in subtitles in the language"));
98 sizer->Add (_burnt_subtitle, wxGBPosition(r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
99 _burnt_subtitle_language = new LanguageTagWidget (this, _("Language of burnt-in subtitles in this content"), content->video ? content->video->burnt_subtitle_language() : boost::none);
100 sizer->Add (_burnt_subtitle_language->sizer(), wxGBPosition(r, 1), wxGBSpan(1, 2), wxEXPAND);
103 _ignore_video = new CheckBox(this, _("Ignore this content's video and use only audio, subtitles and closed captions"));
104 sizer->Add(_ignore_video, wxGBPosition(r, 0), wxGBSpan(1, 3));
107 auto overall = new wxBoxSizer (wxVERTICAL);
108 overall->Add (sizer, 1, wxALL, DCPOMATIC_DIALOG_BORDER);
109 auto buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);
111 overall->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
114 SetSizerAndFit (overall);
116 _ignore_video->Enable(static_cast<bool>(_content->video));
117 _ignore_video->SetValue(_content->video ? !content->video->use() : false);
119 auto fcs = dynamic_pointer_cast<FFmpegContent>(content);
120 _filters_allowed = static_cast<bool>(fcs);
122 _filters_list = fcs->filters();
126 bool const single_frame_image_content = dynamic_pointer_cast<const ImageContent>(_content) && _content->number_of_paths() == 1;
127 video_frame_rate_label->Enable (!single_frame_image_content);
128 _video_frame_rate->Enable (!single_frame_image_content);
130 auto vfr = _content->video_frame_rate ();
132 _video_frame_rate->SetValue (std_to_wx(locale_convert<string>(*vfr)));
135 _burnt_subtitle->SetValue (_content->video && static_cast<bool>(_content->video->burnt_subtitle_language()));
136 _burnt_subtitle_language->set (_content->video ? _content->video->burnt_subtitle_language() : boost::none);
138 _filters_button->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::edit_filters, this));
139 _set_video_frame_rate->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::set_video_frame_rate, this));
140 _video_frame_rate->Bind (wxEVT_TEXT, boost::bind(&ContentAdvancedDialog::video_frame_rate_changed, this));
141 _burnt_subtitle->bind(&ContentAdvancedDialog::burnt_subtitle_changed, this);
143 setup_sensitivity ();
148 ContentAdvancedDialog::ignore_video() const
150 return _ignore_video->GetValue();
155 ContentAdvancedDialog::setup_filters ()
157 if (!_filters_allowed) {
158 checked_set (_filters, _("None"));
159 _filters->Enable (false);
160 _filters_button->Enable (false);
164 auto p = Filter::ffmpeg_string(_filters_list);
166 checked_set (_filters, _("None"));
168 if (p.length() > 25) {
169 p = p.substr(0, 25) + "...";
171 checked_set (_filters, p);
177 ContentAdvancedDialog::edit_filters ()
179 if (!_filters_allowed) {
183 auto dialog = make_wx<FilterDialog>(this, _filters_list);
184 dialog->ActiveChanged.connect(bind(&ContentAdvancedDialog::filters_changed, this, _1));
190 ContentAdvancedDialog::filters_changed(vector<Filter> const& filters)
192 _filters_list = filters;
198 ContentAdvancedDialog::video_frame_rate() const
200 if (_video_frame_rate->GetValue() == wxT("")) {
204 return locale_convert<double>(wx_to_std(_video_frame_rate->GetValue()));
209 ContentAdvancedDialog::set_video_frame_rate ()
211 _set_video_frame_rate->Enable (false);
216 ContentAdvancedDialog::video_frame_rate_changed ()
219 /* If the user clicks "set" now, with no frame rate entered, it would unset the video
220 frame rate in the selected content. This can't be allowed for some content types.
222 if (_video_frame_rate->GetValue() == wxT("") && (dynamic_pointer_cast<DCPContent>(_content) || dynamic_pointer_cast<FFmpegContent>(_content))) {
226 _set_video_frame_rate->Enable (enable);
231 ContentAdvancedDialog::setup_sensitivity ()
233 _burnt_subtitle->Enable (static_cast<bool>(_content->video));
234 _burnt_subtitle_language->enable (_content->video && _burnt_subtitle->GetValue());
239 ContentAdvancedDialog::burnt_subtitle_changed ()
241 setup_sensitivity ();
245 optional<dcp::LanguageTag>
246 ContentAdvancedDialog::burnt_subtitle_language() const
248 return _burnt_subtitle_language->get();