2 Copyright (C) 2019-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/>.
21 #include "content_version_dialog.h"
22 #include "editable_list.h"
23 #include "language_tag_dialog.h"
24 #include "language_tag_widget.h"
25 #include "smpte_metadata_dialog.h"
26 #include "rating_dialog.h"
28 #include <dcp/types.h>
29 #include <wx/gbsizer.h>
30 #include <wx/spinctrl.h>
34 using boost::optional;
35 using std::shared_ptr;
37 #if BOOST_VERSION >= 106100
38 using namespace boost::placeholders;
43 additional_subtitle_language_column (dcp::LanguageTag r, int)
50 ratings_column (dcp::Rating r, int c)
61 content_versions_column (string v, int)
67 SMPTEMetadataDialog::SMPTEMetadataDialog (wxWindow* parent, weak_ptr<Film> weak_film)
68 : wxDialog (parent, wxID_ANY, _("Metadata"))
69 , WeakFilm (weak_film)
71 wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
72 SetSizer (overall_sizer);
74 wxFlexGridSizer* sizer = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
75 sizer->AddGrowableCol (1, 1);
77 add_label_to_sizer (sizer, this, _("Title language"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL);
78 _name_language = new LanguageTagWidget(
80 wxString::Format(_("The language that the film's title (\"%s\") is in"), std_to_wx(film()->name())),
81 film()->name_language()
83 sizer->Add (_name_language->sizer(), 0, wxEXPAND);
85 add_label_to_sizer (sizer, this, _("Audio language"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL);
86 _audio_language = new LanguageTagWidget(
88 _("The main language that is spoken in the film's soundtrack"),
89 film()->audio_language()
91 sizer->Add (_audio_language->sizer(), 0, wxEXPAND);
93 _enable_main_subtitle_language = new wxCheckBox (this, wxID_ANY, _("Main subtitle language"));
94 sizer->Add (_enable_main_subtitle_language, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP);
95 vector<dcp::LanguageTag> subtitle_languages = film()->subtitle_languages();
96 _main_subtitle_language = new LanguageTagWidget(
98 _("The main language that is displayed in the film's subtitles"),
99 subtitle_languages.empty() ? dcp::LanguageTag("en-US") : subtitle_languages.front()
101 sizer->Add (_main_subtitle_language->sizer(), 0, wxEXPAND);
104 int flags = wxALIGN_TOP | wxLEFT | wxRIGHT | wxTOP;
106 flags |= wxALIGN_RIGHT;
108 wxStaticText* m = create_label (this, _("Additional subtitle languages"), true);
109 sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
112 vector<EditableListColumn> columns;
113 columns.push_back (EditableListColumn("Language", 250, true));
114 _additional_subtitle_languages = new EditableList<dcp::LanguageTag, LanguageTagDialog> (
117 boost::bind(&SMPTEMetadataDialog::additional_subtitle_languages, this),
118 boost::bind(&SMPTEMetadataDialog::set_additional_subtitle_languages, this, _1),
119 boost::bind(&additional_subtitle_language_column, _1, _2),
123 sizer->Add (_additional_subtitle_languages, 1, wxEXPAND);
125 Button* edit_release_territory = 0;
126 add_label_to_sizer (sizer, this, _("Release territory"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL);
128 wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
129 _release_territory = new wxStaticText (this, wxID_ANY, wxT(""));
130 s->Add (_release_territory, 1, wxLEFT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_X_GAP);
131 edit_release_territory = new Button (this, _("Edit..."));
132 s->Add (edit_release_territory, 0, wxLEFT, DCPOMATIC_SIZER_GAP);
133 sizer->Add (s, 0, wxEXPAND);
136 add_label_to_sizer (sizer, this, _("Version number"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL);
137 _version_number = new wxSpinCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 1000);
138 sizer->Add (_version_number, 0);
140 add_label_to_sizer (sizer, this, _("Status"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL);
141 _status = new wxChoice (this, wxID_ANY);
142 sizer->Add (_status, 0);
144 add_label_to_sizer (sizer, this, _("Chain"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL);
145 _chain = new wxTextCtrl (this, wxID_ANY);
146 sizer->Add (_chain, 1, wxEXPAND);
148 add_label_to_sizer (sizer, this, _("Distributor"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL);
149 _distributor = new wxTextCtrl (this, wxID_ANY);
150 sizer->Add (_distributor, 1, wxEXPAND);
152 add_label_to_sizer (sizer, this, _("Facility"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL);
153 _facility = new wxTextCtrl (this, wxID_ANY);
154 sizer->Add (_facility, 1, wxEXPAND);
156 add_label_to_sizer (sizer, this, _("Luminance"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL);
158 wxSizer* s = new wxBoxSizer (wxHORIZONTAL);
159 _luminance_value = new wxSpinCtrlDouble (this, wxID_ANY);
160 _luminance_value->SetDigits (1);
161 _luminance_value->SetIncrement (0.1);
162 s->Add (_luminance_value, 0);
163 _luminance_unit = new wxChoice (this, wxID_ANY);
164 s->Add (_luminance_unit, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
165 sizer->Add (s, 1, wxEXPAND);
169 int flags = wxALIGN_TOP | wxLEFT | wxRIGHT | wxTOP;
171 flags |= wxALIGN_RIGHT;
173 wxStaticText* m = create_label (this, _("Ratings"), true);
174 sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
178 columns.push_back (EditableListColumn("Agency", 200, true));
179 columns.push_back (EditableListColumn("Label", 50, true));
180 _ratings = new EditableList<dcp::Rating, RatingDialog> (
183 boost::bind(&SMPTEMetadataDialog::ratings, this),
184 boost::bind(&SMPTEMetadataDialog::set_ratings, this, _1),
185 boost::bind(&ratings_column, _1, _2),
189 sizer->Add (_ratings, 1, wxEXPAND);
192 int flags = wxALIGN_TOP | wxLEFT | wxRIGHT | wxTOP;
194 flags |= wxALIGN_RIGHT;
196 wxStaticText* m = create_label (this, _("Content versions"), true);
197 sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
201 columns.push_back (EditableListColumn("Version", 350, true));
202 _content_versions = new EditableList<string, ContentVersionDialog> (
205 boost::bind(&SMPTEMetadataDialog::content_versions, this),
206 boost::bind(&SMPTEMetadataDialog::set_content_versions, this, _1),
207 boost::bind(&content_versions_column, _1, _2),
211 sizer->Add (_content_versions, 1, wxEXPAND);
213 overall_sizer->Add (sizer, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
215 wxSizer* buttons = CreateSeparatedButtonSizer (wxCLOSE);
217 overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
220 overall_sizer->Layout ();
221 overall_sizer->SetSizeHints (this);
223 _status->Append (_("Temporary"));
224 _status->Append (_("Pre-release"));
225 _status->Append (_("Final"));
227 _luminance_unit->Append (_("candela per m²"));
228 _luminance_unit->Append (_("foot lambert"));
230 _name_language->Changed.connect (boost::bind(&SMPTEMetadataDialog::name_language_changed, this, _1));
231 _audio_language->Changed.connect (boost::bind(&SMPTEMetadataDialog::audio_language_changed, this, _1));
232 _enable_main_subtitle_language->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_main_subtitle_changed, this));
233 _main_subtitle_language->Changed.connect (boost::bind(&SMPTEMetadataDialog::main_subtitle_language_changed, this, _1));
234 edit_release_territory->Bind (wxEVT_BUTTON, boost::bind(&SMPTEMetadataDialog::edit_release_territory, this));
235 _version_number->Bind (wxEVT_SPINCTRL, boost::bind(&SMPTEMetadataDialog::version_number_changed, this));
236 _status->Bind (wxEVT_CHOICE, boost::bind(&SMPTEMetadataDialog::status_changed, this));
237 _chain->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::chain_changed, this));
238 _distributor->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::distributor_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));
243 _version_number->SetFocus ();
245 _film_changed_connection = film()->Change.connect(boost::bind(&SMPTEMetadataDialog::film_changed, this, _1, _2));
247 film_changed (ChangeType::DONE, Film::Property::NAME_LANGUAGE);
248 film_changed (ChangeType::DONE, Film::Property::RELEASE_TERRITORY);
249 film_changed (ChangeType::DONE, Film::Property::VERSION_NUMBER);
250 film_changed (ChangeType::DONE, Film::Property::STATUS);
251 film_changed (ChangeType::DONE, Film::Property::CHAIN);
252 film_changed (ChangeType::DONE, Film::Property::DISTRIBUTOR);
253 film_changed (ChangeType::DONE, Film::Property::FACILITY);
254 film_changed (ChangeType::DONE, Film::Property::CONTENT_VERSIONS);
255 film_changed (ChangeType::DONE, Film::Property::LUMINANCE);
256 film_changed (ChangeType::DONE, Film::Property::SUBTITLE_LANGUAGES);
258 setup_sensitivity ();
263 SMPTEMetadataDialog::film_changed (ChangeType type, Film::Property property)
265 if (type != ChangeType::DONE || film()->interop()) {
269 if (property == Film::Property::NAME_LANGUAGE) {
270 _name_language->set (film()->name_language());
271 } else if (property == Film::Property::RELEASE_TERRITORY) {
272 checked_set (_release_territory, std_to_wx(*dcp::LanguageTag::get_subtag_description(dcp::LanguageTag::SubtagType::REGION, film()->release_territory().subtag())));
273 } else if (property == Film::Property::VERSION_NUMBER) {
274 checked_set (_version_number, film()->version_number());
275 } else if (property == Film::Property::STATUS) {
276 switch (film()->status()) {
277 case dcp::Status::TEMP:
278 checked_set (_status, 0);
280 case dcp::Status::PRE:
281 checked_set (_status, 1);
283 case dcp::Status::FINAL:
284 checked_set (_status, 2);
287 } else if (property == Film::Property::CHAIN) {
288 checked_set (_chain, film()->chain());
289 } else if (property == Film::Property::DISTRIBUTOR) {
290 checked_set (_distributor, film()->distributor());
291 } else if (property == Film::Property::FACILITY) {
292 checked_set (_facility, film()->facility());
293 } else if (property == Film::Property::LUMINANCE) {
294 checked_set (_luminance_value, film()->luminance().value());
295 switch (film()->luminance().unit()) {
296 case dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE:
297 checked_set (_luminance_unit, 0);
299 case dcp::Luminance::Unit::FOOT_LAMBERT:
300 checked_set (_luminance_unit, 1);
303 } else if (property == Film::Property::SUBTITLE_LANGUAGES) {
304 vector<dcp::LanguageTag> languages = film()->subtitle_languages();
305 checked_set (_enable_main_subtitle_language, !languages.empty());
306 if (!languages.empty()) {
307 _main_subtitle_language->set (languages.front());
309 _main_subtitle_language->set (dcp::LanguageTag("en-US"));
316 SMPTEMetadataDialog::ratings () const
318 return film()->ratings ();
323 SMPTEMetadataDialog::set_ratings (vector<dcp::Rating> r)
325 film()->set_ratings (r);
330 SMPTEMetadataDialog::content_versions () const
332 return film()->content_versions ();
337 SMPTEMetadataDialog::set_content_versions (vector<string> cv)
339 film()->set_content_versions (cv);
344 SMPTEMetadataDialog::name_language_changed (dcp::LanguageTag tag)
346 film()->set_name_language (tag);
351 SMPTEMetadataDialog::audio_language_changed (dcp::LanguageTag tag)
353 film()->set_audio_language (tag);
358 SMPTEMetadataDialog::edit_release_territory ()
360 auto d = new RegionSubtagDialog(this, film()->release_territory());
364 film()->set_release_territory(*tag);
371 SMPTEMetadataDialog::version_number_changed ()
373 film()->set_version_number (_version_number->GetValue());
378 SMPTEMetadataDialog::status_changed ()
380 switch (_status->GetSelection()) {
382 film()->set_status(dcp::Status::TEMP);
385 film()->set_status(dcp::Status::PRE);
388 film()->set_status(dcp::Status::FINAL);
395 SMPTEMetadataDialog::chain_changed ()
397 film()->set_chain (wx_to_std(_chain->GetValue()));
402 SMPTEMetadataDialog::distributor_changed ()
404 film()->set_distributor (wx_to_std(_distributor->GetValue()));
409 SMPTEMetadataDialog::facility_changed ()
411 film()->set_facility (wx_to_std(_facility->GetValue()));
416 SMPTEMetadataDialog::luminance_changed ()
418 dcp::Luminance::Unit unit;
419 switch (_luminance_unit->GetSelection()) {
421 unit = dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE;
424 unit = dcp::Luminance::Unit::FOOT_LAMBERT;
427 DCPOMATIC_ASSERT (false);
430 film()->set_luminance (dcp::Luminance(_luminance_value->GetValue(), unit));
435 SMPTEMetadataDialog::enable_main_subtitle_changed ()
437 setup_sensitivity ();
438 bool enabled = _enable_main_subtitle_language->GetValue ();
440 film()->set_subtitle_language (_main_subtitle_language->get());
442 set_additional_subtitle_languages (vector<dcp::LanguageTag>());
443 _additional_subtitle_languages->refresh ();
444 film()->unset_subtitle_language ();
450 SMPTEMetadataDialog::setup_sensitivity ()
452 bool const enabled = _enable_main_subtitle_language->GetValue ();
453 _main_subtitle_language->enable (enabled);
454 _additional_subtitle_languages->Enable (enabled);
459 SMPTEMetadataDialog::main_subtitle_language_changed (dcp::LanguageTag tag)
461 vector<dcp::LanguageTag> existing = film()->subtitle_languages();
462 if (existing.empty()) {
463 existing.push_back (tag);
468 film()->set_subtitle_languages (existing);
472 vector<dcp::LanguageTag>
473 SMPTEMetadataDialog::additional_subtitle_languages ()
475 vector<dcp::LanguageTag> all = film()->subtitle_languages();
480 return vector<dcp::LanguageTag>(all.begin() + 1, all.end());
485 SMPTEMetadataDialog::set_additional_subtitle_languages (vector<dcp::LanguageTag> languages)
487 vector<dcp::LanguageTag> all = film()->subtitle_languages();
488 DCPOMATIC_ASSERT (!all.empty());
490 copy (languages.begin(), languages.end(), back_inserter(all));
491 film()->set_subtitle_languages (all);