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 "lib/config.h"
50 #include "lib/cross.h"
51 #include "lib/dcp_content_type.h"
52 #include "lib/emailer.h"
53 #include "lib/exceptions.h"
54 #include "lib/filter.h"
56 #include "lib/ratio.h"
58 #include <dcp/certificate_chain.h>
59 #include <dcp/exceptions.h>
60 #include <dcp/locale_convert.h>
61 #include <dcp/warnings.h>
62 LIBDCP_DISABLE_WARNINGS
63 #include <wx/filepicker.h>
64 #include <wx/preferences.h>
65 #include <wx/spinctrl.h>
66 #include <wx/stdpaths.h>
67 LIBDCP_ENABLE_WARNINGS
69 #include <boost/filesystem.hpp>
79 using std::shared_ptr;
83 using boost::optional;
84 #if BOOST_VERSION >= 106100
85 using namespace boost::placeholders;
87 using dcp::locale_convert;
90 class FullGeneralPage : public GeneralPage
93 FullGeneralPage (wxSize panel_size, int border)
94 : GeneralPage (panel_size, border)
98 void setup () override
100 auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
101 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
104 add_language_controls (table, r);
106 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
107 _master_encoding_threads = new wxSpinCtrl (_panel);
108 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
111 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
112 _server_encoding_threads = new wxSpinCtrl (_panel);
113 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
116 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
117 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, false);
118 table->Add (_config_file, wxGBPosition (r, 1));
121 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
122 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, false);
123 table->Add (_cinemas_file, wxGBPosition (r, 1));
124 auto export_cinemas = new Button (_panel, _("Export..."));
125 table->Add (export_cinemas, wxGBPosition (r, 2));
128 add_label_to_sizer(table, _panel, _("Default \"add file\" location"), true, wxGBPosition(r, 0));
129 _default_add_file_location = new Choice(_panel);
130 table->Add(_default_add_file_location, wxGBPosition(r, 1));
133 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
134 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
135 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
139 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
140 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
143 add_update_controls (table, r);
145 _default_add_file_location->add(_("Same place as last time"));
146 _default_add_file_location->add(_("Same place as project"));
147 _default_add_file_location->bind(&FullGeneralPage::default_add_file_location_changed, this);
149 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::config_file_changed, this));
150 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::cinemas_file_changed, this));
152 _master_encoding_threads->SetRange (1, 128);
153 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
154 _server_encoding_threads->SetRange (1, 128);
155 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
156 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
158 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
159 _analyse_ebur128->bind(&FullGeneralPage::analyse_ebur128_changed, this);
161 _automatic_audio_analysis->bind(&FullGeneralPage::automatic_audio_analysis_changed, this);
164 void config_changed () override
166 auto config = Config::instance ();
168 checked_set (_master_encoding_threads, config->master_encoding_threads ());
169 checked_set (_server_encoding_threads, config->server_encoding_threads ());
170 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
171 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
173 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
174 checked_set (_config_file, config->config_read_file());
175 checked_set (_cinemas_file, config->cinemas_file());
176 checked_set(_default_add_file_location, config->default_add_file_location() == Config::DefaultAddFileLocation::SAME_AS_LAST_TIME ? 0 : 1);
178 GeneralPage::config_changed ();
181 void export_cinemas_file ()
183 auto d = new wxFileDialog (
184 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT("XML files (*.xml)|*.xml"),
185 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
188 if (d->ShowModal () == wxID_OK) {
189 boost::filesystem::copy_file(Config::instance()->cinemas_file(), wx_to_std(d->GetPath()), boost::filesystem::copy_option::overwrite_if_exists);
194 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
195 void analyse_ebur128_changed ()
197 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue());
201 void automatic_audio_analysis_changed ()
203 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue());
206 void master_encoding_threads_changed ()
208 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue());
211 void server_encoding_threads_changed ()
213 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue());
216 void config_file_changed ()
218 auto config = Config::instance();
219 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
220 if (new_file == config->config_read_file()) {
223 bool copy_and_link = true;
224 if (boost::filesystem::exists(new_file)) {
225 auto d = new ConfigMoveDialog (_panel, new_file);
226 if (d->ShowModal() == wxID_OK) {
227 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 auto dialog = new SendTestEmailDialog(_panel);
978 auto result = dialog->ShowModal();
980 if (result == wxID_OK) {
982 wx_to_std(dialog->from()),
983 { wx_to_std(dialog->to()) },
984 wx_to_std(_("DCP-o-matic test email")),
985 wx_to_std(_("This is a test email from DCP-o-matic."))
987 auto config = Config::instance();
989 emailer.send (config->mail_server(), config->mail_port(), config->mail_protocol(), config->mail_user(), config->mail_password());
990 } catch (NetworkError& e) {
991 error_dialog (_panel, std_to_wx(e.summary()), std_to_wx(e.detail().get_value_or("")));
993 } catch (std::exception& e) {
994 error_dialog (_panel, _("Test email sending failed."), std_to_wx(e.what()));
997 error_dialog (_panel, _("Test email sending failed."));
1000 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 AdvancedPage
1495 * @brief Advanced page of the preferences dialog.
1497 class AdvancedPage : public Page
1500 AdvancedPage (wxSize panel_size, int border)
1501 : Page (panel_size, border)
1504 wxString GetName () const override
1506 return _("Advanced");
1509 #ifdef DCPOMATIC_OSX
1510 wxBitmap GetLargeIcon () const override
1512 return wxBitmap(icon_path("advanced"), wxBITMAP_TYPE_PNG);
1517 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1519 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1521 flags |= wxALIGN_RIGHT;
1524 wxStaticText* m = new StaticText (parent, text);
1525 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1528 void setup () override
1530 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1531 table->AddGrowableCol (1, 1);
1532 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1535 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1536 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1537 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1538 s->Add (_maximum_j2k_bandwidth, 1);
1539 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxALIGN_CENTRE_VERTICAL);
1543 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1544 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1545 table->Add (_video_display_mode);
1547 auto restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1548 auto font = restart->GetFont();
1549 font.SetStyle (wxFONTSTYLE_ITALIC);
1550 font.SetPointSize (font.GetPointSize() - 1);
1551 restart->SetFont (font);
1552 table->AddSpacer (0);
1554 _allow_any_dcp_frame_rate = new CheckBox (_panel, _("Allow any DCP frame rate"));
1555 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1556 table->AddSpacer (0);
1558 _allow_any_container = new CheckBox (_panel, _("Allow full-frame and non-standard container ratios"));
1559 table->Add (_allow_any_container, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1560 restart = new StaticText (_panel, _("(restart DCP-o-matic to see all ratios)"));
1561 table->Add (restart, 1, wxEXPAND | wxALL | wxALIGN_CENTRE_VERTICAL);
1562 restart->SetFont (font);
1564 _allow_96khz_audio = new CheckBox (_panel, _("Allow creation of DCPs with 96kHz audio"));
1565 table->Add (_allow_96khz_audio, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1566 table->AddSpacer (0);
1568 _use_all_audio_channels = new CheckBox(_panel, _("Allow mapping to all audio channels"));
1569 table->Add(_use_all_audio_channels, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1570 table->AddSpacer(0);
1572 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1573 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1574 table->AddSpacer (0);
1576 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1577 table->Add (_only_servers_encode, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1578 table->AddSpacer (0);
1581 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1582 auto s = new wxBoxSizer (wxHORIZONTAL);
1583 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1584 s->Add (_frames_in_memory_multiplier, 1);
1589 auto format = create_label (_panel, _("DCP metadata filename format"), true);
1590 #ifdef DCPOMATIC_OSX
1591 auto align = new wxBoxSizer (wxHORIZONTAL);
1592 align->Add (format, 0, wxTOP, 2);
1593 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1595 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1597 dcp::NameFormat::Map titles;
1598 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1599 dcp::NameFormat::Map examples;
1600 examples['t'] = "cpl";
1601 _dcp_metadata_filename_format = new NameFormatEditor (
1602 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1604 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1608 auto format = create_label (_panel, _("DCP asset filename format"), true);
1609 #ifdef DCPOMATIC_OSX
1610 auto align = new wxBoxSizer (wxHORIZONTAL);
1611 align->Add (format, 0, wxTOP, 2);
1612 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1614 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1616 dcp::NameFormat::Map titles;
1617 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1618 titles['r'] = wx_to_std (_("reel number"));
1619 titles['n'] = wx_to_std (_("number of reels"));
1620 titles['c'] = wx_to_std (_("content filename"));
1621 dcp::NameFormat::Map examples;
1622 examples['t'] = "j2c";
1623 examples['r'] = "1";
1624 examples['n'] = "4";
1625 examples['c'] = "myfile.mp4";
1626 _dcp_asset_filename_format = new NameFormatEditor (
1627 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1629 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1633 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1634 auto t = new wxFlexGridSizer (2);
1635 _log_general = new CheckBox (_panel, _("General"));
1636 t->Add (_log_general, 1, wxEXPAND | wxALL);
1637 _log_warning = new CheckBox (_panel, _("Warnings"));
1638 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1639 _log_error = new CheckBox (_panel, _("Errors"));
1640 t->Add (_log_error, 1, wxEXPAND | wxALL);
1641 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1642 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1643 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1644 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1645 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1646 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1647 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1648 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1649 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1650 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1651 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1652 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1653 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1654 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1655 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1656 table->Add (t, 0, wxALL, 6);
1659 #ifdef DCPOMATIC_WINDOWS
1660 _win32_console = new CheckBox (_panel, _("Open console window"));
1661 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1662 table->AddSpacer (0);
1665 _maximum_j2k_bandwidth->SetRange (1, 1000);
1666 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1667 _video_display_mode->Append (_("Simple (safer)"));
1668 #if wxCHECK_VERSION(3, 1, 0)
1669 _video_display_mode->Append (_("OpenGL (faster)"));
1671 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1672 _allow_any_dcp_frame_rate->bind(&AdvancedPage::allow_any_dcp_frame_rate_changed, this);
1673 _allow_any_container->bind(&AdvancedPage::allow_any_container_changed, this);
1674 _allow_96khz_audio->bind(&AdvancedPage::allow_96khz_audio_changed, this);
1675 _use_all_audio_channels->bind(&AdvancedPage::use_all_channels_changed, this);
1676 _show_experimental_audio_processors->bind(&AdvancedPage::show_experimental_audio_processors_changed, this);
1677 _only_servers_encode->bind(&AdvancedPage::only_servers_encode_changed, this);
1678 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1679 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1680 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1681 _log_general->bind(&AdvancedPage::log_changed, this);
1682 _log_warning->bind(&AdvancedPage::log_changed, this);
1683 _log_error->bind(&AdvancedPage::log_changed, this);
1684 _log_timing->bind(&AdvancedPage::log_changed, this);
1685 _log_debug_threed->bind(&AdvancedPage::log_changed, this);
1686 _log_debug_encode->bind(&AdvancedPage::log_changed, this);
1687 _log_debug_email->bind(&AdvancedPage::log_changed, this);
1688 _log_debug_video_view->bind(&AdvancedPage::log_changed, this);
1689 _log_debug_player->bind(&AdvancedPage::log_changed, this);
1690 _log_debug_audio_analysis->bind(&AdvancedPage::log_changed, this);
1691 #ifdef DCPOMATIC_WINDOWS
1692 _win32_console->bind(&AdvancedPage::win32_console_changed, this);
1696 void config_changed () override
1698 auto config = Config::instance ();
1700 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1701 switch (config->video_view_type()) {
1702 case Config::VIDEO_VIEW_SIMPLE:
1703 checked_set (_video_display_mode, 0);
1705 case Config::VIDEO_VIEW_OPENGL:
1706 checked_set (_video_display_mode, 1);
1709 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1710 checked_set (_allow_any_container, config->allow_any_container ());
1711 checked_set (_allow_96khz_audio, config->allow_96khz_audio());
1712 checked_set (_use_all_audio_channels, config->use_all_audio_channels());
1713 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1714 checked_set (_only_servers_encode, config->only_servers_encode ());
1715 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1716 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1717 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1718 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1719 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREE_D);
1720 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1721 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1722 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1723 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1724 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1725 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1726 #ifdef DCPOMATIC_WINDOWS
1727 checked_set (_win32_console, config->win32_console());
1731 void maximum_j2k_bandwidth_changed ()
1733 Config::instance()->set_maximum_j2k_bandwidth(_maximum_j2k_bandwidth->GetValue() * 1000000);
1736 void video_display_mode_changed ()
1738 if (_video_display_mode->GetSelection() == 0) {
1739 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_SIMPLE);
1741 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_OPENGL);
1745 void frames_in_memory_multiplier_changed ()
1747 Config::instance()->set_frames_in_memory_multiplier(_frames_in_memory_multiplier->GetValue());
1750 void allow_any_dcp_frame_rate_changed ()
1752 Config::instance()->set_allow_any_dcp_frame_rate(_allow_any_dcp_frame_rate->GetValue());
1755 void allow_any_container_changed ()
1757 Config::instance()->set_allow_any_container(_allow_any_container->GetValue());
1760 void allow_96khz_audio_changed ()
1762 Config::instance()->set_allow_96hhz_audio(_allow_96khz_audio->GetValue());
1765 void use_all_channels_changed ()
1767 Config::instance()->set_use_all_audio_channels(_use_all_audio_channels->GetValue());
1770 void show_experimental_audio_processors_changed ()
1772 Config::instance()->set_show_experimental_audio_processors(_show_experimental_audio_processors->GetValue());
1775 void only_servers_encode_changed ()
1777 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue());
1780 void dcp_metadata_filename_format_changed ()
1782 Config::instance()->set_dcp_metadata_filename_format(_dcp_metadata_filename_format->get());
1785 void dcp_asset_filename_format_changed ()
1787 Config::instance()->set_dcp_asset_filename_format(_dcp_asset_filename_format->get());
1793 if (_log_general->GetValue ()) {
1794 types |= LogEntry::TYPE_GENERAL;
1796 if (_log_warning->GetValue ()) {
1797 types |= LogEntry::TYPE_WARNING;
1799 if (_log_error->GetValue ()) {
1800 types |= LogEntry::TYPE_ERROR;
1802 if (_log_timing->GetValue ()) {
1803 types |= LogEntry::TYPE_TIMING;
1805 if (_log_debug_threed->GetValue ()) {
1806 types |= LogEntry::TYPE_DEBUG_THREE_D;
1808 if (_log_debug_encode->GetValue ()) {
1809 types |= LogEntry::TYPE_DEBUG_ENCODE;
1811 if (_log_debug_email->GetValue ()) {
1812 types |= LogEntry::TYPE_DEBUG_EMAIL;
1814 if (_log_debug_video_view->GetValue()) {
1815 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1817 if (_log_debug_player->GetValue()) {
1818 types |= LogEntry::TYPE_DEBUG_PLAYER;
1820 if (_log_debug_audio_analysis->GetValue()) {
1821 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1823 Config::instance()->set_log_types (types);
1826 #ifdef DCPOMATIC_WINDOWS
1827 void win32_console_changed ()
1829 Config::instance()->set_win32_console(_win32_console->GetValue());
1833 wxSpinCtrl* _maximum_j2k_bandwidth = nullptr;
1834 wxChoice* _video_display_mode = nullptr;
1835 wxSpinCtrl* _frames_in_memory_multiplier = nullptr;
1836 CheckBox* _allow_any_dcp_frame_rate = nullptr;
1837 CheckBox* _allow_any_container = nullptr;
1838 CheckBox* _allow_96khz_audio = nullptr;
1839 CheckBox* _use_all_audio_channels = nullptr;
1840 CheckBox* _show_experimental_audio_processors = nullptr;
1841 CheckBox* _only_servers_encode = nullptr;
1842 NameFormatEditor* _dcp_metadata_filename_format = nullptr;
1843 NameFormatEditor* _dcp_asset_filename_format = nullptr;
1844 CheckBox* _log_general = nullptr;
1845 CheckBox* _log_warning = nullptr;
1846 CheckBox* _log_error = nullptr;
1847 CheckBox* _log_timing = nullptr;
1848 CheckBox* _log_debug_threed = nullptr;
1849 CheckBox* _log_debug_encode = nullptr;
1850 CheckBox* _log_debug_email = nullptr;
1851 CheckBox* _log_debug_video_view = nullptr;
1852 CheckBox* _log_debug_player = nullptr;
1853 CheckBox* _log_debug_audio_analysis = nullptr;
1854 #ifdef DCPOMATIC_WINDOWS
1855 CheckBox* _win32_console = nullptr;
1860 wxPreferencesEditor*
1861 create_full_config_dialog ()
1863 auto e = new wxPreferencesEditor ();
1865 #ifdef DCPOMATIC_OSX
1866 /* Width that we force some of the config panels to be on OSX so that
1867 the containing window doesn't shrink too much when we select those panels.
1868 This is obviously an unpleasant hack.
1870 wxSize ps = wxSize (750, -1);
1871 int const border = 16;
1873 wxSize ps = wxSize (-1, -1);
1874 int const border = 8;
1877 e->AddPage (new FullGeneralPage (ps, border));
1878 e->AddPage (new SoundPage (ps, border));
1879 e->AddPage (new DefaultsPage (ps, border));
1880 e->AddPage (new EncodingServersPage(ps, border));
1881 e->AddPage (new KeysPage (ps, border));
1882 e->AddPage (new TMSPage (ps, border));
1883 e->AddPage (new EmailPage (ps, border));
1884 e->AddPage (new KDMEmailPage (ps, border));
1885 e->AddPage (new NotificationsPage (ps, border));
1886 e->AddPage (new CoverSheetPage (ps, border));
1887 e->AddPage (new IdentifiersPage (ps, border));
1888 e->AddPage (new AdvancedPage (ps, border));