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/filesystem.h>
61 #include <dcp/locale_convert.h>
62 #include <dcp/warnings.h>
63 LIBDCP_DISABLE_WARNINGS
64 #include <wx/filepicker.h>
65 #include <wx/preferences.h>
66 #include <wx/spinctrl.h>
67 #include <wx/stdpaths.h>
68 LIBDCP_ENABLE_WARNINGS
70 #include <boost/filesystem.hpp>
80 using std::shared_ptr;
84 using boost::optional;
85 #if BOOST_VERSION >= 106100
86 using namespace boost::placeholders;
88 using dcp::locale_convert;
91 class FullGeneralPage : public GeneralPage
94 FullGeneralPage (wxSize panel_size, int border)
95 : GeneralPage (panel_size, border)
99 void setup () override
101 auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
102 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
105 add_language_controls (table, r);
107 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
108 _master_encoding_threads = new wxSpinCtrl (_panel);
109 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
112 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
113 _server_encoding_threads = new wxSpinCtrl (_panel);
114 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
117 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
118 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, false);
119 table->Add (_config_file, wxGBPosition (r, 1));
122 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
123 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, false);
124 table->Add (_cinemas_file, wxGBPosition (r, 1));
125 auto export_cinemas = new Button (_panel, _("Export..."));
126 table->Add (export_cinemas, wxGBPosition (r, 2));
129 add_label_to_sizer(table, _panel, _("Default \"add file\" location"), true, wxGBPosition(r, 0));
130 _default_add_file_location = new Choice(_panel);
131 table->Add(_default_add_file_location, wxGBPosition(r, 1));
134 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
135 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
136 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
140 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
141 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
144 add_update_controls (table, r);
146 _default_add_file_location->add(_("Same place as last time"));
147 _default_add_file_location->add(_("Same place as project"));
148 _default_add_file_location->bind(&FullGeneralPage::default_add_file_location_changed, this);
150 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::config_file_changed, this));
151 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::cinemas_file_changed, this));
153 _master_encoding_threads->SetRange (1, 128);
154 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
155 _server_encoding_threads->SetRange (1, 128);
156 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
157 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
159 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
160 _analyse_ebur128->bind(&FullGeneralPage::analyse_ebur128_changed, this);
162 _automatic_audio_analysis->bind(&FullGeneralPage::automatic_audio_analysis_changed, this);
165 void config_changed () override
167 auto config = Config::instance ();
169 checked_set (_master_encoding_threads, config->master_encoding_threads ());
170 checked_set (_server_encoding_threads, config->server_encoding_threads ());
171 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
172 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
174 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
175 checked_set (_config_file, config->config_read_file());
176 checked_set (_cinemas_file, config->cinemas_file());
177 checked_set(_default_add_file_location, config->default_add_file_location() == Config::DefaultAddFileLocation::SAME_AS_LAST_TIME ? 0 : 1);
179 GeneralPage::config_changed ();
182 void export_cinemas_file ()
185 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT("XML files (*.xml)|*.xml"),
186 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
189 if (dialog.ShowModal() == wxID_OK) {
190 dcp::filesystem::copy_file(Config::instance()->cinemas_file(), wx_to_std(dialog.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 (dcp::filesystem::exists(new_file)) {
225 ConfigMoveDialog dialog(_panel, new_file);
226 if (dialog.ShowModal() == wxID_OK) {
227 copy_and_link = false;
233 if (new_file != config->config_read_file()) {
234 config->copy_and_link (new_file);
237 config->link (new_file);
241 void cinemas_file_changed ()
243 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
246 void default_add_file_location_changed()
248 Config::instance()->set_default_add_file_location(
249 _default_add_file_location->get().get_value_or(0) == 0 ? Config::DefaultAddFileLocation::SAME_AS_LAST_TIME : Config::DefaultAddFileLocation::SAME_AS_PROJECT
253 Choice* _default_add_file_location;
254 wxSpinCtrl* _master_encoding_threads;
255 wxSpinCtrl* _server_encoding_threads;
256 FilePickerCtrl* _config_file;
257 FilePickerCtrl* _cinemas_file;
258 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
259 CheckBox* _analyse_ebur128;
261 CheckBox* _automatic_audio_analysis;
265 class DefaultsPage : public Page
268 DefaultsPage (wxSize panel_size, int border)
269 : Page (panel_size, border)
272 wxString GetName () const override
274 return _("Defaults");
278 wxBitmap GetLargeIcon () const override
280 return wxBitmap(icon_path("defaults"), wxBITMAP_TYPE_PNG);
285 void setup () override
287 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
288 table->AddGrowableCol (1, 1);
289 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
292 add_label_to_sizer (table, _panel, _("Default duration of still images"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
293 auto s = new wxBoxSizer (wxHORIZONTAL);
294 _still_length = new wxSpinCtrl (_panel);
295 s->Add (_still_length);
296 add_label_to_sizer (s, _panel, _("s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
300 add_label_to_sizer (table, _panel, _("Default directory for new films"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
301 #ifdef DCPOMATIC_USE_OWN_PICKER
302 _directory = new DirPickerCtrl (_panel);
304 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
306 table->Add (_directory, 1, wxEXPAND);
308 add_label_to_sizer (table, _panel, _("Default content type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
309 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
310 table->Add (_dcp_content_type);
312 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
313 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
314 table->Add (_dcp_audio_channels);
317 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
318 auto s = new wxBoxSizer (wxHORIZONTAL);
319 _j2k_bandwidth = new wxSpinCtrl (_panel);
320 s->Add (_j2k_bandwidth);
321 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
326 add_label_to_sizer (table, _panel, _("Default audio delay"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
327 auto s = new wxBoxSizer (wxHORIZONTAL);
328 _audio_delay = new wxSpinCtrl (_panel);
329 s->Add (_audio_delay);
330 add_label_to_sizer (s, _panel, _("ms"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
334 add_label_to_sizer (table, _panel, _("Default standard"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
335 _standard = new wxChoice (_panel, wxID_ANY);
336 table->Add (_standard);
338 _enable_audio_language = new CheckBox(_panel, _("Default audio language"));
339 table->Add(_enable_audio_language, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
340 _audio_language = new LanguageTagWidget(_panel, _("Default audio language to use for new DCPs"), Config::instance()->default_audio_language(), wxString("cmnr-Hant-"));
341 table->Add(_audio_language->sizer());
343 _enable_territory = new CheckBox(_panel, _("Default territory"));
344 table->Add(_enable_territory, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
345 _territory = new RegionSubtagWidget(_panel, _("Default territory to use for new DCPs"), Config::instance()->default_territory(), wxString("cmnr-Hant-"));
346 table->Add(_territory->sizer());
348 table->Add (_enable_metadata["facility"] = new CheckBox (_panel, _("Default facility")), 0, wxALIGN_CENTRE_VERTICAL);
349 table->Add (_metadata["facility"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
351 table->Add (_enable_metadata["studio"] = new CheckBox (_panel, _("Default studio")), 0, wxALIGN_CENTRE_VERTICAL);
352 table->Add (_metadata["studio"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
354 table->Add (_enable_metadata["chain"] = new CheckBox (_panel, _("Default chain")), 0, wxALIGN_CENTRE_VERTICAL);
355 table->Add (_metadata["chain"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
357 table->Add (_enable_metadata["distributor"] = new CheckBox (_panel, _("Default distributor")), 0, wxALIGN_CENTRE_VERTICAL);
358 table->Add (_metadata["distributor"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
360 add_label_to_sizer (table, _panel, _("Default KDM directory"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
361 #ifdef DCPOMATIC_USE_OWN_PICKER
362 _kdm_directory = new DirPickerCtrl (_panel);
364 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
366 table->Add (_kdm_directory, 1, wxEXPAND);
368 add_label_to_sizer (table, _panel, _("Default KDM type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
369 _kdm_type = new KDMChoice (_panel);
370 table->Add (_kdm_type, 1, wxEXPAND);
372 add_label_to_sizer (table, _panel, _("Default KDM duration"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
373 _kdm_duration = new wxSpinCtrl (_panel);
374 _kdm_duration_unit = new wxChoice (_panel, wxID_ANY);
375 auto kdm_duration_sizer = new wxBoxSizer (wxHORIZONTAL);
376 kdm_duration_sizer->Add (_kdm_duration, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
377 kdm_duration_sizer->Add (_kdm_duration_unit, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
378 table->Add (kdm_duration_sizer, 1, wxEXPAND);
380 table->Add (_use_isdcf_name_by_default = new CheckBox(_panel, _("Use ISDCF name by default")), 0, wxALIGN_CENTRE_VERTICAL);
382 _still_length->SetRange (1, 3600);
383 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
385 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
386 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
387 _kdm_type->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_type_changed, this));
388 _kdm_duration_unit->Append (_("days"));
389 _kdm_duration_unit->Append (_("weeks"));
390 _kdm_duration_unit->Append (_("months"));
391 _kdm_duration_unit->Append (_("years"));
393 _kdm_duration->Bind (wxEVT_SPINCTRL, boost::bind(&DefaultsPage::kdm_duration_changed, this));
394 _kdm_duration_unit->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_duration_changed, this));
396 _use_isdcf_name_by_default->bind(&DefaultsPage::use_isdcf_name_by_default_changed, this);
398 for (auto i: DCPContentType::all()) {
399 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
402 setup_audio_channels_choice (_dcp_audio_channels, 2);
404 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
405 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
407 _j2k_bandwidth->SetRange (50, 250);
408 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
410 _audio_delay->SetRange (-1000, 1000);
411 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
413 _standard->Append (_("SMPTE"));
414 _standard->Append (_("Interop"));
415 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
417 for (auto const& i: _enable_metadata) {
418 i.second->bind(&DefaultsPage::metadata_changed, this);
421 for (auto const& i: _metadata) {
422 i.second->Bind (wxEVT_TEXT, boost::bind(&DefaultsPage::metadata_changed, this));
425 _enable_audio_language->bind(&DefaultsPage::enable_audio_language_toggled, this);
426 _audio_language->Changed.connect(boost::bind(&DefaultsPage::audio_language_changed, this));
428 _enable_territory->bind(&DefaultsPage::enable_territory_toggled, this);
429 _territory->Changed.connect(boost::bind(&DefaultsPage::territory_changed, this));
432 void config_changed () override
434 auto config = Config::instance ();
436 auto const ct = DCPContentType::all ();
437 for (size_t i = 0; i < ct.size(); ++i) {
438 if (ct[i] == config->default_dcp_content_type()) {
439 _dcp_content_type->SetSelection (i);
443 checked_set (_still_length, config->default_still_length ());
444 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
445 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
446 _kdm_type->set (config->default_kdm_type());
447 checked_set (_use_isdcf_name_by_default, config->use_isdcf_name_by_default());
448 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
449 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
450 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
451 checked_set (_audio_delay, config->default_audio_delay ());
452 checked_set (_standard, config->default_interop() ? 1 : 0);
453 auto dal = config->default_audio_language();
454 checked_set(_enable_audio_language, static_cast<bool>(dal));
455 checked_set(_audio_language, dal ? dal : boost::none);
456 auto dt = config->default_territory();
457 checked_set(_enable_territory, static_cast<bool>(dt));
458 checked_set(_territory, dt ? dt : boost::none);
460 auto metadata = config->default_metadata();
462 for (auto const& i: metadata) {
463 _enable_metadata[i.first]->SetValue(true);
464 checked_set (_metadata[i.first], i.second);
467 for (auto const& i: _enable_metadata) {
468 if (metadata.find(i.first) == metadata.end()) {
469 checked_set (i.second, false);
473 for (auto const& i: _metadata) {
474 if (metadata.find(i.first) == metadata.end()) {
475 checked_set (i.second, wxT(""));
479 checked_set (_kdm_duration, config->default_kdm_duration().duration);
480 switch (config->default_kdm_duration().unit) {
481 case RoughDuration::Unit::DAYS:
482 _kdm_duration->SetRange(1, 365);
483 checked_set (_kdm_duration_unit, 0);
485 case RoughDuration::Unit::WEEKS:
486 _kdm_duration->SetRange(1, 52);
487 checked_set (_kdm_duration_unit, 1);
489 case RoughDuration::Unit::MONTHS:
490 _kdm_duration->SetRange(1, 12);
491 checked_set (_kdm_duration_unit, 2);
493 case RoughDuration::Unit::YEARS:
494 _kdm_duration->SetRange(1, 40);
495 checked_set (_kdm_duration_unit, 3);
499 setup_sensitivity ();
502 void kdm_duration_changed ()
504 auto config = Config::instance();
505 auto duration = _kdm_duration->GetValue();
506 RoughDuration::Unit unit = RoughDuration::Unit::DAYS;
507 switch (_kdm_duration_unit->GetSelection()) {
509 unit = RoughDuration::Unit::DAYS;
512 unit = RoughDuration::Unit::WEEKS;
515 unit = RoughDuration::Unit::MONTHS;
518 unit = RoughDuration::Unit::YEARS;
521 config->set_default_kdm_duration (RoughDuration(duration, unit));
524 void j2k_bandwidth_changed ()
526 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
529 void audio_delay_changed ()
531 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
534 void dcp_audio_channels_changed ()
536 int const s = _dcp_audio_channels->GetSelection ();
537 if (s != wxNOT_FOUND) {
538 Config::instance()->set_default_dcp_audio_channels (
539 locale_convert<int>(string_client_data(_dcp_audio_channels->GetClientObject(s)))
544 void directory_changed ()
546 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
549 void kdm_directory_changed ()
551 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
554 void kdm_type_changed ()
556 Config::instance()->set_default_kdm_type(_kdm_type->get());
559 void use_isdcf_name_by_default_changed ()
561 Config::instance()->set_use_isdcf_name_by_default (_use_isdcf_name_by_default->GetValue());
564 void still_length_changed ()
566 Config::instance()->set_default_still_length (_still_length->GetValue ());
569 void dcp_content_type_changed ()
571 auto ct = DCPContentType::all ();
572 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
575 void standard_changed ()
577 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
580 void metadata_changed ()
582 map<string, string> metadata;
583 for (auto const& i: _enable_metadata) {
584 if (i.second->GetValue()) {
585 metadata[i.first] = wx_to_std(_metadata[i.first]->GetValue());
588 Config::instance()->set_default_metadata (metadata);
589 setup_sensitivity ();
592 void enable_audio_language_toggled()
595 audio_language_changed();
598 void audio_language_changed()
600 if (_enable_audio_language->get()) {
601 Config::instance()->set_default_audio_language(_audio_language->get().get_value_or(dcp::LanguageTag("en-US")));
603 Config::instance()->unset_default_audio_language();
607 void enable_territory_toggled()
613 void territory_changed()
615 if (_enable_territory->get()) {
616 Config::instance()->set_default_territory(_territory->get().get_value_or(dcp::LanguageTag::RegionSubtag("US")));
618 Config::instance()->unset_default_territory();
622 void setup_sensitivity ()
624 _audio_language->enable(_enable_audio_language->get());
625 _territory->enable(_enable_territory->get());
626 for (auto const& i: _enable_metadata) {
627 _metadata[i.first]->Enable(i.second->GetValue());
631 wxSpinCtrl* _j2k_bandwidth;
632 wxSpinCtrl* _audio_delay;
633 wxSpinCtrl* _still_length;
634 #ifdef DCPOMATIC_USE_OWN_PICKER
635 DirPickerCtrl* _directory;
636 DirPickerCtrl* _kdm_directory;
638 wxDirPickerCtrl* _directory;
639 wxDirPickerCtrl* _kdm_directory;
641 KDMChoice* _kdm_type;
642 wxSpinCtrl* _kdm_duration;
643 wxChoice* _kdm_duration_unit;
644 CheckBox* _use_isdcf_name_by_default;
645 wxChoice* _dcp_content_type;
646 wxChoice* _dcp_audio_channels;
648 CheckBox* _enable_audio_language;
649 LanguageTagWidget* _audio_language;
650 CheckBox* _enable_territory;
651 RegionSubtagWidget* _territory;
652 map<string, CheckBox*> _enable_metadata;
653 map<string, wxTextCtrl*> _metadata;
657 class EncodingServersPage : public Page
660 EncodingServersPage (wxSize panel_size, int border)
661 : Page (panel_size, border)
664 wxString GetName () const override
670 wxBitmap GetLargeIcon () const override
672 return wxBitmap(icon_path("servers"), wxBITMAP_TYPE_PNG);
677 void setup () override
679 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
680 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
682 vector<EditableListColumn> columns;
683 columns.push_back (EditableListColumn(_("IP address / host name")));
684 _servers_list = new EditableList<string, ServerDialog> (
687 boost::bind (&Config::servers, Config::instance()),
688 boost::bind (&Config::set_servers, Config::instance(), _1),
689 boost::bind (&EncodingServersPage::server_column, this, _1),
690 EditableListTitle::INVISIBLE,
691 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
694 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
696 _use_any_servers->bind(&EncodingServersPage::use_any_servers_changed, this);
699 void config_changed () override
701 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
702 _servers_list->refresh ();
705 void use_any_servers_changed ()
707 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
710 string server_column (string s)
715 CheckBox* _use_any_servers;
716 EditableList<string, ServerDialog>* _servers_list;
720 class TMSPage : public Page
723 TMSPage (wxSize panel_size, int border)
724 : Page (panel_size, border)
727 wxString GetName () const override
733 wxBitmap GetLargeIcon () const override
735 return wxBitmap(icon_path("tms"), wxBITMAP_TYPE_PNG);
740 void setup () override
742 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
743 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
745 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
746 table->AddGrowableCol (1, 1);
747 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
749 add_label_to_sizer (table, _panel, _("Protocol"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
750 _tms_protocol = new wxChoice (_panel, wxID_ANY);
751 table->Add (_tms_protocol, 1, wxEXPAND);
753 _tms_passive = new CheckBox(_panel, _("Passive mode"));
754 table->Add(_tms_passive, 1, wxEXPAND);
757 add_label_to_sizer (table, _panel, _("IP address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
758 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
759 table->Add (_tms_ip, 1, wxEXPAND);
761 add_label_to_sizer (table, _panel, _("Target path"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
762 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
763 table->Add (_tms_path, 1, wxEXPAND);
765 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
766 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
767 table->Add (_tms_user, 1, wxEXPAND);
769 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
770 _tms_password = new PasswordEntry (_panel);
771 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
773 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
774 _tms_protocol->Append (_("FTP (for Dolby)"));
776 _upload->bind(&TMSPage::upload_changed, this);
777 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
778 _tms_passive->bind(&TMSPage::tms_passive_changed, this);
780 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
781 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
782 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
783 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
786 void config_changed () override
788 auto config = Config::instance ();
790 checked_set (_upload, config->upload_after_make_dcp());
791 checked_set (_tms_protocol, static_cast<int>(config->tms_protocol()));
792 checked_set(_tms_passive, config->tms_protocol() == FileTransferProtocol::FTP && config->tms_passive());
793 checked_set (_tms_ip, config->tms_ip ());
794 checked_set (_tms_path, config->tms_path ());
795 checked_set (_tms_user, config->tms_user ());
796 checked_set (_tms_password, config->tms_password ());
798 _tms_passive->Enable(config->tms_protocol() == FileTransferProtocol::FTP);
801 void upload_changed ()
803 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
806 void tms_protocol_changed ()
808 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
811 void tms_passive_changed()
813 Config::instance()->set_tms_passive(_tms_passive->get());
816 void tms_ip_changed ()
818 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
821 void tms_path_changed ()
823 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
826 void tms_user_changed ()
828 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
831 void tms_password_changed ()
833 Config::instance()->set_tms_password (_tms_password->get());
837 CheckBox* _tms_passive;
838 wxChoice* _tms_protocol;
840 wxTextCtrl* _tms_path;
841 wxTextCtrl* _tms_user;
842 PasswordEntry* _tms_password;
846 class EmailPage : public Page
849 EmailPage (wxSize panel_size, int border)
850 : Page (panel_size, border)
853 wxString GetName () const override
859 wxBitmap GetLargeIcon () const override
861 return wxBitmap(icon_path("email"), wxBITMAP_TYPE_PNG);
866 void setup () override
868 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
869 table->AddGrowableCol (1, 1);
870 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
872 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
874 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
875 _server = new wxTextCtrl (_panel, wxID_ANY);
876 s->Add (_server, 1, wxEXPAND | wxALL);
877 add_label_to_sizer (s, _panel, _("port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
878 _port = new wxSpinCtrl (_panel, wxID_ANY);
879 _port->SetRange (0, 65535);
881 add_label_to_sizer (s, _panel, _("protocol"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
882 _protocol = new wxChoice (_panel, wxID_ANY);
883 /* Make sure this matches the switches in config_changed and port_changed below */
884 _protocol->Append (_("Auto"));
885 _protocol->Append (_("Plain"));
886 _protocol->Append (_("STARTTLS"));
887 _protocol->Append (_("SSL"));
888 s->Add (_protocol, 1, wxALIGN_CENTER_VERTICAL);
889 table->Add (s, 1, wxEXPAND | wxALL);
892 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
893 _user = new wxTextCtrl (_panel, wxID_ANY);
894 table->Add (_user, 1, wxEXPAND | wxALL);
896 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
897 _password = new PasswordEntry (_panel);
898 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
900 table->AddSpacer (0);
901 _send_test_email = new Button (_panel, _("Send test email..."));
902 table->Add (_send_test_email);
904 _server->Bind (wxEVT_TEXT, boost::bind(&EmailPage::server_changed, this));
905 _port->Bind (wxEVT_SPINCTRL, boost::bind(&EmailPage::port_changed, this));
906 _protocol->Bind (wxEVT_CHOICE, boost::bind(&EmailPage::protocol_changed, this));
907 _user->Bind (wxEVT_TEXT, boost::bind(&EmailPage::user_changed, this));
908 _password->Changed.connect (boost::bind(&EmailPage::password_changed, this));
909 _send_test_email->Bind (wxEVT_BUTTON, boost::bind(&EmailPage::send_test_email_clicked, this));
912 void config_changed () override
914 auto config = Config::instance ();
916 checked_set (_server, config->mail_server());
917 checked_set (_port, config->mail_port());
918 switch (config->mail_protocol()) {
919 case EmailProtocol::AUTO:
920 checked_set (_protocol, 0);
922 case EmailProtocol::PLAIN:
923 checked_set (_protocol, 1);
925 case EmailProtocol::STARTTLS:
926 checked_set (_protocol, 2);
928 case EmailProtocol::SSL:
929 checked_set (_protocol, 3);
932 checked_set (_user, config->mail_user());
933 checked_set (_password, config->mail_password());
936 void server_changed ()
938 Config::instance()->set_mail_server(wx_to_std(_server->GetValue()));
943 Config::instance()->set_mail_port(_port->GetValue());
946 void protocol_changed ()
948 switch (_protocol->GetSelection()) {
950 Config::instance()->set_mail_protocol(EmailProtocol::AUTO);
953 Config::instance()->set_mail_protocol(EmailProtocol::PLAIN);
956 Config::instance()->set_mail_protocol(EmailProtocol::STARTTLS);
959 Config::instance()->set_mail_protocol(EmailProtocol::SSL);
966 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
969 void password_changed ()
971 Config::instance()->set_mail_password(_password->get());
974 void send_test_email_clicked ()
976 SendTestEmailDialog dialog(_panel);
977 if (dialog.ShowModal() != 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."));
1003 wxTextCtrl* _server;
1005 wxChoice* _protocol;
1007 PasswordEntry* _password;
1008 Button* _send_test_email;
1012 class KDMEmailPage : public Page
1016 KDMEmailPage (wxSize panel_size, int border)
1017 #ifdef DCPOMATIC_OSX
1018 /* We have to force both width and height of this one */
1019 : Page (wxSize (panel_size.GetWidth(), 128), border)
1021 : Page (panel_size, border)
1025 wxString GetName () const override
1027 return _("KDM Email");
1030 #ifdef DCPOMATIC_OSX
1031 wxBitmap GetLargeIcon () const override
1033 return wxBitmap(icon_path("kdm_email"), wxBITMAP_TYPE_PNG);
1038 void setup () override
1040 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1041 table->AddGrowableCol (1, 1);
1042 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1044 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1045 _subject = new wxTextCtrl (_panel, wxID_ANY);
1046 table->Add (_subject, 1, wxEXPAND | wxALL);
1048 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1049 _from = new wxTextCtrl (_panel, wxID_ANY);
1050 table->Add (_from, 1, wxEXPAND | wxALL);
1052 vector<EditableListColumn> columns;
1053 columns.push_back (EditableListColumn(_("Address")));
1054 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1055 _cc = new EditableList<string, EmailDialog> (
1058 bind (&Config::kdm_cc, Config::instance()),
1059 bind (&Config::set_kdm_cc, Config::instance(), _1),
1060 [] (string s, int) {
1063 EditableListTitle::VISIBLE,
1064 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1066 table->Add (_cc, 1, wxEXPAND | wxALL);
1068 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1069 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1070 table->Add (_bcc, 1, wxEXPAND | wxALL);
1072 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1073 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1075 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1076 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1080 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1081 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1082 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1083 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1084 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
1087 void config_changed () override
1089 auto config = Config::instance ();
1091 checked_set (_subject, config->kdm_subject ());
1092 checked_set (_from, config->kdm_from ());
1093 checked_set (_bcc, config->kdm_bcc ());
1094 checked_set (_email, Config::instance()->kdm_email ());
1097 void kdm_subject_changed ()
1099 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
1102 void kdm_from_changed ()
1104 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
1107 void kdm_bcc_changed ()
1109 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
1112 void kdm_email_changed ()
1114 if (_email->GetValue().IsEmpty ()) {
1115 /* Sometimes we get sent an erroneous notification that the email
1116 is empty; I don't know why.
1120 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
1125 Config::instance()->reset_kdm_email ();
1126 checked_set (_email, Config::instance()->kdm_email ());
1129 wxTextCtrl* _subject;
1131 EditableList<string, EmailDialog>* _cc;
1134 wxButton* _reset_email;
1138 class NotificationsPage : public Page
1141 NotificationsPage (wxSize panel_size, int border)
1142 #ifdef DCPOMATIC_OSX
1143 /* We have to force both width and height of this one */
1144 : Page (wxSize (panel_size.GetWidth(), 128), border)
1146 : Page (panel_size, border)
1150 wxString GetName () const override
1152 return _("Notifications");
1155 #ifdef DCPOMATIC_OSX
1156 wxBitmap GetLargeIcon () const override
1158 return wxBitmap(icon_path("notifications"), wxBITMAP_TYPE_PNG);
1163 void setup () override
1165 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1166 table->AddGrowableCol (1, 1);
1167 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1169 _enable_message_box = new CheckBox (_panel, _("Message box"));
1170 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
1171 table->AddSpacer (0);
1173 _enable_email = new CheckBox (_panel, _("Email"));
1174 table->Add (_enable_email, 1, wxEXPAND | wxALL);
1175 table->AddSpacer (0);
1177 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1178 _subject = new wxTextCtrl (_panel, wxID_ANY);
1179 table->Add (_subject, 1, wxEXPAND | wxALL);
1181 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1182 _from = new wxTextCtrl (_panel, wxID_ANY);
1183 table->Add (_from, 1, wxEXPAND | wxALL);
1185 add_label_to_sizer (table, _panel, _("To address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1186 _to = new wxTextCtrl (_panel, wxID_ANY);
1187 table->Add (_to, 1, wxEXPAND | wxALL);
1189 vector<EditableListColumn> columns;
1190 columns.push_back (EditableListColumn(_("Address")));
1191 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1192 _cc = new EditableList<string, EmailDialog> (
1195 bind (&Config::notification_cc, Config::instance()),
1196 bind (&Config::set_notification_cc, Config::instance(), _1),
1197 [] (string s, int) {
1200 EditableListTitle::VISIBLE,
1201 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1203 table->Add (_cc, 1, wxEXPAND | wxALL);
1205 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1206 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1207 table->Add (_bcc, 1, wxEXPAND | wxALL);
1209 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1210 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1212 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1213 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1217 _enable_message_box->bind(&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX);
1218 _enable_email->bind(&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL);
1220 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
1221 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
1222 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
1223 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
1224 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
1225 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
1227 setup_sensitivity ();
1230 void setup_sensitivity ()
1232 bool const s = _enable_email->GetValue();
1233 _subject->Enable(s);
1239 _reset_email->Enable(s);
1242 void config_changed () override
1244 auto config = Config::instance ();
1246 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
1247 checked_set (_enable_email, config->notification(Config::EMAIL));
1248 checked_set (_subject, config->notification_subject ());
1249 checked_set (_from, config->notification_from ());
1250 checked_set (_to, config->notification_to ());
1251 checked_set (_bcc, config->notification_bcc ());
1252 checked_set (_email, Config::instance()->notification_email ());
1254 setup_sensitivity ();
1257 void notification_subject_changed ()
1259 Config::instance()->set_notification_subject(wx_to_std(_subject->GetValue()));
1262 void notification_from_changed ()
1264 Config::instance()->set_notification_from(wx_to_std(_from->GetValue()));
1267 void notification_to_changed ()
1269 Config::instance()->set_notification_to(wx_to_std(_to->GetValue()));
1272 void notification_bcc_changed ()
1274 Config::instance()->set_notification_bcc(wx_to_std(_bcc->GetValue()));
1277 void notification_email_changed ()
1279 if (_email->GetValue().IsEmpty()) {
1280 /* Sometimes we get sent an erroneous notification that the email
1281 is empty; I don't know why.
1285 Config::instance()->set_notification_email(wx_to_std(_email->GetValue()));
1290 Config::instance()->reset_notification_email();
1291 checked_set (_email, Config::instance()->notification_email());
1294 void type_changed (CheckBox* b, Config::Notification n)
1296 Config::instance()->set_notification(n, b->GetValue());
1297 setup_sensitivity ();
1300 CheckBox* _enable_message_box;
1301 CheckBox* _enable_email;
1303 wxTextCtrl* _subject;
1306 EditableList<string, EmailDialog>* _cc;
1309 wxButton* _reset_email;
1313 class CoverSheetPage : public Page
1317 CoverSheetPage (wxSize panel_size, int border)
1318 #ifdef DCPOMATIC_OSX
1319 /* We have to force both width and height of this one */
1320 : Page (wxSize (panel_size.GetWidth(), 128), border)
1322 : Page (panel_size, border)
1326 wxString GetName () const override
1328 return _("Cover Sheet");
1331 #ifdef DCPOMATIC_OSX
1332 wxBitmap GetLargeIcon () const override
1334 return wxBitmap(icon_path("cover_sheet"), wxBITMAP_TYPE_PNG);
1339 void setup () override
1341 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1342 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1344 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1345 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1347 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1348 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1351 void config_changed () override
1353 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1356 void cover_sheet_changed ()
1358 if (_cover_sheet->GetValue().IsEmpty ()) {
1359 /* Sometimes we get sent an erroneous notification that the cover sheet
1360 is empty; I don't know why.
1364 Config::instance()->set_cover_sheet(wx_to_std(_cover_sheet->GetValue()));
1367 void reset_cover_sheet ()
1369 Config::instance()->reset_cover_sheet();
1370 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1373 wxTextCtrl* _cover_sheet;
1374 wxButton* _reset_cover_sheet;
1378 class IdentifiersPage : public Page
1381 IdentifiersPage (wxSize panel_size, int border)
1382 : Page (panel_size, border)
1385 wxString GetName () const override
1387 return _("Identifiers");
1390 #ifdef DCPOMATIC_OSX
1391 wxBitmap GetLargeIcon () const override
1393 return wxBitmap(icon_path("identifiers"), wxBITMAP_TYPE_PNG);
1398 void setup () override
1400 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1401 table->AddGrowableCol (1, 1);
1403 add_label_to_sizer (table, _panel, _("Issuer"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1404 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1405 _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."));
1406 table->Add (_issuer, 1, wxALL | wxEXPAND);
1408 add_label_to_sizer (table, _panel, _("Creator"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1409 _creator = new wxTextCtrl (_panel, wxID_ANY);
1410 _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."));
1411 table->Add (_creator, 1, wxALL | wxEXPAND);
1413 add_label_to_sizer (table, _panel, _("Company name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1414 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1415 _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."));
1416 table->Add (_company_name, 1, wxALL | wxEXPAND);
1418 add_label_to_sizer (table, _panel, _("Product name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1419 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1420 _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."));
1421 table->Add (_product_name, 1, wxALL | wxEXPAND);
1423 add_label_to_sizer (table, _panel, _("Product version"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1424 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1425 _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."));
1426 table->Add (_product_version, 1, wxALL | wxEXPAND);
1428 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1429 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1430 _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."));
1431 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1433 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1435 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1436 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1437 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1438 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1439 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1440 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1443 void config_changed () override
1445 auto config = Config::instance ();
1446 checked_set (_issuer, config->dcp_issuer ());
1447 checked_set (_creator, config->dcp_creator ());
1448 checked_set (_company_name, config->dcp_company_name ());
1449 checked_set (_product_name, config->dcp_product_name ());
1450 checked_set (_product_version, config->dcp_product_version ());
1451 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1454 void issuer_changed ()
1456 Config::instance()->set_dcp_issuer(wx_to_std(_issuer->GetValue()));
1459 void creator_changed ()
1461 Config::instance()->set_dcp_creator(wx_to_std(_creator->GetValue()));
1464 void company_name_changed ()
1466 Config::instance()->set_dcp_company_name(wx_to_std(_company_name->GetValue()));
1469 void product_name_changed ()
1471 Config::instance()->set_dcp_product_name(wx_to_std(_product_name->GetValue()));
1474 void product_version_changed ()
1476 Config::instance()->set_dcp_product_version(wx_to_std(_product_version->GetValue()));
1479 void j2k_comment_changed ()
1481 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1484 wxTextCtrl* _issuer;
1485 wxTextCtrl* _creator;
1486 wxTextCtrl* _company_name;
1487 wxTextCtrl* _product_name;
1488 wxTextCtrl* _product_version;
1489 wxTextCtrl* _j2k_comment;
1493 class NonStandardPage : public Page
1496 NonStandardPage(wxSize panel_size, int border)
1497 : Page(panel_size, border)
1500 wxString GetName() const override
1502 return _("Non-standard");
1505 #ifdef DCPOMATIC_OSX
1506 wxBitmap GetLargeIcon() const override
1508 return wxBitmap(icon_path("non_standard"), wxBITMAP_TYPE_PNG);
1513 void setup() override
1515 auto table = new wxFlexGridSizer(2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1516 table->AddGrowableCol(1, 1);
1517 _panel->GetSizer()->Add(table, 1, wxALL | wxEXPAND, _border);
1520 add_label_to_sizer(table, _panel, _("Maximum JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1521 auto s = new wxBoxSizer(wxHORIZONTAL);
1522 _maximum_j2k_bandwidth = new wxSpinCtrl(_panel);
1523 s->Add(_maximum_j2k_bandwidth, 1);
1524 add_label_to_sizer(s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxALIGN_CENTRE_VERTICAL);
1528 auto checkbox = [this, table](wxString name, CheckBox*& variable) {
1529 variable = new CheckBox(_panel, name);
1530 table->Add(variable, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1531 table->AddSpacer(0);
1534 checkbox(_("Allow any DCP frame rate"), _allow_any_dcp_frame_rate);
1536 _allow_any_container = new CheckBox(_panel, _("Allow full-frame and non-standard container ratios"));
1537 table->Add(_allow_any_container, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1538 auto restart = new StaticText(_panel, _("(restart DCP-o-matic to see all ratios)"));
1539 auto font = restart->GetFont();
1540 font.SetStyle(wxFONTSTYLE_ITALIC);
1541 font.SetPointSize(font.GetPointSize() - 1);
1542 restart->SetFont(font);
1543 table->Add(restart, 1, wxALIGN_CENTRE_VERTICAL | wxBOTTOM, DCPOMATIC_CHECKBOX_BOTTOM_PAD);
1544 restart->SetFont(font);
1546 checkbox(_("Allow creation of DCPs with 96kHz audio"), _allow_96khz_audio);
1547 checkbox(_("Allow mapping to all audio channels"), _use_all_audio_channels);
1548 checkbox(_("Allow use of SMPTE Bv2.0"), _allow_smpte_bv20);
1551 add_label_to_sizer(table, _panel, _("ISDCF name part length"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1552 auto s = new wxBoxSizer(wxHORIZONTAL);
1553 _isdcf_name_part_length = new wxSpinCtrl(_panel);
1554 s->Add(_isdcf_name_part_length, 1);
1558 _maximum_j2k_bandwidth->SetRange(1, 1000);
1559 _maximum_j2k_bandwidth->Bind(wxEVT_SPINCTRL, boost::bind(&NonStandardPage::maximum_j2k_bandwidth_changed, this));
1560 _allow_any_dcp_frame_rate->bind(&NonStandardPage::allow_any_dcp_frame_rate_changed, this);
1561 _allow_any_container->bind(&NonStandardPage::allow_any_container_changed, this);
1562 _allow_96khz_audio->bind(&NonStandardPage::allow_96khz_audio_changed, this);
1563 _use_all_audio_channels->bind(&NonStandardPage::use_all_channels_changed, this);
1564 _allow_smpte_bv20->bind(&NonStandardPage::allow_smpte_bv20_changed, this);
1565 _isdcf_name_part_length->SetRange(14, 256);
1566 _isdcf_name_part_length->Bind(wxEVT_SPINCTRL, boost::bind(&NonStandardPage::isdcf_name_part_length_changed, this));
1569 void config_changed() override
1571 auto config = Config::instance();
1573 checked_set(_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1574 checked_set(_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate());
1575 checked_set(_allow_any_container, config->allow_any_container());
1576 checked_set(_allow_96khz_audio, config->allow_96khz_audio());
1577 checked_set(_use_all_audio_channels, config->use_all_audio_channels());
1578 checked_set(_allow_smpte_bv20, config->allow_smpte_bv20());
1579 checked_set(_isdcf_name_part_length, config->isdcf_name_part_length());
1582 void maximum_j2k_bandwidth_changed()
1584 Config::instance()->set_maximum_j2k_bandwidth(_maximum_j2k_bandwidth->GetValue() * 1000000);
1587 void allow_any_dcp_frame_rate_changed()
1589 Config::instance()->set_allow_any_dcp_frame_rate(_allow_any_dcp_frame_rate->GetValue());
1592 void allow_any_container_changed()
1594 Config::instance()->set_allow_any_container(_allow_any_container->GetValue());
1597 void allow_96khz_audio_changed()
1599 Config::instance()->set_allow_96hhz_audio(_allow_96khz_audio->GetValue());
1602 void use_all_channels_changed()
1604 Config::instance()->set_use_all_audio_channels(_use_all_audio_channels->GetValue());
1607 void allow_smpte_bv20_changed()
1609 Config::instance()->set_allow_smpte_bv20(_allow_smpte_bv20->GetValue());
1612 void isdcf_name_part_length_changed()
1614 Config::instance()->set_isdcf_name_part_length(_isdcf_name_part_length->GetValue());
1617 wxSpinCtrl* _maximum_j2k_bandwidth = nullptr;
1618 CheckBox* _allow_any_dcp_frame_rate = nullptr;
1619 CheckBox* _allow_any_container = nullptr;
1620 CheckBox* _allow_96khz_audio = nullptr;
1621 CheckBox* _use_all_audio_channels = nullptr;
1622 CheckBox* _allow_smpte_bv20 = nullptr;
1623 wxSpinCtrl* _isdcf_name_part_length = nullptr;
1628 /** @class AdvancedPage
1629 * @brief Advanced page of the preferences dialog.
1631 class AdvancedPage : public Page
1634 AdvancedPage (wxSize panel_size, int border)
1635 : Page (panel_size, border)
1638 wxString GetName () const override
1640 return _("Advanced");
1643 #ifdef DCPOMATIC_OSX
1644 wxBitmap GetLargeIcon () const override
1646 return wxBitmap(icon_path("advanced"), wxBITMAP_TYPE_PNG);
1651 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1653 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1655 flags |= wxALIGN_RIGHT;
1658 wxStaticText* m = new StaticText (parent, text);
1659 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1662 void setup () override
1664 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1665 table->AddGrowableCol (1, 1);
1666 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1668 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1669 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1670 table->Add (_video_display_mode);
1672 auto restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1673 auto font = restart->GetFont();
1674 font.SetStyle (wxFONTSTYLE_ITALIC);
1675 font.SetPointSize (font.GetPointSize() - 1);
1676 restart->SetFont (font);
1677 table->AddSpacer (0);
1679 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1680 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1681 table->AddSpacer (0);
1683 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1684 table->Add (_only_servers_encode, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1685 table->AddSpacer (0);
1688 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1689 auto s = new wxBoxSizer (wxHORIZONTAL);
1690 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1691 s->Add (_frames_in_memory_multiplier, 1);
1696 auto format = create_label (_panel, _("DCP metadata filename format"), true);
1697 #ifdef DCPOMATIC_OSX
1698 auto align = new wxBoxSizer (wxHORIZONTAL);
1699 align->Add (format, 0, wxTOP, 2);
1700 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1702 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1704 dcp::NameFormat::Map titles;
1705 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1706 dcp::NameFormat::Map examples;
1707 examples['t'] = "cpl";
1708 _dcp_metadata_filename_format = new NameFormatEditor (
1709 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1711 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1715 auto format = create_label (_panel, _("DCP asset filename format"), true);
1716 #ifdef DCPOMATIC_OSX
1717 auto align = new wxBoxSizer (wxHORIZONTAL);
1718 align->Add (format, 0, wxTOP, 2);
1719 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1721 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1723 dcp::NameFormat::Map titles;
1724 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1725 titles['r'] = wx_to_std (_("reel number"));
1726 titles['n'] = wx_to_std (_("number of reels"));
1727 titles['c'] = wx_to_std (_("content filename"));
1728 dcp::NameFormat::Map examples;
1729 examples['t'] = "j2c";
1730 examples['r'] = "1";
1731 examples['n'] = "4";
1732 examples['c'] = "myfile.mp4";
1733 _dcp_asset_filename_format = new NameFormatEditor (
1734 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1736 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1740 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1741 auto t = new wxFlexGridSizer (2);
1742 _log_general = new CheckBox (_panel, _("General"));
1743 t->Add (_log_general, 1, wxEXPAND | wxALL);
1744 _log_warning = new CheckBox (_panel, _("Warnings"));
1745 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1746 _log_error = new CheckBox (_panel, _("Errors"));
1747 t->Add (_log_error, 1, wxEXPAND | wxALL);
1748 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1749 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1750 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1751 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1752 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1753 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1754 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1755 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1756 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1757 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1758 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1759 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1760 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1761 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1762 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1763 table->Add (t, 0, wxALL, 6);
1766 #ifdef DCPOMATIC_WINDOWS
1767 _win32_console = new CheckBox (_panel, _("Open console window"));
1768 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1769 table->AddSpacer (0);
1772 _video_display_mode->Append (_("Simple (safer)"));
1773 #if wxCHECK_VERSION(3, 1, 0)
1774 _video_display_mode->Append (_("OpenGL (faster)"));
1776 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1777 _show_experimental_audio_processors->bind(&AdvancedPage::show_experimental_audio_processors_changed, this);
1778 _only_servers_encode->bind(&AdvancedPage::only_servers_encode_changed, this);
1779 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1780 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1781 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1782 _log_general->bind(&AdvancedPage::log_changed, this);
1783 _log_warning->bind(&AdvancedPage::log_changed, this);
1784 _log_error->bind(&AdvancedPage::log_changed, this);
1785 _log_timing->bind(&AdvancedPage::log_changed, this);
1786 _log_debug_threed->bind(&AdvancedPage::log_changed, this);
1787 _log_debug_encode->bind(&AdvancedPage::log_changed, this);
1788 _log_debug_email->bind(&AdvancedPage::log_changed, this);
1789 _log_debug_video_view->bind(&AdvancedPage::log_changed, this);
1790 _log_debug_player->bind(&AdvancedPage::log_changed, this);
1791 _log_debug_audio_analysis->bind(&AdvancedPage::log_changed, this);
1792 #ifdef DCPOMATIC_WINDOWS
1793 _win32_console->bind(&AdvancedPage::win32_console_changed, this);
1797 void config_changed () override
1799 auto config = Config::instance ();
1801 switch (config->video_view_type()) {
1802 case Config::VIDEO_VIEW_SIMPLE:
1803 checked_set (_video_display_mode, 0);
1805 case Config::VIDEO_VIEW_OPENGL:
1806 checked_set (_video_display_mode, 1);
1809 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1810 checked_set (_only_servers_encode, config->only_servers_encode ());
1811 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1812 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1813 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1814 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1815 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREE_D);
1816 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1817 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1818 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1819 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1820 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1821 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1822 #ifdef DCPOMATIC_WINDOWS
1823 checked_set (_win32_console, config->win32_console());
1827 void video_display_mode_changed ()
1829 if (_video_display_mode->GetSelection() == 0) {
1830 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_SIMPLE);
1832 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_OPENGL);
1836 void frames_in_memory_multiplier_changed ()
1838 Config::instance()->set_frames_in_memory_multiplier(_frames_in_memory_multiplier->GetValue());
1841 void show_experimental_audio_processors_changed ()
1843 Config::instance()->set_show_experimental_audio_processors(_show_experimental_audio_processors->GetValue());
1846 void only_servers_encode_changed ()
1848 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue());
1851 void dcp_metadata_filename_format_changed ()
1853 Config::instance()->set_dcp_metadata_filename_format(_dcp_metadata_filename_format->get());
1856 void dcp_asset_filename_format_changed ()
1858 Config::instance()->set_dcp_asset_filename_format(_dcp_asset_filename_format->get());
1864 if (_log_general->GetValue ()) {
1865 types |= LogEntry::TYPE_GENERAL;
1867 if (_log_warning->GetValue ()) {
1868 types |= LogEntry::TYPE_WARNING;
1870 if (_log_error->GetValue ()) {
1871 types |= LogEntry::TYPE_ERROR;
1873 if (_log_timing->GetValue ()) {
1874 types |= LogEntry::TYPE_TIMING;
1876 if (_log_debug_threed->GetValue ()) {
1877 types |= LogEntry::TYPE_DEBUG_THREE_D;
1879 if (_log_debug_encode->GetValue ()) {
1880 types |= LogEntry::TYPE_DEBUG_ENCODE;
1882 if (_log_debug_email->GetValue ()) {
1883 types |= LogEntry::TYPE_DEBUG_EMAIL;
1885 if (_log_debug_video_view->GetValue()) {
1886 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1888 if (_log_debug_player->GetValue()) {
1889 types |= LogEntry::TYPE_DEBUG_PLAYER;
1891 if (_log_debug_audio_analysis->GetValue()) {
1892 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1894 Config::instance()->set_log_types (types);
1897 #ifdef DCPOMATIC_WINDOWS
1898 void win32_console_changed ()
1900 Config::instance()->set_win32_console(_win32_console->GetValue());
1904 wxChoice* _video_display_mode = nullptr;
1905 wxSpinCtrl* _frames_in_memory_multiplier = nullptr;
1906 CheckBox* _show_experimental_audio_processors = nullptr;
1907 CheckBox* _only_servers_encode = nullptr;
1908 NameFormatEditor* _dcp_metadata_filename_format = nullptr;
1909 NameFormatEditor* _dcp_asset_filename_format = nullptr;
1910 CheckBox* _log_general = nullptr;
1911 CheckBox* _log_warning = nullptr;
1912 CheckBox* _log_error = nullptr;
1913 CheckBox* _log_timing = nullptr;
1914 CheckBox* _log_debug_threed = nullptr;
1915 CheckBox* _log_debug_encode = nullptr;
1916 CheckBox* _log_debug_email = nullptr;
1917 CheckBox* _log_debug_video_view = nullptr;
1918 CheckBox* _log_debug_player = nullptr;
1919 CheckBox* _log_debug_audio_analysis = nullptr;
1920 #ifdef DCPOMATIC_WINDOWS
1921 CheckBox* _win32_console = nullptr;
1926 wxPreferencesEditor*
1927 create_full_config_dialog ()
1929 auto e = new wxPreferencesEditor ();
1931 #ifdef DCPOMATIC_OSX
1932 /* Width that we force some of the config panels to be on OSX so that
1933 the containing window doesn't shrink too much when we select those panels.
1934 This is obviously an unpleasant hack.
1936 wxSize ps = wxSize (750, -1);
1937 int const border = 16;
1939 wxSize ps = wxSize (-1, -1);
1940 int const border = 8;
1943 e->AddPage (new FullGeneralPage (ps, border));
1944 e->AddPage (new SoundPage (ps, border));
1945 e->AddPage (new DefaultsPage (ps, border));
1946 e->AddPage (new EncodingServersPage(ps, border));
1947 e->AddPage (new KeysPage (ps, border));
1948 e->AddPage (new TMSPage (ps, border));
1949 e->AddPage (new EmailPage (ps, border));
1950 e->AddPage (new KDMEmailPage (ps, border));
1951 e->AddPage (new NotificationsPage (ps, border));
1952 e->AddPage (new CoverSheetPage (ps, border));
1953 e->AddPage (new IdentifiersPage (ps, border));
1954 e->AddPage (new NonStandardPage (ps, border));
1955 e->AddPage (new AdvancedPage (ps, border));