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"
48 #include "gpu_config_panel.h"
50 #include "lib/config.h"
51 #include "lib/cross.h"
52 #include "lib/dcp_content_type.h"
53 #include "lib/emailer.h"
54 #include "lib/exceptions.h"
55 #include "lib/filter.h"
57 #include "lib/ratio.h"
59 #include <dcp/certificate_chain.h>
60 #include <dcp/exceptions.h>
61 #include <dcp/filesystem.h>
62 #include <dcp/locale_convert.h>
63 #include <dcp/warnings.h>
64 LIBDCP_DISABLE_WARNINGS
65 #include <wx/filepicker.h>
66 #include <wx/preferences.h>
67 #include <wx/spinctrl.h>
68 #include <wx/stdpaths.h>
69 LIBDCP_ENABLE_WARNINGS
71 #include <boost/filesystem.hpp>
81 using std::shared_ptr;
85 using boost::optional;
86 #if BOOST_VERSION >= 106100
87 using namespace boost::placeholders;
89 using dcp::locale_convert;
92 class FullGeneralPage : public GeneralPage
95 FullGeneralPage (wxSize panel_size, int border)
96 : GeneralPage (panel_size, border)
100 void setup () override
102 auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
103 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
106 add_language_controls (table, r);
108 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
109 _master_encoding_threads = new wxSpinCtrl (_panel);
110 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
113 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
114 _server_encoding_threads = new wxSpinCtrl (_panel);
115 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
118 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
119 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, false);
120 table->Add (_config_file, wxGBPosition (r, 1));
123 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
124 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, false);
125 table->Add (_cinemas_file, wxGBPosition (r, 1));
126 auto export_cinemas = new Button (_panel, _("Export..."));
127 table->Add (export_cinemas, wxGBPosition (r, 2));
130 add_label_to_sizer(table, _panel, _("Default \"add file\" location"), true, wxGBPosition(r, 0));
131 _default_add_file_location = new Choice(_panel);
132 table->Add(_default_add_file_location, wxGBPosition(r, 1));
135 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
136 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
137 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
141 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
142 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
145 add_update_controls (table, r);
147 _default_add_file_location->add(_("Same place as last time"));
148 _default_add_file_location->add(_("Same place as project"));
149 _default_add_file_location->bind(&FullGeneralPage::default_add_file_location_changed, this);
151 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::config_file_changed, this));
152 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::cinemas_file_changed, this));
154 _master_encoding_threads->SetRange (1, 128);
155 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
156 _server_encoding_threads->SetRange (1, 128);
157 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
158 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
160 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
161 _analyse_ebur128->bind(&FullGeneralPage::analyse_ebur128_changed, this);
163 _automatic_audio_analysis->bind(&FullGeneralPage::automatic_audio_analysis_changed, this);
166 void config_changed () override
168 auto config = Config::instance ();
170 checked_set (_master_encoding_threads, config->master_encoding_threads ());
171 checked_set (_server_encoding_threads, config->server_encoding_threads ());
172 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
173 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
175 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
176 checked_set (_config_file, config->config_read_file());
177 checked_set (_cinemas_file, config->cinemas_file());
178 checked_set(_default_add_file_location, config->default_add_file_location() == Config::DefaultAddFileLocation::SAME_AS_LAST_TIME ? 0 : 1);
180 GeneralPage::config_changed ();
183 void export_cinemas_file ()
186 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT("XML files (*.xml)|*.xml"),
187 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
190 if (dialog.ShowModal() == wxID_OK) {
191 dcp::filesystem::copy_file(Config::instance()->cinemas_file(), wx_to_std(dialog.GetPath()), boost::filesystem::copy_option::overwrite_if_exists);
195 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
196 void analyse_ebur128_changed ()
198 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue());
202 void automatic_audio_analysis_changed ()
204 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue());
207 void master_encoding_threads_changed ()
209 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue());
212 void server_encoding_threads_changed ()
214 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue());
217 void config_file_changed ()
219 auto config = Config::instance();
220 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
221 if (new_file == config->config_read_file()) {
224 bool copy_and_link = true;
225 if (dcp::filesystem::exists(new_file)) {
226 ConfigMoveDialog dialog(_panel, new_file);
227 if (dialog.ShowModal() == wxID_OK) {
228 copy_and_link = false;
234 if (new_file != config->config_read_file()) {
235 config->copy_and_link (new_file);
238 config->link (new_file);
242 void cinemas_file_changed ()
244 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
247 void default_add_file_location_changed()
249 Config::instance()->set_default_add_file_location(
250 _default_add_file_location->get().get_value_or(0) == 0 ? Config::DefaultAddFileLocation::SAME_AS_LAST_TIME : Config::DefaultAddFileLocation::SAME_AS_PROJECT
254 Choice* _default_add_file_location;
255 wxSpinCtrl* _master_encoding_threads;
256 wxSpinCtrl* _server_encoding_threads;
257 FilePickerCtrl* _config_file;
258 FilePickerCtrl* _cinemas_file;
259 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
260 CheckBox* _analyse_ebur128;
262 CheckBox* _automatic_audio_analysis;
266 class DefaultsPage : public Page
269 DefaultsPage (wxSize panel_size, int border)
270 : Page (panel_size, border)
273 wxString GetName () const override
275 return _("Defaults");
279 wxBitmap GetLargeIcon () const override
281 return wxBitmap(icon_path("defaults"), wxBITMAP_TYPE_PNG);
286 void setup () override
288 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
289 table->AddGrowableCol (1, 1);
290 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
293 add_label_to_sizer (table, _panel, _("Default duration of still images"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
294 auto s = new wxBoxSizer (wxHORIZONTAL);
295 _still_length = new wxSpinCtrl (_panel);
296 s->Add (_still_length);
297 add_label_to_sizer (s, _panel, _("s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
301 add_label_to_sizer (table, _panel, _("Default directory for new films"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
302 #ifdef DCPOMATIC_USE_OWN_PICKER
303 _directory = new DirPickerCtrl (_panel);
305 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
307 table->Add (_directory, 1, wxEXPAND);
309 add_label_to_sizer (table, _panel, _("Default content type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
310 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
311 table->Add (_dcp_content_type);
313 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
314 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
315 table->Add (_dcp_audio_channels);
318 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
319 auto s = new wxBoxSizer (wxHORIZONTAL);
320 _j2k_bandwidth = new wxSpinCtrl (_panel);
321 s->Add (_j2k_bandwidth);
322 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
327 add_label_to_sizer (table, _panel, _("Default audio delay"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
328 auto s = new wxBoxSizer (wxHORIZONTAL);
329 _audio_delay = new wxSpinCtrl (_panel);
330 s->Add (_audio_delay);
331 add_label_to_sizer (s, _panel, _("ms"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
335 add_label_to_sizer (table, _panel, _("Default standard"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
336 _standard = new wxChoice (_panel, wxID_ANY);
337 table->Add (_standard);
339 _enable_audio_language = new CheckBox(_panel, _("Default audio language"));
340 table->Add(_enable_audio_language, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
341 _audio_language = new LanguageTagWidget(_panel, _("Default audio language to use for new DCPs"), Config::instance()->default_audio_language(), wxString("cmnr-Hant-"));
342 table->Add(_audio_language->sizer());
344 _enable_territory = new CheckBox(_panel, _("Default territory"));
345 table->Add(_enable_territory, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
346 _territory = new RegionSubtagWidget(_panel, _("Default territory to use for new DCPs"), Config::instance()->default_territory(), wxString("cmnr-Hant-"));
347 table->Add(_territory->sizer());
349 table->Add (_enable_metadata["facility"] = new CheckBox (_panel, _("Default facility")), 0, wxALIGN_CENTRE_VERTICAL);
350 table->Add (_metadata["facility"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
352 table->Add (_enable_metadata["studio"] = new CheckBox (_panel, _("Default studio")), 0, wxALIGN_CENTRE_VERTICAL);
353 table->Add (_metadata["studio"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
355 table->Add (_enable_metadata["chain"] = new CheckBox (_panel, _("Default chain")), 0, wxALIGN_CENTRE_VERTICAL);
356 table->Add (_metadata["chain"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
358 table->Add (_enable_metadata["distributor"] = new CheckBox (_panel, _("Default distributor")), 0, wxALIGN_CENTRE_VERTICAL);
359 table->Add (_metadata["distributor"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
361 add_label_to_sizer (table, _panel, _("Default KDM directory"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
362 #ifdef DCPOMATIC_USE_OWN_PICKER
363 _kdm_directory = new DirPickerCtrl (_panel);
365 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
367 table->Add (_kdm_directory, 1, wxEXPAND);
369 add_label_to_sizer (table, _panel, _("Default KDM type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
370 _kdm_type = new KDMChoice (_panel);
371 table->Add (_kdm_type, 1, wxEXPAND);
373 add_label_to_sizer (table, _panel, _("Default KDM duration"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
374 _kdm_duration = new wxSpinCtrl (_panel);
375 _kdm_duration_unit = new wxChoice (_panel, wxID_ANY);
376 auto kdm_duration_sizer = new wxBoxSizer (wxHORIZONTAL);
377 kdm_duration_sizer->Add (_kdm_duration, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
378 kdm_duration_sizer->Add (_kdm_duration_unit, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
379 table->Add (kdm_duration_sizer, 1, wxEXPAND);
381 table->Add (_use_isdcf_name_by_default = new CheckBox(_panel, _("Use ISDCF name by default")), 0, wxALIGN_CENTRE_VERTICAL);
383 _still_length->SetRange (1, 3600);
384 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
386 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
387 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
388 _kdm_type->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_type_changed, this));
389 _kdm_duration_unit->Append (_("days"));
390 _kdm_duration_unit->Append (_("weeks"));
391 _kdm_duration_unit->Append (_("months"));
392 _kdm_duration_unit->Append (_("years"));
394 _kdm_duration->Bind (wxEVT_SPINCTRL, boost::bind(&DefaultsPage::kdm_duration_changed, this));
395 _kdm_duration_unit->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_duration_changed, this));
397 _use_isdcf_name_by_default->bind(&DefaultsPage::use_isdcf_name_by_default_changed, this);
399 for (auto i: DCPContentType::all()) {
400 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
403 setup_audio_channels_choice (_dcp_audio_channels, 2);
405 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
406 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
408 _j2k_bandwidth->SetRange (50, 250);
409 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
411 _audio_delay->SetRange (-1000, 1000);
412 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
414 _standard->Append (_("SMPTE"));
415 _standard->Append (_("Interop"));
416 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
418 for (auto const& i: _enable_metadata) {
419 i.second->bind(&DefaultsPage::metadata_changed, this);
422 for (auto const& i: _metadata) {
423 i.second->Bind (wxEVT_TEXT, boost::bind(&DefaultsPage::metadata_changed, this));
426 _enable_audio_language->bind(&DefaultsPage::enable_audio_language_toggled, this);
427 _audio_language->Changed.connect(boost::bind(&DefaultsPage::audio_language_changed, this));
429 _enable_territory->bind(&DefaultsPage::enable_territory_toggled, this);
430 _territory->Changed.connect(boost::bind(&DefaultsPage::territory_changed, this));
433 void config_changed () override
435 auto config = Config::instance ();
437 auto const ct = DCPContentType::all ();
438 for (size_t i = 0; i < ct.size(); ++i) {
439 if (ct[i] == config->default_dcp_content_type()) {
440 _dcp_content_type->SetSelection (i);
444 checked_set (_still_length, config->default_still_length ());
445 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
446 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
447 _kdm_type->set (config->default_kdm_type());
448 checked_set (_use_isdcf_name_by_default, config->use_isdcf_name_by_default());
449 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
450 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
451 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
452 checked_set (_audio_delay, config->default_audio_delay ());
453 checked_set (_standard, config->default_interop() ? 1 : 0);
454 auto dal = config->default_audio_language();
455 checked_set(_enable_audio_language, static_cast<bool>(dal));
456 checked_set(_audio_language, dal ? dal : boost::none);
457 auto dt = config->default_territory();
458 checked_set(_enable_territory, static_cast<bool>(dt));
459 checked_set(_territory, dt ? dt : boost::none);
461 auto metadata = config->default_metadata();
463 for (auto const& i: metadata) {
464 _enable_metadata[i.first]->SetValue(true);
465 checked_set (_metadata[i.first], i.second);
468 for (auto const& i: _enable_metadata) {
469 if (metadata.find(i.first) == metadata.end()) {
470 checked_set (i.second, false);
474 for (auto const& i: _metadata) {
475 if (metadata.find(i.first) == metadata.end()) {
476 checked_set (i.second, wxT(""));
480 checked_set (_kdm_duration, config->default_kdm_duration().duration);
481 switch (config->default_kdm_duration().unit) {
482 case RoughDuration::Unit::DAYS:
483 _kdm_duration->SetRange(1, 365);
484 checked_set (_kdm_duration_unit, 0);
486 case RoughDuration::Unit::WEEKS:
487 _kdm_duration->SetRange(1, 52);
488 checked_set (_kdm_duration_unit, 1);
490 case RoughDuration::Unit::MONTHS:
491 _kdm_duration->SetRange(1, 12);
492 checked_set (_kdm_duration_unit, 2);
494 case RoughDuration::Unit::YEARS:
495 _kdm_duration->SetRange(1, 40);
496 checked_set (_kdm_duration_unit, 3);
500 setup_sensitivity ();
503 void kdm_duration_changed ()
505 auto config = Config::instance();
506 auto duration = _kdm_duration->GetValue();
507 RoughDuration::Unit unit = RoughDuration::Unit::DAYS;
508 switch (_kdm_duration_unit->GetSelection()) {
510 unit = RoughDuration::Unit::DAYS;
513 unit = RoughDuration::Unit::WEEKS;
516 unit = RoughDuration::Unit::MONTHS;
519 unit = RoughDuration::Unit::YEARS;
522 config->set_default_kdm_duration (RoughDuration(duration, unit));
525 void j2k_bandwidth_changed ()
527 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
530 void audio_delay_changed ()
532 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
535 void dcp_audio_channels_changed ()
537 int const s = _dcp_audio_channels->GetSelection ();
538 if (s != wxNOT_FOUND) {
539 Config::instance()->set_default_dcp_audio_channels (
540 locale_convert<int>(string_client_data(_dcp_audio_channels->GetClientObject(s)))
545 void directory_changed ()
547 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
550 void kdm_directory_changed ()
552 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
555 void kdm_type_changed ()
557 Config::instance()->set_default_kdm_type(_kdm_type->get());
560 void use_isdcf_name_by_default_changed ()
562 Config::instance()->set_use_isdcf_name_by_default (_use_isdcf_name_by_default->GetValue());
565 void still_length_changed ()
567 Config::instance()->set_default_still_length (_still_length->GetValue ());
570 void dcp_content_type_changed ()
572 auto ct = DCPContentType::all ();
573 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
576 void standard_changed ()
578 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
581 void metadata_changed ()
583 map<string, string> metadata;
584 for (auto const& i: _enable_metadata) {
585 if (i.second->GetValue()) {
586 metadata[i.first] = wx_to_std(_metadata[i.first]->GetValue());
589 Config::instance()->set_default_metadata (metadata);
590 setup_sensitivity ();
593 void enable_audio_language_toggled()
596 audio_language_changed();
599 void audio_language_changed()
601 if (_enable_audio_language->get()) {
602 Config::instance()->set_default_audio_language(_audio_language->get().get_value_or(dcp::LanguageTag("en-US")));
604 Config::instance()->unset_default_audio_language();
608 void enable_territory_toggled()
614 void territory_changed()
616 if (_enable_territory->get()) {
617 Config::instance()->set_default_territory(_territory->get().get_value_or(dcp::LanguageTag::RegionSubtag("US")));
619 Config::instance()->unset_default_territory();
623 void setup_sensitivity ()
625 _audio_language->enable(_enable_audio_language->get());
626 _territory->enable(_enable_territory->get());
627 for (auto const& i: _enable_metadata) {
628 _metadata[i.first]->Enable(i.second->GetValue());
632 wxSpinCtrl* _j2k_bandwidth;
633 wxSpinCtrl* _audio_delay;
634 wxSpinCtrl* _still_length;
635 #ifdef DCPOMATIC_USE_OWN_PICKER
636 DirPickerCtrl* _directory;
637 DirPickerCtrl* _kdm_directory;
639 wxDirPickerCtrl* _directory;
640 wxDirPickerCtrl* _kdm_directory;
642 KDMChoice* _kdm_type;
643 wxSpinCtrl* _kdm_duration;
644 wxChoice* _kdm_duration_unit;
645 CheckBox* _use_isdcf_name_by_default;
646 wxChoice* _dcp_content_type;
647 wxChoice* _dcp_audio_channels;
649 CheckBox* _enable_audio_language;
650 LanguageTagWidget* _audio_language;
651 CheckBox* _enable_territory;
652 RegionSubtagWidget* _territory;
653 map<string, CheckBox*> _enable_metadata;
654 map<string, wxTextCtrl*> _metadata;
658 class EncodingServersPage : public Page
661 EncodingServersPage (wxSize panel_size, int border)
662 : Page (panel_size, border)
665 wxString GetName () const override
671 wxBitmap GetLargeIcon () const override
673 return wxBitmap(icon_path("servers"), wxBITMAP_TYPE_PNG);
678 void setup () override
680 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
681 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
683 vector<EditableListColumn> columns;
684 columns.push_back (EditableListColumn(_("IP address / host name")));
685 _servers_list = new EditableList<string, ServerDialog> (
688 boost::bind (&Config::servers, Config::instance()),
689 boost::bind (&Config::set_servers, Config::instance(), _1),
690 boost::bind (&EncodingServersPage::server_column, this, _1),
691 EditableListTitle::INVISIBLE,
692 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
695 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
697 _use_any_servers->bind(&EncodingServersPage::use_any_servers_changed, this);
700 void config_changed () override
702 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
703 _servers_list->refresh ();
706 void use_any_servers_changed ()
708 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
711 string server_column (string s)
716 CheckBox* _use_any_servers;
717 EditableList<string, ServerDialog>* _servers_list;
721 class TMSPage : public Page
724 TMSPage (wxSize panel_size, int border)
725 : Page (panel_size, border)
728 wxString GetName () const override
734 wxBitmap GetLargeIcon () const override
736 return wxBitmap(icon_path("tms"), wxBITMAP_TYPE_PNG);
741 void setup () override
743 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
744 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
746 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
747 table->AddGrowableCol (1, 1);
748 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
750 add_label_to_sizer (table, _panel, _("Protocol"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
751 _tms_protocol = new wxChoice (_panel, wxID_ANY);
752 table->Add (_tms_protocol, 1, wxEXPAND);
754 _tms_passive = new CheckBox(_panel, _("Passive mode"));
755 table->Add(_tms_passive, 1, wxEXPAND);
758 add_label_to_sizer (table, _panel, _("IP address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
759 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
760 table->Add (_tms_ip, 1, wxEXPAND);
762 add_label_to_sizer (table, _panel, _("Target path"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
763 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
764 table->Add (_tms_path, 1, wxEXPAND);
766 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
767 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
768 table->Add (_tms_user, 1, wxEXPAND);
770 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
771 _tms_password = new PasswordEntry (_panel);
772 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
774 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
775 _tms_protocol->Append (_("FTP (for Dolby)"));
777 _upload->bind(&TMSPage::upload_changed, this);
778 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
779 _tms_passive->bind(&TMSPage::tms_passive_changed, this);
781 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
782 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
783 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
784 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
787 void config_changed () override
789 auto config = Config::instance ();
791 checked_set (_upload, config->upload_after_make_dcp());
792 checked_set (_tms_protocol, static_cast<int>(config->tms_protocol()));
793 checked_set(_tms_passive, config->tms_protocol() == FileTransferProtocol::FTP && config->tms_passive());
794 checked_set (_tms_ip, config->tms_ip ());
795 checked_set (_tms_path, config->tms_path ());
796 checked_set (_tms_user, config->tms_user ());
797 checked_set (_tms_password, config->tms_password ());
799 _tms_passive->Enable(config->tms_protocol() == FileTransferProtocol::FTP);
802 void upload_changed ()
804 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
807 void tms_protocol_changed ()
809 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
812 void tms_passive_changed()
814 Config::instance()->set_tms_passive(_tms_passive->get());
817 void tms_ip_changed ()
819 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
822 void tms_path_changed ()
824 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
827 void tms_user_changed ()
829 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
832 void tms_password_changed ()
834 Config::instance()->set_tms_password (_tms_password->get());
838 CheckBox* _tms_passive;
839 wxChoice* _tms_protocol;
841 wxTextCtrl* _tms_path;
842 wxTextCtrl* _tms_user;
843 PasswordEntry* _tms_password;
847 class EmailPage : public Page
850 EmailPage (wxSize panel_size, int border)
851 : Page (panel_size, border)
854 wxString GetName () const override
860 wxBitmap GetLargeIcon () const override
862 return wxBitmap(icon_path("email"), wxBITMAP_TYPE_PNG);
867 void setup () override
869 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
870 table->AddGrowableCol (1, 1);
871 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
873 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
875 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
876 _server = new wxTextCtrl (_panel, wxID_ANY);
877 s->Add (_server, 1, wxEXPAND | wxALL);
878 add_label_to_sizer (s, _panel, _("port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
879 _port = new wxSpinCtrl (_panel, wxID_ANY);
880 _port->SetRange (0, 65535);
882 add_label_to_sizer (s, _panel, _("protocol"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
883 _protocol = new wxChoice (_panel, wxID_ANY);
884 /* Make sure this matches the switches in config_changed and port_changed below */
885 _protocol->Append (_("Auto"));
886 _protocol->Append (_("Plain"));
887 _protocol->Append (_("STARTTLS"));
888 _protocol->Append (_("SSL"));
889 s->Add (_protocol, 1, wxALIGN_CENTER_VERTICAL);
890 table->Add (s, 1, wxEXPAND | wxALL);
893 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
894 _user = new wxTextCtrl (_panel, wxID_ANY);
895 table->Add (_user, 1, wxEXPAND | wxALL);
897 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
898 _password = new PasswordEntry (_panel);
899 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
901 table->AddSpacer (0);
902 _send_test_email = new Button (_panel, _("Send test email..."));
903 table->Add (_send_test_email);
905 _server->Bind (wxEVT_TEXT, boost::bind(&EmailPage::server_changed, this));
906 _port->Bind (wxEVT_SPINCTRL, boost::bind(&EmailPage::port_changed, this));
907 _protocol->Bind (wxEVT_CHOICE, boost::bind(&EmailPage::protocol_changed, this));
908 _user->Bind (wxEVT_TEXT, boost::bind(&EmailPage::user_changed, this));
909 _password->Changed.connect (boost::bind(&EmailPage::password_changed, this));
910 _send_test_email->Bind (wxEVT_BUTTON, boost::bind(&EmailPage::send_test_email_clicked, this));
913 void config_changed () override
915 auto config = Config::instance ();
917 checked_set (_server, config->mail_server());
918 checked_set (_port, config->mail_port());
919 switch (config->mail_protocol()) {
920 case EmailProtocol::AUTO:
921 checked_set (_protocol, 0);
923 case EmailProtocol::PLAIN:
924 checked_set (_protocol, 1);
926 case EmailProtocol::STARTTLS:
927 checked_set (_protocol, 2);
929 case EmailProtocol::SSL:
930 checked_set (_protocol, 3);
933 checked_set (_user, config->mail_user());
934 checked_set (_password, config->mail_password());
937 void server_changed ()
939 Config::instance()->set_mail_server(wx_to_std(_server->GetValue()));
944 Config::instance()->set_mail_port(_port->GetValue());
947 void protocol_changed ()
949 switch (_protocol->GetSelection()) {
951 Config::instance()->set_mail_protocol(EmailProtocol::AUTO);
954 Config::instance()->set_mail_protocol(EmailProtocol::PLAIN);
957 Config::instance()->set_mail_protocol(EmailProtocol::STARTTLS);
960 Config::instance()->set_mail_protocol(EmailProtocol::SSL);
967 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
970 void password_changed ()
972 Config::instance()->set_mail_password(_password->get());
975 void send_test_email_clicked ()
977 SendTestEmailDialog dialog(_panel);
978 if (dialog.ShowModal() != wxID_OK) {
983 wx_to_std(dialog.from()),
984 { wx_to_std(dialog.to()) },
985 wx_to_std(_("DCP-o-matic test email")),
986 wx_to_std(_("This is a test email from DCP-o-matic."))
988 auto config = Config::instance();
990 emailer.send(config->mail_server(), config->mail_port(), config->mail_protocol(), config->mail_user(), config->mail_password());
991 } catch (NetworkError& e) {
992 error_dialog(_panel, std_to_wx(e.summary()), std_to_wx(e.detail().get_value_or("")));
994 } catch (std::exception& e) {
995 error_dialog(_panel, _("Test email sending failed."), std_to_wx(e.what()));
998 error_dialog(_panel, _("Test email sending failed."));
1001 message_dialog(_panel, _("Test email sent."));
1004 wxTextCtrl* _server;
1006 wxChoice* _protocol;
1008 PasswordEntry* _password;
1009 Button* _send_test_email;
1013 class KDMEmailPage : public Page
1017 KDMEmailPage (wxSize panel_size, int border)
1018 #ifdef DCPOMATIC_OSX
1019 /* We have to force both width and height of this one */
1020 : Page (wxSize (panel_size.GetWidth(), 128), border)
1022 : Page (panel_size, border)
1026 wxString GetName () const override
1028 return _("KDM Email");
1031 #ifdef DCPOMATIC_OSX
1032 wxBitmap GetLargeIcon () const override
1034 return wxBitmap(icon_path("kdm_email"), wxBITMAP_TYPE_PNG);
1039 void setup () override
1041 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1042 table->AddGrowableCol (1, 1);
1043 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1045 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1046 _subject = new wxTextCtrl (_panel, wxID_ANY);
1047 table->Add (_subject, 1, wxEXPAND | wxALL);
1049 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1050 _from = new wxTextCtrl (_panel, wxID_ANY);
1051 table->Add (_from, 1, wxEXPAND | wxALL);
1053 vector<EditableListColumn> columns;
1054 columns.push_back (EditableListColumn(_("Address")));
1055 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1056 _cc = new EditableList<string, EmailDialog> (
1059 bind (&Config::kdm_cc, Config::instance()),
1060 bind (&Config::set_kdm_cc, Config::instance(), _1),
1061 [] (string s, int) {
1064 EditableListTitle::VISIBLE,
1065 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1067 table->Add (_cc, 1, wxEXPAND | wxALL);
1069 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1070 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1071 table->Add (_bcc, 1, wxEXPAND | wxALL);
1073 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1074 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1076 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1077 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1081 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1082 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1083 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1084 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1085 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
1088 void config_changed () override
1090 auto config = Config::instance ();
1092 checked_set (_subject, config->kdm_subject ());
1093 checked_set (_from, config->kdm_from ());
1094 checked_set (_bcc, config->kdm_bcc ());
1095 checked_set (_email, Config::instance()->kdm_email ());
1098 void kdm_subject_changed ()
1100 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
1103 void kdm_from_changed ()
1105 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
1108 void kdm_bcc_changed ()
1110 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
1113 void kdm_email_changed ()
1115 if (_email->GetValue().IsEmpty ()) {
1116 /* Sometimes we get sent an erroneous notification that the email
1117 is empty; I don't know why.
1121 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
1126 Config::instance()->reset_kdm_email ();
1127 checked_set (_email, Config::instance()->kdm_email ());
1130 wxTextCtrl* _subject;
1132 EditableList<string, EmailDialog>* _cc;
1135 wxButton* _reset_email;
1139 class NotificationsPage : public Page
1142 NotificationsPage (wxSize panel_size, int border)
1143 #ifdef DCPOMATIC_OSX
1144 /* We have to force both width and height of this one */
1145 : Page (wxSize (panel_size.GetWidth(), 128), border)
1147 : Page (panel_size, border)
1151 wxString GetName () const override
1153 return _("Notifications");
1156 #ifdef DCPOMATIC_OSX
1157 wxBitmap GetLargeIcon () const override
1159 return wxBitmap(icon_path("notifications"), wxBITMAP_TYPE_PNG);
1164 void setup () override
1166 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1167 table->AddGrowableCol (1, 1);
1168 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1170 _enable_message_box = new CheckBox (_panel, _("Message box"));
1171 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
1172 table->AddSpacer (0);
1174 _enable_email = new CheckBox (_panel, _("Email"));
1175 table->Add (_enable_email, 1, wxEXPAND | wxALL);
1176 table->AddSpacer (0);
1178 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1179 _subject = new wxTextCtrl (_panel, wxID_ANY);
1180 table->Add (_subject, 1, wxEXPAND | wxALL);
1182 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1183 _from = new wxTextCtrl (_panel, wxID_ANY);
1184 table->Add (_from, 1, wxEXPAND | wxALL);
1186 add_label_to_sizer (table, _panel, _("To address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1187 _to = new wxTextCtrl (_panel, wxID_ANY);
1188 table->Add (_to, 1, wxEXPAND | wxALL);
1190 vector<EditableListColumn> columns;
1191 columns.push_back (EditableListColumn(_("Address")));
1192 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1193 _cc = new EditableList<string, EmailDialog> (
1196 bind (&Config::notification_cc, Config::instance()),
1197 bind (&Config::set_notification_cc, Config::instance(), _1),
1198 [] (string s, int) {
1201 EditableListTitle::VISIBLE,
1202 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1204 table->Add (_cc, 1, wxEXPAND | wxALL);
1206 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1207 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1208 table->Add (_bcc, 1, wxEXPAND | wxALL);
1210 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1211 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1213 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1214 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1218 _enable_message_box->bind(&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX);
1219 _enable_email->bind(&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL);
1221 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
1222 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
1223 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
1224 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
1225 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
1226 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
1228 setup_sensitivity ();
1231 void setup_sensitivity ()
1233 bool const s = _enable_email->GetValue();
1234 _subject->Enable(s);
1240 _reset_email->Enable(s);
1243 void config_changed () override
1245 auto config = Config::instance ();
1247 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
1248 checked_set (_enable_email, config->notification(Config::EMAIL));
1249 checked_set (_subject, config->notification_subject ());
1250 checked_set (_from, config->notification_from ());
1251 checked_set (_to, config->notification_to ());
1252 checked_set (_bcc, config->notification_bcc ());
1253 checked_set (_email, Config::instance()->notification_email ());
1255 setup_sensitivity ();
1258 void notification_subject_changed ()
1260 Config::instance()->set_notification_subject(wx_to_std(_subject->GetValue()));
1263 void notification_from_changed ()
1265 Config::instance()->set_notification_from(wx_to_std(_from->GetValue()));
1268 void notification_to_changed ()
1270 Config::instance()->set_notification_to(wx_to_std(_to->GetValue()));
1273 void notification_bcc_changed ()
1275 Config::instance()->set_notification_bcc(wx_to_std(_bcc->GetValue()));
1278 void notification_email_changed ()
1280 if (_email->GetValue().IsEmpty()) {
1281 /* Sometimes we get sent an erroneous notification that the email
1282 is empty; I don't know why.
1286 Config::instance()->set_notification_email(wx_to_std(_email->GetValue()));
1291 Config::instance()->reset_notification_email();
1292 checked_set (_email, Config::instance()->notification_email());
1295 void type_changed (CheckBox* b, Config::Notification n)
1297 Config::instance()->set_notification(n, b->GetValue());
1298 setup_sensitivity ();
1301 CheckBox* _enable_message_box;
1302 CheckBox* _enable_email;
1304 wxTextCtrl* _subject;
1307 EditableList<string, EmailDialog>* _cc;
1310 wxButton* _reset_email;
1314 class CoverSheetPage : public Page
1318 CoverSheetPage (wxSize panel_size, int border)
1319 #ifdef DCPOMATIC_OSX
1320 /* We have to force both width and height of this one */
1321 : Page (wxSize (panel_size.GetWidth(), 128), border)
1323 : Page (panel_size, border)
1327 wxString GetName () const override
1329 return _("Cover Sheet");
1332 #ifdef DCPOMATIC_OSX
1333 wxBitmap GetLargeIcon () const override
1335 return wxBitmap(icon_path("cover_sheet"), wxBITMAP_TYPE_PNG);
1340 void setup () override
1342 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1343 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1345 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1346 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1348 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1349 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1352 void config_changed () override
1354 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1357 void cover_sheet_changed ()
1359 if (_cover_sheet->GetValue().IsEmpty ()) {
1360 /* Sometimes we get sent an erroneous notification that the cover sheet
1361 is empty; I don't know why.
1365 Config::instance()->set_cover_sheet(wx_to_std(_cover_sheet->GetValue()));
1368 void reset_cover_sheet ()
1370 Config::instance()->reset_cover_sheet();
1371 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1374 wxTextCtrl* _cover_sheet;
1375 wxButton* _reset_cover_sheet;
1379 class IdentifiersPage : public Page
1382 IdentifiersPage (wxSize panel_size, int border)
1383 : Page (panel_size, border)
1386 wxString GetName () const override
1388 return _("Identifiers");
1391 #ifdef DCPOMATIC_OSX
1392 wxBitmap GetLargeIcon () const override
1394 return wxBitmap(icon_path("identifiers"), wxBITMAP_TYPE_PNG);
1399 void setup () override
1401 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1402 table->AddGrowableCol (1, 1);
1404 add_label_to_sizer (table, _panel, _("Issuer"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1405 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1406 _issuer->SetToolTip (_("This will be written to the DCP's XML files as the <Issuer>. If it is blank, a default value mentioning DCP-o-matic will be used."));
1407 table->Add (_issuer, 1, wxALL | wxEXPAND);
1409 add_label_to_sizer (table, _panel, _("Creator"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1410 _creator = new wxTextCtrl (_panel, wxID_ANY);
1411 _creator->SetToolTip (_("This will be written to the DCP's XML files as the <Creator>. If it is blank, a default value mentioning DCP-o-matic will be used."));
1412 table->Add (_creator, 1, wxALL | wxEXPAND);
1414 add_label_to_sizer (table, _panel, _("Company name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1415 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1416 _company_name->SetToolTip (_("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 DCP-o-matic library) will be used."));
1417 table->Add (_company_name, 1, wxALL | wxEXPAND);
1419 add_label_to_sizer (table, _panel, _("Product name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1420 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1421 _product_name->SetToolTip (_("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 DCP-o-matic library) will be used."));
1422 table->Add (_product_name, 1, wxALL | wxEXPAND);
1424 add_label_to_sizer (table, _panel, _("Product version"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1425 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1426 _product_version->SetToolTip (_("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 DCP-o-matic library) will be used."));
1427 table->Add (_product_version, 1, wxALL | wxEXPAND);
1429 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1430 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1431 _j2k_comment->SetToolTip (_("This will be written to the DCP's JPEG2000 data as a comment. If it is blank, a default value mentioning libdcp (an internal DCP-o-matic library) will be used."));
1432 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1434 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1436 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1437 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1438 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1439 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1440 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1441 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1444 void config_changed () override
1446 auto config = Config::instance ();
1447 checked_set (_issuer, config->dcp_issuer ());
1448 checked_set (_creator, config->dcp_creator ());
1449 checked_set (_company_name, config->dcp_company_name ());
1450 checked_set (_product_name, config->dcp_product_name ());
1451 checked_set (_product_version, config->dcp_product_version ());
1452 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1455 void issuer_changed ()
1457 Config::instance()->set_dcp_issuer(wx_to_std(_issuer->GetValue()));
1460 void creator_changed ()
1462 Config::instance()->set_dcp_creator(wx_to_std(_creator->GetValue()));
1465 void company_name_changed ()
1467 Config::instance()->set_dcp_company_name(wx_to_std(_company_name->GetValue()));
1470 void product_name_changed ()
1472 Config::instance()->set_dcp_product_name(wx_to_std(_product_name->GetValue()));
1475 void product_version_changed ()
1477 Config::instance()->set_dcp_product_version(wx_to_std(_product_version->GetValue()));
1480 void j2k_comment_changed ()
1482 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1485 wxTextCtrl* _issuer;
1486 wxTextCtrl* _creator;
1487 wxTextCtrl* _company_name;
1488 wxTextCtrl* _product_name;
1489 wxTextCtrl* _product_version;
1490 wxTextCtrl* _j2k_comment;
1494 class NonStandardPage : public Page
1497 NonStandardPage(wxSize panel_size, int border)
1498 : Page(panel_size, border)
1501 wxString GetName() const override
1503 return _("Non-standard");
1506 #ifdef DCPOMATIC_OSX
1507 wxBitmap GetLargeIcon() const override
1509 return wxBitmap(icon_path("non_standard"), wxBITMAP_TYPE_PNG);
1514 void setup() override
1516 auto table = new wxFlexGridSizer(2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1517 table->AddGrowableCol(1, 1);
1518 _panel->GetSizer()->Add(table, 1, wxALL | wxEXPAND, _border);
1521 add_label_to_sizer(table, _panel, _("Maximum JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1522 auto s = new wxBoxSizer(wxHORIZONTAL);
1523 _maximum_j2k_bandwidth = new wxSpinCtrl(_panel);
1524 s->Add(_maximum_j2k_bandwidth, 1);
1525 add_label_to_sizer(s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxALIGN_CENTRE_VERTICAL);
1529 auto checkbox = [this, table](wxString name, CheckBox*& variable) {
1530 variable = new CheckBox(_panel, name);
1531 table->Add(variable, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1532 table->AddSpacer(0);
1535 checkbox(_("Allow any DCP frame rate"), _allow_any_dcp_frame_rate);
1537 _allow_any_container = new CheckBox(_panel, _("Allow full-frame and non-standard container ratios"));
1538 table->Add(_allow_any_container, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1539 auto restart = new StaticText(_panel, _("(restart DCP-o-matic to see all ratios)"));
1540 auto font = restart->GetFont();
1541 font.SetStyle(wxFONTSTYLE_ITALIC);
1542 font.SetPointSize(font.GetPointSize() - 1);
1543 restart->SetFont(font);
1544 table->Add(restart, 1, wxALIGN_CENTRE_VERTICAL | wxBOTTOM, DCPOMATIC_CHECKBOX_BOTTOM_PAD);
1545 restart->SetFont(font);
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_bandwidth->SetRange(1, 1000);
1560 _maximum_j2k_bandwidth->Bind(wxEVT_SPINCTRL, boost::bind(&NonStandardPage::maximum_j2k_bandwidth_changed, this));
1561 _allow_any_dcp_frame_rate->bind(&NonStandardPage::allow_any_dcp_frame_rate_changed, this);
1562 _allow_any_container->bind(&NonStandardPage::allow_any_container_changed, this);
1563 _allow_96khz_audio->bind(&NonStandardPage::allow_96khz_audio_changed, this);
1564 _use_all_audio_channels->bind(&NonStandardPage::use_all_channels_changed, this);
1565 _allow_smpte_bv20->bind(&NonStandardPage::allow_smpte_bv20_changed, this);
1566 _isdcf_name_part_length->SetRange(14, 256);
1567 _isdcf_name_part_length->Bind(wxEVT_SPINCTRL, boost::bind(&NonStandardPage::isdcf_name_part_length_changed, this));
1570 void config_changed() override
1572 auto config = Config::instance();
1574 checked_set(_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1575 checked_set(_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate());
1576 checked_set(_allow_any_container, config->allow_any_container());
1577 checked_set(_allow_96khz_audio, config->allow_96khz_audio());
1578 checked_set(_use_all_audio_channels, config->use_all_audio_channels());
1579 checked_set(_allow_smpte_bv20, config->allow_smpte_bv20());
1580 checked_set(_isdcf_name_part_length, config->isdcf_name_part_length());
1583 void maximum_j2k_bandwidth_changed()
1585 Config::instance()->set_maximum_j2k_bandwidth(_maximum_j2k_bandwidth->GetValue() * 1000000);
1588 void allow_any_dcp_frame_rate_changed()
1590 Config::instance()->set_allow_any_dcp_frame_rate(_allow_any_dcp_frame_rate->GetValue());
1593 void allow_any_container_changed()
1595 Config::instance()->set_allow_any_container(_allow_any_container->GetValue());
1598 void allow_96khz_audio_changed()
1600 Config::instance()->set_allow_96hhz_audio(_allow_96khz_audio->GetValue());
1603 void use_all_channels_changed()
1605 Config::instance()->set_use_all_audio_channels(_use_all_audio_channels->GetValue());
1608 void allow_smpte_bv20_changed()
1610 Config::instance()->set_allow_smpte_bv20(_allow_smpte_bv20->GetValue());
1613 void isdcf_name_part_length_changed()
1615 Config::instance()->set_isdcf_name_part_length(_isdcf_name_part_length->GetValue());
1618 wxSpinCtrl* _maximum_j2k_bandwidth = nullptr;
1619 CheckBox* _allow_any_dcp_frame_rate = nullptr;
1620 CheckBox* _allow_any_container = nullptr;
1621 CheckBox* _allow_96khz_audio = nullptr;
1622 CheckBox* _use_all_audio_channels = nullptr;
1623 CheckBox* _allow_smpte_bv20 = nullptr;
1624 wxSpinCtrl* _isdcf_name_part_length = nullptr;
1629 /** @class AdvancedPage
1630 * @brief Advanced page of the preferences dialog.
1632 class AdvancedPage : public Page
1635 AdvancedPage (wxSize panel_size, int border)
1636 : Page (panel_size, border)
1639 wxString GetName () const override
1641 return _("Advanced");
1644 #ifdef DCPOMATIC_OSX
1645 wxBitmap GetLargeIcon () const override
1647 return wxBitmap(icon_path("advanced"), wxBITMAP_TYPE_PNG);
1652 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1654 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1656 flags |= wxALIGN_RIGHT;
1659 wxStaticText* m = new StaticText (parent, text);
1660 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1663 void setup () override
1665 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1666 table->AddGrowableCol (1, 1);
1667 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1669 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1670 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1671 table->Add (_video_display_mode);
1673 auto restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1674 auto font = restart->GetFont();
1675 font.SetStyle (wxFONTSTYLE_ITALIC);
1676 font.SetPointSize (font.GetPointSize() - 1);
1677 restart->SetFont (font);
1678 table->AddSpacer (0);
1680 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1681 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1682 table->AddSpacer (0);
1684 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1685 table->Add (_only_servers_encode, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1686 table->AddSpacer (0);
1689 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1690 auto s = new wxBoxSizer (wxHORIZONTAL);
1691 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1692 s->Add (_frames_in_memory_multiplier, 1);
1697 auto format = create_label (_panel, _("DCP metadata filename format"), true);
1698 #ifdef DCPOMATIC_OSX
1699 auto align = new wxBoxSizer (wxHORIZONTAL);
1700 align->Add (format, 0, wxTOP, 2);
1701 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1703 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1705 dcp::NameFormat::Map titles;
1706 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1707 dcp::NameFormat::Map examples;
1708 examples['t'] = "cpl";
1709 _dcp_metadata_filename_format = new NameFormatEditor (
1710 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1712 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1716 auto format = create_label (_panel, _("DCP asset filename format"), true);
1717 #ifdef DCPOMATIC_OSX
1718 auto align = new wxBoxSizer (wxHORIZONTAL);
1719 align->Add (format, 0, wxTOP, 2);
1720 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1722 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1724 dcp::NameFormat::Map titles;
1725 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1726 titles['r'] = wx_to_std (_("reel number"));
1727 titles['n'] = wx_to_std (_("number of reels"));
1728 titles['c'] = wx_to_std (_("content filename"));
1729 dcp::NameFormat::Map examples;
1730 examples['t'] = "j2c";
1731 examples['r'] = "1";
1732 examples['n'] = "4";
1733 examples['c'] = "myfile.mp4";
1734 _dcp_asset_filename_format = new NameFormatEditor (
1735 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1737 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1741 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1742 auto t = new wxFlexGridSizer (2);
1743 _log_general = new CheckBox (_panel, _("General"));
1744 t->Add (_log_general, 1, wxEXPAND | wxALL);
1745 _log_warning = new CheckBox (_panel, _("Warnings"));
1746 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1747 _log_error = new CheckBox (_panel, _("Errors"));
1748 t->Add (_log_error, 1, wxEXPAND | wxALL);
1749 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1750 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1751 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1752 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1753 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1754 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1755 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1756 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1757 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1758 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1759 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1760 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1761 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1762 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1763 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1764 table->Add (t, 0, wxALL, 6);
1767 #ifdef DCPOMATIC_WINDOWS
1768 _win32_console = new CheckBox (_panel, _("Open console window"));
1769 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1770 table->AddSpacer (0);
1773 _video_display_mode->Append (_("Simple (safer)"));
1774 #if wxCHECK_VERSION(3, 1, 0)
1775 _video_display_mode->Append (_("OpenGL (faster)"));
1777 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1778 _show_experimental_audio_processors->bind(&AdvancedPage::show_experimental_audio_processors_changed, this);
1779 _only_servers_encode->bind(&AdvancedPage::only_servers_encode_changed, this);
1780 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1781 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1782 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1783 _log_general->bind(&AdvancedPage::log_changed, this);
1784 _log_warning->bind(&AdvancedPage::log_changed, this);
1785 _log_error->bind(&AdvancedPage::log_changed, this);
1786 _log_timing->bind(&AdvancedPage::log_changed, this);
1787 _log_debug_threed->bind(&AdvancedPage::log_changed, this);
1788 _log_debug_encode->bind(&AdvancedPage::log_changed, this);
1789 _log_debug_email->bind(&AdvancedPage::log_changed, this);
1790 _log_debug_video_view->bind(&AdvancedPage::log_changed, this);
1791 _log_debug_player->bind(&AdvancedPage::log_changed, this);
1792 _log_debug_audio_analysis->bind(&AdvancedPage::log_changed, this);
1793 #ifdef DCPOMATIC_WINDOWS
1794 _win32_console->bind(&AdvancedPage::win32_console_changed, this);
1798 void config_changed () override
1800 auto config = Config::instance ();
1802 switch (config->video_view_type()) {
1803 case Config::VIDEO_VIEW_SIMPLE:
1804 checked_set (_video_display_mode, 0);
1806 case Config::VIDEO_VIEW_OPENGL:
1807 checked_set (_video_display_mode, 1);
1810 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1811 checked_set (_only_servers_encode, config->only_servers_encode ());
1812 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1813 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1814 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1815 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1816 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREE_D);
1817 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1818 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1819 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1820 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1821 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1822 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1823 #ifdef DCPOMATIC_WINDOWS
1824 checked_set (_win32_console, config->win32_console());
1828 void video_display_mode_changed ()
1830 if (_video_display_mode->GetSelection() == 0) {
1831 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_SIMPLE);
1833 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_OPENGL);
1837 void frames_in_memory_multiplier_changed ()
1839 Config::instance()->set_frames_in_memory_multiplier(_frames_in_memory_multiplier->GetValue());
1842 void show_experimental_audio_processors_changed ()
1844 Config::instance()->set_show_experimental_audio_processors(_show_experimental_audio_processors->GetValue());
1847 void only_servers_encode_changed ()
1849 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue());
1852 void dcp_metadata_filename_format_changed ()
1854 Config::instance()->set_dcp_metadata_filename_format(_dcp_metadata_filename_format->get());
1857 void dcp_asset_filename_format_changed ()
1859 Config::instance()->set_dcp_asset_filename_format(_dcp_asset_filename_format->get());
1865 if (_log_general->GetValue ()) {
1866 types |= LogEntry::TYPE_GENERAL;
1868 if (_log_warning->GetValue ()) {
1869 types |= LogEntry::TYPE_WARNING;
1871 if (_log_error->GetValue ()) {
1872 types |= LogEntry::TYPE_ERROR;
1874 if (_log_timing->GetValue ()) {
1875 types |= LogEntry::TYPE_TIMING;
1877 if (_log_debug_threed->GetValue ()) {
1878 types |= LogEntry::TYPE_DEBUG_THREE_D;
1880 if (_log_debug_encode->GetValue ()) {
1881 types |= LogEntry::TYPE_DEBUG_ENCODE;
1883 if (_log_debug_email->GetValue ()) {
1884 types |= LogEntry::TYPE_DEBUG_EMAIL;
1886 if (_log_debug_video_view->GetValue()) {
1887 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1889 if (_log_debug_player->GetValue()) {
1890 types |= LogEntry::TYPE_DEBUG_PLAYER;
1892 if (_log_debug_audio_analysis->GetValue()) {
1893 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1895 Config::instance()->set_log_types (types);
1898 #ifdef DCPOMATIC_WINDOWS
1899 void win32_console_changed ()
1901 Config::instance()->set_win32_console(_win32_console->GetValue());
1905 wxChoice* _video_display_mode = nullptr;
1906 wxSpinCtrl* _frames_in_memory_multiplier = nullptr;
1907 CheckBox* _show_experimental_audio_processors = nullptr;
1908 CheckBox* _only_servers_encode = nullptr;
1909 NameFormatEditor* _dcp_metadata_filename_format = nullptr;
1910 NameFormatEditor* _dcp_asset_filename_format = nullptr;
1911 CheckBox* _log_general = nullptr;
1912 CheckBox* _log_warning = nullptr;
1913 CheckBox* _log_error = nullptr;
1914 CheckBox* _log_timing = nullptr;
1915 CheckBox* _log_debug_threed = nullptr;
1916 CheckBox* _log_debug_encode = nullptr;
1917 CheckBox* _log_debug_email = nullptr;
1918 CheckBox* _log_debug_video_view = nullptr;
1919 CheckBox* _log_debug_player = nullptr;
1920 CheckBox* _log_debug_audio_analysis = nullptr;
1921 #ifdef DCPOMATIC_WINDOWS
1922 CheckBox* _win32_console = nullptr;
1927 wxPreferencesEditor*
1928 create_full_config_dialog ()
1930 auto e = new wxPreferencesEditor ();
1932 #ifdef DCPOMATIC_OSX
1933 /* Width that we force some of the config panels to be on OSX so that
1934 the containing window doesn't shrink too much when we select those panels.
1935 This is obviously an unpleasant hack.
1937 wxSize ps = wxSize (750, -1);
1938 int const border = 16;
1940 wxSize ps = wxSize (-1, -1);
1941 int const border = 8;
1944 e->AddPage (new FullGeneralPage (ps, border));
1945 e->AddPage (new SoundPage (ps, border));
1946 e->AddPage (new DefaultsPage (ps, border));
1947 e->AddPage (new EncodingServersPage(ps, border));
1948 e->AddPage (new GPUPage (ps, border));
1949 e->AddPage (new KeysPage (ps, border));
1950 e->AddPage (new TMSPage (ps, border));
1951 e->AddPage (new EmailPage (ps, border));
1952 e->AddPage (new KDMEmailPage (ps, border));
1953 e->AddPage (new NotificationsPage (ps, border));
1954 e->AddPage (new CoverSheetPage (ps, border));
1955 e->AddPage (new IdentifiersPage (ps, border));
1956 e->AddPage (new NonStandardPage (ps, border));
1957 e->AddPage (new AdvancedPage (ps, border));