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 "content_advanced_dialog.h"
23 #include "dcpomatic_button.h"
24 #include "filter_dialog.h"
25 #include "language_tag_widget.h"
26 #include "static_text.h"
28 #include "lib/content.h"
29 #include "lib/dcp_content.h"
30 #include "lib/filter.h"
31 #include "lib/ffmpeg_content.h"
32 #include "lib/image_content.h"
33 #include "lib/video_content.h"
34 #include <dcp/warnings.h>
35 LIBDCP_DISABLE_WARNINGS
36 #include <wx/gbsizer.h>
37 #include <wx/propgrid/property.h>
38 #include <wx/propgrid/props.h>
40 LIBDCP_ENABLE_WARNINGS
41 #include <boost/bind/bind.hpp>
47 using std::dynamic_pointer_cast;
48 using boost::optional;
49 using std::shared_ptr;
50 #if BOOST_VERSION >= 106100
51 using namespace boost::placeholders;
53 using dcp::locale_convert;
57 ContentAdvancedDialog::ContentAdvancedDialog (wxWindow* parent, shared_ptr<Content> content)
58 : wxDialog (parent, wxID_ANY, _("Advanced content settings"))
61 auto sizer = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
66 auto size = dc.GetTextExtent (wxT ("A quite long name"));
68 size.SetWidth (size.GetWidth() + 64);
72 add_label_to_sizer (sizer, this, _("Video filters"), true, wxGBPosition(r, 0));
73 _filters = new StaticText (this, _("None"), wxDefaultPosition, size);
74 _filters_button = new Button (this, _("Edit..."));
75 auto filters = new wxBoxSizer (wxHORIZONTAL);
76 filters->Add (_filters, 1, wxALL | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP);
77 filters->Add (_filters_button, 0, wxALL, DCPOMATIC_SIZER_GAP);
78 sizer->Add (filters, wxGBPosition(r, 1), wxGBSpan(1, 2));
81 wxStaticText* video_frame_rate_label;
82 if (_content->video) {
83 video_frame_rate_label = add_label_to_sizer (sizer, this, _("Override detected video frame rate"), true, wxGBPosition(r, 0));
85 video_frame_rate_label = add_label_to_sizer (sizer, this, _("Video frame rate that content was prepared for"), true, wxGBPosition(r, 0));
87 _video_frame_rate = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0, wxNumericPropertyValidator(wxNumericPropertyValidator::Float));
88 sizer->Add (_video_frame_rate, wxGBPosition(r, 1));
89 _set_video_frame_rate = new Button (this, _("Set"));
90 _set_video_frame_rate->Enable (false);
91 sizer->Add (_set_video_frame_rate, wxGBPosition(r, 2));
94 /// TRANSLATORS: next to this control is a language selector, so together they will read, for example
95 /// "Video has burnt-in subtitles in the language fr-FR"
96 _burnt_subtitle = new wxCheckBox (this, wxID_ANY, _("Video has burnt-in subtitles in the language"));
97 sizer->Add (_burnt_subtitle, wxGBPosition(r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
98 _burnt_subtitle_language = new LanguageTagWidget (this, _("Language of burnt-in subtitles in this content"), content->video ? content->video->burnt_subtitle_language() : boost::none);
99 sizer->Add (_burnt_subtitle_language->sizer(), wxGBPosition(r, 1), wxGBSpan(1, 2), wxEXPAND);
102 auto ignore_video = new wxCheckBox (this, wxID_ANY, _("Ignore this content's video and use only audio, subtitles and closed captions"));
103 sizer->Add (ignore_video, wxGBPosition(r, 0), wxGBSpan(1, 3));
106 auto overall = new wxBoxSizer (wxVERTICAL);
107 overall->Add (sizer, 1, wxALL, DCPOMATIC_DIALOG_BORDER);
108 auto buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);
110 overall->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
113 SetSizerAndFit (overall);
115 ignore_video->Enable (static_cast<bool>(_content->video));
116 ignore_video->SetValue (_content->video ? !content->video->use() : false);
119 bool const single_frame_image_content = dynamic_pointer_cast<const ImageContent>(_content) && _content->number_of_paths() == 1;
120 video_frame_rate_label->Enable (!single_frame_image_content);
121 _video_frame_rate->Enable (!single_frame_image_content);
123 auto vfr = _content->video_frame_rate ();
125 _video_frame_rate->SetValue (std_to_wx(locale_convert<string>(*vfr)));
128 _burnt_subtitle->SetValue (_content->video && static_cast<bool>(_content->video->burnt_subtitle_language()));
129 _burnt_subtitle_language->set (_content->video ? _content->video->burnt_subtitle_language() : boost::none);
131 ignore_video->Bind (wxEVT_CHECKBOX, bind(&ContentAdvancedDialog::ignore_video_changed, this, _1));
132 _filters_button->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::edit_filters, this));
133 _set_video_frame_rate->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::set_video_frame_rate, this));
134 _video_frame_rate->Bind (wxEVT_TEXT, boost::bind(&ContentAdvancedDialog::video_frame_rate_changed, this));
135 _burnt_subtitle->Bind (wxEVT_CHECKBOX, boost::bind(&ContentAdvancedDialog::burnt_subtitle_changed, this));
136 _burnt_subtitle_language->Changed.connect (boost::bind(&ContentAdvancedDialog::burnt_subtitle_language_changed, this));
138 setup_sensitivity ();
143 ContentAdvancedDialog::ignore_video_changed (wxCommandEvent& ev)
145 if (_content->video) {
146 _content->video->set_use (!ev.IsChecked());
152 ContentAdvancedDialog::setup_filters ()
154 auto fcs = dynamic_pointer_cast<FFmpegContent>(_content);
156 checked_set (_filters, _("None"));
157 _filters->Enable (false);
158 _filters_button->Enable (false);
162 auto p = Filter::ffmpeg_string (fcs->filters());
164 checked_set (_filters, _("None"));
166 if (p.length() > 25) {
167 p = p.substr(0, 25) + "...";
169 checked_set (_filters, p);
175 ContentAdvancedDialog::edit_filters ()
177 auto fcs = dynamic_pointer_cast<FFmpegContent>(_content);
182 auto d = new FilterDialog (this, fcs->filters());
183 d->ActiveChanged.connect (bind(&ContentAdvancedDialog::filters_changed, this, _1));
190 ContentAdvancedDialog::filters_changed (vector<Filter const *> filters)
192 auto fcs = dynamic_pointer_cast<FFmpegContent>(_content);
197 fcs->set_filters (filters);
203 ContentAdvancedDialog::set_video_frame_rate ()
205 if (_video_frame_rate->GetValue() != wxT("")) {
206 _content->set_video_frame_rate (locale_convert<double>(wx_to_std(_video_frame_rate->GetValue())));
208 _content->unset_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 ();
246 ContentAdvancedDialog::burnt_subtitle_language_changed ()
248 DCPOMATIC_ASSERT (_content->video);
249 _content->video->set_burnt_subtitle_language (_burnt_subtitle_language->get());