2 Copyright (C) 2012-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 "advanced_dcp_settings_dialog.h"
23 #include "audio_dialog.h"
24 #include "check_box.h"
25 #include "check_box.h"
26 #include "dcp_panel.h"
27 #include "dcpomatic_button.h"
28 #include "dcpomatic_spin_ctrl.h"
29 #include "focus_manager.h"
30 #include "interop_metadata_dialog.h"
31 #include "language_tag_dialog.h"
32 #include "markers_dialog.h"
33 #include "smpte_metadata_dialog.h"
34 #include "static_text.h"
36 #include "lib/audio_content.h"
37 #include "lib/audio_processor.h"
38 #include "lib/config.h"
39 #include "lib/dcp_content.h"
40 #include "lib/dcp_content_type.h"
41 #include "lib/ffmpeg_content.h"
43 #include "lib/ratio.h"
44 #include "lib/scope_guard.h"
45 #include "lib/text_content.h"
47 #include "lib/video_content.h"
48 #include <dcp/locale_convert.h>
49 #include <dcp/warnings.h>
50 LIBDCP_DISABLE_WARNINGS
51 #include <wx/gbsizer.h>
52 #include <wx/notebook.h>
53 #include <wx/spinctrl.h>
55 LIBDCP_ENABLE_WARNINGS
56 #include <boost/lexical_cast.hpp>
63 using std::shared_ptr;
67 using boost::lexical_cast;
68 #if BOOST_VERSION >= 106100
69 using namespace boost::placeholders;
71 using dcp::locale_convert;
74 DCPPanel::DCPPanel (wxNotebook* n, shared_ptr<Film> film, weak_ptr<FilmViewer> viewer)
77 , _generally_sensitive (true)
79 _panel = new wxPanel (n);
80 _sizer = new wxBoxSizer (wxVERTICAL);
81 _panel->SetSizer (_sizer);
83 _grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
84 _sizer->Add (_grid, 0, wxEXPAND | wxALL, 8);
86 _name_label = create_label (_panel, _("Name"), true);
87 _name = new wxTextCtrl (_panel, wxID_ANY);
88 FocusManager::instance()->add(_name);
90 _use_isdcf_name = new CheckBox (_panel, _("Use ISDCF name"));
91 _copy_isdcf_name_button = new Button (_panel, _("Copy as name"));
93 /* wxST_ELLIPSIZE_MIDDLE works around a bug in GTK2 and/or wxWidgets, see
94 http://trac.wxwidgets.org/ticket/12539
96 _dcp_name = new StaticText (
97 _panel, wxT (""), wxDefaultPosition, wxDefaultSize,
98 wxALIGN_CENTRE_HORIZONTAL | wxST_NO_AUTORESIZE | wxST_ELLIPSIZE_MIDDLE
101 _enable_audio_language = new wxCheckBox (_panel, wxID_ANY, _("Audio language"));
102 _audio_language = new wxStaticText (_panel, wxID_ANY, wxT(""));
103 _edit_audio_language = new Button (_panel, _("Edit..."));
105 _dcp_content_type_label = create_label (_panel, _("Content Type"), true);
106 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
108 _encrypted = new CheckBox (_panel, _("Encrypted"));
110 wxClientDC dc (_panel);
111 auto size = dc.GetTextExtent (wxT ("GGGGGGGG..."));
114 _reels_label = create_label (_panel, _("Reels"), true);
115 _reel_type = new wxChoice (_panel, wxID_ANY);
117 _reel_length_label = create_label (_panel, _("Reel length"), true);
118 _reel_length = new SpinCtrl (_panel, DCPOMATIC_SPIN_CTRL_WIDTH);
119 _reel_length_gb_label = create_label (_panel, _("GB"), false);
121 _standard_label = create_label (_panel, _("Standard"), true);
122 _standard = new wxChoice (_panel, wxID_ANY);
124 _markers = new Button (_panel, _("Markers..."));
125 _metadata = new Button (_panel, _("Metadata..."));
126 _advanced = new Button(_panel, _("Advanced..."));
128 _notebook = new wxNotebook (_panel, wxID_ANY);
129 _sizer->Add (_notebook, 1, wxEXPAND | wxTOP, 6);
131 _notebook->AddPage (make_video_panel (), _("Video"), false);
132 _notebook->AddPage (make_audio_panel (), _("Audio"), false);
134 _name->Bind (wxEVT_TEXT, boost::bind(&DCPPanel::name_changed, this));
135 _use_isdcf_name->Bind (wxEVT_CHECKBOX, boost::bind(&DCPPanel::use_isdcf_name_toggled, this));
136 _copy_isdcf_name_button->Bind(wxEVT_BUTTON, boost::bind(&DCPPanel::copy_isdcf_name_button_clicked, this));
137 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind(&DCPPanel::dcp_content_type_changed, this));
138 _encrypted->Bind (wxEVT_CHECKBOX, boost::bind(&DCPPanel::encrypted_toggled, this));
139 _reel_type->Bind (wxEVT_CHOICE, boost::bind(&DCPPanel::reel_type_changed, this));
140 _reel_length->Bind (wxEVT_SPINCTRL, boost::bind(&DCPPanel::reel_length_changed, this));
141 _standard->Bind (wxEVT_CHOICE, boost::bind(&DCPPanel::standard_changed, this));
142 _markers->Bind (wxEVT_BUTTON, boost::bind(&DCPPanel::markers_clicked, this));
143 _metadata->Bind (wxEVT_BUTTON, boost::bind(&DCPPanel::metadata_clicked, this));
144 _advanced->Bind (wxEVT_BUTTON, boost::bind(&DCPPanel::advanced_clicked, this));
145 _enable_audio_language->Bind (wxEVT_CHECKBOX, boost::bind(&DCPPanel::enable_audio_language_toggled, this));
146 _edit_audio_language->Bind (wxEVT_BUTTON, boost::bind(&DCPPanel::edit_audio_language_clicked, this));
148 for (auto i: DCPContentType::all()) {
149 _dcp_content_type->Append (std_to_wx(i->pretty_name()));
152 _reel_type->Append (_("Single reel"));
153 _reel_type->Append (_("Split by video content"));
154 /// TRANSLATORS: translate the word "Custom" here; do not include the "Reel|" prefix
155 _reel_type->Append (S_("Reel|Custom"));
157 _reel_length->SetRange (1, 64);
159 _standard->Append (_("SMPTE"));
160 _standard->Append (_("Interop"));
162 Config::instance()->Changed.connect (boost::bind(&DCPPanel::config_changed, this, _1));
168 DCPPanel::add_to_grid ()
172 auto name_sizer = new wxBoxSizer (wxHORIZONTAL);
173 name_sizer->Add (_name_label, 0, wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_X_GAP);
174 name_sizer->Add (_name, 1, wxRIGHT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_X_GAP);
175 _grid->Add (name_sizer, wxGBPosition(r, 0), wxGBSpan(1, 2), wxRIGHT | wxEXPAND, DCPOMATIC_DIALOG_BORDER);
178 int flags = wxALIGN_CENTER_VERTICAL;
180 flags |= wxALIGN_RIGHT;
183 _grid->Add (_use_isdcf_name, wxGBPosition(r, 0), wxDefaultSpan, flags);
185 auto s = new wxBoxSizer (wxHORIZONTAL);
186 s->Add (_copy_isdcf_name_button, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
187 _grid->Add (s, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND | wxBOTTOM, DCPOMATIC_CHECKBOX_BOTTOM_PAD);
191 _grid->Add (_dcp_name, wxGBPosition(r, 0), wxGBSpan(1, 2), wxALIGN_CENTER_VERTICAL | wxEXPAND);
195 auto s = new wxBoxSizer (wxHORIZONTAL);
196 s->Add (_enable_audio_language, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, DCPOMATIC_SIZER_GAP);
197 s->Add (_audio_language, 1, wxALIGN_CENTER_VERTICAL | wxBOTTOM, DCPOMATIC_CHECKBOX_BOTTOM_PAD);
198 s->Add (_edit_audio_language, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, DCPOMATIC_CHECKBOX_BOTTOM_PAD);
199 _grid->Add (s, wxGBPosition(r, 0), wxGBSpan(1, 2), wxEXPAND | wxALIGN_CENTER_VERTICAL);
203 add_label_to_sizer (_grid, _dcp_content_type_label, true, wxGBPosition(r, 0));
204 _grid->Add (_dcp_content_type, wxGBPosition(r, 1));
207 _grid->Add (_encrypted, wxGBPosition(r, 0), wxGBSpan(1, 2));
210 add_label_to_sizer (_grid, _reels_label, true, wxGBPosition(r, 0));
211 _grid->Add (_reel_type, wxGBPosition(r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
214 add_label_to_sizer (_grid, _reel_length_label, true, wxGBPosition(r, 0));
216 auto s = new wxBoxSizer (wxHORIZONTAL);
217 s->Add (_reel_length);
218 add_label_to_sizer (s, _reel_length_gb_label, false, 0, wxLEFT | wxALIGN_CENTER_VERTICAL);
219 _grid->Add (s, wxGBPosition(r, 1));
223 add_label_to_sizer (_grid, _standard_label, true, wxGBPosition(r, 0));
224 _grid->Add (_standard, wxGBPosition(r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
227 auto extra = new wxBoxSizer (wxHORIZONTAL);
228 extra->Add (_markers, 1, wxRIGHT, DCPOMATIC_SIZER_X_GAP);
229 extra->Add (_metadata, 1, wxRIGHT, DCPOMATIC_SIZER_X_GAP);
230 extra->Add(_advanced, 1, wxRIGHT, DCPOMATIC_SIZER_X_GAP);
231 _grid->Add (extra, wxGBPosition(r, 0), wxGBSpan(1, 2));
237 DCPPanel::name_changed ()
243 _film->set_name (string(_name->GetValue().mb_str()));
248 DCPPanel::j2k_bandwidth_changed ()
254 _film->set_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
259 DCPPanel::encrypted_toggled ()
265 _film->set_encrypted (_encrypted->GetValue());
269 /** Called when the frame rate choice widget has been changed */
271 DCPPanel::frame_rate_choice_changed ()
277 _film->set_video_frame_rate (
278 boost::lexical_cast<int>(
279 wx_to_std(_frame_rate_choice->GetString(_frame_rate_choice->GetSelection()))
286 /** Called when the frame rate spin widget has been changed */
288 DCPPanel::frame_rate_spin_changed ()
294 _film->set_video_frame_rate (_frame_rate_spin->GetValue());
299 DCPPanel::audio_channels_changed ()
305 _film->set_audio_channels (locale_convert<int>(string_client_data(_audio_channels->GetClientObject(_audio_channels->GetSelection()))));
310 DCPPanel::resolution_changed ()
316 _film->set_resolution (_resolution->GetSelection() == 0 ? Resolution::TWO_K : Resolution::FOUR_K);
321 DCPPanel::standard_changed ()
327 _film->set_interop (_standard->GetSelection() == 1);
332 DCPPanel::markers_clicked ()
334 if (_markers_dialog) {
335 _markers_dialog->Destroy ();
336 _markers_dialog = nullptr;
339 _markers_dialog = new MarkersDialog (_panel, _film, _viewer);
340 _markers_dialog->Show();
345 DCPPanel::metadata_clicked ()
347 if (_film->interop()) {
348 if (_interop_metadata_dialog) {
349 _interop_metadata_dialog->Destroy ();
350 _interop_metadata_dialog = nullptr;
353 _interop_metadata_dialog = new InteropMetadataDialog (_panel, _film);
354 _interop_metadata_dialog->setup ();
355 _interop_metadata_dialog->Show ();
357 if (_smpte_metadata_dialog) {
358 _smpte_metadata_dialog->Destroy ();
359 _smpte_metadata_dialog = nullptr;
362 _smpte_metadata_dialog = new SMPTEMetadataDialog (_panel, _film);
363 _smpte_metadata_dialog->setup ();
364 _smpte_metadata_dialog->Show ();
370 DCPPanel::advanced_clicked()
372 auto dialog = new AdvancedDCPSettingsDialog(_panel, _film);
373 ScopeGuard sg = [dialog]() { dialog->Destroy(); };
375 if (dialog->ShowModal() == wxID_OK) {
376 _film->set_write_cpl_metadata(dialog->write_cpl_metadata());
382 DCPPanel::film_changed (Film::Property p)
385 case Film::Property::NONE:
387 case Film::Property::CONTAINER:
390 case Film::Property::NAME:
391 checked_set (_name, _film->name());
394 case Film::Property::DCP_CONTENT_TYPE:
396 auto index = DCPContentType::as_index(_film->dcp_content_type());
397 DCPOMATIC_ASSERT (index);
398 checked_set (_dcp_content_type, *index);
402 case Film::Property::ENCRYPTED:
403 checked_set (_encrypted, _film->encrypted ());
405 case Film::Property::RESOLUTION:
406 checked_set (_resolution, _film->resolution() == Resolution::TWO_K ? 0 : 1);
410 case Film::Property::J2K_BANDWIDTH:
411 checked_set (_j2k_bandwidth, _film->j2k_bandwidth() / 1000000);
413 case Film::Property::USE_ISDCF_NAME:
415 checked_set (_use_isdcf_name, _film->use_isdcf_name());
416 if (_film->use_isdcf_name()) {
417 /* We are going back to using an ISDCF name. Remove anything after a _ in the current name,
418 in case the user has clicked 'Copy as name' then re-ticked 'Use ISDCF name' (#1513).
420 string const name = _film->name ();
421 string::size_type const u = name.find("_");
422 if (u != string::npos) {
423 _film->set_name (name.substr(0, u));
429 case Film::Property::VIDEO_FRAME_RATE:
432 for (unsigned int i = 0; i < _frame_rate_choice->GetCount(); ++i) {
433 if (wx_to_std(_frame_rate_choice->GetString(i)) == boost::lexical_cast<string>(_film->video_frame_rate())) {
434 checked_set (_frame_rate_choice, i);
441 checked_set (_frame_rate_choice, -1);
444 checked_set (_frame_rate_spin, _film->video_frame_rate ());
446 _best_frame_rate->Enable (_film->best_video_frame_rate () != _film->video_frame_rate ());
450 case Film::Property::AUDIO_CHANNELS:
451 if (_film->audio_channels() < minimum_allowed_audio_channels()) {
452 _film->set_audio_channels (minimum_allowed_audio_channels());
454 checked_set (_audio_channels, locale_convert<string>(max(minimum_allowed_audio_channels(), _film->audio_channels())));
458 case Film::Property::THREE_D:
459 checked_set (_three_d, _film->three_d());
462 case Film::Property::REENCODE_J2K:
463 checked_set (_reencode_j2k, _film->reencode_j2k());
465 case Film::Property::INTEROP:
466 checked_set (_standard, _film->interop() ? 1 : 0);
468 _markers->Enable (!_film->interop());
470 case Film::Property::AUDIO_PROCESSOR:
471 if (_film->audio_processor()) {
472 checked_set (_audio_processor, _film->audio_processor()->id());
474 checked_set (_audio_processor, 0);
476 setup_audio_channels_choice (_audio_channels, minimum_allowed_audio_channels());
477 film_changed (Film::Property::AUDIO_CHANNELS);
479 case Film::Property::REEL_TYPE:
480 checked_set (_reel_type, static_cast<int>(_film->reel_type()));
481 _reel_length->Enable (_film->reel_type() == ReelType::BY_LENGTH);
483 case Film::Property::REEL_LENGTH:
484 checked_set (_reel_length, _film->reel_length() / 1000000000LL);
486 case Film::Property::CONTENT:
488 setup_sensitivity ();
490 case Film::Property::AUDIO_LANGUAGE:
492 auto al = _film->audio_language();
493 checked_set (_enable_audio_language, static_cast<bool>(al));
494 checked_set (_audio_language, al ? std_to_wx(al->to_string()) : wxT(""));
496 setup_sensitivity ();
499 case Film::Property::AUDIO_FRAME_RATE:
500 if (_audio_sample_rate) {
501 checked_set (_audio_sample_rate, _film->audio_frame_rate() == 48000 ? 0 : 1);
504 case Film::Property::CONTENT_VERSIONS:
505 case Film::Property::VERSION_NUMBER:
506 case Film::Property::RELEASE_TERRITORY:
507 case Film::Property::RATINGS:
508 case Film::Property::FACILITY:
509 case Film::Property::STUDIO:
510 case Film::Property::TEMP_VERSION:
511 case Film::Property::PRE_RELEASE:
512 case Film::Property::RED_BAND:
513 case Film::Property::TWO_D_VERSION_OF_THREE_D:
514 case Film::Property::CHAIN:
515 case Film::Property::LUMINANCE:
525 DCPPanel::film_content_changed (int property)
527 if (property == AudioContentProperty::STREAMS ||
528 property == TextContentProperty::USE ||
529 property == TextContentProperty::BURN ||
530 property == TextContentProperty::LANGUAGE ||
531 property == TextContentProperty::LANGUAGE_IS_ADDITIONAL ||
532 property == VideoContentProperty::CUSTOM_RATIO ||
533 property == VideoContentProperty::CUSTOM_SIZE ||
534 property == VideoContentProperty::BURNT_SUBTITLE_LANGUAGE ||
535 property == VideoContentProperty::CROP ||
536 property == DCPContentProperty::REFERENCE_VIDEO ||
537 property == DCPContentProperty::REFERENCE_AUDIO ||
538 property == DCPContentProperty::REFERENCE_TEXT) {
540 setup_sensitivity ();
546 DCPPanel::setup_container ()
549 auto ratios = Ratio::containers ();
550 auto i = ratios.begin ();
551 while (i != ratios.end() && *i != _film->container()) {
556 if (i == ratios.end()) {
557 checked_set (_container, -1);
558 checked_set (_container_size, wxT(""));
560 checked_set (_container, n);
561 auto const size = fit_ratio_within (_film->container()->ratio(), _film->full_frame ());
562 checked_set (_container_size, wxString::Format("%dx%d", size.width, size.height));
569 /** Called when the container widget has been changed */
571 DCPPanel::container_changed ()
577 int const n = _container->GetSelection ();
579 auto ratios = Ratio::containers ();
580 DCPOMATIC_ASSERT (n < int(ratios.size()));
581 _film->set_container (ratios[n]);
586 /** Called when the DCP content type widget has been changed */
588 DCPPanel::dcp_content_type_changed ()
594 int const n = _dcp_content_type->GetSelection ();
595 if (n != wxNOT_FOUND) {
596 _film->set_dcp_content_type (DCPContentType::from_index(n));
602 DCPPanel::set_film (shared_ptr<Film> film)
604 /* We are changing film, so destroy any dialogs for the old one */
606 _audio_dialog->Destroy ();
607 _audio_dialog = nullptr;
609 if (_markers_dialog) {
610 _markers_dialog->Destroy ();
611 _markers_dialog = nullptr;
613 if (_interop_metadata_dialog) {
614 _interop_metadata_dialog->Destroy ();
615 _interop_metadata_dialog = nullptr;
617 if (_smpte_metadata_dialog) {
618 _smpte_metadata_dialog->Destroy ();
619 _smpte_metadata_dialog = nullptr;
625 /* Really should all the film_changed below but this might be enough */
626 checked_set (_dcp_name, wxT(""));
627 set_general_sensitivity (false);
631 film_changed (Film::Property::NAME);
632 film_changed (Film::Property::USE_ISDCF_NAME);
633 film_changed (Film::Property::CONTENT);
634 film_changed (Film::Property::DCP_CONTENT_TYPE);
635 film_changed (Film::Property::CONTAINER);
636 film_changed (Film::Property::RESOLUTION);
637 film_changed (Film::Property::ENCRYPTED);
638 film_changed (Film::Property::J2K_BANDWIDTH);
639 film_changed (Film::Property::VIDEO_FRAME_RATE);
640 film_changed (Film::Property::AUDIO_CHANNELS);
641 film_changed (Film::Property::SEQUENCE);
642 film_changed (Film::Property::THREE_D);
643 film_changed (Film::Property::INTEROP);
644 film_changed (Film::Property::AUDIO_PROCESSOR);
645 film_changed (Film::Property::REEL_TYPE);
646 film_changed (Film::Property::REEL_LENGTH);
647 film_changed (Film::Property::REENCODE_J2K);
648 film_changed (Film::Property::AUDIO_LANGUAGE);
649 film_changed (Film::Property::AUDIO_FRAME_RATE);
651 set_general_sensitivity(static_cast<bool>(_film));
656 DCPPanel::set_general_sensitivity (bool s)
658 _generally_sensitive = s;
659 setup_sensitivity ();
664 DCPPanel::setup_sensitivity ()
666 _name->Enable (_generally_sensitive);
667 _use_isdcf_name->Enable (_generally_sensitive);
668 _dcp_content_type->Enable (_generally_sensitive);
669 _copy_isdcf_name_button->Enable (_generally_sensitive);
670 _enable_audio_language->Enable (_generally_sensitive);
671 _audio_language->Enable (_enable_audio_language->GetValue());
672 _edit_audio_language->Enable (_enable_audio_language->GetValue());
673 _encrypted->Enable (_generally_sensitive);
674 _reel_type->Enable (_generally_sensitive && _film && !_film->references_dcp_video() && !_film->references_dcp_audio());
675 _reel_length->Enable (_generally_sensitive && _film && _film->reel_type() == ReelType::BY_LENGTH);
676 _markers->Enable (_generally_sensitive && _film && !_film->interop());
677 _metadata->Enable (_generally_sensitive);
678 _frame_rate_choice->Enable (_generally_sensitive && _film && !_film->references_dcp_video() && !_film->contains_atmos_content());
679 _frame_rate_spin->Enable (_generally_sensitive && _film && !_film->references_dcp_video() && !_film->contains_atmos_content());
680 _audio_channels->Enable (_generally_sensitive && _film && !_film->references_dcp_audio() && !_film->contains_atmos_content());
681 _audio_processor->Enable (_generally_sensitive && _film && !_film->references_dcp_audio());
682 _j2k_bandwidth->Enable (_generally_sensitive && _film && !_film->references_dcp_video());
683 _container->Enable (_generally_sensitive && _film && !_film->references_dcp_video());
684 _best_frame_rate->Enable (
685 _generally_sensitive &&
687 _film->best_video_frame_rate () != _film->video_frame_rate() &&
688 !_film->references_dcp_video() &&
689 !_film->contains_atmos_content()
691 _resolution->Enable (_generally_sensitive && _film && !_film->references_dcp_video());
692 _three_d->Enable (_generally_sensitive && _film && !_film->references_dcp_video());
695 _generally_sensitive &&
697 !_film->references_dcp_video() &&
698 !_film->references_dcp_audio() &&
699 !_film->contains_atmos_content()
702 _reencode_j2k->Enable (_generally_sensitive && _film);
703 _show_audio->Enable (_generally_sensitive && _film);
708 DCPPanel::use_isdcf_name_toggled ()
714 _film->set_use_isdcf_name (_use_isdcf_name->GetValue());
718 DCPPanel::setup_dcp_name ()
720 _dcp_name->SetLabel (std_to_wx(_film->dcp_name(true)));
721 _dcp_name->SetToolTip (std_to_wx(_film->dcp_name(true)));
726 DCPPanel::best_frame_rate_clicked ()
732 _film->set_video_frame_rate (_film->best_video_frame_rate());
737 DCPPanel::three_d_changed ()
743 _film->set_three_d (_three_d->GetValue());
748 DCPPanel::reencode_j2k_changed ()
754 _film->set_reencode_j2k (_reencode_j2k->GetValue());
759 DCPPanel::config_changed (Config::Property p)
761 _j2k_bandwidth->SetRange (1, Config::instance()->maximum_j2k_bandwidth() / 1000000);
762 setup_frame_rate_widget ();
764 if (p == Config::SHOW_EXPERIMENTAL_AUDIO_PROCESSORS) {
765 _audio_processor->Clear ();
766 add_audio_processors ();
768 film_changed (Film::Property::AUDIO_PROCESSOR);
775 DCPPanel::setup_frame_rate_widget ()
777 if (Config::instance()->allow_any_dcp_frame_rate()) {
778 _frame_rate_choice->Hide ();
779 _frame_rate_spin->Show ();
781 _frame_rate_choice->Show ();
782 _frame_rate_spin->Hide ();
788 DCPPanel::make_video_panel ()
790 auto panel = new wxPanel (_notebook);
791 auto sizer = new wxBoxSizer (wxVERTICAL);
792 _video_grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
793 sizer->Add (_video_grid, 0, wxALL, 8);
794 panel->SetSizer (sizer);
796 _container_label = create_label (panel, _("Container"), true);
797 _container = new wxChoice (panel, wxID_ANY);
798 _container_size = new StaticText (panel, wxT (""));
800 _resolution_label = create_label (panel, _("Resolution"), true);
801 _resolution = new wxChoice (panel, wxID_ANY);
803 _frame_rate_label = create_label (panel, _("Frame Rate"), true);
804 _frame_rate_choice = new wxChoice (panel, wxID_ANY);
805 _frame_rate_spin = new SpinCtrl (panel, DCPOMATIC_SPIN_CTRL_WIDTH);
806 setup_frame_rate_widget ();
807 _best_frame_rate = new Button (panel, _("Use best"));
809 _three_d = new CheckBox (panel, _("3D"));
811 _j2k_bandwidth_label = create_label (panel, _("JPEG2000 bandwidth\nfor newly-encoded data"), true);
812 _j2k_bandwidth = new SpinCtrl (panel, DCPOMATIC_SPIN_CTRL_WIDTH);
813 _mbits_label = create_label (panel, _("Mbit/s"), false);
815 _reencode_j2k = new CheckBox (panel, _("Re-encode JPEG2000 data from input"));
817 _container->Bind (wxEVT_CHOICE, boost::bind(&DCPPanel::container_changed, this));
818 _frame_rate_choice->Bind (wxEVT_CHOICE, boost::bind(&DCPPanel::frame_rate_choice_changed, this));
819 _frame_rate_spin->Bind (wxEVT_SPINCTRL, boost::bind(&DCPPanel::frame_rate_spin_changed, this));
820 _best_frame_rate->Bind (wxEVT_BUTTON, boost::bind(&DCPPanel::best_frame_rate_clicked, this));
821 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind(&DCPPanel::j2k_bandwidth_changed, this));
822 /* Also listen to wxEVT_TEXT so that typing numbers directly in is always noticed */
823 _j2k_bandwidth->Bind (wxEVT_TEXT, boost::bind(&DCPPanel::j2k_bandwidth_changed, this));
824 _resolution->Bind (wxEVT_CHOICE, boost::bind(&DCPPanel::resolution_changed, this));
825 _three_d->Bind (wxEVT_CHECKBOX, boost::bind(&DCPPanel::three_d_changed, this));
826 _reencode_j2k->Bind (wxEVT_CHECKBOX, boost::bind(&DCPPanel::reencode_j2k_changed, this));
828 for (auto i: Ratio::containers()) {
829 _container->Append (std_to_wx(i->container_nickname()));
832 for (auto i: Config::instance()->allowed_dcp_frame_rates()) {
833 _frame_rate_choice->Append (std_to_wx (boost::lexical_cast<string> (i)));
836 _j2k_bandwidth->SetRange (1, Config::instance()->maximum_j2k_bandwidth() / 1000000);
837 _frame_rate_spin->SetRange (1, 480);
839 _resolution->Append (_("2K"));
840 _resolution->Append (_("4K"));
842 add_video_panel_to_grid ();
849 DCPPanel::add_video_panel_to_grid ()
853 add_label_to_sizer (_video_grid, _container_label, true, wxGBPosition (r, 0));
855 auto s = new wxBoxSizer (wxHORIZONTAL);
856 s->Add (_container, 1, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_X_GAP);
857 s->Add (_container_size, 1, wxLEFT | wxALIGN_CENTER_VERTICAL);
858 _video_grid->Add (s, wxGBPosition(r, 1));
862 add_label_to_sizer (_video_grid, _resolution_label, true, wxGBPosition (r, 0));
863 _video_grid->Add (_resolution, wxGBPosition (r, 1));
866 add_label_to_sizer (_video_grid, _frame_rate_label, true, wxGBPosition (r, 0));
868 _frame_rate_sizer = new wxBoxSizer (wxHORIZONTAL);
869 _frame_rate_sizer->Add (_frame_rate_choice, 1, wxALIGN_CENTER_VERTICAL);
870 _frame_rate_sizer->Add (_frame_rate_spin, 1, wxALIGN_CENTER_VERTICAL);
871 _frame_rate_sizer->Add (_best_frame_rate, 1, wxLEFT | wxALIGN_CENTER_VERTICAL, DCPOMATIC_SIZER_X_GAP);
872 _video_grid->Add (_frame_rate_sizer, wxGBPosition (r, 1));
876 _video_grid->Add (_three_d, wxGBPosition (r, 0), wxGBSpan (1, 2));
879 add_label_to_sizer (_video_grid, _j2k_bandwidth_label, true, wxGBPosition (r, 0));
880 auto s = new wxBoxSizer (wxHORIZONTAL);
881 s->Add (_j2k_bandwidth, 0, wxALIGN_CENTER_VERTICAL);
882 add_label_to_sizer (s, _mbits_label, false, 0, wxLEFT | wxALIGN_CENTER_VERTICAL);
883 _video_grid->Add (s, wxGBPosition(r, 1), wxDefaultSpan);
885 _video_grid->Add (_reencode_j2k, wxGBPosition(r, 0), wxGBSpan(1, 2));
890 DCPPanel::minimum_allowed_audio_channels () const
893 if (_film && _film->audio_processor ()) {
894 min = _film->audio_processor()->out_channels ();
906 DCPPanel::make_audio_panel ()
908 auto panel = new wxPanel (_notebook);
909 _audio_panel_sizer = new wxBoxSizer (wxVERTICAL);
910 _audio_grid = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
911 _audio_panel_sizer->Add (_audio_grid, 0, wxALL, 8);
912 panel->SetSizer (_audio_panel_sizer);
914 _channels_label = create_label (panel, _("Channels"), true);
915 _audio_channels = new wxChoice (panel, wxID_ANY);
916 setup_audio_channels_choice (_audio_channels, minimum_allowed_audio_channels ());
918 if (Config::instance()->allow_96khz_audio()) {
919 _audio_sample_rate_label = create_label (panel, _("Sample rate"), true);
920 _audio_sample_rate = new wxChoice (panel, wxID_ANY);
923 _processor_label = create_label (panel, _("Processor"), true);
924 _audio_processor = new wxChoice (panel, wxID_ANY);
925 add_audio_processors ();
927 _show_audio = new Button (panel, _("Show graph of audio levels..."));
929 _audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DCPPanel::audio_channels_changed, this));
930 if (_audio_sample_rate) {
931 _audio_sample_rate->Bind (wxEVT_CHOICE, boost::bind(&DCPPanel::audio_sample_rate_changed, this));
933 _audio_processor->Bind (wxEVT_CHOICE, boost::bind (&DCPPanel::audio_processor_changed, this));
934 _show_audio->Bind (wxEVT_BUTTON, boost::bind (&DCPPanel::show_audio_clicked, this));
936 if (_audio_sample_rate) {
937 _audio_sample_rate->Append (_("48kHz"));
938 _audio_sample_rate->Append (_("96kHz"));
941 add_audio_panel_to_grid ();
948 DCPPanel::add_audio_panel_to_grid ()
952 add_label_to_sizer (_audio_grid, _channels_label, true, wxGBPosition (r, 0));
953 _audio_grid->Add (_audio_channels, wxGBPosition (r, 1));
956 if (_audio_sample_rate_label && _audio_sample_rate) {
957 add_label_to_sizer (_audio_grid, _audio_sample_rate_label, true, wxGBPosition(r, 0));
958 _audio_grid->Add (_audio_sample_rate, wxGBPosition(r, 1));
962 add_label_to_sizer (_audio_grid, _processor_label, true, wxGBPosition (r, 0));
963 _audio_grid->Add (_audio_processor, wxGBPosition (r, 1));
966 _audio_grid->Add (_show_audio, wxGBPosition (r, 0), wxGBSpan (1, 2));
972 DCPPanel::copy_isdcf_name_button_clicked ()
974 _film->set_name (_film->isdcf_name (true));
975 _film->set_use_isdcf_name (false);
980 DCPPanel::audio_processor_changed ()
986 auto const s = string_client_data (_audio_processor->GetClientObject (_audio_processor->GetSelection ()));
987 _film->set_audio_processor (AudioProcessor::from_id (s));
992 DCPPanel::show_audio_clicked ()
999 _audio_dialog->Destroy ();
1000 _audio_dialog = nullptr;
1003 auto d = new AudioDialog (_panel, _film, _viewer);
1009 DCPPanel::reel_type_changed ()
1015 _film->set_reel_type (static_cast<ReelType>(_reel_type->GetSelection()));
1020 DCPPanel::reel_length_changed ()
1026 _film->set_reel_length (_reel_length->GetValue() * 1000000000LL);
1031 DCPPanel::add_audio_processors ()
1033 _audio_processor->Append (_("None"), new wxStringClientData(N_("none")));
1034 for (auto ap: AudioProcessor::visible()) {
1035 _audio_processor->Append (std_to_wx(ap->name()), new wxStringClientData(std_to_wx(ap->id())));
1037 _audio_panel_sizer->Layout();
1042 DCPPanel::enable_audio_language_toggled ()
1044 setup_sensitivity ();
1045 if (_enable_audio_language->GetValue()) {
1046 auto al = wx_to_std (_audio_language->GetLabel());
1047 _film->set_audio_language (al.empty() ? dcp::LanguageTag("en-US") : dcp::LanguageTag(al));
1049 _film->set_audio_language (boost::none);
1055 DCPPanel::edit_audio_language_clicked ()
1057 DCPOMATIC_ASSERT (_film->audio_language());
1058 auto d = new LanguageTagDialog (_panel, *_film->audio_language());
1059 if (d->ShowModal() == wxID_OK) {
1060 _film->set_audio_language(d->get());
1067 DCPPanel::audio_sample_rate_changed ()
1069 if (_audio_sample_rate) {
1070 _film->set_audio_frame_rate (_audio_sample_rate->GetSelection() == 0 ? 48000 : 96000);