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 "dir_picker_ctrl.h"
32 #include "editable_list.h"
33 #include "email_dialog.h"
34 #include "file_picker_ctrl.h"
35 #include "filter_dialog.h"
36 #include "full_config_dialog.h"
37 #include "kdm_choice.h"
38 #include "language_tag_widget.h"
39 #include "make_chain_dialog.h"
40 #include "nag_dialog.h"
41 #include "name_format_editor.h"
42 #include "password_entry.h"
43 #include "region_subtag_widget.h"
44 #include "send_test_email_dialog.h"
45 #include "server_dialog.h"
46 #include "static_text.h"
48 #include "lib/config.h"
49 #include "lib/cross.h"
50 #include "lib/dcp_content_type.h"
51 #include "lib/emailer.h"
52 #include "lib/exceptions.h"
53 #include "lib/filter.h"
55 #include "lib/ratio.h"
57 #include <dcp/certificate_chain.h>
58 #include <dcp/exceptions.h>
59 #include <dcp/locale_convert.h>
60 #include <dcp/warnings.h>
61 LIBDCP_DISABLE_WARNINGS
62 #include <wx/filepicker.h>
63 #include <wx/preferences.h>
64 #include <wx/spinctrl.h>
65 #include <wx/stdpaths.h>
66 LIBDCP_ENABLE_WARNINGS
68 #include <boost/filesystem.hpp>
78 using std::shared_ptr;
82 using boost::optional;
83 #if BOOST_VERSION >= 106100
84 using namespace boost::placeholders;
86 using dcp::locale_convert;
89 class FullGeneralPage : public GeneralPage
92 FullGeneralPage (wxSize panel_size, int border)
93 : GeneralPage (panel_size, border)
97 void setup () override
99 auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
100 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
103 add_language_controls (table, r);
105 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
106 _master_encoding_threads = new wxSpinCtrl (_panel);
107 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
110 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
111 _server_encoding_threads = new wxSpinCtrl (_panel);
112 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
115 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
116 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, false);
117 table->Add (_config_file, wxGBPosition (r, 1));
120 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
121 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, false);
122 table->Add (_cinemas_file, wxGBPosition (r, 1));
123 auto export_cinemas = new Button (_panel, _("Export..."));
124 table->Add (export_cinemas, wxGBPosition (r, 2));
127 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
128 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
129 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
133 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
134 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
137 add_update_controls (table, r);
139 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::config_file_changed, this));
140 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::cinemas_file_changed, this));
142 _master_encoding_threads->SetRange (1, 128);
143 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
144 _server_encoding_threads->SetRange (1, 128);
145 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
146 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
148 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
149 _analyse_ebur128->bind(&FullGeneralPage::analyse_ebur128_changed, this);
151 _automatic_audio_analysis->bind(&FullGeneralPage::automatic_audio_analysis_changed, this);
154 void config_changed () override
156 auto config = Config::instance ();
158 checked_set (_master_encoding_threads, config->master_encoding_threads ());
159 checked_set (_server_encoding_threads, config->server_encoding_threads ());
160 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
161 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
163 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
164 checked_set (_config_file, config->config_read_file());
165 checked_set (_cinemas_file, config->cinemas_file());
167 GeneralPage::config_changed ();
170 void export_cinemas_file ()
172 auto d = new wxFileDialog (
173 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT("XML files (*.xml)|*.xml"),
174 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
177 if (d->ShowModal () == wxID_OK) {
178 boost::filesystem::copy_file(Config::instance()->cinemas_file(), wx_to_std(d->GetPath()), boost::filesystem::copy_option::overwrite_if_exists);
183 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
184 void analyse_ebur128_changed ()
186 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue());
190 void automatic_audio_analysis_changed ()
192 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue());
195 void master_encoding_threads_changed ()
197 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue());
200 void server_encoding_threads_changed ()
202 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue());
205 void config_file_changed ()
207 auto config = Config::instance();
208 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
209 if (new_file == config->config_read_file()) {
212 bool copy_and_link = true;
213 if (boost::filesystem::exists(new_file)) {
214 auto d = new ConfigMoveDialog (_panel, new_file);
215 if (d->ShowModal() == wxID_OK) {
216 copy_and_link = false;
223 if (new_file != config->config_read_file()) {
224 config->copy_and_link (new_file);
227 config->link (new_file);
231 void cinemas_file_changed ()
233 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
236 wxSpinCtrl* _master_encoding_threads;
237 wxSpinCtrl* _server_encoding_threads;
238 FilePickerCtrl* _config_file;
239 FilePickerCtrl* _cinemas_file;
240 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
241 CheckBox* _analyse_ebur128;
243 CheckBox* _automatic_audio_analysis;
247 class DefaultsPage : public Page
250 DefaultsPage (wxSize panel_size, int border)
251 : Page (panel_size, border)
254 wxString GetName () const override
256 return _("Defaults");
260 wxBitmap GetLargeIcon () const override
262 return wxBitmap(icon_path("defaults"), wxBITMAP_TYPE_PNG);
267 void setup () override
269 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
270 table->AddGrowableCol (1, 1);
271 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
274 add_label_to_sizer (table, _panel, _("Default duration of still images"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
275 auto s = new wxBoxSizer (wxHORIZONTAL);
276 _still_length = new wxSpinCtrl (_panel);
277 s->Add (_still_length);
278 add_label_to_sizer (s, _panel, _("s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
282 add_label_to_sizer (table, _panel, _("Default directory for new films"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
283 #ifdef DCPOMATIC_USE_OWN_PICKER
284 _directory = new DirPickerCtrl (_panel);
286 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
288 table->Add (_directory, 1, wxEXPAND);
290 add_label_to_sizer (table, _panel, _("Default content type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
291 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
292 table->Add (_dcp_content_type);
294 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
295 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
296 table->Add (_dcp_audio_channels);
299 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
300 auto s = new wxBoxSizer (wxHORIZONTAL);
301 _j2k_bandwidth = new wxSpinCtrl (_panel);
302 s->Add (_j2k_bandwidth);
303 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
308 add_label_to_sizer (table, _panel, _("Default audio delay"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
309 auto s = new wxBoxSizer (wxHORIZONTAL);
310 _audio_delay = new wxSpinCtrl (_panel);
311 s->Add (_audio_delay);
312 add_label_to_sizer (s, _panel, _("ms"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
316 add_label_to_sizer (table, _panel, _("Default standard"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
317 _standard = new wxChoice (_panel, wxID_ANY);
318 table->Add (_standard);
320 _enable_audio_language = new CheckBox(_panel, _("Default audio language"));
321 table->Add(_enable_audio_language, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
322 _audio_language = new LanguageTagWidget(_panel, _("Default audio language to use for new DCPs"), Config::instance()->default_audio_language(), wxString("cmnr-Hant-"));
323 table->Add(_audio_language->sizer());
325 _enable_territory = new CheckBox(_panel, _("Default territory"));
326 table->Add(_enable_territory, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
327 _territory = new RegionSubtagWidget(_panel, _("Default territory to use for new DCPs"), Config::instance()->default_territory(), wxString("cmnr-Hant-"));
328 table->Add(_territory->sizer());
330 table->Add (_enable_metadata["facility"] = new CheckBox (_panel, _("Default facility")), 0, wxALIGN_CENTRE_VERTICAL);
331 table->Add (_metadata["facility"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
333 table->Add (_enable_metadata["studio"] = new CheckBox (_panel, _("Default studio")), 0, wxALIGN_CENTRE_VERTICAL);
334 table->Add (_metadata["studio"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
336 table->Add (_enable_metadata["chain"] = new CheckBox (_panel, _("Default chain")), 0, wxALIGN_CENTRE_VERTICAL);
337 table->Add (_metadata["chain"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
339 table->Add (_enable_metadata["distributor"] = new CheckBox (_panel, _("Default distributor")), 0, wxALIGN_CENTRE_VERTICAL);
340 table->Add (_metadata["distributor"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
342 add_label_to_sizer (table, _panel, _("Default KDM directory"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
343 #ifdef DCPOMATIC_USE_OWN_PICKER
344 _kdm_directory = new DirPickerCtrl (_panel);
346 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
348 table->Add (_kdm_directory, 1, wxEXPAND);
350 add_label_to_sizer (table, _panel, _("Default KDM type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
351 _kdm_type = new KDMChoice (_panel);
352 table->Add (_kdm_type, 1, wxEXPAND);
354 add_label_to_sizer (table, _panel, _("Default KDM duration"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
355 _kdm_duration = new wxSpinCtrl (_panel);
356 _kdm_duration_unit = new wxChoice (_panel, wxID_ANY);
357 auto kdm_duration_sizer = new wxBoxSizer (wxHORIZONTAL);
358 kdm_duration_sizer->Add (_kdm_duration, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
359 kdm_duration_sizer->Add (_kdm_duration_unit, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
360 table->Add (kdm_duration_sizer, 1, wxEXPAND);
362 table->Add (_use_isdcf_name_by_default = new CheckBox(_panel, _("Use ISDCF name by default")), 0, wxALIGN_CENTRE_VERTICAL);
364 _still_length->SetRange (1, 3600);
365 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
367 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
368 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
369 _kdm_type->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_type_changed, this));
370 _kdm_duration_unit->Append (_("days"));
371 _kdm_duration_unit->Append (_("weeks"));
372 _kdm_duration_unit->Append (_("months"));
373 _kdm_duration_unit->Append (_("years"));
375 _kdm_duration->Bind (wxEVT_SPINCTRL, boost::bind(&DefaultsPage::kdm_duration_changed, this));
376 _kdm_duration_unit->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_duration_changed, this));
378 _use_isdcf_name_by_default->bind(&DefaultsPage::use_isdcf_name_by_default_changed, this);
380 for (auto i: DCPContentType::all()) {
381 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
384 setup_audio_channels_choice (_dcp_audio_channels, 2);
386 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
387 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
389 _j2k_bandwidth->SetRange (50, 250);
390 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
392 _audio_delay->SetRange (-1000, 1000);
393 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
395 _standard->Append (_("SMPTE"));
396 _standard->Append (_("Interop"));
397 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
399 for (auto const& i: _enable_metadata) {
400 i.second->bind(&DefaultsPage::metadata_changed, this);
403 for (auto const& i: _metadata) {
404 i.second->Bind (wxEVT_TEXT, boost::bind(&DefaultsPage::metadata_changed, this));
407 _enable_audio_language->bind(&DefaultsPage::enable_audio_language_toggled, this);
408 _audio_language->Changed.connect(boost::bind(&DefaultsPage::audio_language_changed, this));
410 _enable_territory->bind(&DefaultsPage::enable_territory_toggled, this);
411 _territory->Changed.connect(boost::bind(&DefaultsPage::territory_changed, this));
414 void config_changed () override
416 auto config = Config::instance ();
418 auto const ct = DCPContentType::all ();
419 for (size_t i = 0; i < ct.size(); ++i) {
420 if (ct[i] == config->default_dcp_content_type()) {
421 _dcp_content_type->SetSelection (i);
425 checked_set (_still_length, config->default_still_length ());
426 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
427 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
428 _kdm_type->set (config->default_kdm_type());
429 checked_set (_use_isdcf_name_by_default, config->use_isdcf_name_by_default());
430 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
431 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
432 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
433 checked_set (_audio_delay, config->default_audio_delay ());
434 checked_set (_standard, config->default_interop() ? 1 : 0);
435 auto dal = config->default_audio_language();
436 checked_set(_enable_audio_language, static_cast<bool>(dal));
437 checked_set(_audio_language, dal ? dal : boost::none);
438 auto dt = config->default_territory();
439 checked_set(_enable_territory, static_cast<bool>(dt));
440 checked_set(_territory, dt ? dt : boost::none);
442 auto metadata = config->default_metadata();
444 for (auto const& i: metadata) {
445 _enable_metadata[i.first]->SetValue(true);
446 checked_set (_metadata[i.first], i.second);
449 for (auto const& i: _enable_metadata) {
450 if (metadata.find(i.first) == metadata.end()) {
451 checked_set (i.second, false);
455 for (auto const& i: _metadata) {
456 if (metadata.find(i.first) == metadata.end()) {
457 checked_set (i.second, wxT(""));
461 checked_set (_kdm_duration, config->default_kdm_duration().duration);
462 switch (config->default_kdm_duration().unit) {
463 case RoughDuration::Unit::DAYS:
464 _kdm_duration->SetRange(1, 365);
465 checked_set (_kdm_duration_unit, 0);
467 case RoughDuration::Unit::WEEKS:
468 _kdm_duration->SetRange(1, 52);
469 checked_set (_kdm_duration_unit, 1);
471 case RoughDuration::Unit::MONTHS:
472 _kdm_duration->SetRange(1, 12);
473 checked_set (_kdm_duration_unit, 2);
475 case RoughDuration::Unit::YEARS:
476 _kdm_duration->SetRange(1, 40);
477 checked_set (_kdm_duration_unit, 3);
481 setup_sensitivity ();
484 void kdm_duration_changed ()
486 auto config = Config::instance();
487 auto duration = _kdm_duration->GetValue();
488 RoughDuration::Unit unit = RoughDuration::Unit::DAYS;
489 switch (_kdm_duration_unit->GetSelection()) {
491 unit = RoughDuration::Unit::DAYS;
494 unit = RoughDuration::Unit::WEEKS;
497 unit = RoughDuration::Unit::MONTHS;
500 unit = RoughDuration::Unit::YEARS;
503 config->set_default_kdm_duration (RoughDuration(duration, unit));
506 void j2k_bandwidth_changed ()
508 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
511 void audio_delay_changed ()
513 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
516 void dcp_audio_channels_changed ()
518 int const s = _dcp_audio_channels->GetSelection ();
519 if (s != wxNOT_FOUND) {
520 Config::instance()->set_default_dcp_audio_channels (
521 locale_convert<int>(string_client_data(_dcp_audio_channels->GetClientObject(s)))
526 void directory_changed ()
528 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
531 void kdm_directory_changed ()
533 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
536 void kdm_type_changed ()
538 Config::instance()->set_default_kdm_type(_kdm_type->get());
541 void use_isdcf_name_by_default_changed ()
543 Config::instance()->set_use_isdcf_name_by_default (_use_isdcf_name_by_default->GetValue());
546 void still_length_changed ()
548 Config::instance()->set_default_still_length (_still_length->GetValue ());
551 void dcp_content_type_changed ()
553 auto ct = DCPContentType::all ();
554 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
557 void standard_changed ()
559 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
562 void metadata_changed ()
564 map<string, string> metadata;
565 for (auto const& i: _enable_metadata) {
566 if (i.second->GetValue()) {
567 metadata[i.first] = wx_to_std(_metadata[i.first]->GetValue());
570 Config::instance()->set_default_metadata (metadata);
571 setup_sensitivity ();
574 void enable_audio_language_toggled()
577 audio_language_changed();
580 void audio_language_changed()
582 if (_enable_audio_language->get()) {
583 Config::instance()->set_default_audio_language(_audio_language->get().get_value_or(dcp::LanguageTag("en-US")));
585 Config::instance()->unset_default_audio_language();
589 void enable_territory_toggled()
595 void territory_changed()
597 if (_enable_territory->get()) {
598 Config::instance()->set_default_territory(_territory->get().get_value_or(dcp::LanguageTag::RegionSubtag("US")));
600 Config::instance()->unset_default_territory();
604 void setup_sensitivity ()
606 _audio_language->enable(_enable_audio_language->get());
607 _territory->enable(_enable_territory->get());
608 for (auto const& i: _enable_metadata) {
609 _metadata[i.first]->Enable(i.second->GetValue());
613 wxSpinCtrl* _j2k_bandwidth;
614 wxSpinCtrl* _audio_delay;
615 wxSpinCtrl* _still_length;
616 #ifdef DCPOMATIC_USE_OWN_PICKER
617 DirPickerCtrl* _directory;
618 DirPickerCtrl* _kdm_directory;
620 wxDirPickerCtrl* _directory;
621 wxDirPickerCtrl* _kdm_directory;
623 KDMChoice* _kdm_type;
624 wxSpinCtrl* _kdm_duration;
625 wxChoice* _kdm_duration_unit;
626 CheckBox* _use_isdcf_name_by_default;
627 wxChoice* _dcp_content_type;
628 wxChoice* _dcp_audio_channels;
630 CheckBox* _enable_audio_language;
631 LanguageTagWidget* _audio_language;
632 CheckBox* _enable_territory;
633 RegionSubtagWidget* _territory;
634 map<string, CheckBox*> _enable_metadata;
635 map<string, wxTextCtrl*> _metadata;
639 class EncodingServersPage : public Page
642 EncodingServersPage (wxSize panel_size, int border)
643 : Page (panel_size, border)
646 wxString GetName () const override
652 wxBitmap GetLargeIcon () const override
654 return wxBitmap(icon_path("servers"), wxBITMAP_TYPE_PNG);
659 void setup () override
661 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
662 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
664 vector<EditableListColumn> columns;
665 columns.push_back (EditableListColumn(_("IP address / host name")));
666 _servers_list = new EditableList<string, ServerDialog> (
669 boost::bind (&Config::servers, Config::instance()),
670 boost::bind (&Config::set_servers, Config::instance(), _1),
671 boost::bind (&EncodingServersPage::server_column, this, _1),
672 EditableListTitle::INVISIBLE,
673 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
676 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
678 _use_any_servers->bind(&EncodingServersPage::use_any_servers_changed, this);
681 void config_changed () override
683 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
684 _servers_list->refresh ();
687 void use_any_servers_changed ()
689 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
692 string server_column (string s)
697 CheckBox* _use_any_servers;
698 EditableList<string, ServerDialog>* _servers_list;
702 class TMSPage : public Page
705 TMSPage (wxSize panel_size, int border)
706 : Page (panel_size, border)
709 wxString GetName () const override
715 wxBitmap GetLargeIcon () const override
717 return wxBitmap(icon_path("tms"), wxBITMAP_TYPE_PNG);
722 void setup () override
724 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
725 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
727 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
728 table->AddGrowableCol (1, 1);
729 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
731 add_label_to_sizer (table, _panel, _("Protocol"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
732 _tms_protocol = new wxChoice (_panel, wxID_ANY);
733 table->Add (_tms_protocol, 1, wxEXPAND);
735 _tms_passive = new CheckBox(_panel, _("Passive mode"));
736 table->Add(_tms_passive, 1, wxEXPAND);
739 add_label_to_sizer (table, _panel, _("IP address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
740 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
741 table->Add (_tms_ip, 1, wxEXPAND);
743 add_label_to_sizer (table, _panel, _("Target path"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
744 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
745 table->Add (_tms_path, 1, wxEXPAND);
747 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
748 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
749 table->Add (_tms_user, 1, wxEXPAND);
751 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
752 _tms_password = new PasswordEntry (_panel);
753 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
755 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
756 _tms_protocol->Append (_("FTP (for Dolby)"));
758 _upload->bind(&TMSPage::upload_changed, this);
759 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
760 _tms_passive->bind(&TMSPage::tms_passive_changed, this);
762 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
763 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
764 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
765 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
768 void config_changed () override
770 auto config = Config::instance ();
772 checked_set (_upload, config->upload_after_make_dcp());
773 checked_set (_tms_protocol, static_cast<int>(config->tms_protocol()));
774 checked_set(_tms_passive, config->tms_protocol() == FileTransferProtocol::FTP && config->tms_passive());
775 checked_set (_tms_ip, config->tms_ip ());
776 checked_set (_tms_path, config->tms_path ());
777 checked_set (_tms_user, config->tms_user ());
778 checked_set (_tms_password, config->tms_password ());
780 _tms_passive->Enable(config->tms_protocol() == FileTransferProtocol::FTP);
783 void upload_changed ()
785 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
788 void tms_protocol_changed ()
790 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
793 void tms_passive_changed()
795 Config::instance()->set_tms_passive(_tms_passive->get());
798 void tms_ip_changed ()
800 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
803 void tms_path_changed ()
805 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
808 void tms_user_changed ()
810 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
813 void tms_password_changed ()
815 Config::instance()->set_tms_password (_tms_password->get());
819 CheckBox* _tms_passive;
820 wxChoice* _tms_protocol;
822 wxTextCtrl* _tms_path;
823 wxTextCtrl* _tms_user;
824 PasswordEntry* _tms_password;
828 class EmailPage : public Page
831 EmailPage (wxSize panel_size, int border)
832 : Page (panel_size, border)
835 wxString GetName () const override
841 wxBitmap GetLargeIcon () const override
843 return wxBitmap(icon_path("email"), wxBITMAP_TYPE_PNG);
848 void setup () override
850 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
851 table->AddGrowableCol (1, 1);
852 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
854 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
856 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
857 _server = new wxTextCtrl (_panel, wxID_ANY);
858 s->Add (_server, 1, wxEXPAND | wxALL);
859 add_label_to_sizer (s, _panel, _("port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
860 _port = new wxSpinCtrl (_panel, wxID_ANY);
861 _port->SetRange (0, 65535);
863 add_label_to_sizer (s, _panel, _("protocol"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
864 _protocol = new wxChoice (_panel, wxID_ANY);
865 /* Make sure this matches the switches in config_changed and port_changed below */
866 _protocol->Append (_("Auto"));
867 _protocol->Append (_("Plain"));
868 _protocol->Append (_("STARTTLS"));
869 _protocol->Append (_("SSL"));
870 s->Add (_protocol, 1, wxALIGN_CENTER_VERTICAL);
871 table->Add (s, 1, wxEXPAND | wxALL);
874 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
875 _user = new wxTextCtrl (_panel, wxID_ANY);
876 table->Add (_user, 1, wxEXPAND | wxALL);
878 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
879 _password = new PasswordEntry (_panel);
880 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
882 table->AddSpacer (0);
883 _send_test_email = new Button (_panel, _("Send test email..."));
884 table->Add (_send_test_email);
886 _server->Bind (wxEVT_TEXT, boost::bind(&EmailPage::server_changed, this));
887 _port->Bind (wxEVT_SPINCTRL, boost::bind(&EmailPage::port_changed, this));
888 _protocol->Bind (wxEVT_CHOICE, boost::bind(&EmailPage::protocol_changed, this));
889 _user->Bind (wxEVT_TEXT, boost::bind(&EmailPage::user_changed, this));
890 _password->Changed.connect (boost::bind(&EmailPage::password_changed, this));
891 _send_test_email->Bind (wxEVT_BUTTON, boost::bind(&EmailPage::send_test_email_clicked, this));
894 void config_changed () override
896 auto config = Config::instance ();
898 checked_set (_server, config->mail_server());
899 checked_set (_port, config->mail_port());
900 switch (config->mail_protocol()) {
901 case EmailProtocol::AUTO:
902 checked_set (_protocol, 0);
904 case EmailProtocol::PLAIN:
905 checked_set (_protocol, 1);
907 case EmailProtocol::STARTTLS:
908 checked_set (_protocol, 2);
910 case EmailProtocol::SSL:
911 checked_set (_protocol, 3);
914 checked_set (_user, config->mail_user());
915 checked_set (_password, config->mail_password());
918 void server_changed ()
920 Config::instance()->set_mail_server(wx_to_std(_server->GetValue()));
925 Config::instance()->set_mail_port(_port->GetValue());
928 void protocol_changed ()
930 switch (_protocol->GetSelection()) {
932 Config::instance()->set_mail_protocol(EmailProtocol::AUTO);
935 Config::instance()->set_mail_protocol(EmailProtocol::PLAIN);
938 Config::instance()->set_mail_protocol(EmailProtocol::STARTTLS);
941 Config::instance()->set_mail_protocol(EmailProtocol::SSL);
948 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
951 void password_changed ()
953 Config::instance()->set_mail_password(_password->get());
956 void send_test_email_clicked ()
958 auto dialog = new SendTestEmailDialog(_panel);
959 auto result = dialog->ShowModal();
961 if (result == wxID_OK) {
963 wx_to_std(dialog->from()),
964 { wx_to_std(dialog->to()) },
965 wx_to_std(_("DCP-o-matic test email")),
966 wx_to_std(_("This is a test email from DCP-o-matic."))
968 auto config = Config::instance();
970 emailer.send (config->mail_server(), config->mail_port(), config->mail_protocol(), config->mail_user(), config->mail_password());
971 } catch (NetworkError& e) {
972 error_dialog (_panel, std_to_wx(e.summary()), std_to_wx(e.detail().get_value_or("")));
974 } catch (std::exception& e) {
975 error_dialog (_panel, _("Test email sending failed."), std_to_wx(e.what()));
978 error_dialog (_panel, _("Test email sending failed."));
981 message_dialog (_panel, _("Test email sent."));
989 PasswordEntry* _password;
990 Button* _send_test_email;
994 class KDMEmailPage : public Page
998 KDMEmailPage (wxSize panel_size, int border)
1000 /* We have to force both width and height of this one */
1001 : Page (wxSize (panel_size.GetWidth(), 128), border)
1003 : Page (panel_size, border)
1007 wxString GetName () const override
1009 return _("KDM Email");
1012 #ifdef DCPOMATIC_OSX
1013 wxBitmap GetLargeIcon () const override
1015 return wxBitmap(icon_path("kdm_email"), wxBITMAP_TYPE_PNG);
1020 void setup () override
1022 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1023 table->AddGrowableCol (1, 1);
1024 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1026 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1027 _subject = new wxTextCtrl (_panel, wxID_ANY);
1028 table->Add (_subject, 1, wxEXPAND | wxALL);
1030 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1031 _from = new wxTextCtrl (_panel, wxID_ANY);
1032 table->Add (_from, 1, wxEXPAND | wxALL);
1034 vector<EditableListColumn> columns;
1035 columns.push_back (EditableListColumn(_("Address")));
1036 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1037 _cc = new EditableList<string, EmailDialog> (
1040 bind (&Config::kdm_cc, Config::instance()),
1041 bind (&Config::set_kdm_cc, Config::instance(), _1),
1042 [] (string s, int) {
1045 EditableListTitle::VISIBLE,
1046 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1048 table->Add (_cc, 1, wxEXPAND | wxALL);
1050 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1051 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1052 table->Add (_bcc, 1, wxEXPAND | wxALL);
1054 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1055 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1057 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1058 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1062 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1063 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1064 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1065 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1066 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
1069 void config_changed () override
1071 auto config = Config::instance ();
1073 checked_set (_subject, config->kdm_subject ());
1074 checked_set (_from, config->kdm_from ());
1075 checked_set (_bcc, config->kdm_bcc ());
1076 checked_set (_email, Config::instance()->kdm_email ());
1079 void kdm_subject_changed ()
1081 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
1084 void kdm_from_changed ()
1086 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
1089 void kdm_bcc_changed ()
1091 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
1094 void kdm_email_changed ()
1096 if (_email->GetValue().IsEmpty ()) {
1097 /* Sometimes we get sent an erroneous notification that the email
1098 is empty; I don't know why.
1102 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
1107 Config::instance()->reset_kdm_email ();
1108 checked_set (_email, Config::instance()->kdm_email ());
1111 wxTextCtrl* _subject;
1113 EditableList<string, EmailDialog>* _cc;
1116 wxButton* _reset_email;
1120 class NotificationsPage : public Page
1123 NotificationsPage (wxSize panel_size, int border)
1124 #ifdef DCPOMATIC_OSX
1125 /* We have to force both width and height of this one */
1126 : Page (wxSize (panel_size.GetWidth(), 128), border)
1128 : Page (panel_size, border)
1132 wxString GetName () const override
1134 return _("Notifications");
1137 #ifdef DCPOMATIC_OSX
1138 wxBitmap GetLargeIcon () const override
1140 return wxBitmap(icon_path("notifications"), wxBITMAP_TYPE_PNG);
1145 void setup () override
1147 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1148 table->AddGrowableCol (1, 1);
1149 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1151 _enable_message_box = new CheckBox (_panel, _("Message box"));
1152 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
1153 table->AddSpacer (0);
1155 _enable_email = new CheckBox (_panel, _("Email"));
1156 table->Add (_enable_email, 1, wxEXPAND | wxALL);
1157 table->AddSpacer (0);
1159 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1160 _subject = new wxTextCtrl (_panel, wxID_ANY);
1161 table->Add (_subject, 1, wxEXPAND | wxALL);
1163 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1164 _from = new wxTextCtrl (_panel, wxID_ANY);
1165 table->Add (_from, 1, wxEXPAND | wxALL);
1167 add_label_to_sizer (table, _panel, _("To address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1168 _to = new wxTextCtrl (_panel, wxID_ANY);
1169 table->Add (_to, 1, wxEXPAND | wxALL);
1171 vector<EditableListColumn> columns;
1172 columns.push_back (EditableListColumn(_("Address")));
1173 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1174 _cc = new EditableList<string, EmailDialog> (
1177 bind (&Config::notification_cc, Config::instance()),
1178 bind (&Config::set_notification_cc, Config::instance(), _1),
1179 [] (string s, int) {
1182 EditableListTitle::VISIBLE,
1183 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1185 table->Add (_cc, 1, wxEXPAND | wxALL);
1187 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1188 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1189 table->Add (_bcc, 1, wxEXPAND | wxALL);
1191 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1192 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1194 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1195 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1199 _enable_message_box->bind(&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX);
1200 _enable_email->bind(&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL);
1202 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
1203 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
1204 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
1205 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
1206 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
1207 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
1209 setup_sensitivity ();
1212 void setup_sensitivity ()
1214 bool const s = _enable_email->GetValue();
1215 _subject->Enable(s);
1221 _reset_email->Enable(s);
1224 void config_changed () override
1226 auto config = Config::instance ();
1228 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
1229 checked_set (_enable_email, config->notification(Config::EMAIL));
1230 checked_set (_subject, config->notification_subject ());
1231 checked_set (_from, config->notification_from ());
1232 checked_set (_to, config->notification_to ());
1233 checked_set (_bcc, config->notification_bcc ());
1234 checked_set (_email, Config::instance()->notification_email ());
1236 setup_sensitivity ();
1239 void notification_subject_changed ()
1241 Config::instance()->set_notification_subject(wx_to_std(_subject->GetValue()));
1244 void notification_from_changed ()
1246 Config::instance()->set_notification_from(wx_to_std(_from->GetValue()));
1249 void notification_to_changed ()
1251 Config::instance()->set_notification_to(wx_to_std(_to->GetValue()));
1254 void notification_bcc_changed ()
1256 Config::instance()->set_notification_bcc(wx_to_std(_bcc->GetValue()));
1259 void notification_email_changed ()
1261 if (_email->GetValue().IsEmpty()) {
1262 /* Sometimes we get sent an erroneous notification that the email
1263 is empty; I don't know why.
1267 Config::instance()->set_notification_email(wx_to_std(_email->GetValue()));
1272 Config::instance()->reset_notification_email();
1273 checked_set (_email, Config::instance()->notification_email());
1276 void type_changed (CheckBox* b, Config::Notification n)
1278 Config::instance()->set_notification(n, b->GetValue());
1279 setup_sensitivity ();
1282 CheckBox* _enable_message_box;
1283 CheckBox* _enable_email;
1285 wxTextCtrl* _subject;
1288 EditableList<string, EmailDialog>* _cc;
1291 wxButton* _reset_email;
1295 class CoverSheetPage : public Page
1299 CoverSheetPage (wxSize panel_size, int border)
1300 #ifdef DCPOMATIC_OSX
1301 /* We have to force both width and height of this one */
1302 : Page (wxSize (panel_size.GetWidth(), 128), border)
1304 : Page (panel_size, border)
1308 wxString GetName () const override
1310 return _("Cover Sheet");
1313 #ifdef DCPOMATIC_OSX
1314 wxBitmap GetLargeIcon () const override
1316 return wxBitmap(icon_path("cover_sheet"), wxBITMAP_TYPE_PNG);
1321 void setup () override
1323 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1324 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1326 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1327 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1329 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1330 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1333 void config_changed () override
1335 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1338 void cover_sheet_changed ()
1340 if (_cover_sheet->GetValue().IsEmpty ()) {
1341 /* Sometimes we get sent an erroneous notification that the cover sheet
1342 is empty; I don't know why.
1346 Config::instance()->set_cover_sheet(wx_to_std(_cover_sheet->GetValue()));
1349 void reset_cover_sheet ()
1351 Config::instance()->reset_cover_sheet();
1352 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1355 wxTextCtrl* _cover_sheet;
1356 wxButton* _reset_cover_sheet;
1360 class IdentifiersPage : public Page
1363 IdentifiersPage (wxSize panel_size, int border)
1364 : Page (panel_size, border)
1367 wxString GetName () const override
1369 return _("Identifiers");
1372 #ifdef DCPOMATIC_OSX
1373 wxBitmap GetLargeIcon () const override
1375 return wxBitmap(icon_path("identifiers"), wxBITMAP_TYPE_PNG);
1380 void setup () override
1382 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1383 table->AddGrowableCol (1, 1);
1385 add_label_to_sizer (table, _panel, _("Issuer"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1386 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1387 _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."));
1388 table->Add (_issuer, 1, wxALL | wxEXPAND);
1390 add_label_to_sizer (table, _panel, _("Creator"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1391 _creator = new wxTextCtrl (_panel, wxID_ANY);
1392 _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."));
1393 table->Add (_creator, 1, wxALL | wxEXPAND);
1395 add_label_to_sizer (table, _panel, _("Company name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1396 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1397 _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."));
1398 table->Add (_company_name, 1, wxALL | wxEXPAND);
1400 add_label_to_sizer (table, _panel, _("Product name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1401 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1402 _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."));
1403 table->Add (_product_name, 1, wxALL | wxEXPAND);
1405 add_label_to_sizer (table, _panel, _("Product version"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1406 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1407 _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."));
1408 table->Add (_product_version, 1, wxALL | wxEXPAND);
1410 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1411 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1412 _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."));
1413 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1415 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1417 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1418 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1419 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1420 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1421 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1422 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1425 void config_changed () override
1427 auto config = Config::instance ();
1428 checked_set (_issuer, config->dcp_issuer ());
1429 checked_set (_creator, config->dcp_creator ());
1430 checked_set (_company_name, config->dcp_company_name ());
1431 checked_set (_product_name, config->dcp_product_name ());
1432 checked_set (_product_version, config->dcp_product_version ());
1433 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1436 void issuer_changed ()
1438 Config::instance()->set_dcp_issuer(wx_to_std(_issuer->GetValue()));
1441 void creator_changed ()
1443 Config::instance()->set_dcp_creator(wx_to_std(_creator->GetValue()));
1446 void company_name_changed ()
1448 Config::instance()->set_dcp_company_name(wx_to_std(_company_name->GetValue()));
1451 void product_name_changed ()
1453 Config::instance()->set_dcp_product_name(wx_to_std(_product_name->GetValue()));
1456 void product_version_changed ()
1458 Config::instance()->set_dcp_product_version(wx_to_std(_product_version->GetValue()));
1461 void j2k_comment_changed ()
1463 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1466 wxTextCtrl* _issuer;
1467 wxTextCtrl* _creator;
1468 wxTextCtrl* _company_name;
1469 wxTextCtrl* _product_name;
1470 wxTextCtrl* _product_version;
1471 wxTextCtrl* _j2k_comment;
1475 /** @class AdvancedPage
1476 * @brief Advanced page of the preferences dialog.
1478 class AdvancedPage : public Page
1481 AdvancedPage (wxSize panel_size, int border)
1482 : Page (panel_size, border)
1485 wxString GetName () const override
1487 return _("Advanced");
1490 #ifdef DCPOMATIC_OSX
1491 wxBitmap GetLargeIcon () const override
1493 return wxBitmap(icon_path("advanced"), wxBITMAP_TYPE_PNG);
1498 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1500 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1502 flags |= wxALIGN_RIGHT;
1505 wxStaticText* m = new StaticText (parent, text);
1506 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1509 void setup () override
1511 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1512 table->AddGrowableCol (1, 1);
1513 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1516 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1517 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1518 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1519 s->Add (_maximum_j2k_bandwidth, 1);
1520 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxALIGN_CENTRE_VERTICAL);
1524 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1525 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1526 table->Add (_video_display_mode);
1528 auto restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1529 auto font = restart->GetFont();
1530 font.SetStyle (wxFONTSTYLE_ITALIC);
1531 font.SetPointSize (font.GetPointSize() - 1);
1532 restart->SetFont (font);
1533 table->AddSpacer (0);
1535 _allow_any_dcp_frame_rate = new CheckBox (_panel, _("Allow any DCP frame rate"));
1536 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1537 table->AddSpacer (0);
1539 _allow_any_container = new CheckBox (_panel, _("Allow full-frame and non-standard container ratios"));
1540 table->Add (_allow_any_container, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1541 restart = new StaticText (_panel, _("(restart DCP-o-matic to see all ratios)"));
1542 table->Add (restart, 1, wxEXPAND | wxALL | wxALIGN_CENTRE_VERTICAL);
1543 restart->SetFont (font);
1545 _allow_96khz_audio = new CheckBox (_panel, _("Allow creation of DCPs with 96kHz audio"));
1546 table->Add (_allow_96khz_audio, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1547 table->AddSpacer (0);
1549 _use_all_audio_channels = new CheckBox(_panel, _("Allow mapping to all audio channels"));
1550 table->Add(_use_all_audio_channels, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1551 table->AddSpacer(0);
1553 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1554 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1555 table->AddSpacer (0);
1557 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1558 table->Add (_only_servers_encode, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1559 table->AddSpacer (0);
1562 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1563 auto s = new wxBoxSizer (wxHORIZONTAL);
1564 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1565 s->Add (_frames_in_memory_multiplier, 1);
1570 auto format = create_label (_panel, _("DCP metadata filename format"), true);
1571 #ifdef DCPOMATIC_OSX
1572 auto align = new wxBoxSizer (wxHORIZONTAL);
1573 align->Add (format, 0, wxTOP, 2);
1574 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1576 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1578 dcp::NameFormat::Map titles;
1579 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1580 dcp::NameFormat::Map examples;
1581 examples['t'] = "cpl";
1582 _dcp_metadata_filename_format = new NameFormatEditor (
1583 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1585 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1589 auto format = create_label (_panel, _("DCP asset 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 (j2c/pcm/sub)"));
1599 titles['r'] = wx_to_std (_("reel number"));
1600 titles['n'] = wx_to_std (_("number of reels"));
1601 titles['c'] = wx_to_std (_("content filename"));
1602 dcp::NameFormat::Map examples;
1603 examples['t'] = "j2c";
1604 examples['r'] = "1";
1605 examples['n'] = "4";
1606 examples['c'] = "myfile.mp4";
1607 _dcp_asset_filename_format = new NameFormatEditor (
1608 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1610 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1614 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1615 auto t = new wxFlexGridSizer (2);
1616 _log_general = new CheckBox (_panel, _("General"));
1617 t->Add (_log_general, 1, wxEXPAND | wxALL);
1618 _log_warning = new CheckBox (_panel, _("Warnings"));
1619 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1620 _log_error = new CheckBox (_panel, _("Errors"));
1621 t->Add (_log_error, 1, wxEXPAND | wxALL);
1622 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1623 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1624 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1625 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1626 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1627 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1628 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1629 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1630 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1631 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1632 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1633 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1634 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1635 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1636 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1637 table->Add (t, 0, wxALL, 6);
1640 #ifdef DCPOMATIC_WINDOWS
1641 _win32_console = new CheckBox (_panel, _("Open console window"));
1642 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1643 table->AddSpacer (0);
1646 _maximum_j2k_bandwidth->SetRange (1, 1000);
1647 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1648 _video_display_mode->Append (_("Simple (safer)"));
1649 #if wxCHECK_VERSION(3, 1, 0)
1650 _video_display_mode->Append (_("OpenGL (faster)"));
1652 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1653 _allow_any_dcp_frame_rate->bind(&AdvancedPage::allow_any_dcp_frame_rate_changed, this);
1654 _allow_any_container->bind(&AdvancedPage::allow_any_container_changed, this);
1655 _allow_96khz_audio->bind(&AdvancedPage::allow_96khz_audio_changed, this);
1656 _use_all_audio_channels->bind(&AdvancedPage::use_all_channels_changed, this);
1657 _show_experimental_audio_processors->bind(&AdvancedPage::show_experimental_audio_processors_changed, this);
1658 _only_servers_encode->bind(&AdvancedPage::only_servers_encode_changed, this);
1659 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1660 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1661 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1662 _log_general->bind(&AdvancedPage::log_changed, this);
1663 _log_warning->bind(&AdvancedPage::log_changed, this);
1664 _log_error->bind(&AdvancedPage::log_changed, this);
1665 _log_timing->bind(&AdvancedPage::log_changed, this);
1666 _log_debug_threed->bind(&AdvancedPage::log_changed, this);
1667 _log_debug_encode->bind(&AdvancedPage::log_changed, this);
1668 _log_debug_email->bind(&AdvancedPage::log_changed, this);
1669 _log_debug_video_view->bind(&AdvancedPage::log_changed, this);
1670 _log_debug_player->bind(&AdvancedPage::log_changed, this);
1671 _log_debug_audio_analysis->bind(&AdvancedPage::log_changed, this);
1672 #ifdef DCPOMATIC_WINDOWS
1673 _win32_console->bind(&AdvancedPage::win32_console_changed, this);
1677 void config_changed () override
1679 auto config = Config::instance ();
1681 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1682 switch (config->video_view_type()) {
1683 case Config::VIDEO_VIEW_SIMPLE:
1684 checked_set (_video_display_mode, 0);
1686 case Config::VIDEO_VIEW_OPENGL:
1687 checked_set (_video_display_mode, 1);
1690 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1691 checked_set (_allow_any_container, config->allow_any_container ());
1692 checked_set (_allow_96khz_audio, config->allow_96khz_audio());
1693 checked_set (_use_all_audio_channels, config->use_all_audio_channels());
1694 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1695 checked_set (_only_servers_encode, config->only_servers_encode ());
1696 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1697 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1698 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1699 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1700 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREE_D);
1701 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1702 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1703 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1704 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1705 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1706 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1707 #ifdef DCPOMATIC_WINDOWS
1708 checked_set (_win32_console, config->win32_console());
1712 void maximum_j2k_bandwidth_changed ()
1714 Config::instance()->set_maximum_j2k_bandwidth(_maximum_j2k_bandwidth->GetValue() * 1000000);
1717 void video_display_mode_changed ()
1719 if (_video_display_mode->GetSelection() == 0) {
1720 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_SIMPLE);
1722 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_OPENGL);
1726 void frames_in_memory_multiplier_changed ()
1728 Config::instance()->set_frames_in_memory_multiplier(_frames_in_memory_multiplier->GetValue());
1731 void allow_any_dcp_frame_rate_changed ()
1733 Config::instance()->set_allow_any_dcp_frame_rate(_allow_any_dcp_frame_rate->GetValue());
1736 void allow_any_container_changed ()
1738 Config::instance()->set_allow_any_container(_allow_any_container->GetValue());
1741 void allow_96khz_audio_changed ()
1743 Config::instance()->set_allow_96hhz_audio(_allow_96khz_audio->GetValue());
1746 void use_all_channels_changed ()
1748 Config::instance()->set_use_all_audio_channels(_use_all_audio_channels->GetValue());
1751 void show_experimental_audio_processors_changed ()
1753 Config::instance()->set_show_experimental_audio_processors(_show_experimental_audio_processors->GetValue());
1756 void only_servers_encode_changed ()
1758 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue());
1761 void dcp_metadata_filename_format_changed ()
1763 Config::instance()->set_dcp_metadata_filename_format(_dcp_metadata_filename_format->get());
1766 void dcp_asset_filename_format_changed ()
1768 Config::instance()->set_dcp_asset_filename_format(_dcp_asset_filename_format->get());
1774 if (_log_general->GetValue ()) {
1775 types |= LogEntry::TYPE_GENERAL;
1777 if (_log_warning->GetValue ()) {
1778 types |= LogEntry::TYPE_WARNING;
1780 if (_log_error->GetValue ()) {
1781 types |= LogEntry::TYPE_ERROR;
1783 if (_log_timing->GetValue ()) {
1784 types |= LogEntry::TYPE_TIMING;
1786 if (_log_debug_threed->GetValue ()) {
1787 types |= LogEntry::TYPE_DEBUG_THREE_D;
1789 if (_log_debug_encode->GetValue ()) {
1790 types |= LogEntry::TYPE_DEBUG_ENCODE;
1792 if (_log_debug_email->GetValue ()) {
1793 types |= LogEntry::TYPE_DEBUG_EMAIL;
1795 if (_log_debug_video_view->GetValue()) {
1796 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1798 if (_log_debug_player->GetValue()) {
1799 types |= LogEntry::TYPE_DEBUG_PLAYER;
1801 if (_log_debug_audio_analysis->GetValue()) {
1802 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1804 Config::instance()->set_log_types (types);
1807 #ifdef DCPOMATIC_WINDOWS
1808 void win32_console_changed ()
1810 Config::instance()->set_win32_console(_win32_console->GetValue());
1814 wxSpinCtrl* _maximum_j2k_bandwidth = nullptr;
1815 wxChoice* _video_display_mode = nullptr;
1816 wxSpinCtrl* _frames_in_memory_multiplier = nullptr;
1817 CheckBox* _allow_any_dcp_frame_rate = nullptr;
1818 CheckBox* _allow_any_container = nullptr;
1819 CheckBox* _allow_96khz_audio = nullptr;
1820 CheckBox* _use_all_audio_channels = nullptr;
1821 CheckBox* _show_experimental_audio_processors = nullptr;
1822 CheckBox* _only_servers_encode = nullptr;
1823 NameFormatEditor* _dcp_metadata_filename_format = nullptr;
1824 NameFormatEditor* _dcp_asset_filename_format = nullptr;
1825 CheckBox* _log_general = nullptr;
1826 CheckBox* _log_warning = nullptr;
1827 CheckBox* _log_error = nullptr;
1828 CheckBox* _log_timing = nullptr;
1829 CheckBox* _log_debug_threed = nullptr;
1830 CheckBox* _log_debug_encode = nullptr;
1831 CheckBox* _log_debug_email = nullptr;
1832 CheckBox* _log_debug_video_view = nullptr;
1833 CheckBox* _log_debug_player = nullptr;
1834 CheckBox* _log_debug_audio_analysis = nullptr;
1835 #ifdef DCPOMATIC_WINDOWS
1836 CheckBox* _win32_console = nullptr;
1841 wxPreferencesEditor*
1842 create_full_config_dialog ()
1844 auto e = new wxPreferencesEditor ();
1846 #ifdef DCPOMATIC_OSX
1847 /* Width that we force some of the config panels to be on OSX so that
1848 the containing window doesn't shrink too much when we select those panels.
1849 This is obviously an unpleasant hack.
1851 wxSize ps = wxSize (750, -1);
1852 int const border = 16;
1854 wxSize ps = wxSize (-1, -1);
1855 int const border = 8;
1858 e->AddPage (new FullGeneralPage (ps, border));
1859 e->AddPage (new SoundPage (ps, border));
1860 e->AddPage (new DefaultsPage (ps, border));
1861 e->AddPage (new EncodingServersPage(ps, border));
1862 e->AddPage (new KeysPage (ps, border));
1863 e->AddPage (new TMSPage (ps, border));
1864 e->AddPage (new EmailPage (ps, border));
1865 e->AddPage (new KDMEmailPage (ps, border));
1866 e->AddPage (new NotificationsPage (ps, border));
1867 e->AddPage (new CoverSheetPage (ps, border));
1868 e->AddPage (new IdentifiersPage (ps, border));
1869 e->AddPage (new AdvancedPage (ps, border));