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 /** @file src/full_config_dialog.cc
23 * @brief A dialogue to edit all DCP-o-matic configuration.
27 #include "check_box.h"
28 #include "config_dialog.h"
29 #include "config_move_dialog.h"
30 #include "dcpomatic_button.h"
31 #include "dcpomatic_choice.h"
32 #include "dir_picker_ctrl.h"
33 #include "editable_list.h"
34 #include "email_dialog.h"
35 #include "file_picker_ctrl.h"
36 #include "filter_dialog.h"
37 #include "full_config_dialog.h"
38 #include "kdm_choice.h"
39 #include "language_tag_widget.h"
40 #include "make_chain_dialog.h"
41 #include "nag_dialog.h"
42 #include "name_format_editor.h"
43 #include "password_entry.h"
44 #include "region_subtag_widget.h"
45 #include "send_test_email_dialog.h"
46 #include "server_dialog.h"
47 #include "static_text.h"
49 #include "grok/gpu_config_panel.h"
52 #include "wx_variant.h"
53 #include "lib/config.h"
54 #include "lib/cross.h"
55 #include "lib/email.h"
56 #include "lib/exceptions.h"
57 #include "lib/filter.h"
59 #include "lib/ratio.h"
61 #include <dcp/certificate_chain.h>
62 #include <dcp/exceptions.h>
63 #include <dcp/filesystem.h>
64 #include <dcp/locale_convert.h>
65 #include <dcp/warnings.h>
66 LIBDCP_DISABLE_WARNINGS
67 #include <wx/filepicker.h>
68 #include <wx/preferences.h>
69 #include <wx/spinctrl.h>
70 #include <wx/stdpaths.h>
71 LIBDCP_ENABLE_WARNINGS
73 #include <boost/filesystem.hpp>
83 using std::shared_ptr;
87 using boost::optional;
88 #if BOOST_VERSION >= 106100
89 using namespace boost::placeholders;
91 using dcp::locale_convert;
94 class FullGeneralPage : public GeneralPage
97 FullGeneralPage (wxSize panel_size, int border)
98 : GeneralPage (panel_size, border)
102 void setup () override
104 auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
105 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
108 add_language_controls (table, r);
110 add_label_to_sizer(table, _panel, variant::wx::insert_dcpomatic(_("Number of threads %s should use")), true, wxGBPosition(r, 0));
111 _master_encoding_threads = new wxSpinCtrl (_panel);
112 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
115 add_label_to_sizer(table, _panel, variant::wx::insert_dcpomatic_encode_server(_("Number of threads %s should use")), true, wxGBPosition(r, 0));
116 _server_encoding_threads = new wxSpinCtrl (_panel);
117 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
120 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
121 _config_file = new FilePickerCtrl(_panel, _("Select configuration file"), "*.xml", true, false, "ConfigFilePath");
122 table->Add (_config_file, wxGBPosition (r, 1));
125 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
126 _cinemas_file = new FilePickerCtrl(_panel, _("Select cinema and screen database file"), "*.xml", true, false, "CinemaDatabasePath");
127 table->Add (_cinemas_file, wxGBPosition (r, 1));
128 auto export_cinemas = new Button (_panel, _("Export..."));
129 table->Add (export_cinemas, wxGBPosition (r, 2));
132 add_label_to_sizer(table, _panel, _("Default \"add file\" location"), true, wxGBPosition(r, 0));
133 _default_add_file_location = new Choice(_panel);
134 table->Add(_default_add_file_location, wxGBPosition(r, 1));
137 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
138 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
139 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
143 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
144 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
147 add_update_controls (table, r);
149 _default_add_file_location->add_entry(_("Same place as last time"));
150 _default_add_file_location->add_entry(_("Same place as project"));
151 _default_add_file_location->bind(&FullGeneralPage::default_add_file_location_changed, this);
153 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::config_file_changed, this));
154 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::cinemas_file_changed, this));
156 _master_encoding_threads->SetRange (1, 128);
157 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
158 _server_encoding_threads->SetRange (1, 128);
159 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
160 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
162 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
163 _analyse_ebur128->bind(&FullGeneralPage::analyse_ebur128_changed, this);
165 _automatic_audio_analysis->bind(&FullGeneralPage::automatic_audio_analysis_changed, this);
168 void config_changed () override
170 auto config = Config::instance ();
172 checked_set (_master_encoding_threads, config->master_encoding_threads ());
173 checked_set (_server_encoding_threads, config->server_encoding_threads ());
174 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
175 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
177 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
178 checked_set (_config_file, config->config_read_file());
179 checked_set (_cinemas_file, config->cinemas_file());
180 checked_set(_default_add_file_location, config->default_add_file_location() == Config::DefaultAddFileLocation::SAME_AS_LAST_TIME ? 0 : 1);
182 GeneralPage::config_changed ();
185 void export_cinemas_file ()
188 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT("XML files (*.xml)|*.xml"),
189 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
192 if (dialog.ShowModal() == wxID_OK) {
193 dcp::filesystem::copy_file(Config::instance()->cinemas_file(), wx_to_std(dialog.GetPath()), boost::filesystem::copy_option::overwrite_if_exists);
197 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
198 void analyse_ebur128_changed ()
200 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue());
204 void automatic_audio_analysis_changed ()
206 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue());
209 void master_encoding_threads_changed ()
211 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue());
214 void server_encoding_threads_changed ()
216 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue());
219 void config_file_changed ()
221 auto config = Config::instance();
222 auto const new_file = _config_file->path();
223 if (!new_file || *new_file == config->config_read_file()) {
226 bool copy_and_link = true;
227 if (dcp::filesystem::exists(*new_file)) {
228 ConfigMoveDialog dialog(_panel, *new_file);
229 if (dialog.ShowModal() == wxID_OK) {
230 copy_and_link = false;
236 if (new_file != config->config_read_file()) {
237 config->copy_and_link(*new_file);
240 config->link(*new_file);
244 void cinemas_file_changed ()
246 if (auto path = _cinemas_file->path()) {
247 Config::instance()->set_cinemas_file(*path);
251 void default_add_file_location_changed()
253 Config::instance()->set_default_add_file_location(
254 _default_add_file_location->get().get_value_or(0) == 0 ? Config::DefaultAddFileLocation::SAME_AS_LAST_TIME : Config::DefaultAddFileLocation::SAME_AS_PROJECT
258 Choice* _default_add_file_location;
259 wxSpinCtrl* _master_encoding_threads;
260 wxSpinCtrl* _server_encoding_threads;
261 FilePickerCtrl* _config_file;
262 FilePickerCtrl* _cinemas_file;
263 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
264 CheckBox* _analyse_ebur128;
266 CheckBox* _automatic_audio_analysis;
270 class DefaultsPage : public Page
273 DefaultsPage (wxSize panel_size, int border)
274 : Page (panel_size, border)
277 wxString GetName () const override
279 return _("Defaults");
283 wxBitmap GetLargeIcon () const override
285 return wxBitmap(icon_path("defaults"), wxBITMAP_TYPE_PNG);
290 void setup () override
292 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
293 table->AddGrowableCol (1, 1);
294 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
297 add_label_to_sizer (table, _panel, _("Default duration of still images"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
298 auto s = new wxBoxSizer (wxHORIZONTAL);
299 _still_length = new wxSpinCtrl (_panel);
300 s->Add (_still_length);
301 add_label_to_sizer (s, _panel, _("s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
305 add_label_to_sizer (table, _panel, _("Default directory for new films"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
306 #ifdef DCPOMATIC_USE_OWN_PICKER
307 _directory = new DirPickerCtrl (_panel);
309 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
311 table->Add (_directory, 1, wxEXPAND);
314 add_label_to_sizer(table, _panel, _("Default JPEG2000 bit rate"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
315 auto s = new wxBoxSizer (wxHORIZONTAL);
316 _j2k_video_bit_rate = new wxSpinCtrl(_panel);
317 s->Add(_j2k_video_bit_rate);
318 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
323 add_label_to_sizer(table, _panel, _("Default MPEG2 bit rate"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
324 auto s = new wxBoxSizer (wxHORIZONTAL);
325 _mpeg2_video_bit_rate = new wxSpinCtrl(_panel);
326 s->Add(_mpeg2_video_bit_rate);
327 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
332 add_label_to_sizer (table, _panel, _("Default audio delay"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
333 auto s = new wxBoxSizer (wxHORIZONTAL);
334 _audio_delay = new wxSpinCtrl (_panel);
335 s->Add (_audio_delay);
336 add_label_to_sizer (s, _panel, _("ms"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
340 add_label_to_sizer (table, _panel, _("Default standard"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
341 _standard = new wxChoice (_panel, wxID_ANY);
342 table->Add (_standard);
344 _enable_audio_language = new CheckBox(_panel, _("Default audio language"));
345 table->Add(_enable_audio_language, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
346 _audio_language = new LanguageTagWidget(_panel, _("Default audio language to use for new DCPs"), Config::instance()->default_audio_language(), wxString("cmnr-Hant-"));
347 table->Add(_audio_language->sizer());
349 _enable_territory = new CheckBox(_panel, _("Default territory"));
350 table->Add(_enable_territory, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
351 _territory = new RegionSubtagWidget(_panel, _("Default territory to use for new DCPs"), Config::instance()->default_territory(), wxString("cmnr-Hant-"));
352 table->Add(_territory->sizer());
354 table->Add (_enable_metadata["facility"] = new CheckBox (_panel, _("Default facility")), 0, wxALIGN_CENTRE_VERTICAL);
355 table->Add (_metadata["facility"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
357 table->Add (_enable_metadata["studio"] = new CheckBox (_panel, _("Default studio")), 0, wxALIGN_CENTRE_VERTICAL);
358 table->Add (_metadata["studio"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
360 table->Add (_enable_metadata["chain"] = new CheckBox (_panel, _("Default chain")), 0, wxALIGN_CENTRE_VERTICAL);
361 table->Add (_metadata["chain"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
363 table->Add (_enable_metadata["distributor"] = new CheckBox (_panel, _("Default distributor")), 0, wxALIGN_CENTRE_VERTICAL);
364 table->Add (_metadata["distributor"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
366 add_label_to_sizer (table, _panel, _("Default KDM directory"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
367 #ifdef DCPOMATIC_USE_OWN_PICKER
368 _kdm_directory = new DirPickerCtrl (_panel);
370 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
372 table->Add (_kdm_directory, 1, wxEXPAND);
374 add_label_to_sizer (table, _panel, _("Default KDM type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
375 _kdm_type = new KDMChoice (_panel);
376 table->Add (_kdm_type, 1, wxEXPAND);
378 add_label_to_sizer (table, _panel, _("Default KDM duration"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
379 _kdm_duration = new wxSpinCtrl (_panel);
380 _kdm_duration_unit = new wxChoice (_panel, wxID_ANY);
381 auto kdm_duration_sizer = new wxBoxSizer (wxHORIZONTAL);
382 kdm_duration_sizer->Add (_kdm_duration, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
383 kdm_duration_sizer->Add (_kdm_duration_unit, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
384 table->Add (kdm_duration_sizer, 1, wxEXPAND);
386 table->Add (_use_isdcf_name_by_default = new CheckBox(_panel, _("Use ISDCF name by default")), 0, wxALIGN_CENTRE_VERTICAL);
388 _still_length->SetRange (1, 3600);
389 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
391 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
392 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
393 _kdm_type->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_type_changed, this));
394 _kdm_duration_unit->Append (_("days"));
395 _kdm_duration_unit->Append (_("weeks"));
396 _kdm_duration_unit->Append (_("months"));
397 _kdm_duration_unit->Append (_("years"));
399 _kdm_duration->Bind (wxEVT_SPINCTRL, boost::bind(&DefaultsPage::kdm_duration_changed, this));
400 _kdm_duration_unit->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_duration_changed, this));
402 _use_isdcf_name_by_default->bind(&DefaultsPage::use_isdcf_name_by_default_changed, this);
404 _j2k_video_bit_rate->SetRange(50, 250);
405 _j2k_video_bit_rate->Bind(wxEVT_SPINCTRL, boost::bind(&DefaultsPage::j2k_video_bit_rate_changed, this));
406 _mpeg2_video_bit_rate->SetRange(1, 50);
407 _mpeg2_video_bit_rate->Bind(wxEVT_SPINCTRL, boost::bind(&DefaultsPage::mpeg2_video_bit_rate_changed, this));
409 _audio_delay->SetRange (-1000, 1000);
410 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
412 _standard->Append (_("SMPTE"));
413 _standard->Append (_("Interop"));
414 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
416 for (auto const& i: _enable_metadata) {
417 i.second->bind(&DefaultsPage::metadata_changed, this);
420 for (auto const& i: _metadata) {
421 i.second->Bind (wxEVT_TEXT, boost::bind(&DefaultsPage::metadata_changed, this));
424 _enable_audio_language->bind(&DefaultsPage::enable_audio_language_toggled, this);
425 _audio_language->Changed.connect(boost::bind(&DefaultsPage::audio_language_changed, this));
427 _enable_territory->bind(&DefaultsPage::enable_territory_toggled, this);
428 _territory->Changed.connect(boost::bind(&DefaultsPage::territory_changed, this));
431 void config_changed () override
433 auto config = Config::instance ();
434 checked_set (_still_length, config->default_still_length ());
435 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
436 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
437 _kdm_type->set (config->default_kdm_type());
438 checked_set (_use_isdcf_name_by_default, config->use_isdcf_name_by_default());
439 checked_set(_j2k_video_bit_rate, config->default_video_bit_rate(VideoEncoding::JPEG2000) / 1000000);
440 _j2k_video_bit_rate->SetRange(50, config->maximum_video_bit_rate(VideoEncoding::JPEG2000) / 1000000);
441 checked_set(_mpeg2_video_bit_rate, config->default_video_bit_rate(VideoEncoding::MPEG2) / 1000000);
442 _mpeg2_video_bit_rate->SetRange(1, config->maximum_video_bit_rate(VideoEncoding::MPEG2) / 1000000);
443 checked_set (_audio_delay, config->default_audio_delay ());
444 checked_set (_standard, config->default_interop() ? 1 : 0);
445 auto dal = config->default_audio_language();
446 checked_set(_enable_audio_language, static_cast<bool>(dal));
447 checked_set(_audio_language, dal ? dal : boost::none);
448 auto dt = config->default_territory();
449 checked_set(_enable_territory, static_cast<bool>(dt));
450 checked_set(_territory, dt ? dt : boost::none);
452 auto metadata = config->default_metadata();
454 for (auto const& i: metadata) {
455 _enable_metadata[i.first]->SetValue(true);
456 checked_set (_metadata[i.first], i.second);
459 for (auto const& i: _enable_metadata) {
460 if (metadata.find(i.first) == metadata.end()) {
461 checked_set (i.second, false);
465 for (auto const& i: _metadata) {
466 if (metadata.find(i.first) == metadata.end()) {
467 checked_set (i.second, wxT(""));
471 checked_set (_kdm_duration, config->default_kdm_duration().duration);
472 switch (config->default_kdm_duration().unit) {
473 case RoughDuration::Unit::DAYS:
474 _kdm_duration->SetRange(1, 365);
475 checked_set (_kdm_duration_unit, 0);
477 case RoughDuration::Unit::WEEKS:
478 _kdm_duration->SetRange(1, 52);
479 checked_set (_kdm_duration_unit, 1);
481 case RoughDuration::Unit::MONTHS:
482 _kdm_duration->SetRange(1, 12);
483 checked_set (_kdm_duration_unit, 2);
485 case RoughDuration::Unit::YEARS:
486 _kdm_duration->SetRange(1, 40);
487 checked_set (_kdm_duration_unit, 3);
491 setup_sensitivity ();
494 void kdm_duration_changed ()
496 auto config = Config::instance();
497 auto duration = _kdm_duration->GetValue();
498 RoughDuration::Unit unit = RoughDuration::Unit::DAYS;
499 switch (_kdm_duration_unit->GetSelection()) {
501 unit = RoughDuration::Unit::DAYS;
504 unit = RoughDuration::Unit::WEEKS;
507 unit = RoughDuration::Unit::MONTHS;
510 unit = RoughDuration::Unit::YEARS;
513 config->set_default_kdm_duration (RoughDuration(duration, unit));
516 void j2k_video_bit_rate_changed()
518 Config::instance()->set_default_video_bit_rate(VideoEncoding::JPEG2000, _j2k_video_bit_rate->GetValue() * 1000000);
521 void mpeg2_video_bit_rate_changed()
523 Config::instance()->set_default_video_bit_rate(VideoEncoding::MPEG2, _mpeg2_video_bit_rate->GetValue() * 1000000);
526 void audio_delay_changed ()
528 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
531 void directory_changed ()
533 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
536 void kdm_directory_changed ()
538 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
541 void kdm_type_changed ()
543 Config::instance()->set_default_kdm_type(_kdm_type->get());
546 void use_isdcf_name_by_default_changed ()
548 Config::instance()->set_use_isdcf_name_by_default (_use_isdcf_name_by_default->GetValue());
551 void still_length_changed ()
553 Config::instance()->set_default_still_length (_still_length->GetValue ());
556 void standard_changed ()
558 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
561 void metadata_changed ()
563 map<string, string> metadata;
564 for (auto const& i: _enable_metadata) {
565 if (i.second->GetValue()) {
566 metadata[i.first] = wx_to_std(_metadata[i.first]->GetValue());
569 Config::instance()->set_default_metadata (metadata);
570 setup_sensitivity ();
573 void enable_audio_language_toggled()
576 audio_language_changed();
579 void audio_language_changed()
581 if (_enable_audio_language->get()) {
582 Config::instance()->set_default_audio_language(_audio_language->get().get_value_or(dcp::LanguageTag("en-US")));
584 Config::instance()->unset_default_audio_language();
588 void enable_territory_toggled()
594 void territory_changed()
596 if (_enable_territory->get()) {
597 Config::instance()->set_default_territory(_territory->get().get_value_or(dcp::LanguageTag::RegionSubtag("US")));
599 Config::instance()->unset_default_territory();
603 void setup_sensitivity ()
605 _audio_language->enable(_enable_audio_language->get());
606 _territory->enable(_enable_territory->get());
607 for (auto const& i: _enable_metadata) {
608 _metadata[i.first]->Enable(i.second->GetValue());
612 wxSpinCtrl* _j2k_video_bit_rate;
613 wxSpinCtrl* _mpeg2_video_bit_rate;
614 wxSpinCtrl* _audio_delay;
615 wxSpinCtrl* _still_length;
616 #ifdef DCPOMATIC_USE_OWN_PICKER
617 DirPickerCtrl* _directory;
618 DirPickerCtrl* _kdm_directory;
620 wxDirPickerCtrl* _directory;
621 wxDirPickerCtrl* _kdm_directory;
623 KDMChoice* _kdm_type;
624 wxSpinCtrl* _kdm_duration;
625 wxChoice* _kdm_duration_unit;
626 CheckBox* _use_isdcf_name_by_default;
628 CheckBox* _enable_audio_language;
629 LanguageTagWidget* _audio_language;
630 CheckBox* _enable_territory;
631 RegionSubtagWidget* _territory;
632 map<string, CheckBox*> _enable_metadata;
633 map<string, wxTextCtrl*> _metadata;
637 class EncodingServersPage : public Page
640 EncodingServersPage (wxSize panel_size, int border)
641 : Page (panel_size, border)
644 wxString GetName () const override
650 wxBitmap GetLargeIcon () const override
652 return wxBitmap(icon_path("servers"), wxBITMAP_TYPE_PNG);
657 void setup () override
659 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
660 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
662 vector<EditableListColumn> columns;
663 columns.push_back (EditableListColumn(_("IP address / host name")));
664 _servers_list = new EditableList<string, ServerDialog> (
667 boost::bind (&Config::servers, Config::instance()),
668 boost::bind (&Config::set_servers, Config::instance(), _1),
669 boost::bind (&EncodingServersPage::server_column, this, _1),
670 EditableListTitle::INVISIBLE,
671 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
674 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
676 _use_any_servers->bind(&EncodingServersPage::use_any_servers_changed, this);
679 void config_changed () override
681 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
682 _servers_list->refresh ();
685 void use_any_servers_changed ()
687 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
690 string server_column (string s)
695 CheckBox* _use_any_servers;
696 EditableList<string, ServerDialog>* _servers_list;
700 class TMSPage : public Page
703 TMSPage (wxSize panel_size, int border)
704 : Page (panel_size, border)
707 wxString GetName () const override
713 wxBitmap GetLargeIcon () const override
715 return wxBitmap(icon_path("tms"), wxBITMAP_TYPE_PNG);
720 void setup () override
722 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
723 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
725 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
726 table->AddGrowableCol (1, 1);
727 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
729 add_label_to_sizer (table, _panel, _("Protocol"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
730 _tms_protocol = new wxChoice (_panel, wxID_ANY);
731 table->Add (_tms_protocol, 1, wxEXPAND);
733 _tms_passive = new CheckBox(_panel, _("Passive mode"));
734 table->Add(_tms_passive, 1, wxEXPAND);
737 add_label_to_sizer (table, _panel, _("IP address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
738 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
739 table->Add (_tms_ip, 1, wxEXPAND);
741 add_label_to_sizer (table, _panel, _("Target path"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
742 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
743 table->Add (_tms_path, 1, wxEXPAND);
745 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
746 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
747 table->Add (_tms_user, 1, wxEXPAND);
749 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
750 _tms_password = new PasswordEntry (_panel);
751 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
753 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
754 _tms_protocol->Append (_("FTP (for Dolby)"));
756 _upload->bind(&TMSPage::upload_changed, this);
757 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
758 _tms_passive->bind(&TMSPage::tms_passive_changed, this);
760 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
761 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
762 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
763 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
766 void config_changed () override
768 auto config = Config::instance ();
770 checked_set (_upload, config->upload_after_make_dcp());
771 checked_set (_tms_protocol, static_cast<int>(config->tms_protocol()));
772 checked_set(_tms_passive, config->tms_protocol() == FileTransferProtocol::FTP && config->tms_passive());
773 checked_set (_tms_ip, config->tms_ip ());
774 checked_set (_tms_path, config->tms_path ());
775 checked_set (_tms_user, config->tms_user ());
776 checked_set (_tms_password, config->tms_password ());
778 _tms_passive->Enable(config->tms_protocol() == FileTransferProtocol::FTP);
781 void upload_changed ()
783 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
786 void tms_protocol_changed ()
788 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
791 void tms_passive_changed()
793 Config::instance()->set_tms_passive(_tms_passive->get());
796 void tms_ip_changed ()
798 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
801 void tms_path_changed ()
803 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
806 void tms_user_changed ()
808 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
811 void tms_password_changed ()
813 Config::instance()->set_tms_password (_tms_password->get());
817 CheckBox* _tms_passive;
818 wxChoice* _tms_protocol;
820 wxTextCtrl* _tms_path;
821 wxTextCtrl* _tms_user;
822 PasswordEntry* _tms_password;
826 class EmailPage : public Page
829 EmailPage (wxSize panel_size, int border)
830 : Page (panel_size, border)
833 wxString GetName () const override
839 wxBitmap GetLargeIcon () const override
841 return wxBitmap(icon_path("email"), wxBITMAP_TYPE_PNG);
846 void setup () override
848 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
849 table->AddGrowableCol (1, 1);
850 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
852 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
854 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
855 _server = new wxTextCtrl (_panel, wxID_ANY);
856 s->Add (_server, 1, wxEXPAND | wxALL);
857 add_label_to_sizer (s, _panel, _("port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
858 _port = new wxSpinCtrl (_panel, wxID_ANY);
859 _port->SetRange (0, 65535);
861 add_label_to_sizer (s, _panel, _("protocol"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
862 _protocol = new wxChoice (_panel, wxID_ANY);
863 /* Make sure this matches the switches in config_changed and port_changed below */
864 _protocol->Append (_("Auto"));
865 _protocol->Append (_("Plain"));
866 _protocol->Append (_("STARTTLS"));
867 _protocol->Append (_("SSL"));
868 s->Add (_protocol, 1, wxALIGN_CENTER_VERTICAL);
869 table->Add (s, 1, wxEXPAND | wxALL);
872 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
873 _user = new wxTextCtrl (_panel, wxID_ANY);
874 table->Add (_user, 1, wxEXPAND | wxALL);
876 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
877 _password = new PasswordEntry (_panel);
878 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
880 table->AddSpacer (0);
881 _send_test_email = new Button (_panel, _("Send test email..."));
882 table->Add (_send_test_email);
884 _server->Bind (wxEVT_TEXT, boost::bind(&EmailPage::server_changed, this));
885 _port->Bind (wxEVT_SPINCTRL, boost::bind(&EmailPage::port_changed, this));
886 _protocol->Bind (wxEVT_CHOICE, boost::bind(&EmailPage::protocol_changed, this));
887 _user->Bind (wxEVT_TEXT, boost::bind(&EmailPage::user_changed, this));
888 _password->Changed.connect (boost::bind(&EmailPage::password_changed, this));
889 _send_test_email->Bind (wxEVT_BUTTON, boost::bind(&EmailPage::send_test_email_clicked, this));
892 void config_changed () override
894 auto config = Config::instance ();
896 checked_set (_server, config->mail_server());
897 checked_set (_port, config->mail_port());
898 switch (config->mail_protocol()) {
899 case EmailProtocol::AUTO:
900 checked_set (_protocol, 0);
902 case EmailProtocol::PLAIN:
903 checked_set (_protocol, 1);
905 case EmailProtocol::STARTTLS:
906 checked_set (_protocol, 2);
908 case EmailProtocol::SSL:
909 checked_set (_protocol, 3);
912 checked_set (_user, config->mail_user());
913 checked_set (_password, config->mail_password());
916 void server_changed ()
918 Config::instance()->set_mail_server(wx_to_std(_server->GetValue()));
923 Config::instance()->set_mail_port(_port->GetValue());
926 void protocol_changed ()
928 switch (_protocol->GetSelection()) {
930 Config::instance()->set_mail_protocol(EmailProtocol::AUTO);
933 Config::instance()->set_mail_protocol(EmailProtocol::PLAIN);
936 Config::instance()->set_mail_protocol(EmailProtocol::STARTTLS);
939 Config::instance()->set_mail_protocol(EmailProtocol::SSL);
946 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
949 void password_changed ()
951 Config::instance()->set_mail_password(_password->get());
954 void send_test_email_clicked ()
956 SendTestEmailDialog dialog(_panel);
957 if (dialog.ShowModal() != wxID_OK) {
962 wx_to_std(dialog.from()),
963 { wx_to_std(dialog.to()) },
964 wx_to_std(variant::wx::insert_dcpomatic(_("%s test email"))),
965 wx_to_std(variant::wx::insert_dcpomatic(_("This is a test email from %s.")))
967 auto config = Config::instance();
969 email.send(config->mail_server(), config->mail_port(), config->mail_protocol(), config->mail_user(), config->mail_password());
970 } catch (NetworkError& e) {
971 error_dialog(_panel, std_to_wx(e.summary()), std_to_wx(e.detail().get_value_or("")));
973 } catch (std::exception& e) {
974 error_dialog(_panel, _("Test email sending failed."), std_to_wx(e.what()));
977 error_dialog(_panel, _("Test email sending failed."));
980 message_dialog(_panel, _("Test email sent."));
987 PasswordEntry* _password;
988 Button* _send_test_email;
992 class KDMEmailPage : public Page
996 KDMEmailPage (wxSize panel_size, int border)
998 /* We have to force both width and height of this one */
999 : Page (wxSize (panel_size.GetWidth(), 128), border)
1001 : Page (panel_size, border)
1005 wxString GetName () const override
1007 return _("KDM Email");
1010 #ifdef DCPOMATIC_OSX
1011 wxBitmap GetLargeIcon () const override
1013 return wxBitmap(icon_path("kdm_email"), wxBITMAP_TYPE_PNG);
1018 void setup () override
1020 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1021 table->AddGrowableCol (1, 1);
1022 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1024 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1025 _subject = new wxTextCtrl (_panel, wxID_ANY);
1026 table->Add (_subject, 1, wxEXPAND | wxALL);
1028 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1029 _from = new wxTextCtrl (_panel, wxID_ANY);
1030 table->Add (_from, 1, wxEXPAND | wxALL);
1032 vector<EditableListColumn> columns;
1033 columns.push_back (EditableListColumn(_("Address")));
1034 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1035 _cc = new EditableList<string, EmailDialog> (
1038 bind (&Config::kdm_cc, Config::instance()),
1039 bind (&Config::set_kdm_cc, Config::instance(), _1),
1040 [] (string s, int) {
1043 EditableListTitle::VISIBLE,
1044 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1046 table->Add (_cc, 1, wxEXPAND | wxALL);
1048 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1049 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1050 table->Add (_bcc, 1, wxEXPAND | wxALL);
1052 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1053 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1055 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1056 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1060 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1061 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1062 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1063 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1064 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
1067 void config_changed () override
1069 auto config = Config::instance ();
1071 checked_set (_subject, config->kdm_subject ());
1072 checked_set (_from, config->kdm_from ());
1073 checked_set (_bcc, config->kdm_bcc ());
1074 checked_set (_email, Config::instance()->kdm_email ());
1077 void kdm_subject_changed ()
1079 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
1082 void kdm_from_changed ()
1084 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
1087 void kdm_bcc_changed ()
1089 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
1092 void kdm_email_changed ()
1094 if (_email->GetValue().IsEmpty ()) {
1095 /* Sometimes we get sent an erroneous notification that the email
1096 is empty; I don't know why.
1100 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
1105 Config::instance()->reset_kdm_email ();
1106 checked_set (_email, Config::instance()->kdm_email ());
1109 wxTextCtrl* _subject;
1111 EditableList<string, EmailDialog>* _cc;
1114 wxButton* _reset_email;
1118 class NotificationsPage : public Page
1121 NotificationsPage (wxSize panel_size, int border)
1122 #ifdef DCPOMATIC_OSX
1123 /* We have to force both width and height of this one */
1124 : Page (wxSize (panel_size.GetWidth(), 128), border)
1126 : Page (panel_size, border)
1130 wxString GetName () const override
1132 return _("Notifications");
1135 #ifdef DCPOMATIC_OSX
1136 wxBitmap GetLargeIcon () const override
1138 return wxBitmap(icon_path("notifications"), wxBITMAP_TYPE_PNG);
1143 void setup () override
1145 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1146 table->AddGrowableCol (1, 1);
1147 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1149 _enable_message_box = new CheckBox (_panel, _("Message box"));
1150 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
1151 table->AddSpacer (0);
1153 _enable_email = new CheckBox (_panel, _("Email"));
1154 table->Add (_enable_email, 1, wxEXPAND | wxALL);
1155 table->AddSpacer (0);
1157 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1158 _subject = new wxTextCtrl (_panel, wxID_ANY);
1159 table->Add (_subject, 1, wxEXPAND | wxALL);
1161 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1162 _from = new wxTextCtrl (_panel, wxID_ANY);
1163 table->Add (_from, 1, wxEXPAND | wxALL);
1165 add_label_to_sizer (table, _panel, _("To address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1166 _to = new wxTextCtrl (_panel, wxID_ANY);
1167 table->Add (_to, 1, wxEXPAND | wxALL);
1169 vector<EditableListColumn> columns;
1170 columns.push_back (EditableListColumn(_("Address")));
1171 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1172 _cc = new EditableList<string, EmailDialog> (
1175 bind (&Config::notification_cc, Config::instance()),
1176 bind (&Config::set_notification_cc, Config::instance(), _1),
1177 [] (string s, int) {
1180 EditableListTitle::VISIBLE,
1181 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1183 table->Add (_cc, 1, wxEXPAND | wxALL);
1185 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1186 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1187 table->Add (_bcc, 1, wxEXPAND | wxALL);
1189 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1190 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1192 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1193 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1197 _enable_message_box->bind(&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX);
1198 _enable_email->bind(&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL);
1200 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
1201 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
1202 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
1203 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
1204 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
1205 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
1207 setup_sensitivity ();
1210 void setup_sensitivity ()
1212 bool const s = _enable_email->GetValue();
1213 _subject->Enable(s);
1219 _reset_email->Enable(s);
1222 void config_changed () override
1224 auto config = Config::instance ();
1226 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
1227 checked_set (_enable_email, config->notification(Config::EMAIL));
1228 checked_set (_subject, config->notification_subject ());
1229 checked_set (_from, config->notification_from ());
1230 checked_set (_to, config->notification_to ());
1231 checked_set (_bcc, config->notification_bcc ());
1232 checked_set (_email, Config::instance()->notification_email ());
1234 setup_sensitivity ();
1237 void notification_subject_changed ()
1239 Config::instance()->set_notification_subject(wx_to_std(_subject->GetValue()));
1242 void notification_from_changed ()
1244 Config::instance()->set_notification_from(wx_to_std(_from->GetValue()));
1247 void notification_to_changed ()
1249 Config::instance()->set_notification_to(wx_to_std(_to->GetValue()));
1252 void notification_bcc_changed ()
1254 Config::instance()->set_notification_bcc(wx_to_std(_bcc->GetValue()));
1257 void notification_email_changed ()
1259 if (_email->GetValue().IsEmpty()) {
1260 /* Sometimes we get sent an erroneous notification that the email
1261 is empty; I don't know why.
1265 Config::instance()->set_notification_email(wx_to_std(_email->GetValue()));
1270 Config::instance()->reset_notification_email();
1271 checked_set (_email, Config::instance()->notification_email());
1274 void type_changed (CheckBox* b, Config::Notification n)
1276 Config::instance()->set_notification(n, b->GetValue());
1277 setup_sensitivity ();
1280 CheckBox* _enable_message_box;
1281 CheckBox* _enable_email;
1283 wxTextCtrl* _subject;
1286 EditableList<string, EmailDialog>* _cc;
1289 wxButton* _reset_email;
1293 class CoverSheetPage : public Page
1297 CoverSheetPage (wxSize panel_size, int border)
1298 #ifdef DCPOMATIC_OSX
1299 /* We have to force both width and height of this one */
1300 : Page (wxSize (panel_size.GetWidth(), 128), border)
1302 : Page (panel_size, border)
1306 wxString GetName () const override
1308 return _("Cover Sheet");
1311 #ifdef DCPOMATIC_OSX
1312 wxBitmap GetLargeIcon () const override
1314 return wxBitmap(icon_path("cover_sheet"), wxBITMAP_TYPE_PNG);
1319 void setup () override
1321 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1322 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1324 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1325 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1327 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1328 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1331 void config_changed () override
1333 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1336 void cover_sheet_changed ()
1338 if (_cover_sheet->GetValue().IsEmpty ()) {
1339 /* Sometimes we get sent an erroneous notification that the cover sheet
1340 is empty; I don't know why.
1344 Config::instance()->set_cover_sheet(wx_to_std(_cover_sheet->GetValue()));
1347 void reset_cover_sheet ()
1349 Config::instance()->reset_cover_sheet();
1350 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1353 wxTextCtrl* _cover_sheet;
1354 wxButton* _reset_cover_sheet;
1358 class IdentifiersPage : public Page
1361 IdentifiersPage (wxSize panel_size, int border)
1362 : Page (panel_size, border)
1365 wxString GetName () const override
1367 return _("Identifiers");
1370 #ifdef DCPOMATIC_OSX
1371 wxBitmap GetLargeIcon () const override
1373 return wxBitmap(icon_path("identifiers"), wxBITMAP_TYPE_PNG);
1378 void setup () override
1380 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1381 table->AddGrowableCol (1, 1);
1383 add_label_to_sizer (table, _panel, _("Issuer"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1384 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1385 _issuer->SetToolTip(
1386 variant::wx::insert_dcpomatic(
1387 _("This will be written to the DCP's XML files as the <Issuer>. If it is blank, a default value mentioning %s will be used.")
1389 table->Add (_issuer, 1, wxALL | wxEXPAND);
1391 add_label_to_sizer (table, _panel, _("Creator"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1392 _creator = new wxTextCtrl (_panel, wxID_ANY);
1393 _creator->SetToolTip(
1394 variant::wx::insert_dcpomatic(
1395 _("This will be written to the DCP's XML files as the <Creator>. If it is blank, a default value mentioning %s will be used.")
1397 table->Add (_creator, 1, wxALL | wxEXPAND);
1399 add_label_to_sizer (table, _panel, _("Company name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1400 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1401 _company_name->SetToolTip(
1402 variant::wx::insert_dcpomatic(
1403 _("This will be written to the DCP's MXF files as the 'company name'. If it is blank, a default value mentioning libdcp (an internal %s library) will be used.")
1405 table->Add (_company_name, 1, wxALL | wxEXPAND);
1407 add_label_to_sizer (table, _panel, _("Product name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1408 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1409 _product_name->SetToolTip(
1410 variant::wx::insert_dcpomatic(
1411 _("This will be written to the DCP's MXF files as the 'product name'. If it is blank, a default value mentioning libdcp (an internal %s library) will be used.")
1413 table->Add (_product_name, 1, wxALL | wxEXPAND);
1415 add_label_to_sizer (table, _panel, _("Product version"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1416 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1417 _product_version->SetToolTip(
1418 variant::wx::insert_dcpomatic(
1419 _("This will be written to the DCP's MXF files as the 'product version'. If it is blank, a default value mentioning libdcp (an internal %s library) will be used.")
1421 table->Add (_product_version, 1, wxALL | wxEXPAND);
1423 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1424 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1425 _j2k_comment->SetToolTip(
1426 variant::wx::insert_dcpomatic(
1427 _("This will be written to the DCP's JPEG2000 data as a comment. If it is blank, a default value mentioning libdcp (an internal %s library) will be used.")
1429 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1431 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1433 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1434 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1435 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1436 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1437 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1438 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1441 void config_changed () override
1443 auto config = Config::instance ();
1444 checked_set (_issuer, config->dcp_issuer ());
1445 checked_set (_creator, config->dcp_creator ());
1446 checked_set (_company_name, config->dcp_company_name ());
1447 checked_set (_product_name, config->dcp_product_name ());
1448 checked_set (_product_version, config->dcp_product_version ());
1449 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1452 void issuer_changed ()
1454 Config::instance()->set_dcp_issuer(wx_to_std(_issuer->GetValue()));
1457 void creator_changed ()
1459 Config::instance()->set_dcp_creator(wx_to_std(_creator->GetValue()));
1462 void company_name_changed ()
1464 Config::instance()->set_dcp_company_name(wx_to_std(_company_name->GetValue()));
1467 void product_name_changed ()
1469 Config::instance()->set_dcp_product_name(wx_to_std(_product_name->GetValue()));
1472 void product_version_changed ()
1474 Config::instance()->set_dcp_product_version(wx_to_std(_product_version->GetValue()));
1477 void j2k_comment_changed ()
1479 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1482 wxTextCtrl* _issuer;
1483 wxTextCtrl* _creator;
1484 wxTextCtrl* _company_name;
1485 wxTextCtrl* _product_name;
1486 wxTextCtrl* _product_version;
1487 wxTextCtrl* _j2k_comment;
1491 class NonStandardPage : public Page
1494 NonStandardPage(wxSize panel_size, int border)
1495 : Page(panel_size, border)
1498 wxString GetName() const override
1500 return _("Non-standard");
1503 #ifdef DCPOMATIC_OSX
1504 wxBitmap GetLargeIcon() const override
1506 return wxBitmap(icon_path("non_standard"), wxBITMAP_TYPE_PNG);
1511 void setup() override
1513 auto table = new wxFlexGridSizer(2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1514 table->AddGrowableCol(1, 1);
1515 _panel->GetSizer()->Add(table, 1, wxALL | wxEXPAND, _border);
1518 add_label_to_sizer(table, _panel, _("Maximum JPEG2000 bit rate"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1519 auto s = new wxBoxSizer(wxHORIZONTAL);
1520 _maximum_j2k_video_bit_rate = new wxSpinCtrl(_panel);
1521 s->Add(_maximum_j2k_video_bit_rate, 1);
1522 add_label_to_sizer(s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxALIGN_CENTRE_VERTICAL);
1527 add_label_to_sizer(table, _panel, _("Maximum MPEG2 bit rate"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1528 auto s = new wxBoxSizer(wxHORIZONTAL);
1529 _maximum_mpeg2_video_bit_rate = new wxSpinCtrl(_panel);
1530 s->Add(_maximum_mpeg2_video_bit_rate, 1);
1531 add_label_to_sizer(s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxALIGN_CENTRE_VERTICAL);
1535 auto checkbox = [this, table](wxString name, CheckBox*& variable) {
1536 variable = new CheckBox(_panel, name);
1537 table->Add(variable, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1538 table->AddSpacer(0);
1541 checkbox(_("Allow any DCP frame rate"), _allow_any_dcp_frame_rate);
1543 _allow_any_container = new CheckBox(_panel, _("Allow full-frame and non-standard container ratios"));
1544 table->Add(_allow_any_container, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1545 table->AddSpacer(0);
1547 checkbox(_("Allow creation of DCPs with 96kHz audio"), _allow_96khz_audio);
1548 checkbox(_("Allow mapping to all audio channels"), _use_all_audio_channels);
1549 checkbox(_("Allow use of SMPTE Bv2.0"), _allow_smpte_bv20);
1552 add_label_to_sizer(table, _panel, _("ISDCF name part length"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1553 auto s = new wxBoxSizer(wxHORIZONTAL);
1554 _isdcf_name_part_length = new wxSpinCtrl(_panel);
1555 s->Add(_isdcf_name_part_length, 1);
1559 _maximum_j2k_video_bit_rate->SetRange(1, 1000);
1560 _maximum_j2k_video_bit_rate->Bind(wxEVT_SPINCTRL, boost::bind(&NonStandardPage::maximum_j2k_video_bit_rate_changed, this));
1561 _maximum_mpeg2_video_bit_rate->SetRange(1, 100);
1562 _maximum_mpeg2_video_bit_rate->Bind(wxEVT_SPINCTRL, boost::bind(&NonStandardPage::maximum_mpeg2_video_bit_rate_changed, this));
1563 _allow_any_dcp_frame_rate->bind(&NonStandardPage::allow_any_dcp_frame_rate_changed, this);
1564 _allow_any_container->bind(&NonStandardPage::allow_any_container_changed, this);
1565 _allow_96khz_audio->bind(&NonStandardPage::allow_96khz_audio_changed, this);
1566 _use_all_audio_channels->bind(&NonStandardPage::use_all_channels_changed, this);
1567 _allow_smpte_bv20->bind(&NonStandardPage::allow_smpte_bv20_changed, this);
1568 _isdcf_name_part_length->SetRange(1, 256);
1569 _isdcf_name_part_length->Bind(wxEVT_SPINCTRL, boost::bind(&NonStandardPage::isdcf_name_part_length_changed, this));
1572 void config_changed() override
1574 auto config = Config::instance();
1576 checked_set(_maximum_j2k_video_bit_rate, config->maximum_video_bit_rate(VideoEncoding::JPEG2000) / 1000000);
1577 checked_set(_maximum_mpeg2_video_bit_rate, config->maximum_video_bit_rate(VideoEncoding::MPEG2) / 1000000);
1578 checked_set(_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate());
1579 checked_set(_allow_any_container, config->allow_any_container());
1580 checked_set(_allow_96khz_audio, config->allow_96khz_audio());
1581 checked_set(_use_all_audio_channels, config->use_all_audio_channels());
1582 checked_set(_allow_smpte_bv20, config->allow_smpte_bv20());
1583 checked_set(_isdcf_name_part_length, config->isdcf_name_part_length());
1586 void maximum_j2k_video_bit_rate_changed()
1588 Config::instance()->set_maximum_video_bit_rate(VideoEncoding::JPEG2000, _maximum_j2k_video_bit_rate->GetValue() * 1000000);
1591 void maximum_mpeg2_video_bit_rate_changed()
1593 Config::instance()->set_maximum_video_bit_rate(VideoEncoding::MPEG2, _maximum_mpeg2_video_bit_rate->GetValue() * 1000000);
1596 void allow_any_dcp_frame_rate_changed()
1598 Config::instance()->set_allow_any_dcp_frame_rate(_allow_any_dcp_frame_rate->GetValue());
1601 void allow_any_container_changed()
1603 Config::instance()->set_allow_any_container(_allow_any_container->GetValue());
1606 void allow_96khz_audio_changed()
1608 Config::instance()->set_allow_96hhz_audio(_allow_96khz_audio->GetValue());
1611 void use_all_channels_changed()
1613 Config::instance()->set_use_all_audio_channels(_use_all_audio_channels->GetValue());
1616 void allow_smpte_bv20_changed()
1618 Config::instance()->set_allow_smpte_bv20(_allow_smpte_bv20->GetValue());
1621 void isdcf_name_part_length_changed()
1623 Config::instance()->set_isdcf_name_part_length(_isdcf_name_part_length->GetValue());
1626 wxSpinCtrl* _maximum_j2k_video_bit_rate = nullptr;
1627 wxSpinCtrl* _maximum_mpeg2_video_bit_rate = nullptr;
1628 CheckBox* _allow_any_dcp_frame_rate = nullptr;
1629 CheckBox* _allow_any_container = nullptr;
1630 CheckBox* _allow_96khz_audio = nullptr;
1631 CheckBox* _use_all_audio_channels = nullptr;
1632 CheckBox* _allow_smpte_bv20 = nullptr;
1633 wxSpinCtrl* _isdcf_name_part_length = nullptr;
1638 /** @class AdvancedPage
1639 * @brief Advanced page of the preferences dialog.
1641 class AdvancedPage : public Page
1644 AdvancedPage (wxSize panel_size, int border)
1645 : Page (panel_size, border)
1648 wxString GetName () const override
1650 return _("Advanced");
1653 #ifdef DCPOMATIC_OSX
1654 wxBitmap GetLargeIcon () const override
1656 return wxBitmap(icon_path("advanced"), wxBITMAP_TYPE_PNG);
1661 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1663 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1665 flags |= wxALIGN_RIGHT;
1668 wxStaticText* m = new StaticText (parent, text);
1669 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1672 void setup () override
1674 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1675 table->AddGrowableCol (1, 1);
1676 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1678 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1679 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1680 table->Add (_video_display_mode);
1682 auto restart = add_label_to_sizer(table, _panel, variant::wx::insert_dcpomatic(_("(restart %s to change display mode)")), false);
1683 auto font = restart->GetFont();
1684 font.SetStyle (wxFONTSTYLE_ITALIC);
1685 font.SetPointSize (font.GetPointSize() - 1);
1686 restart->SetFont (font);
1687 table->AddSpacer (0);
1689 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1690 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1691 table->AddSpacer (0);
1693 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1694 table->Add (_only_servers_encode, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1695 table->AddSpacer (0);
1698 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1699 auto s = new wxBoxSizer (wxHORIZONTAL);
1700 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1701 s->Add (_frames_in_memory_multiplier, 1);
1706 auto format = create_label (_panel, _("DCP metadata filename format"), true);
1707 #ifdef DCPOMATIC_OSX
1708 auto align = new wxBoxSizer (wxHORIZONTAL);
1709 align->Add (format, 0, wxTOP, 2);
1710 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1712 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1714 dcp::NameFormat::Map titles;
1715 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1716 dcp::NameFormat::Map examples;
1717 examples['t'] = "cpl";
1718 _dcp_metadata_filename_format = new NameFormatEditor (
1719 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1721 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1725 auto format = create_label (_panel, _("DCP asset filename format"), true);
1726 #ifdef DCPOMATIC_OSX
1727 auto align = new wxBoxSizer (wxHORIZONTAL);
1728 align->Add (format, 0, wxTOP, 2);
1729 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1731 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1733 dcp::NameFormat::Map titles;
1734 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1735 titles['r'] = wx_to_std (_("reel number"));
1736 titles['n'] = wx_to_std (_("number of reels"));
1737 titles['c'] = wx_to_std (_("content filename"));
1738 dcp::NameFormat::Map examples;
1739 examples['t'] = "j2c";
1740 examples['r'] = "1";
1741 examples['n'] = "4";
1742 examples['c'] = "myfile.mp4";
1743 _dcp_asset_filename_format = new NameFormatEditor (
1744 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1746 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1750 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1751 auto t = new wxFlexGridSizer (2);
1752 _log_general = new CheckBox (_panel, _("General"));
1753 t->Add (_log_general, 1, wxEXPAND | wxALL);
1754 _log_warning = new CheckBox (_panel, _("Warnings"));
1755 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1756 _log_error = new CheckBox (_panel, _("Errors"));
1757 t->Add (_log_error, 1, wxEXPAND | wxALL);
1758 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1759 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1760 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1761 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1762 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1763 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1764 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1765 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1766 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1767 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1768 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1769 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1770 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1771 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1772 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1773 table->Add (t, 0, wxALL, 6);
1776 #ifdef DCPOMATIC_WINDOWS
1777 _win32_console = new CheckBox (_panel, _("Open console window"));
1778 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1779 table->AddSpacer (0);
1782 _video_display_mode->Append (_("Simple (safer)"));
1783 #if wxCHECK_VERSION(3, 1, 0)
1784 _video_display_mode->Append (_("OpenGL (faster)"));
1786 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1787 _show_experimental_audio_processors->bind(&AdvancedPage::show_experimental_audio_processors_changed, this);
1788 _only_servers_encode->bind(&AdvancedPage::only_servers_encode_changed, this);
1789 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1790 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1791 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1792 _log_general->bind(&AdvancedPage::log_changed, this);
1793 _log_warning->bind(&AdvancedPage::log_changed, this);
1794 _log_error->bind(&AdvancedPage::log_changed, this);
1795 _log_timing->bind(&AdvancedPage::log_changed, this);
1796 _log_debug_threed->bind(&AdvancedPage::log_changed, this);
1797 _log_debug_encode->bind(&AdvancedPage::log_changed, this);
1798 _log_debug_email->bind(&AdvancedPage::log_changed, this);
1799 _log_debug_video_view->bind(&AdvancedPage::log_changed, this);
1800 _log_debug_player->bind(&AdvancedPage::log_changed, this);
1801 _log_debug_audio_analysis->bind(&AdvancedPage::log_changed, this);
1802 #ifdef DCPOMATIC_WINDOWS
1803 _win32_console->bind(&AdvancedPage::win32_console_changed, this);
1807 void config_changed () override
1809 auto config = Config::instance ();
1811 switch (config->video_view_type()) {
1812 case Config::VIDEO_VIEW_SIMPLE:
1813 checked_set (_video_display_mode, 0);
1815 case Config::VIDEO_VIEW_OPENGL:
1816 checked_set (_video_display_mode, 1);
1819 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1820 checked_set (_only_servers_encode, config->only_servers_encode ());
1821 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1822 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1823 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1824 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1825 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREE_D);
1826 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1827 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1828 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1829 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1830 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1831 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1832 #ifdef DCPOMATIC_WINDOWS
1833 checked_set (_win32_console, config->win32_console());
1837 void video_display_mode_changed ()
1839 if (_video_display_mode->GetSelection() == 0) {
1840 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_SIMPLE);
1842 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_OPENGL);
1846 void frames_in_memory_multiplier_changed ()
1848 Config::instance()->set_frames_in_memory_multiplier(_frames_in_memory_multiplier->GetValue());
1851 void show_experimental_audio_processors_changed ()
1853 Config::instance()->set_show_experimental_audio_processors(_show_experimental_audio_processors->GetValue());
1856 void only_servers_encode_changed ()
1858 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue());
1861 void dcp_metadata_filename_format_changed ()
1863 Config::instance()->set_dcp_metadata_filename_format(_dcp_metadata_filename_format->get());
1866 void dcp_asset_filename_format_changed ()
1868 Config::instance()->set_dcp_asset_filename_format(_dcp_asset_filename_format->get());
1874 if (_log_general->GetValue ()) {
1875 types |= LogEntry::TYPE_GENERAL;
1877 if (_log_warning->GetValue ()) {
1878 types |= LogEntry::TYPE_WARNING;
1880 if (_log_error->GetValue ()) {
1881 types |= LogEntry::TYPE_ERROR;
1883 if (_log_timing->GetValue ()) {
1884 types |= LogEntry::TYPE_TIMING;
1886 if (_log_debug_threed->GetValue ()) {
1887 types |= LogEntry::TYPE_DEBUG_THREE_D;
1889 if (_log_debug_encode->GetValue ()) {
1890 types |= LogEntry::TYPE_DEBUG_ENCODE;
1892 if (_log_debug_email->GetValue ()) {
1893 types |= LogEntry::TYPE_DEBUG_EMAIL;
1895 if (_log_debug_video_view->GetValue()) {
1896 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1898 if (_log_debug_player->GetValue()) {
1899 types |= LogEntry::TYPE_DEBUG_PLAYER;
1901 if (_log_debug_audio_analysis->GetValue()) {
1902 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1904 Config::instance()->set_log_types (types);
1907 #ifdef DCPOMATIC_WINDOWS
1908 void win32_console_changed ()
1910 Config::instance()->set_win32_console(_win32_console->GetValue());
1914 wxChoice* _video_display_mode = nullptr;
1915 wxSpinCtrl* _frames_in_memory_multiplier = nullptr;
1916 CheckBox* _show_experimental_audio_processors = nullptr;
1917 CheckBox* _only_servers_encode = nullptr;
1918 NameFormatEditor* _dcp_metadata_filename_format = nullptr;
1919 NameFormatEditor* _dcp_asset_filename_format = nullptr;
1920 CheckBox* _log_general = nullptr;
1921 CheckBox* _log_warning = nullptr;
1922 CheckBox* _log_error = nullptr;
1923 CheckBox* _log_timing = nullptr;
1924 CheckBox* _log_debug_threed = nullptr;
1925 CheckBox* _log_debug_encode = nullptr;
1926 CheckBox* _log_debug_email = nullptr;
1927 CheckBox* _log_debug_video_view = nullptr;
1928 CheckBox* _log_debug_player = nullptr;
1929 CheckBox* _log_debug_audio_analysis = nullptr;
1930 #ifdef DCPOMATIC_WINDOWS
1931 CheckBox* _win32_console = nullptr;
1936 wxPreferencesEditor*
1937 create_full_config_dialog ()
1939 auto e = new wxPreferencesEditor ();
1941 #ifdef DCPOMATIC_OSX
1942 /* Width that we force some of the config panels to be on OSX so that
1943 the containing window doesn't shrink too much when we select those panels.
1944 This is obviously an unpleasant hack.
1946 wxSize ps = wxSize(900, -1);
1947 int const border = 16;
1949 wxSize ps = wxSize (-1, -1);
1950 int const border = 8;
1953 e->AddPage (new FullGeneralPage (ps, border));
1954 e->AddPage (new SoundPage (ps, border));
1955 e->AddPage (new DefaultsPage (ps, border));
1956 e->AddPage (new EncodingServersPage(ps, border));
1957 #ifdef DCPOMATIC_GROK
1958 e->AddPage (new GPUPage (ps, border));
1960 e->AddPage (new KeysPage (ps, border));
1961 e->AddPage (new TMSPage (ps, border));
1962 e->AddPage (new EmailPage (ps, border));
1963 e->AddPage (new KDMEmailPage (ps, border));
1964 e->AddPage (new NotificationsPage (ps, border));
1965 e->AddPage (new CoverSheetPage (ps, border));
1966 e->AddPage (new IdentifiersPage (ps, border));
1967 e->AddPage (new NonStandardPage (ps, border));
1968 e->AddPage (new AdvancedPage (ps, border));