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 additional_subtitle_language_column (dcp::LanguageTag r, int)
53 ratings_column (dcp::Rating r, int c)
64 content_versions_column (string v, int)
71 SMPTEMetadataDialog::main_panel (wxWindow* parent)
73 auto panel = new wxPanel (parent, wxID_ANY);
75 auto sizer = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
76 sizer->AddGrowableCol (1, 1);
78 add_label_to_sizer (sizer, panel, _("Title language"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
79 _name_language = new LanguageTagWidget(
81 wxString::Format(_("The language that the film's title (\"%s\") is in"), std_to_wx(film()->name())),
82 film()->name_language()
84 sizer->Add (_name_language->sizer(), 0, wxEXPAND);
86 add_label_to_sizer (sizer, panel, _("Audio language"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
87 _audio_language = new LanguageTagWidget(
89 _("The main language that is spoken in the film's soundtrack"),
90 film()->audio_language()
92 sizer->Add (_audio_language->sizer(), 0, wxEXPAND);
94 _enable_main_subtitle_language = new wxCheckBox (panel, wxID_ANY, _("Main subtitle language"));
95 sizer->Add (_enable_main_subtitle_language, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP);
96 auto subtitle_languages = film()->subtitle_languages();
97 _main_subtitle_language = new LanguageTagWidget(
99 _("The main language that is displayed in the film's subtitles"),
100 subtitle_languages.empty() ? dcp::LanguageTag("en-US") : subtitle_languages.front()
102 sizer->Add (_main_subtitle_language->sizer(), 0, wxEXPAND);
105 int flags = wxALIGN_TOP | wxRIGHT | wxTOP;
107 flags |= wxALIGN_RIGHT;
109 auto m = create_label (panel, _("Additional subtitle languages"), true);
110 sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
113 vector<EditableListColumn> columns;
114 columns.push_back (EditableListColumn("Language", 250, true));
115 _additional_subtitle_languages = new EditableList<dcp::LanguageTag, LanguageTagDialog> (
118 boost::bind(&SMPTEMetadataDialog::additional_subtitle_languages, this),
119 boost::bind(&SMPTEMetadataDialog::set_additional_subtitle_languages, this, _1),
120 boost::bind(&additional_subtitle_language_column, _1, _2),
124 sizer->Add (_additional_subtitle_languages, 1, wxEXPAND);
127 int flags = wxALIGN_TOP | wxRIGHT | wxTOP;
129 flags |= wxALIGN_RIGHT;
131 auto m = create_label (panel, _("Ratings"), true);
132 sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
136 columns.push_back (EditableListColumn("Agency", 200, true));
137 columns.push_back (EditableListColumn("Label", 50, true));
138 _ratings = new EditableList<dcp::Rating, RatingDialog> (
141 boost::bind(&SMPTEMetadataDialog::ratings, this),
142 boost::bind(&SMPTEMetadataDialog::set_ratings, this, _1),
143 boost::bind(&ratings_column, _1, _2),
147 sizer->Add (_ratings, 1, wxEXPAND);
149 auto overall_sizer = new wxBoxSizer (wxVERTICAL);
150 overall_sizer->Add (sizer, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
151 panel->SetSizer (overall_sizer);
158 SMPTEMetadataDialog::advanced_panel (wxWindow* parent)
160 auto panel = new wxPanel (parent, wxID_ANY);
162 auto sizer = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
163 sizer->AddGrowableCol (1, 1);
165 _enable_release_territory = new wxCheckBox (panel, wxID_ANY, _("Release territory"));
166 sizer->Add (_enable_release_territory, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP);
168 auto s = new wxBoxSizer (wxHORIZONTAL);
169 _release_territory_text = new wxStaticText (panel, wxID_ANY, wxT(""));
170 s->Add (_release_territory_text, 1, wxLEFT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_X_GAP);
171 _edit_release_territory = new Button (panel, _("Edit..."));
172 s->Add (_edit_release_territory, 0, wxLEFT, DCPOMATIC_SIZER_GAP);
173 sizer->Add (s, 0, wxEXPAND);
176 add_label_to_sizer (sizer, panel, _("Version number"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
177 _version_number = new wxSpinCtrl (panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 1000);
178 sizer->Add (_version_number, 0);
180 add_label_to_sizer (sizer, panel, _("Status"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
181 _status = new wxChoice (panel, wxID_ANY);
182 sizer->Add (_status, 0);
184 _enable_chain = new wxCheckBox (panel, wxID_ANY, _("Chain"));
185 sizer->Add (_enable_chain, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
186 _chain = new wxTextCtrl (panel, wxID_ANY);
187 sizer->Add (_chain, 1, wxEXPAND);
189 _enable_distributor = new wxCheckBox (panel, wxID_ANY, _("Distributor"));
190 sizer->Add (_enable_distributor, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
191 _distributor = new wxTextCtrl (panel, wxID_ANY);
192 sizer->Add (_distributor, 1, wxEXPAND);
194 _enable_facility = new wxCheckBox (panel, wxID_ANY, _("Facility"));
195 sizer->Add (_enable_facility, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
196 _facility = new wxTextCtrl (panel, wxID_ANY);
197 sizer->Add (_facility, 1, wxEXPAND);
199 add_label_to_sizer (sizer, panel, _("Luminance"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
201 auto s = new wxBoxSizer (wxHORIZONTAL);
202 _luminance_value = new wxSpinCtrlDouble (panel, wxID_ANY);
203 _luminance_value->SetDigits (1);
204 _luminance_value->SetIncrement (0.1);
205 s->Add (_luminance_value, 0);
206 _luminance_unit = new wxChoice (panel, wxID_ANY);
207 s->Add (_luminance_unit, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
208 sizer->Add (s, 1, wxEXPAND);
212 int flags = wxALIGN_TOP | wxRIGHT | wxTOP;
214 flags |= wxALIGN_RIGHT;
216 auto m = create_label (panel, _("Content versions"), true);
217 sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
220 vector<EditableListColumn> columns;
221 columns.push_back (EditableListColumn("Version", 350, true));
222 _content_versions = new EditableList<string, ContentVersionDialog> (
225 boost::bind(&SMPTEMetadataDialog::content_versions, this),
226 boost::bind(&SMPTEMetadataDialog::set_content_versions, this, _1),
227 boost::bind(&content_versions_column, _1, _2),
231 sizer->Add (_content_versions, 1, wxEXPAND);
233 auto overall_sizer = new wxBoxSizer (wxVERTICAL);
234 overall_sizer->Add (sizer, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
235 panel->SetSizer (overall_sizer);
241 SMPTEMetadataDialog::SMPTEMetadataDialog (wxWindow* parent, weak_ptr<Film> weak_film)
242 : wxDialog (parent, wxID_ANY, _("Metadata"))
243 , WeakFilm (weak_film)
245 auto notebook = new wxNotebook (this, wxID_ANY);
246 notebook->AddPage (main_panel(notebook), _("Standard"));
247 notebook->AddPage (advanced_panel(notebook), _("Advanced"));
249 auto overall_sizer = new wxBoxSizer (wxVERTICAL);
250 overall_sizer->Add (notebook, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
252 auto buttons = CreateSeparatedButtonSizer (wxCLOSE);
254 overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
257 SetSizer (overall_sizer);
258 overall_sizer->Layout ();
259 overall_sizer->SetSizeHints (this);
261 _status->Append (_("Temporary"));
262 _status->Append (_("Pre-release"));
263 _status->Append (_("Final"));
265 _luminance_unit->Append (wxString::FromUTF8(_("candela per m²")));
266 _luminance_unit->Append (_("foot lambert"));
268 _name_language->Changed.connect (boost::bind(&SMPTEMetadataDialog::name_language_changed, this, _1));
269 _audio_language->Changed.connect (boost::bind(&SMPTEMetadataDialog::audio_language_changed, this, _1));
270 _enable_main_subtitle_language->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_main_subtitle_changed, this));
271 _edit_release_territory->Bind (wxEVT_BUTTON, boost::bind(&SMPTEMetadataDialog::edit_release_territory, this));
272 _main_subtitle_language->Changed.connect (boost::bind(&SMPTEMetadataDialog::main_subtitle_language_changed, this, _1));
273 _version_number->Bind (wxEVT_SPINCTRL, boost::bind(&SMPTEMetadataDialog::version_number_changed, this));
274 _status->Bind (wxEVT_CHOICE, boost::bind(&SMPTEMetadataDialog::status_changed, this));
275 _enable_chain->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_chain_changed, this));
276 _chain->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::chain_changed, this));
277 _enable_distributor->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_distributor_changed, this));
278 _distributor->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::distributor_changed, this));
279 _enable_facility->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_facility_changed, this));
280 _facility->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::facility_changed, this));
281 _luminance_value->Bind (wxEVT_SPINCTRLDOUBLE, boost::bind(&SMPTEMetadataDialog::luminance_changed, this));
282 _luminance_unit->Bind (wxEVT_CHOICE, boost::bind(&SMPTEMetadataDialog::luminance_changed, this));
283 _enable_release_territory->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_release_territory_changed, this));
285 _version_number->SetFocus ();
287 _film_changed_connection = film()->Change.connect(boost::bind(&SMPTEMetadataDialog::film_changed, this, _1, _2));
289 film_changed (ChangeType::DONE, Film::Property::NAME_LANGUAGE);
290 film_changed (ChangeType::DONE, Film::Property::RELEASE_TERRITORY);
291 film_changed (ChangeType::DONE, Film::Property::VERSION_NUMBER);
292 film_changed (ChangeType::DONE, Film::Property::STATUS);
293 film_changed (ChangeType::DONE, Film::Property::CHAIN);
294 film_changed (ChangeType::DONE, Film::Property::DISTRIBUTOR);
295 film_changed (ChangeType::DONE, Film::Property::FACILITY);
296 film_changed (ChangeType::DONE, Film::Property::CONTENT_VERSIONS);
297 film_changed (ChangeType::DONE, Film::Property::LUMINANCE);
298 film_changed (ChangeType::DONE, Film::Property::SUBTITLE_LANGUAGES);
300 setup_sensitivity ();
305 SMPTEMetadataDialog::film_changed (ChangeType type, Film::Property property)
307 if (type != ChangeType::DONE || film()->interop()) {
311 if (property == Film::Property::NAME_LANGUAGE) {
312 _name_language->set (film()->name_language());
313 } else if (property == Film::Property::RELEASE_TERRITORY) {
314 auto rt = film()->release_territory();
315 checked_set (_enable_release_territory, static_cast<bool>(rt));
317 _release_territory = *rt;
318 checked_set (_release_territory_text, std_to_wx(*dcp::LanguageTag::get_subtag_description(*_release_territory)));
320 } else if (property == Film::Property::VERSION_NUMBER) {
321 checked_set (_version_number, film()->version_number());
322 } else if (property == Film::Property::STATUS) {
323 switch (film()->status()) {
324 case dcp::Status::TEMP:
325 checked_set (_status, 0);
327 case dcp::Status::PRE:
328 checked_set (_status, 1);
330 case dcp::Status::FINAL:
331 checked_set (_status, 2);
334 } else if (property == Film::Property::CHAIN) {
335 checked_set (_enable_chain, static_cast<bool>(film()->chain()));
336 if (film()->chain()) {
337 checked_set (_chain, *film()->chain());
339 } else if (property == Film::Property::DISTRIBUTOR) {
340 checked_set (_enable_distributor, static_cast<bool>(film()->distributor()));
341 if (film()->distributor()) {
342 checked_set (_distributor, *film()->distributor());
344 } else if (property == Film::Property::FACILITY) {
345 checked_set (_enable_facility, static_cast<bool>(film()->facility()));
346 if (film()->facility()) {
347 checked_set (_facility, *film()->facility());
349 } else if (property == Film::Property::LUMINANCE) {
350 auto lum = film()->luminance();
352 checked_set (_luminance_value, lum->value());
353 switch (lum->unit()) {
354 case dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE:
355 checked_set (_luminance_unit, 0);
357 case dcp::Luminance::Unit::FOOT_LAMBERT:
358 checked_set (_luminance_unit, 1);
362 checked_set (_luminance_value, 4.5);
363 checked_set (_luminance_unit, 1);
365 } else if (property == Film::Property::SUBTITLE_LANGUAGES) {
366 auto languages = film()->subtitle_languages();
367 checked_set (_enable_main_subtitle_language, !languages.empty());
368 if (!languages.empty()) {
369 _main_subtitle_language->set (languages.front());
371 _main_subtitle_language->set (dcp::LanguageTag("en-US"));
378 SMPTEMetadataDialog::ratings () const
380 return film()->ratings ();
385 SMPTEMetadataDialog::set_ratings (vector<dcp::Rating> r)
387 film()->set_ratings (r);
392 SMPTEMetadataDialog::content_versions () const
394 return film()->content_versions ();
399 SMPTEMetadataDialog::set_content_versions (vector<string> cv)
401 film()->set_content_versions (cv);
406 SMPTEMetadataDialog::name_language_changed (dcp::LanguageTag tag)
408 film()->set_name_language (tag);
413 SMPTEMetadataDialog::audio_language_changed (dcp::LanguageTag tag)
415 film()->set_audio_language (tag);
420 SMPTEMetadataDialog::edit_release_territory ()
422 DCPOMATIC_ASSERT (film()->release_territory());
423 auto d = new RegionSubtagDialog(this, *film()->release_territory());
427 _release_territory = *tag;
428 film()->set_release_territory(*tag);
435 SMPTEMetadataDialog::version_number_changed ()
437 film()->set_version_number (_version_number->GetValue());
442 SMPTEMetadataDialog::status_changed ()
444 switch (_status->GetSelection()) {
446 film()->set_status(dcp::Status::TEMP);
449 film()->set_status(dcp::Status::PRE);
452 film()->set_status(dcp::Status::FINAL);
459 SMPTEMetadataDialog::chain_changed ()
461 film()->set_chain (wx_to_std(_chain->GetValue()));
466 SMPTEMetadataDialog::distributor_changed ()
468 film()->set_distributor (wx_to_std(_distributor->GetValue()));
473 SMPTEMetadataDialog::facility_changed ()
475 film()->set_facility (wx_to_std(_facility->GetValue()));
480 SMPTEMetadataDialog::luminance_changed ()
482 dcp::Luminance::Unit unit;
483 switch (_luminance_unit->GetSelection()) {
485 unit = dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE;
488 unit = dcp::Luminance::Unit::FOOT_LAMBERT;
491 DCPOMATIC_ASSERT (false);
494 film()->set_luminance (dcp::Luminance(_luminance_value->GetValue(), unit));
499 SMPTEMetadataDialog::enable_main_subtitle_changed ()
501 setup_sensitivity ();
502 if (_enable_main_subtitle_language->GetValue()) {
503 film()->set_subtitle_language (_main_subtitle_language->get());
505 set_additional_subtitle_languages (vector<dcp::LanguageTag>());
506 _additional_subtitle_languages->refresh ();
507 film()->unset_subtitle_language ();
513 SMPTEMetadataDialog::setup_sensitivity ()
516 auto const enabled = _enable_release_territory->GetValue();
517 _release_territory_text->Enable (enabled);
518 _edit_release_territory->Enable (enabled);
521 _chain->Enable (_enable_chain->GetValue());
522 _distributor->Enable (_enable_distributor->GetValue());
523 _facility->Enable (_enable_facility->GetValue());
526 auto const enabled = _enable_main_subtitle_language->GetValue();
527 _main_subtitle_language->enable (enabled);
528 _additional_subtitle_languages->Enable (enabled);
534 SMPTEMetadataDialog::main_subtitle_language_changed (dcp::LanguageTag tag)
536 auto existing = film()->subtitle_languages();
537 if (existing.empty()) {
538 existing.push_back (tag);
543 film()->set_subtitle_languages (existing);
547 vector<dcp::LanguageTag>
548 SMPTEMetadataDialog::additional_subtitle_languages ()
550 auto all = film()->subtitle_languages();
555 return vector<dcp::LanguageTag>(all.begin() + 1, all.end());
560 SMPTEMetadataDialog::set_additional_subtitle_languages (vector<dcp::LanguageTag> languages)
562 auto all = film()->subtitle_languages();
563 DCPOMATIC_ASSERT (!all.empty());
565 copy (languages.begin(), languages.end(), back_inserter(all));
566 film()->set_subtitle_languages (all);
571 SMPTEMetadataDialog::enable_release_territory_changed ()
573 setup_sensitivity ();
574 if (_enable_release_territory->GetValue()) {
575 film()->set_release_territory (_release_territory.get_value_or(dcp::LanguageTag::RegionSubtag("US")));
577 film()->set_release_territory ();
583 SMPTEMetadataDialog::enable_chain_changed ()
585 setup_sensitivity ();
586 if (_enable_chain->GetValue()) {
587 film()->set_chain (wx_to_std(_chain->GetValue()));
589 film()->set_chain ();
595 SMPTEMetadataDialog::enable_distributor_changed ()
597 setup_sensitivity ();
598 if (_enable_distributor->GetValue()) {
599 film()->set_distributor (wx_to_std(_distributor->GetValue()));
601 film()->set_distributor ();
607 SMPTEMetadataDialog::enable_facility_changed ()
609 setup_sensitivity ();
610 if (_enable_facility->GetValue()) {
611 film()->set_facility (wx_to_std(_facility->GetValue()));
613 film()->set_facility ();