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>
44 using std::dynamic_pointer_cast;
45 using std::shared_ptr;
49 using boost::optional;
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 _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 _filters_button->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::edit_filters, this));
132 _set_video_frame_rate->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::set_video_frame_rate, this));
133 _video_frame_rate->Bind (wxEVT_TEXT, boost::bind(&ContentAdvancedDialog::video_frame_rate_changed, this));
134 _burnt_subtitle->Bind (wxEVT_CHECKBOX, boost::bind(&ContentAdvancedDialog::burnt_subtitle_changed, this));
135 _burnt_subtitle_language->Changed.connect (boost::bind(&ContentAdvancedDialog::burnt_subtitle_language_changed, this));
137 setup_sensitivity ();
142 ContentAdvancedDialog::ignore_video() const
144 return _ignore_video->GetValue();
149 ContentAdvancedDialog::setup_filters ()
151 auto fcs = dynamic_pointer_cast<FFmpegContent>(_content);
153 checked_set (_filters, _("None"));
154 _filters->Enable (false);
155 _filters_button->Enable (false);
159 auto p = Filter::ffmpeg_string (fcs->filters());
161 checked_set (_filters, _("None"));
163 if (p.length() > 25) {
164 p = p.substr(0, 25) + "...";
166 checked_set (_filters, p);
172 ContentAdvancedDialog::edit_filters ()
174 auto fcs = dynamic_pointer_cast<FFmpegContent>(_content);
179 auto d = new FilterDialog (this, fcs->filters());
180 d->ActiveChanged.connect (bind(&ContentAdvancedDialog::filters_changed, this, _1));
187 ContentAdvancedDialog::filters_changed (vector<Filter const *> filters)
189 auto fcs = dynamic_pointer_cast<FFmpegContent>(_content);
194 fcs->set_filters (filters);
200 ContentAdvancedDialog::set_video_frame_rate ()
202 if (_video_frame_rate->GetValue() != wxT("")) {
203 _content->set_video_frame_rate (locale_convert<double>(wx_to_std(_video_frame_rate->GetValue())));
205 _content->unset_video_frame_rate ();
208 _set_video_frame_rate->Enable (false);
213 ContentAdvancedDialog::video_frame_rate_changed ()
216 /* If the user clicks "set" now, with no frame rate entered, it would unset the video
217 frame rate in the selected content. This can't be allowed for some content types.
219 if (_video_frame_rate->GetValue() == wxT("") && (dynamic_pointer_cast<DCPContent>(_content) || dynamic_pointer_cast<FFmpegContent>(_content))) {
223 _set_video_frame_rate->Enable (enable);
228 ContentAdvancedDialog::setup_sensitivity ()
230 _burnt_subtitle->Enable (static_cast<bool>(_content->video));
231 _burnt_subtitle_language->enable (_content->video && _burnt_subtitle->GetValue());
236 ContentAdvancedDialog::burnt_subtitle_changed ()
238 setup_sensitivity ();
243 ContentAdvancedDialog::burnt_subtitle_language_changed ()
245 DCPOMATIC_ASSERT (_content->video);
246 _content->video->set_burnt_subtitle_language (_burnt_subtitle_language->get());