2 Copyright (C) 2019-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_version_dialog.h"
23 #include "editable_list.h"
24 #include "language_tag_dialog.h"
25 #include "language_tag_widget.h"
26 #include "smpte_metadata_dialog.h"
27 #include "rating_dialog.h"
29 #include <dcp/types.h>
30 #include <wx/gbsizer.h>
31 #include <wx/notebook.h>
32 #include <wx/spinctrl.h>
37 using boost::optional;
38 using std::shared_ptr;
40 #if BOOST_VERSION >= 106100
41 using namespace boost::placeholders;
46 ratings_column (dcp::Rating r, int c)
57 content_versions_column (string v, int)
64 SMPTEMetadataDialog::main_panel (wxWindow* parent)
66 auto panel = new wxPanel (parent, wxID_ANY);
68 auto sizer = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
69 sizer->AddGrowableCol (1, 1);
71 add_label_to_sizer (sizer, panel, _("Title language"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
72 _name_language = new LanguageTagWidget(
74 wxString::Format(_("The language that the film's title (\"%s\") is in"), std_to_wx(film()->name())),
75 film()->name_language()
77 sizer->Add (_name_language->sizer(), 0, wxEXPAND);
79 add_label_to_sizer (sizer, panel, _("Audio language"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
80 _audio_language = new LanguageTagWidget(
82 _("The main language that is spoken in the film's soundtrack"),
83 film()->audio_language()
85 sizer->Add (_audio_language->sizer(), 0, wxEXPAND);
88 int flags = wxALIGN_TOP | wxRIGHT | wxTOP;
90 flags |= wxALIGN_RIGHT;
92 auto m = create_label (panel, _("Ratings"), true);
93 sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
96 vector<EditableListColumn> columns;
97 columns.push_back (EditableListColumn("Agency", 200, true));
98 columns.push_back (EditableListColumn("Label", 50, true));
99 _ratings = new EditableList<dcp::Rating, RatingDialog> (
102 boost::bind(&SMPTEMetadataDialog::ratings, this),
103 boost::bind(&SMPTEMetadataDialog::set_ratings, this, _1),
104 boost::bind(&ratings_column, _1, _2),
108 sizer->Add (_ratings, 1, wxEXPAND);
110 auto overall_sizer = new wxBoxSizer (wxVERTICAL);
111 overall_sizer->Add (sizer, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
112 panel->SetSizer (overall_sizer);
119 SMPTEMetadataDialog::advanced_panel (wxWindow* parent)
121 auto panel = new wxPanel (parent, wxID_ANY);
123 auto sizer = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
124 sizer->AddGrowableCol (1, 1);
126 _enable_release_territory = new wxCheckBox (panel, wxID_ANY, _("Release territory"));
127 sizer->Add (_enable_release_territory, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP);
129 auto s = new wxBoxSizer (wxHORIZONTAL);
130 _release_territory_text = new wxStaticText (panel, wxID_ANY, wxT(""));
131 s->Add (_release_territory_text, 1, wxLEFT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_X_GAP);
132 _edit_release_territory = new Button (panel, _("Edit..."));
133 s->Add (_edit_release_territory, 0, wxLEFT, DCPOMATIC_SIZER_GAP);
134 sizer->Add (s, 0, wxEXPAND);
137 add_label_to_sizer (sizer, panel, _("Version number"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
138 _version_number = new wxSpinCtrl (panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 1000);
139 sizer->Add (_version_number, 0);
141 add_label_to_sizer (sizer, panel, _("Status"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
142 _status = new wxChoice (panel, wxID_ANY);
143 sizer->Add (_status, 0);
145 _enable_chain = new wxCheckBox (panel, wxID_ANY, _("Chain"));
146 sizer->Add (_enable_chain, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
147 _chain = new wxTextCtrl (panel, wxID_ANY);
148 sizer->Add (_chain, 1, wxEXPAND);
150 _enable_distributor = new wxCheckBox (panel, wxID_ANY, _("Distributor"));
151 sizer->Add (_enable_distributor, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
152 _distributor = new wxTextCtrl (panel, wxID_ANY);
153 sizer->Add (_distributor, 1, wxEXPAND);
155 _enable_facility = new wxCheckBox (panel, wxID_ANY, _("Facility"));
156 sizer->Add (_enable_facility, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
157 _facility = new wxTextCtrl (panel, wxID_ANY);
158 sizer->Add (_facility, 1, wxEXPAND);
160 add_label_to_sizer (sizer, panel, _("Luminance"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
162 auto s = new wxBoxSizer (wxHORIZONTAL);
163 _luminance_value = new wxSpinCtrlDouble (panel, wxID_ANY);
164 _luminance_value->SetDigits (1);
165 _luminance_value->SetIncrement (0.1);
166 s->Add (_luminance_value, 0);
167 _luminance_unit = new wxChoice (panel, wxID_ANY);
168 s->Add (_luminance_unit, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
169 sizer->Add (s, 1, wxEXPAND);
173 int flags = wxALIGN_TOP | wxRIGHT | wxTOP;
175 flags |= wxALIGN_RIGHT;
177 auto m = create_label (panel, _("Content versions"), true);
178 sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
181 vector<EditableListColumn> columns;
182 columns.push_back (EditableListColumn("Version", 350, true));
183 _content_versions = new EditableList<string, ContentVersionDialog> (
186 boost::bind(&SMPTEMetadataDialog::content_versions, this),
187 boost::bind(&SMPTEMetadataDialog::set_content_versions, this, _1),
188 boost::bind(&content_versions_column, _1, _2),
192 sizer->Add (_content_versions, 1, wxEXPAND);
194 auto overall_sizer = new wxBoxSizer (wxVERTICAL);
195 overall_sizer->Add (sizer, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
196 panel->SetSizer (overall_sizer);
202 SMPTEMetadataDialog::SMPTEMetadataDialog (wxWindow* parent, weak_ptr<Film> weak_film)
203 : wxDialog (parent, wxID_ANY, _("Metadata"))
204 , WeakFilm (weak_film)
206 auto notebook = new wxNotebook (this, wxID_ANY);
207 notebook->AddPage (main_panel(notebook), _("Standard"));
208 notebook->AddPage (advanced_panel(notebook), _("Advanced"));
210 auto overall_sizer = new wxBoxSizer (wxVERTICAL);
211 overall_sizer->Add (notebook, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
213 auto buttons = CreateSeparatedButtonSizer (wxCLOSE);
215 overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
218 SetSizer (overall_sizer);
219 overall_sizer->Layout ();
220 overall_sizer->SetSizeHints (this);
222 _status->Append (_("Temporary"));
223 _status->Append (_("Pre-release"));
224 _status->Append (_("Final"));
226 _luminance_unit->Append (wxString::FromUTF8(_("candela per m²")));
227 _luminance_unit->Append (_("foot lambert"));
229 _name_language->Changed.connect (boost::bind(&SMPTEMetadataDialog::name_language_changed, this, _1));
230 _audio_language->Changed.connect (boost::bind(&SMPTEMetadataDialog::audio_language_changed, this, _1));
231 _edit_release_territory->Bind (wxEVT_BUTTON, boost::bind(&SMPTEMetadataDialog::edit_release_territory, this));
232 _version_number->Bind (wxEVT_SPINCTRL, boost::bind(&SMPTEMetadataDialog::version_number_changed, this));
233 _status->Bind (wxEVT_CHOICE, boost::bind(&SMPTEMetadataDialog::status_changed, this));
234 _enable_chain->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_chain_changed, this));
235 _chain->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::chain_changed, this));
236 _enable_distributor->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_distributor_changed, this));
237 _distributor->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::distributor_changed, this));
238 _enable_facility->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_facility_changed, this));
239 _facility->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::facility_changed, this));
240 _luminance_value->Bind (wxEVT_SPINCTRLDOUBLE, boost::bind(&SMPTEMetadataDialog::luminance_changed, this));
241 _luminance_unit->Bind (wxEVT_CHOICE, boost::bind(&SMPTEMetadataDialog::luminance_changed, this));
242 _enable_release_territory->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_release_territory_changed, this));
244 _version_number->SetFocus ();
246 _film_changed_connection = film()->Change.connect(boost::bind(&SMPTEMetadataDialog::film_changed, this, _1, _2));
248 film_changed (ChangeType::DONE, Film::Property::NAME_LANGUAGE);
249 film_changed (ChangeType::DONE, Film::Property::RELEASE_TERRITORY);
250 film_changed (ChangeType::DONE, Film::Property::VERSION_NUMBER);
251 film_changed (ChangeType::DONE, Film::Property::STATUS);
252 film_changed (ChangeType::DONE, Film::Property::CHAIN);
253 film_changed (ChangeType::DONE, Film::Property::DISTRIBUTOR);
254 film_changed (ChangeType::DONE, Film::Property::FACILITY);
255 film_changed (ChangeType::DONE, Film::Property::CONTENT_VERSIONS);
256 film_changed (ChangeType::DONE, Film::Property::LUMINANCE);
257 film_changed (ChangeType::DONE, Film::Property::SUBTITLE_LANGUAGES);
259 setup_sensitivity ();
264 SMPTEMetadataDialog::film_changed (ChangeType type, Film::Property property)
266 if (type != ChangeType::DONE || film()->interop()) {
270 if (property == Film::Property::NAME_LANGUAGE) {
271 _name_language->set (film()->name_language());
272 } else if (property == Film::Property::RELEASE_TERRITORY) {
273 auto rt = film()->release_territory();
274 checked_set (_enable_release_territory, static_cast<bool>(rt));
276 _release_territory = *rt;
277 checked_set (_release_territory_text, std_to_wx(*dcp::LanguageTag::get_subtag_description(*_release_territory)));
279 } else if (property == Film::Property::VERSION_NUMBER) {
280 checked_set (_version_number, film()->version_number());
281 } else if (property == Film::Property::STATUS) {
282 switch (film()->status()) {
283 case dcp::Status::TEMP:
284 checked_set (_status, 0);
286 case dcp::Status::PRE:
287 checked_set (_status, 1);
289 case dcp::Status::FINAL:
290 checked_set (_status, 2);
293 } else if (property == Film::Property::CHAIN) {
294 checked_set (_enable_chain, static_cast<bool>(film()->chain()));
295 if (film()->chain()) {
296 checked_set (_chain, *film()->chain());
298 } else if (property == Film::Property::DISTRIBUTOR) {
299 checked_set (_enable_distributor, static_cast<bool>(film()->distributor()));
300 if (film()->distributor()) {
301 checked_set (_distributor, *film()->distributor());
303 } else if (property == Film::Property::FACILITY) {
304 checked_set (_enable_facility, static_cast<bool>(film()->facility()));
305 if (film()->facility()) {
306 checked_set (_facility, *film()->facility());
308 } else if (property == Film::Property::LUMINANCE) {
309 auto lum = film()->luminance();
311 checked_set (_luminance_value, lum->value());
312 switch (lum->unit()) {
313 case dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE:
314 checked_set (_luminance_unit, 0);
316 case dcp::Luminance::Unit::FOOT_LAMBERT:
317 checked_set (_luminance_unit, 1);
321 checked_set (_luminance_value, 4.5);
322 checked_set (_luminance_unit, 1);
329 SMPTEMetadataDialog::ratings () const
331 return film()->ratings ();
336 SMPTEMetadataDialog::set_ratings (vector<dcp::Rating> r)
338 film()->set_ratings (r);
343 SMPTEMetadataDialog::content_versions () const
345 return film()->content_versions ();
350 SMPTEMetadataDialog::set_content_versions (vector<string> cv)
352 film()->set_content_versions (cv);
357 SMPTEMetadataDialog::name_language_changed (dcp::LanguageTag tag)
359 film()->set_name_language (tag);
364 SMPTEMetadataDialog::audio_language_changed (dcp::LanguageTag tag)
366 film()->set_audio_language (tag);
371 SMPTEMetadataDialog::edit_release_territory ()
373 DCPOMATIC_ASSERT (film()->release_territory());
374 auto d = new RegionSubtagDialog(this, *film()->release_territory());
378 _release_territory = *tag;
379 film()->set_release_territory(*tag);
386 SMPTEMetadataDialog::version_number_changed ()
388 film()->set_version_number (_version_number->GetValue());
393 SMPTEMetadataDialog::status_changed ()
395 switch (_status->GetSelection()) {
397 film()->set_status(dcp::Status::TEMP);
400 film()->set_status(dcp::Status::PRE);
403 film()->set_status(dcp::Status::FINAL);
410 SMPTEMetadataDialog::chain_changed ()
412 film()->set_chain (wx_to_std(_chain->GetValue()));
417 SMPTEMetadataDialog::distributor_changed ()
419 film()->set_distributor (wx_to_std(_distributor->GetValue()));
424 SMPTEMetadataDialog::facility_changed ()
426 film()->set_facility (wx_to_std(_facility->GetValue()));
431 SMPTEMetadataDialog::luminance_changed ()
433 dcp::Luminance::Unit unit;
434 switch (_luminance_unit->GetSelection()) {
436 unit = dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE;
439 unit = dcp::Luminance::Unit::FOOT_LAMBERT;
442 DCPOMATIC_ASSERT (false);
445 film()->set_luminance (dcp::Luminance(_luminance_value->GetValue(), unit));
450 SMPTEMetadataDialog::setup_sensitivity ()
453 auto const enabled = _enable_release_territory->GetValue();
454 _release_territory_text->Enable (enabled);
455 _edit_release_territory->Enable (enabled);
458 _chain->Enable (_enable_chain->GetValue());
459 _distributor->Enable (_enable_distributor->GetValue());
460 _facility->Enable (_enable_facility->GetValue());
465 SMPTEMetadataDialog::enable_release_territory_changed ()
467 setup_sensitivity ();
468 if (_enable_release_territory->GetValue()) {
469 film()->set_release_territory (_release_territory.get_value_or(dcp::LanguageTag::RegionSubtag("US")));
471 film()->set_release_territory ();
477 SMPTEMetadataDialog::enable_chain_changed ()
479 setup_sensitivity ();
480 if (_enable_chain->GetValue()) {
481 film()->set_chain (wx_to_std(_chain->GetValue()));
483 film()->set_chain ();
489 SMPTEMetadataDialog::enable_distributor_changed ()
491 setup_sensitivity ();
492 if (_enable_distributor->GetValue()) {
493 film()->set_distributor (wx_to_std(_distributor->GetValue()));
495 film()->set_distributor ();
501 SMPTEMetadataDialog::enable_facility_changed ()
503 setup_sensitivity ();
504 if (_enable_facility->GetValue()) {
505 film()->set_facility (wx_to_std(_facility->GetValue()));
507 film()->set_facility ();