2 Copyright (C) 2020 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 "static_text.h"
27 #include "lib/content.h"
28 #include "lib/dcp_content.h"
29 #include "lib/filter.h"
30 #include "lib/ffmpeg_content.h"
31 #include "lib/image_content.h"
32 #include "lib/video_content.h"
33 #include <wx/gbsizer.h>
34 DCPOMATIC_DISABLE_WARNINGS
35 #include <wx/propgrid/props.h>
36 DCPOMATIC_ENABLE_WARNINGS
37 #include <boost/bind.hpp>
43 using boost::dynamic_pointer_cast;
44 using boost::optional;
45 using boost::shared_ptr;
46 #if BOOST_VERSION >= 106100
47 using namespace boost::placeholders;
49 using dcp::locale_convert;
53 ContentAdvancedDialog::ContentAdvancedDialog (wxWindow* parent, shared_ptr<Content> content)
54 : wxDialog (parent, wxID_ANY, _("Advanced content settings"))
57 wxGridBagSizer* sizer = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
62 wxSize size = dc.GetTextExtent (wxT ("A quite long name"));
64 size.SetWidth (size.GetWidth() + 64);
68 add_label_to_sizer (sizer, this, _("Video filters"), true, wxGBPosition(r, 0));
69 _filters = new StaticText (this, _("None"), wxDefaultPosition, size);
70 _filters_button = new Button (this, _("Edit..."));
71 wxBoxSizer* filters = new wxBoxSizer (wxHORIZONTAL);
72 filters->Add (_filters, 1, wxALL | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP);
73 filters->Add (_filters_button, 0, wxALL, DCPOMATIC_SIZER_GAP);
74 sizer->Add (filters, wxGBPosition(r, 1), wxGBSpan(1, 2));
77 wxStaticText* video_frame_rate_label;
78 if (_content->video) {
79 video_frame_rate_label = add_label_to_sizer (sizer, this, _("Override detected video frame rate"), true, wxGBPosition(r, 0));
81 video_frame_rate_label = add_label_to_sizer (sizer, this, _("Video frame rate that content was prepared for"), true, wxGBPosition(r, 0));
83 _video_frame_rate = new wxTextCtrl (this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 0, wxNumericPropertyValidator(wxNumericPropertyValidator::Float));
84 sizer->Add (_video_frame_rate, wxGBPosition(r, 1));
85 _set_video_frame_rate = new Button (this, _("Set"));
86 _set_video_frame_rate->Enable (false);
87 sizer->Add (_set_video_frame_rate, wxGBPosition(r, 2));
90 wxCheckBox* ignore_video = new wxCheckBox (this, wxID_ANY, _("Ignore this content's video and use only audio, subtitles and closed captions"));
91 sizer->Add (ignore_video, wxGBPosition(r, 0), wxGBSpan(1, 3));
94 wxSizer* overall = new wxBoxSizer (wxVERTICAL);
95 overall->Add (sizer, 1, wxALL, DCPOMATIC_DIALOG_BORDER);
96 wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);
98 overall->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
101 SetSizerAndFit (overall);
103 ignore_video->Enable (static_cast<bool>(_content->video));
104 ignore_video->SetValue (_content->video ? !content->video->use() : false);
107 bool const single_frame_image_content = dynamic_pointer_cast<const ImageContent>(_content) && _content->number_of_paths() == 1;
108 video_frame_rate_label->Enable (!single_frame_image_content);
109 _video_frame_rate->Enable (!single_frame_image_content);
111 optional<double> vfr = _content->video_frame_rate ();
113 _video_frame_rate->SetValue (std_to_wx(locale_convert<string>(*vfr)));
116 ignore_video->Bind (wxEVT_CHECKBOX, bind(&ContentAdvancedDialog::ignore_video_changed, this, _1));
117 _filters_button->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::edit_filters, this));
118 _set_video_frame_rate->Bind (wxEVT_BUTTON, bind(&ContentAdvancedDialog::set_video_frame_rate, this));
119 _video_frame_rate->Bind (wxEVT_TEXT, boost::bind(&ContentAdvancedDialog::video_frame_rate_changed, this));
124 ContentAdvancedDialog::ignore_video_changed (wxCommandEvent& ev)
126 if (_content->video) {
127 _content->video->set_use (!ev.IsChecked());
133 ContentAdvancedDialog::setup_filters ()
135 shared_ptr<FFmpegContent> fcs = dynamic_pointer_cast<FFmpegContent>(_content);
137 checked_set (_filters, _("None"));
138 _filters->Enable (false);
139 _filters_button->Enable (false);
143 string p = Filter::ffmpeg_string (fcs->filters());
145 checked_set (_filters, _("None"));
147 if (p.length() > 25) {
148 p = p.substr(0, 25) + "...";
150 checked_set (_filters, p);
156 ContentAdvancedDialog::edit_filters ()
158 shared_ptr<FFmpegContent> fcs = dynamic_pointer_cast<FFmpegContent>(_content);
163 FilterDialog* d = new FilterDialog (this, fcs->filters());
164 d->ActiveChanged.connect (bind(&ContentAdvancedDialog::filters_changed, this, _1));
171 ContentAdvancedDialog::filters_changed (vector<Filter const *> filters)
173 shared_ptr<FFmpegContent> fcs = dynamic_pointer_cast<FFmpegContent>(_content);
178 fcs->set_filters (filters);
184 ContentAdvancedDialog::set_video_frame_rate ()
186 if (_video_frame_rate->GetValue() != wxT("")) {
187 _content->set_video_frame_rate (locale_convert<double>(wx_to_std(_video_frame_rate->GetValue())));
189 _content->unset_video_frame_rate ();
192 _set_video_frame_rate->Enable (false);
197 ContentAdvancedDialog::video_frame_rate_changed ()
200 /* If the user clicks "set" now, with no frame rate entered, it would unset the video
201 frame rate in the selected content. This can't be allowed for some content types.
203 if (_video_frame_rate->GetValue() == wxT("") && (dynamic_pointer_cast<DCPContent>(_content) || dynamic_pointer_cast<FFmpegContent>(_content))) {
207 _set_video_frame_rate->Enable (enable);