a2e9d355adf5bab34c8e6c432ff76b1434707f13
[dcpomatic.git] / src / wx / smpte_metadata_dialog.cc
1 /*
2     Copyright (C) 2019-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
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.
10
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.
15
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/>.
18
19 */
20
21
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"
28 #include "lib/film.h"
29 #include <dcp/types.h>
30 #include <wx/gbsizer.h>
31 #include <wx/spinctrl.h>
32
33
34 using std::string;
35 using std::vector;
36 using boost::optional;
37 using std::shared_ptr;
38 using std::weak_ptr;
39 #if BOOST_VERSION >= 106100
40 using namespace boost::placeholders;
41 #endif
42
43
44 static string
45 ratings_column (dcp::Rating r, int c)
46 {
47         if (c == 0) {
48                 return r.agency;
49         }
50
51         return r.label;
52 }
53
54
55 static string
56 content_versions_column (string v, int)
57 {
58         return v;
59 }
60
61
62 void
63 SMPTEMetadataDialog::setup_standard (wxPanel* panel, wxSizer* sizer)
64 {
65         MetadataDialog::setup_standard (panel, sizer);
66
67         add_label_to_sizer (sizer, panel, _("Title language"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
68         _name_language = new LanguageTagWidget(
69                 panel,
70                 wxString::Format(_("The language that the film's title (\"%s\") is in"), std_to_wx(film()->name())),
71                 film()->name_language()
72                 );
73         sizer->Add (_name_language->sizer(), 0, wxEXPAND);
74
75         {
76                 int flags = wxALIGN_TOP | wxRIGHT | wxTOP;
77 #ifdef __WXOSX__
78                 flags |= wxALIGN_RIGHT;
79 #endif
80                 auto m = create_label (panel, _("Ratings"), true);
81                 sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
82         }
83
84         vector<EditableListColumn> columns;
85         columns.push_back (EditableListColumn("Agency", 200, true));
86         columns.push_back (EditableListColumn("Label", 50, true));
87         _ratings = new EditableList<dcp::Rating, RatingDialog> (
88                 panel,
89                 columns,
90                 boost::bind(&SMPTEMetadataDialog::ratings, this),
91                 boost::bind(&SMPTEMetadataDialog::set_ratings, this, _1),
92                 boost::bind(&ratings_column, _1, _2),
93                 true,
94                 false
95                 );
96         sizer->Add (_ratings, 1, wxEXPAND);
97 }
98
99
100 void
101 SMPTEMetadataDialog::setup_advanced (wxPanel* panel, wxSizer* sizer)
102 {
103         MetadataDialog::setup_advanced (panel, sizer);
104
105         _enable_release_territory = new wxCheckBox (panel, wxID_ANY, _("Release territory"));
106         sizer->Add (_enable_release_territory, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_GAP);
107         {
108                 auto s = new wxBoxSizer (wxHORIZONTAL);
109                 _release_territory_text = new wxStaticText (panel, wxID_ANY, wxT(""));
110                 s->Add (_release_territory_text, 1, wxLEFT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_X_GAP);
111                 _edit_release_territory = new Button (panel, _("Edit..."));
112                 s->Add (_edit_release_territory, 0, wxLEFT, DCPOMATIC_SIZER_GAP);
113                 sizer->Add (s, 0, wxEXPAND);
114         }
115
116         add_label_to_sizer (sizer, panel, _("Version number"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
117         _version_number = new wxSpinCtrl (panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, 1000);
118         sizer->Add (_version_number, 0);
119
120         add_label_to_sizer (sizer, panel, _("Status"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
121         _status = new wxChoice (panel, wxID_ANY);
122         sizer->Add (_status, 0);
123
124         _enable_chain = new wxCheckBox (panel, wxID_ANY, _("Chain"));
125         sizer->Add (_enable_chain, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
126         _chain = new wxTextCtrl (panel, wxID_ANY);
127         sizer->Add (_chain, 1, wxEXPAND);
128
129         _enable_distributor = new wxCheckBox (panel, wxID_ANY, _("Distributor"));
130         sizer->Add (_enable_distributor, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
131         _distributor = new wxTextCtrl (panel, wxID_ANY);
132         sizer->Add (_distributor, 1, wxEXPAND);
133
134         _enable_facility = new wxCheckBox (panel, wxID_ANY, _("Facility"));
135         sizer->Add (_enable_facility, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
136         _facility = new wxTextCtrl (panel, wxID_ANY);
137         sizer->Add (_facility, 1, wxEXPAND);
138
139         add_label_to_sizer (sizer, panel, _("Luminance"), true, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL);
140         {
141                 auto s = new wxBoxSizer (wxHORIZONTAL);
142                 _luminance_value = new wxSpinCtrlDouble (panel, wxID_ANY);
143                 _luminance_value->SetDigits (1);
144                 _luminance_value->SetIncrement (0.1);
145                 s->Add (_luminance_value, 0);
146                 _luminance_unit = new wxChoice (panel, wxID_ANY);
147                 s->Add (_luminance_unit, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
148                 sizer->Add (s, 1, wxEXPAND);
149         }
150
151         {
152                 int flags = wxALIGN_TOP | wxRIGHT | wxTOP;
153 #ifdef __WXOSX__
154                 flags |= wxALIGN_RIGHT;
155 #endif
156                 auto m = create_label (panel, _("Content versions"), true);
157                 sizer->Add (m, 0, flags, DCPOMATIC_SIZER_GAP);
158         }
159
160         vector<EditableListColumn> columns;
161         columns.push_back (EditableListColumn("Version", 350, true));
162         _content_versions = new EditableList<string, ContentVersionDialog> (
163                 panel,
164                 columns,
165                 boost::bind(&SMPTEMetadataDialog::content_versions, this),
166                 boost::bind(&SMPTEMetadataDialog::set_content_versions, this, _1),
167                 boost::bind(&content_versions_column, _1, _2),
168                 true,
169                 false
170                 );
171         sizer->Add (_content_versions, 1, wxEXPAND);
172 }
173
174
175 SMPTEMetadataDialog::SMPTEMetadataDialog (wxWindow* parent, weak_ptr<Film> weak_film)
176         : MetadataDialog (parent, weak_film)
177 {
178
179 }
180
181
182 void
183 SMPTEMetadataDialog::setup ()
184 {
185         MetadataDialog::setup ();
186
187         _status->Append (_("Temporary"));
188         _status->Append (_("Pre-release"));
189         _status->Append (_("Final"));
190
191         _luminance_unit->Append (wxString::FromUTF8(_("candela per m²")));
192         _luminance_unit->Append (_("foot lambert"));
193
194         _name_language->Changed.connect (boost::bind(&SMPTEMetadataDialog::name_language_changed, this, _1));
195         _edit_release_territory->Bind (wxEVT_BUTTON, boost::bind(&SMPTEMetadataDialog::edit_release_territory, this));
196         _version_number->Bind (wxEVT_SPINCTRL, boost::bind(&SMPTEMetadataDialog::version_number_changed, this));
197         _status->Bind (wxEVT_CHOICE, boost::bind(&SMPTEMetadataDialog::status_changed, this));
198         _enable_chain->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_chain_changed, this));
199         _chain->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::chain_changed, this));
200         _enable_distributor->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_distributor_changed, this));
201         _distributor->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::distributor_changed, this));
202         _enable_facility->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_facility_changed, this));
203         _facility->Bind (wxEVT_TEXT, boost::bind(&SMPTEMetadataDialog::facility_changed, this));
204         _luminance_value->Bind (wxEVT_SPINCTRLDOUBLE, boost::bind(&SMPTEMetadataDialog::luminance_changed, this));
205         _luminance_unit->Bind (wxEVT_CHOICE, boost::bind(&SMPTEMetadataDialog::luminance_changed, this));
206         _enable_release_territory->Bind (wxEVT_CHECKBOX, boost::bind(&SMPTEMetadataDialog::enable_release_territory_changed, this));
207
208         _film_changed_connection = film()->Change.connect(boost::bind(&SMPTEMetadataDialog::film_changed, this, _1, _2));
209
210         film_changed (ChangeType::DONE, Film::Property::NAME_LANGUAGE);
211         film_changed (ChangeType::DONE, Film::Property::RELEASE_TERRITORY);
212         film_changed (ChangeType::DONE, Film::Property::VERSION_NUMBER);
213         film_changed (ChangeType::DONE, Film::Property::STATUS);
214         film_changed (ChangeType::DONE, Film::Property::CHAIN);
215         film_changed (ChangeType::DONE, Film::Property::DISTRIBUTOR);
216         film_changed (ChangeType::DONE, Film::Property::FACILITY);
217         film_changed (ChangeType::DONE, Film::Property::CONTENT_VERSIONS);
218         film_changed (ChangeType::DONE, Film::Property::LUMINANCE);
219
220         setup_sensitivity ();
221 }
222
223
224 void
225 SMPTEMetadataDialog::film_changed (ChangeType type, Film::Property property)
226 {
227         if (type != ChangeType::DONE || film()->interop()) {
228                 return;
229         }
230
231         if (property == Film::Property::NAME_LANGUAGE) {
232                 _name_language->set (film()->name_language());
233         } else if (property == Film::Property::RELEASE_TERRITORY) {
234                 auto rt = film()->release_territory();
235                 checked_set (_enable_release_territory, static_cast<bool>(rt));
236                 if (rt) {
237                         _release_territory = *rt;
238                         checked_set (_release_territory_text, std_to_wx(*dcp::LanguageTag::get_subtag_description(*_release_territory)));
239                 }
240         } else if (property == Film::Property::VERSION_NUMBER) {
241                 checked_set (_version_number, film()->version_number());
242         } else if (property == Film::Property::STATUS) {
243                 switch (film()->status()) {
244                 case dcp::Status::TEMP:
245                         checked_set (_status, 0);
246                         break;
247                 case dcp::Status::PRE:
248                         checked_set (_status, 1);
249                         break;
250                 case dcp::Status::FINAL:
251                         checked_set (_status, 2);
252                         break;
253                 }
254         } else if (property == Film::Property::CHAIN) {
255                 checked_set (_enable_chain, static_cast<bool>(film()->chain()));
256                 if (film()->chain()) {
257                         checked_set (_chain, *film()->chain());
258                 }
259         } else if (property == Film::Property::DISTRIBUTOR) {
260                 checked_set (_enable_distributor, static_cast<bool>(film()->distributor()));
261                 if (film()->distributor()) {
262                         checked_set (_distributor, *film()->distributor());
263                 }
264         } else if (property == Film::Property::FACILITY) {
265                 checked_set (_enable_facility, static_cast<bool>(film()->facility()));
266                 if (film()->facility()) {
267                         checked_set (_facility, *film()->facility());
268                 }
269         } else if (property == Film::Property::LUMINANCE) {
270                 auto lum = film()->luminance();
271                 if (lum) {
272                         checked_set (_luminance_value, lum->value());
273                         switch (lum->unit()) {
274                         case dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE:
275                                 checked_set (_luminance_unit, 0);
276                                 break;
277                         case dcp::Luminance::Unit::FOOT_LAMBERT:
278                                 checked_set (_luminance_unit, 1);
279                                 break;
280                         }
281                 } else {
282                         checked_set (_luminance_value, 4.5);
283                         checked_set (_luminance_unit, 1);
284                 }
285         }
286 }
287
288
289 vector<dcp::Rating>
290 SMPTEMetadataDialog::ratings () const
291 {
292         return film()->ratings ();
293 }
294
295
296 void
297 SMPTEMetadataDialog::set_ratings (vector<dcp::Rating> r)
298 {
299         film()->set_ratings (r);
300 }
301
302
303 vector<string>
304 SMPTEMetadataDialog::content_versions () const
305 {
306         return film()->content_versions ();
307 }
308
309
310 void
311 SMPTEMetadataDialog::set_content_versions (vector<string> cv)
312 {
313         film()->set_content_versions (cv);
314 }
315
316
317 void
318 SMPTEMetadataDialog::name_language_changed (dcp::LanguageTag tag)
319 {
320         film()->set_name_language (tag);
321 }
322
323
324 void
325 SMPTEMetadataDialog::edit_release_territory ()
326 {
327         DCPOMATIC_ASSERT (film()->release_territory());
328         auto d = new RegionSubtagDialog(this, *film()->release_territory());
329         d->ShowModal ();
330         auto tag = d->get();
331         if (tag) {
332                 _release_territory = *tag;
333                 film()->set_release_territory(*tag);
334         }
335         d->Destroy ();
336 }
337
338
339 void
340 SMPTEMetadataDialog::version_number_changed ()
341 {
342         film()->set_version_number (_version_number->GetValue());
343 }
344
345
346 void
347 SMPTEMetadataDialog::status_changed ()
348 {
349         switch (_status->GetSelection()) {
350         case 0:
351                 film()->set_status(dcp::Status::TEMP);
352                 break;
353         case 1:
354                 film()->set_status(dcp::Status::PRE);
355                 break;
356         case 2:
357                 film()->set_status(dcp::Status::FINAL);
358                 break;
359         }
360 }
361
362
363 void
364 SMPTEMetadataDialog::chain_changed ()
365 {
366         film()->set_chain (wx_to_std(_chain->GetValue()));
367 }
368
369
370 void
371 SMPTEMetadataDialog::distributor_changed ()
372 {
373         film()->set_distributor (wx_to_std(_distributor->GetValue()));
374 }
375
376
377 void
378 SMPTEMetadataDialog::facility_changed ()
379 {
380         film()->set_facility (wx_to_std(_facility->GetValue()));
381 }
382
383
384 void
385 SMPTEMetadataDialog::luminance_changed ()
386 {
387         dcp::Luminance::Unit unit;
388         switch (_luminance_unit->GetSelection()) {
389         case 0:
390                 unit = dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE;
391                 break;
392         case 1:
393                 unit = dcp::Luminance::Unit::FOOT_LAMBERT;
394                 break;
395         default:
396                 DCPOMATIC_ASSERT (false);
397         }
398
399         film()->set_luminance (dcp::Luminance(_luminance_value->GetValue(), unit));
400 }
401
402
403 void
404 SMPTEMetadataDialog::setup_sensitivity ()
405 {
406         {
407                 auto const enabled = _enable_release_territory->GetValue();
408                 _release_territory_text->Enable (enabled);
409                 _edit_release_territory->Enable (enabled);
410         }
411
412         _chain->Enable (_enable_chain->GetValue());
413         _distributor->Enable (_enable_distributor->GetValue());
414         _facility->Enable (_enable_facility->GetValue());
415 }
416
417
418 void
419 SMPTEMetadataDialog::enable_release_territory_changed ()
420 {
421         setup_sensitivity ();
422         if (_enable_release_territory->GetValue()) {
423                 film()->set_release_territory (_release_territory.get_value_or(dcp::LanguageTag::RegionSubtag("US")));
424         } else {
425                 film()->set_release_territory ();
426         }
427 }
428
429
430 void
431 SMPTEMetadataDialog::enable_chain_changed ()
432 {
433         setup_sensitivity ();
434         if (_enable_chain->GetValue()) {
435                 film()->set_chain (wx_to_std(_chain->GetValue()));
436         } else {
437                 film()->set_chain ();
438         }
439 }
440
441
442 void
443 SMPTEMetadataDialog::enable_distributor_changed ()
444 {
445         setup_sensitivity ();
446         if (_enable_distributor->GetValue()) {
447                 film()->set_distributor (wx_to_std(_distributor->GetValue()));
448         } else {
449                 film()->set_distributor ();
450         }
451 }
452
453
454 void
455 SMPTEMetadataDialog::enable_facility_changed ()
456 {
457         setup_sensitivity ();
458         if (_enable_facility->GetValue()) {
459                 film()->set_facility (wx_to_std(_facility->GetValue()));
460         } else {
461                 film()->set_facility ();
462         }
463 }
464
465