2 Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
22 /** @file src/full_config_dialog.cc
23 * @brief A dialogue to edit all DCP-o-matic configuration.
27 #include "check_box.h"
28 #include "config_dialog.h"
29 #include "config_move_dialog.h"
30 #include "dcpomatic_button.h"
31 #include "dcpomatic_choice.h"
32 #include "dir_picker_ctrl.h"
33 #include "editable_list.h"
34 #include "email_dialog.h"
35 #include "file_picker_ctrl.h"
36 #include "filter_dialog.h"
37 #include "full_config_dialog.h"
38 #include "kdm_choice.h"
39 #include "language_tag_widget.h"
40 #include "make_chain_dialog.h"
41 #include "nag_dialog.h"
42 #include "name_format_editor.h"
43 #include "password_entry.h"
44 #include "region_subtag_widget.h"
45 #include "send_test_email_dialog.h"
46 #include "server_dialog.h"
47 #include "static_text.h"
49 #include "lib/config.h"
50 #include "lib/cross.h"
51 #include "lib/dcp_content_type.h"
52 #include "lib/emailer.h"
53 #include "lib/exceptions.h"
54 #include "lib/filter.h"
56 #include "lib/ratio.h"
58 #include <dcp/certificate_chain.h>
59 #include <dcp/exceptions.h>
60 #include <dcp/locale_convert.h>
61 #include <dcp/warnings.h>
62 LIBDCP_DISABLE_WARNINGS
63 #include <wx/filepicker.h>
64 #include <wx/preferences.h>
65 #include <wx/spinctrl.h>
66 #include <wx/stdpaths.h>
67 LIBDCP_ENABLE_WARNINGS
69 #include <boost/filesystem.hpp>
79 using std::shared_ptr;
83 using boost::optional;
84 #if BOOST_VERSION >= 106100
85 using namespace boost::placeholders;
87 using dcp::locale_convert;
90 class FullGeneralPage : public GeneralPage
93 FullGeneralPage (wxSize panel_size, int border)
94 : GeneralPage (panel_size, border)
98 void setup () override
100 auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
101 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
104 add_language_controls (table, r);
106 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
107 _master_encoding_threads = new wxSpinCtrl (_panel);
108 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
111 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
112 _server_encoding_threads = new wxSpinCtrl (_panel);
113 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
116 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
117 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, false);
118 table->Add (_config_file, wxGBPosition (r, 1));
121 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
122 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, false);
123 table->Add (_cinemas_file, wxGBPosition (r, 1));
124 auto export_cinemas = new Button (_panel, _("Export..."));
125 table->Add (export_cinemas, wxGBPosition (r, 2));
128 add_label_to_sizer(table, _panel, _("Default \"add file\" location"), true, wxGBPosition(r, 0));
129 _default_add_file_location = new Choice(_panel);
130 table->Add(_default_add_file_location, wxGBPosition(r, 1));
133 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
134 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
135 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
139 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
140 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
143 add_update_controls (table, r);
145 _default_add_file_location->add(_("Same place as last time"));
146 _default_add_file_location->add(_("Same place as project"));
147 _default_add_file_location->bind(&FullGeneralPage::default_add_file_location_changed, this);
149 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::config_file_changed, this));
150 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::cinemas_file_changed, this));
152 _master_encoding_threads->SetRange (1, 128);
153 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
154 _server_encoding_threads->SetRange (1, 128);
155 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
156 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
158 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
159 _analyse_ebur128->bind(&FullGeneralPage::analyse_ebur128_changed, this);
161 _automatic_audio_analysis->bind(&FullGeneralPage::automatic_audio_analysis_changed, this);
164 void config_changed () override
166 auto config = Config::instance ();
168 checked_set (_master_encoding_threads, config->master_encoding_threads ());
169 checked_set (_server_encoding_threads, config->server_encoding_threads ());
170 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
171 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
173 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
174 checked_set (_config_file, config->config_read_file());
175 checked_set (_cinemas_file, config->cinemas_file());
176 checked_set(_default_add_file_location, config->default_add_file_location() == Config::DefaultAddFileLocation::SAME_AS_LAST_TIME ? 0 : 1);
178 GeneralPage::config_changed ();
181 void export_cinemas_file ()
184 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT("XML files (*.xml)|*.xml"),
185 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
188 if (dialog.ShowModal() == wxID_OK) {
189 boost::filesystem::copy_file(Config::instance()->cinemas_file(), wx_to_std(dialog.GetPath()), boost::filesystem::copy_option::overwrite_if_exists);
193 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
194 void analyse_ebur128_changed ()
196 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue());
200 void automatic_audio_analysis_changed ()
202 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue());
205 void master_encoding_threads_changed ()
207 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue());
210 void server_encoding_threads_changed ()
212 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue());
215 void config_file_changed ()
217 auto config = Config::instance();
218 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
219 if (new_file == config->config_read_file()) {
222 bool copy_and_link = true;
223 if (boost::filesystem::exists(new_file)) {
224 ConfigMoveDialog dialog(_panel, new_file);
225 if (dialog.ShowModal() == wxID_OK) {
226 copy_and_link = false;
232 if (new_file != config->config_read_file()) {
233 config->copy_and_link (new_file);
236 config->link (new_file);
240 void cinemas_file_changed ()
242 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
245 void default_add_file_location_changed()
247 Config::instance()->set_default_add_file_location(
248 _default_add_file_location->get().get_value_or(0) == 0 ? Config::DefaultAddFileLocation::SAME_AS_LAST_TIME : Config::DefaultAddFileLocation::SAME_AS_PROJECT
252 Choice* _default_add_file_location;
253 wxSpinCtrl* _master_encoding_threads;
254 wxSpinCtrl* _server_encoding_threads;
255 FilePickerCtrl* _config_file;
256 FilePickerCtrl* _cinemas_file;
257 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
258 CheckBox* _analyse_ebur128;
260 CheckBox* _automatic_audio_analysis;
264 class DefaultsPage : public Page
267 DefaultsPage (wxSize panel_size, int border)
268 : Page (panel_size, border)
271 wxString GetName () const override
273 return _("Defaults");
277 wxBitmap GetLargeIcon () const override
279 return wxBitmap(icon_path("defaults"), wxBITMAP_TYPE_PNG);
284 void setup () override
286 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
287 table->AddGrowableCol (1, 1);
288 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
291 add_label_to_sizer (table, _panel, _("Default duration of still images"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
292 auto s = new wxBoxSizer (wxHORIZONTAL);
293 _still_length = new wxSpinCtrl (_panel);
294 s->Add (_still_length);
295 add_label_to_sizer (s, _panel, _("s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
299 add_label_to_sizer (table, _panel, _("Default directory for new films"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
300 #ifdef DCPOMATIC_USE_OWN_PICKER
301 _directory = new DirPickerCtrl (_panel);
303 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
305 table->Add (_directory, 1, wxEXPAND);
307 add_label_to_sizer (table, _panel, _("Default content type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
308 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
309 table->Add (_dcp_content_type);
311 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
312 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
313 table->Add (_dcp_audio_channels);
316 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
317 auto s = new wxBoxSizer (wxHORIZONTAL);
318 _j2k_bandwidth = new wxSpinCtrl (_panel);
319 s->Add (_j2k_bandwidth);
320 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
325 add_label_to_sizer (table, _panel, _("Default audio delay"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
326 auto s = new wxBoxSizer (wxHORIZONTAL);
327 _audio_delay = new wxSpinCtrl (_panel);
328 s->Add (_audio_delay);
329 add_label_to_sizer (s, _panel, _("ms"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
333 add_label_to_sizer (table, _panel, _("Default standard"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
334 _standard = new wxChoice (_panel, wxID_ANY);
335 table->Add (_standard);
337 _enable_audio_language = new CheckBox(_panel, _("Default audio language"));
338 table->Add(_enable_audio_language, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
339 _audio_language = new LanguageTagWidget(_panel, _("Default audio language to use for new DCPs"), Config::instance()->default_audio_language(), wxString("cmnr-Hant-"));
340 table->Add(_audio_language->sizer());
342 _enable_territory = new CheckBox(_panel, _("Default territory"));
343 table->Add(_enable_territory, 1, wxEXPAND | wxALIGN_CENTRE_VERTICAL);
344 _territory = new RegionSubtagWidget(_panel, _("Default territory to use for new DCPs"), Config::instance()->default_territory(), wxString("cmnr-Hant-"));
345 table->Add(_territory->sizer());
347 table->Add (_enable_metadata["facility"] = new CheckBox (_panel, _("Default facility")), 0, wxALIGN_CENTRE_VERTICAL);
348 table->Add (_metadata["facility"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
350 table->Add (_enable_metadata["studio"] = new CheckBox (_panel, _("Default studio")), 0, wxALIGN_CENTRE_VERTICAL);
351 table->Add (_metadata["studio"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
353 table->Add (_enable_metadata["chain"] = new CheckBox (_panel, _("Default chain")), 0, wxALIGN_CENTRE_VERTICAL);
354 table->Add (_metadata["chain"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
356 table->Add (_enable_metadata["distributor"] = new CheckBox (_panel, _("Default distributor")), 0, wxALIGN_CENTRE_VERTICAL);
357 table->Add (_metadata["distributor"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
359 add_label_to_sizer (table, _panel, _("Default KDM directory"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
360 #ifdef DCPOMATIC_USE_OWN_PICKER
361 _kdm_directory = new DirPickerCtrl (_panel);
363 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
365 table->Add (_kdm_directory, 1, wxEXPAND);
367 add_label_to_sizer (table, _panel, _("Default KDM type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
368 _kdm_type = new KDMChoice (_panel);
369 table->Add (_kdm_type, 1, wxEXPAND);
371 add_label_to_sizer (table, _panel, _("Default KDM duration"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
372 _kdm_duration = new wxSpinCtrl (_panel);
373 _kdm_duration_unit = new wxChoice (_panel, wxID_ANY);
374 auto kdm_duration_sizer = new wxBoxSizer (wxHORIZONTAL);
375 kdm_duration_sizer->Add (_kdm_duration, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
376 kdm_duration_sizer->Add (_kdm_duration_unit, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
377 table->Add (kdm_duration_sizer, 1, wxEXPAND);
379 table->Add (_use_isdcf_name_by_default = new CheckBox(_panel, _("Use ISDCF name by default")), 0, wxALIGN_CENTRE_VERTICAL);
381 _still_length->SetRange (1, 3600);
382 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
384 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
385 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
386 _kdm_type->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_type_changed, this));
387 _kdm_duration_unit->Append (_("days"));
388 _kdm_duration_unit->Append (_("weeks"));
389 _kdm_duration_unit->Append (_("months"));
390 _kdm_duration_unit->Append (_("years"));
392 _kdm_duration->Bind (wxEVT_SPINCTRL, boost::bind(&DefaultsPage::kdm_duration_changed, this));
393 _kdm_duration_unit->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_duration_changed, this));
395 _use_isdcf_name_by_default->bind(&DefaultsPage::use_isdcf_name_by_default_changed, this);
397 for (auto i: DCPContentType::all()) {
398 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
401 setup_audio_channels_choice (_dcp_audio_channels, 2);
403 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
404 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
406 _j2k_bandwidth->SetRange (50, 250);
407 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
409 _audio_delay->SetRange (-1000, 1000);
410 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
412 _standard->Append (_("SMPTE"));
413 _standard->Append (_("Interop"));
414 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
416 for (auto const& i: _enable_metadata) {
417 i.second->bind(&DefaultsPage::metadata_changed, this);
420 for (auto const& i: _metadata) {
421 i.second->Bind (wxEVT_TEXT, boost::bind(&DefaultsPage::metadata_changed, this));
424 _enable_audio_language->bind(&DefaultsPage::enable_audio_language_toggled, this);
425 _audio_language->Changed.connect(boost::bind(&DefaultsPage::audio_language_changed, this));
427 _enable_territory->bind(&DefaultsPage::enable_territory_toggled, this);
428 _territory->Changed.connect(boost::bind(&DefaultsPage::territory_changed, this));
431 void config_changed () override
433 auto config = Config::instance ();
435 auto const ct = DCPContentType::all ();
436 for (size_t i = 0; i < ct.size(); ++i) {
437 if (ct[i] == config->default_dcp_content_type()) {
438 _dcp_content_type->SetSelection (i);
442 checked_set (_still_length, config->default_still_length ());
443 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
444 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
445 _kdm_type->set (config->default_kdm_type());
446 checked_set (_use_isdcf_name_by_default, config->use_isdcf_name_by_default());
447 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
448 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
449 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
450 checked_set (_audio_delay, config->default_audio_delay ());
451 checked_set (_standard, config->default_interop() ? 1 : 0);
452 auto dal = config->default_audio_language();
453 checked_set(_enable_audio_language, static_cast<bool>(dal));
454 checked_set(_audio_language, dal ? dal : boost::none);
455 auto dt = config->default_territory();
456 checked_set(_enable_territory, static_cast<bool>(dt));
457 checked_set(_territory, dt ? dt : boost::none);
459 auto metadata = config->default_metadata();
461 for (auto const& i: metadata) {
462 _enable_metadata[i.first]->SetValue(true);
463 checked_set (_metadata[i.first], i.second);
466 for (auto const& i: _enable_metadata) {
467 if (metadata.find(i.first) == metadata.end()) {
468 checked_set (i.second, false);
472 for (auto const& i: _metadata) {
473 if (metadata.find(i.first) == metadata.end()) {
474 checked_set (i.second, wxT(""));
478 checked_set (_kdm_duration, config->default_kdm_duration().duration);
479 switch (config->default_kdm_duration().unit) {
480 case RoughDuration::Unit::DAYS:
481 _kdm_duration->SetRange(1, 365);
482 checked_set (_kdm_duration_unit, 0);
484 case RoughDuration::Unit::WEEKS:
485 _kdm_duration->SetRange(1, 52);
486 checked_set (_kdm_duration_unit, 1);
488 case RoughDuration::Unit::MONTHS:
489 _kdm_duration->SetRange(1, 12);
490 checked_set (_kdm_duration_unit, 2);
492 case RoughDuration::Unit::YEARS:
493 _kdm_duration->SetRange(1, 40);
494 checked_set (_kdm_duration_unit, 3);
498 setup_sensitivity ();
501 void kdm_duration_changed ()
503 auto config = Config::instance();
504 auto duration = _kdm_duration->GetValue();
505 RoughDuration::Unit unit = RoughDuration::Unit::DAYS;
506 switch (_kdm_duration_unit->GetSelection()) {
508 unit = RoughDuration::Unit::DAYS;
511 unit = RoughDuration::Unit::WEEKS;
514 unit = RoughDuration::Unit::MONTHS;
517 unit = RoughDuration::Unit::YEARS;
520 config->set_default_kdm_duration (RoughDuration(duration, unit));
523 void j2k_bandwidth_changed ()
525 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
528 void audio_delay_changed ()
530 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
533 void dcp_audio_channels_changed ()
535 int const s = _dcp_audio_channels->GetSelection ();
536 if (s != wxNOT_FOUND) {
537 Config::instance()->set_default_dcp_audio_channels (
538 locale_convert<int>(string_client_data(_dcp_audio_channels->GetClientObject(s)))
543 void directory_changed ()
545 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
548 void kdm_directory_changed ()
550 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
553 void kdm_type_changed ()
555 Config::instance()->set_default_kdm_type(_kdm_type->get());
558 void use_isdcf_name_by_default_changed ()
560 Config::instance()->set_use_isdcf_name_by_default (_use_isdcf_name_by_default->GetValue());
563 void still_length_changed ()
565 Config::instance()->set_default_still_length (_still_length->GetValue ());
568 void dcp_content_type_changed ()
570 auto ct = DCPContentType::all ();
571 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
574 void standard_changed ()
576 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
579 void metadata_changed ()
581 map<string, string> metadata;
582 for (auto const& i: _enable_metadata) {
583 if (i.second->GetValue()) {
584 metadata[i.first] = wx_to_std(_metadata[i.first]->GetValue());
587 Config::instance()->set_default_metadata (metadata);
588 setup_sensitivity ();
591 void enable_audio_language_toggled()
594 audio_language_changed();
597 void audio_language_changed()
599 if (_enable_audio_language->get()) {
600 Config::instance()->set_default_audio_language(_audio_language->get().get_value_or(dcp::LanguageTag("en-US")));
602 Config::instance()->unset_default_audio_language();
606 void enable_territory_toggled()
612 void territory_changed()
614 if (_enable_territory->get()) {
615 Config::instance()->set_default_territory(_territory->get().get_value_or(dcp::LanguageTag::RegionSubtag("US")));
617 Config::instance()->unset_default_territory();
621 void setup_sensitivity ()
623 _audio_language->enable(_enable_audio_language->get());
624 _territory->enable(_enable_territory->get());
625 for (auto const& i: _enable_metadata) {
626 _metadata[i.first]->Enable(i.second->GetValue());
630 wxSpinCtrl* _j2k_bandwidth;
631 wxSpinCtrl* _audio_delay;
632 wxSpinCtrl* _still_length;
633 #ifdef DCPOMATIC_USE_OWN_PICKER
634 DirPickerCtrl* _directory;
635 DirPickerCtrl* _kdm_directory;
637 wxDirPickerCtrl* _directory;
638 wxDirPickerCtrl* _kdm_directory;
640 KDMChoice* _kdm_type;
641 wxSpinCtrl* _kdm_duration;
642 wxChoice* _kdm_duration_unit;
643 CheckBox* _use_isdcf_name_by_default;
644 wxChoice* _dcp_content_type;
645 wxChoice* _dcp_audio_channels;
647 CheckBox* _enable_audio_language;
648 LanguageTagWidget* _audio_language;
649 CheckBox* _enable_territory;
650 RegionSubtagWidget* _territory;
651 map<string, CheckBox*> _enable_metadata;
652 map<string, wxTextCtrl*> _metadata;
656 class EncodingServersPage : public Page
659 EncodingServersPage (wxSize panel_size, int border)
660 : Page (panel_size, border)
663 wxString GetName () const override
669 wxBitmap GetLargeIcon () const override
671 return wxBitmap(icon_path("servers"), wxBITMAP_TYPE_PNG);
676 void setup () override
678 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
679 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
681 vector<EditableListColumn> columns;
682 columns.push_back (EditableListColumn(_("IP address / host name")));
683 _servers_list = new EditableList<string, ServerDialog> (
686 boost::bind (&Config::servers, Config::instance()),
687 boost::bind (&Config::set_servers, Config::instance(), _1),
688 boost::bind (&EncodingServersPage::server_column, this, _1),
689 EditableListTitle::INVISIBLE,
690 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
693 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
695 _use_any_servers->bind(&EncodingServersPage::use_any_servers_changed, this);
698 void config_changed () override
700 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
701 _servers_list->refresh ();
704 void use_any_servers_changed ()
706 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
709 string server_column (string s)
714 CheckBox* _use_any_servers;
715 EditableList<string, ServerDialog>* _servers_list;
719 class TMSPage : public Page
722 TMSPage (wxSize panel_size, int border)
723 : Page (panel_size, border)
726 wxString GetName () const override
732 wxBitmap GetLargeIcon () const override
734 return wxBitmap(icon_path("tms"), wxBITMAP_TYPE_PNG);
739 void setup () override
741 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
742 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
744 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
745 table->AddGrowableCol (1, 1);
746 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
748 add_label_to_sizer (table, _panel, _("Protocol"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
749 _tms_protocol = new wxChoice (_panel, wxID_ANY);
750 table->Add (_tms_protocol, 1, wxEXPAND);
752 _tms_passive = new CheckBox(_panel, _("Passive mode"));
753 table->Add(_tms_passive, 1, wxEXPAND);
756 add_label_to_sizer (table, _panel, _("IP address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
757 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
758 table->Add (_tms_ip, 1, wxEXPAND);
760 add_label_to_sizer (table, _panel, _("Target path"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
761 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
762 table->Add (_tms_path, 1, wxEXPAND);
764 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
765 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
766 table->Add (_tms_user, 1, wxEXPAND);
768 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
769 _tms_password = new PasswordEntry (_panel);
770 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
772 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
773 _tms_protocol->Append (_("FTP (for Dolby)"));
775 _upload->bind(&TMSPage::upload_changed, this);
776 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
777 _tms_passive->bind(&TMSPage::tms_passive_changed, this);
779 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
780 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
781 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
782 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
785 void config_changed () override
787 auto config = Config::instance ();
789 checked_set (_upload, config->upload_after_make_dcp());
790 checked_set (_tms_protocol, static_cast<int>(config->tms_protocol()));
791 checked_set(_tms_passive, config->tms_protocol() == FileTransferProtocol::FTP && config->tms_passive());
792 checked_set (_tms_ip, config->tms_ip ());
793 checked_set (_tms_path, config->tms_path ());
794 checked_set (_tms_user, config->tms_user ());
795 checked_set (_tms_password, config->tms_password ());
797 _tms_passive->Enable(config->tms_protocol() == FileTransferProtocol::FTP);
800 void upload_changed ()
802 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
805 void tms_protocol_changed ()
807 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
810 void tms_passive_changed()
812 Config::instance()->set_tms_passive(_tms_passive->get());
815 void tms_ip_changed ()
817 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
820 void tms_path_changed ()
822 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
825 void tms_user_changed ()
827 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
830 void tms_password_changed ()
832 Config::instance()->set_tms_password (_tms_password->get());
836 CheckBox* _tms_passive;
837 wxChoice* _tms_protocol;
839 wxTextCtrl* _tms_path;
840 wxTextCtrl* _tms_user;
841 PasswordEntry* _tms_password;
845 class EmailPage : public Page
848 EmailPage (wxSize panel_size, int border)
849 : Page (panel_size, border)
852 wxString GetName () const override
858 wxBitmap GetLargeIcon () const override
860 return wxBitmap(icon_path("email"), wxBITMAP_TYPE_PNG);
865 void setup () override
867 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
868 table->AddGrowableCol (1, 1);
869 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
871 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
873 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
874 _server = new wxTextCtrl (_panel, wxID_ANY);
875 s->Add (_server, 1, wxEXPAND | wxALL);
876 add_label_to_sizer (s, _panel, _("port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
877 _port = new wxSpinCtrl (_panel, wxID_ANY);
878 _port->SetRange (0, 65535);
880 add_label_to_sizer (s, _panel, _("protocol"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
881 _protocol = new wxChoice (_panel, wxID_ANY);
882 /* Make sure this matches the switches in config_changed and port_changed below */
883 _protocol->Append (_("Auto"));
884 _protocol->Append (_("Plain"));
885 _protocol->Append (_("STARTTLS"));
886 _protocol->Append (_("SSL"));
887 s->Add (_protocol, 1, wxALIGN_CENTER_VERTICAL);
888 table->Add (s, 1, wxEXPAND | wxALL);
891 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
892 _user = new wxTextCtrl (_panel, wxID_ANY);
893 table->Add (_user, 1, wxEXPAND | wxALL);
895 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
896 _password = new PasswordEntry (_panel);
897 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
899 table->AddSpacer (0);
900 _send_test_email = new Button (_panel, _("Send test email..."));
901 table->Add (_send_test_email);
903 _server->Bind (wxEVT_TEXT, boost::bind(&EmailPage::server_changed, this));
904 _port->Bind (wxEVT_SPINCTRL, boost::bind(&EmailPage::port_changed, this));
905 _protocol->Bind (wxEVT_CHOICE, boost::bind(&EmailPage::protocol_changed, this));
906 _user->Bind (wxEVT_TEXT, boost::bind(&EmailPage::user_changed, this));
907 _password->Changed.connect (boost::bind(&EmailPage::password_changed, this));
908 _send_test_email->Bind (wxEVT_BUTTON, boost::bind(&EmailPage::send_test_email_clicked, this));
911 void config_changed () override
913 auto config = Config::instance ();
915 checked_set (_server, config->mail_server());
916 checked_set (_port, config->mail_port());
917 switch (config->mail_protocol()) {
918 case EmailProtocol::AUTO:
919 checked_set (_protocol, 0);
921 case EmailProtocol::PLAIN:
922 checked_set (_protocol, 1);
924 case EmailProtocol::STARTTLS:
925 checked_set (_protocol, 2);
927 case EmailProtocol::SSL:
928 checked_set (_protocol, 3);
931 checked_set (_user, config->mail_user());
932 checked_set (_password, config->mail_password());
935 void server_changed ()
937 Config::instance()->set_mail_server(wx_to_std(_server->GetValue()));
942 Config::instance()->set_mail_port(_port->GetValue());
945 void protocol_changed ()
947 switch (_protocol->GetSelection()) {
949 Config::instance()->set_mail_protocol(EmailProtocol::AUTO);
952 Config::instance()->set_mail_protocol(EmailProtocol::PLAIN);
955 Config::instance()->set_mail_protocol(EmailProtocol::STARTTLS);
958 Config::instance()->set_mail_protocol(EmailProtocol::SSL);
965 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
968 void password_changed ()
970 Config::instance()->set_mail_password(_password->get());
973 void send_test_email_clicked ()
975 SendTestEmailDialog dialog(_panel);
976 if (dialog.ShowModal() != wxID_OK) {
981 wx_to_std(dialog.from()),
982 { wx_to_std(dialog.to()) },
983 wx_to_std(_("DCP-o-matic test email")),
984 wx_to_std(_("This is a test email from DCP-o-matic."))
986 auto config = Config::instance();
988 emailer.send(config->mail_server(), config->mail_port(), config->mail_protocol(), config->mail_user(), config->mail_password());
989 } catch (NetworkError& e) {
990 error_dialog(_panel, std_to_wx(e.summary()), std_to_wx(e.detail().get_value_or("")));
992 } catch (std::exception& e) {
993 error_dialog(_panel, _("Test email sending failed."), std_to_wx(e.what()));
996 error_dialog(_panel, _("Test email sending failed."));
999 message_dialog(_panel, _("Test email sent."));
1002 wxTextCtrl* _server;
1004 wxChoice* _protocol;
1006 PasswordEntry* _password;
1007 Button* _send_test_email;
1011 class KDMEmailPage : public Page
1015 KDMEmailPage (wxSize panel_size, int border)
1016 #ifdef DCPOMATIC_OSX
1017 /* We have to force both width and height of this one */
1018 : Page (wxSize (panel_size.GetWidth(), 128), border)
1020 : Page (panel_size, border)
1024 wxString GetName () const override
1026 return _("KDM Email");
1029 #ifdef DCPOMATIC_OSX
1030 wxBitmap GetLargeIcon () const override
1032 return wxBitmap(icon_path("kdm_email"), wxBITMAP_TYPE_PNG);
1037 void setup () override
1039 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1040 table->AddGrowableCol (1, 1);
1041 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1043 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1044 _subject = new wxTextCtrl (_panel, wxID_ANY);
1045 table->Add (_subject, 1, wxEXPAND | wxALL);
1047 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1048 _from = new wxTextCtrl (_panel, wxID_ANY);
1049 table->Add (_from, 1, wxEXPAND | wxALL);
1051 vector<EditableListColumn> columns;
1052 columns.push_back (EditableListColumn(_("Address")));
1053 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1054 _cc = new EditableList<string, EmailDialog> (
1057 bind (&Config::kdm_cc, Config::instance()),
1058 bind (&Config::set_kdm_cc, Config::instance(), _1),
1059 [] (string s, int) {
1062 EditableListTitle::VISIBLE,
1063 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1065 table->Add (_cc, 1, wxEXPAND | wxALL);
1067 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1068 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1069 table->Add (_bcc, 1, wxEXPAND | wxALL);
1071 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1072 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1074 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1075 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1079 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1080 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1081 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1082 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1083 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
1086 void config_changed () override
1088 auto config = Config::instance ();
1090 checked_set (_subject, config->kdm_subject ());
1091 checked_set (_from, config->kdm_from ());
1092 checked_set (_bcc, config->kdm_bcc ());
1093 checked_set (_email, Config::instance()->kdm_email ());
1096 void kdm_subject_changed ()
1098 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
1101 void kdm_from_changed ()
1103 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
1106 void kdm_bcc_changed ()
1108 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
1111 void kdm_email_changed ()
1113 if (_email->GetValue().IsEmpty ()) {
1114 /* Sometimes we get sent an erroneous notification that the email
1115 is empty; I don't know why.
1119 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
1124 Config::instance()->reset_kdm_email ();
1125 checked_set (_email, Config::instance()->kdm_email ());
1128 wxTextCtrl* _subject;
1130 EditableList<string, EmailDialog>* _cc;
1133 wxButton* _reset_email;
1137 class NotificationsPage : public Page
1140 NotificationsPage (wxSize panel_size, int border)
1141 #ifdef DCPOMATIC_OSX
1142 /* We have to force both width and height of this one */
1143 : Page (wxSize (panel_size.GetWidth(), 128), border)
1145 : Page (panel_size, border)
1149 wxString GetName () const override
1151 return _("Notifications");
1154 #ifdef DCPOMATIC_OSX
1155 wxBitmap GetLargeIcon () const override
1157 return wxBitmap(icon_path("notifications"), wxBITMAP_TYPE_PNG);
1162 void setup () override
1164 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1165 table->AddGrowableCol (1, 1);
1166 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1168 _enable_message_box = new CheckBox (_panel, _("Message box"));
1169 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
1170 table->AddSpacer (0);
1172 _enable_email = new CheckBox (_panel, _("Email"));
1173 table->Add (_enable_email, 1, wxEXPAND | wxALL);
1174 table->AddSpacer (0);
1176 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1177 _subject = new wxTextCtrl (_panel, wxID_ANY);
1178 table->Add (_subject, 1, wxEXPAND | wxALL);
1180 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1181 _from = new wxTextCtrl (_panel, wxID_ANY);
1182 table->Add (_from, 1, wxEXPAND | wxALL);
1184 add_label_to_sizer (table, _panel, _("To address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1185 _to = new wxTextCtrl (_panel, wxID_ANY);
1186 table->Add (_to, 1, wxEXPAND | wxALL);
1188 vector<EditableListColumn> columns;
1189 columns.push_back (EditableListColumn(_("Address")));
1190 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1191 _cc = new EditableList<string, EmailDialog> (
1194 bind (&Config::notification_cc, Config::instance()),
1195 bind (&Config::set_notification_cc, Config::instance(), _1),
1196 [] (string s, int) {
1199 EditableListTitle::VISIBLE,
1200 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1202 table->Add (_cc, 1, wxEXPAND | wxALL);
1204 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1205 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1206 table->Add (_bcc, 1, wxEXPAND | wxALL);
1208 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1209 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1211 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1212 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1216 _enable_message_box->bind(&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX);
1217 _enable_email->bind(&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL);
1219 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
1220 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
1221 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
1222 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
1223 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
1224 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
1226 setup_sensitivity ();
1229 void setup_sensitivity ()
1231 bool const s = _enable_email->GetValue();
1232 _subject->Enable(s);
1238 _reset_email->Enable(s);
1241 void config_changed () override
1243 auto config = Config::instance ();
1245 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
1246 checked_set (_enable_email, config->notification(Config::EMAIL));
1247 checked_set (_subject, config->notification_subject ());
1248 checked_set (_from, config->notification_from ());
1249 checked_set (_to, config->notification_to ());
1250 checked_set (_bcc, config->notification_bcc ());
1251 checked_set (_email, Config::instance()->notification_email ());
1253 setup_sensitivity ();
1256 void notification_subject_changed ()
1258 Config::instance()->set_notification_subject(wx_to_std(_subject->GetValue()));
1261 void notification_from_changed ()
1263 Config::instance()->set_notification_from(wx_to_std(_from->GetValue()));
1266 void notification_to_changed ()
1268 Config::instance()->set_notification_to(wx_to_std(_to->GetValue()));
1271 void notification_bcc_changed ()
1273 Config::instance()->set_notification_bcc(wx_to_std(_bcc->GetValue()));
1276 void notification_email_changed ()
1278 if (_email->GetValue().IsEmpty()) {
1279 /* Sometimes we get sent an erroneous notification that the email
1280 is empty; I don't know why.
1284 Config::instance()->set_notification_email(wx_to_std(_email->GetValue()));
1289 Config::instance()->reset_notification_email();
1290 checked_set (_email, Config::instance()->notification_email());
1293 void type_changed (CheckBox* b, Config::Notification n)
1295 Config::instance()->set_notification(n, b->GetValue());
1296 setup_sensitivity ();
1299 CheckBox* _enable_message_box;
1300 CheckBox* _enable_email;
1302 wxTextCtrl* _subject;
1305 EditableList<string, EmailDialog>* _cc;
1308 wxButton* _reset_email;
1312 class CoverSheetPage : public Page
1316 CoverSheetPage (wxSize panel_size, int border)
1317 #ifdef DCPOMATIC_OSX
1318 /* We have to force both width and height of this one */
1319 : Page (wxSize (panel_size.GetWidth(), 128), border)
1321 : Page (panel_size, border)
1325 wxString GetName () const override
1327 return _("Cover Sheet");
1330 #ifdef DCPOMATIC_OSX
1331 wxBitmap GetLargeIcon () const override
1333 return wxBitmap(icon_path("cover_sheet"), wxBITMAP_TYPE_PNG);
1338 void setup () override
1340 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1341 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1343 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1344 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1346 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1347 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1350 void config_changed () override
1352 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1355 void cover_sheet_changed ()
1357 if (_cover_sheet->GetValue().IsEmpty ()) {
1358 /* Sometimes we get sent an erroneous notification that the cover sheet
1359 is empty; I don't know why.
1363 Config::instance()->set_cover_sheet(wx_to_std(_cover_sheet->GetValue()));
1366 void reset_cover_sheet ()
1368 Config::instance()->reset_cover_sheet();
1369 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1372 wxTextCtrl* _cover_sheet;
1373 wxButton* _reset_cover_sheet;
1377 class IdentifiersPage : public Page
1380 IdentifiersPage (wxSize panel_size, int border)
1381 : Page (panel_size, border)
1384 wxString GetName () const override
1386 return _("Identifiers");
1389 #ifdef DCPOMATIC_OSX
1390 wxBitmap GetLargeIcon () const override
1392 return wxBitmap(icon_path("identifiers"), wxBITMAP_TYPE_PNG);
1397 void setup () override
1399 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1400 table->AddGrowableCol (1, 1);
1402 add_label_to_sizer (table, _panel, _("Issuer"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1403 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1404 _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."));
1405 table->Add (_issuer, 1, wxALL | wxEXPAND);
1407 add_label_to_sizer (table, _panel, _("Creator"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1408 _creator = new wxTextCtrl (_panel, wxID_ANY);
1409 _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."));
1410 table->Add (_creator, 1, wxALL | wxEXPAND);
1412 add_label_to_sizer (table, _panel, _("Company name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1413 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1414 _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."));
1415 table->Add (_company_name, 1, wxALL | wxEXPAND);
1417 add_label_to_sizer (table, _panel, _("Product name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1418 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1419 _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."));
1420 table->Add (_product_name, 1, wxALL | wxEXPAND);
1422 add_label_to_sizer (table, _panel, _("Product version"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1423 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1424 _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."));
1425 table->Add (_product_version, 1, wxALL | wxEXPAND);
1427 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1428 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1429 _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."));
1430 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1432 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1434 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1435 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1436 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1437 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1438 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1439 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1442 void config_changed () override
1444 auto config = Config::instance ();
1445 checked_set (_issuer, config->dcp_issuer ());
1446 checked_set (_creator, config->dcp_creator ());
1447 checked_set (_company_name, config->dcp_company_name ());
1448 checked_set (_product_name, config->dcp_product_name ());
1449 checked_set (_product_version, config->dcp_product_version ());
1450 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1453 void issuer_changed ()
1455 Config::instance()->set_dcp_issuer(wx_to_std(_issuer->GetValue()));
1458 void creator_changed ()
1460 Config::instance()->set_dcp_creator(wx_to_std(_creator->GetValue()));
1463 void company_name_changed ()
1465 Config::instance()->set_dcp_company_name(wx_to_std(_company_name->GetValue()));
1468 void product_name_changed ()
1470 Config::instance()->set_dcp_product_name(wx_to_std(_product_name->GetValue()));
1473 void product_version_changed ()
1475 Config::instance()->set_dcp_product_version(wx_to_std(_product_version->GetValue()));
1478 void j2k_comment_changed ()
1480 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1483 wxTextCtrl* _issuer;
1484 wxTextCtrl* _creator;
1485 wxTextCtrl* _company_name;
1486 wxTextCtrl* _product_name;
1487 wxTextCtrl* _product_version;
1488 wxTextCtrl* _j2k_comment;
1492 /** @class AdvancedPage
1493 * @brief Advanced page of the preferences dialog.
1495 class AdvancedPage : public Page
1498 AdvancedPage (wxSize panel_size, int border)
1499 : Page (panel_size, border)
1502 wxString GetName () const override
1504 return _("Advanced");
1507 #ifdef DCPOMATIC_OSX
1508 wxBitmap GetLargeIcon () const override
1510 return wxBitmap(icon_path("advanced"), wxBITMAP_TYPE_PNG);
1515 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1517 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1519 flags |= wxALIGN_RIGHT;
1522 wxStaticText* m = new StaticText (parent, text);
1523 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1526 void setup () override
1528 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1529 table->AddGrowableCol (1, 1);
1530 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1533 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1534 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1535 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1536 s->Add (_maximum_j2k_bandwidth, 1);
1537 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxALIGN_CENTRE_VERTICAL);
1541 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1542 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1543 table->Add (_video_display_mode);
1545 auto restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1546 auto font = restart->GetFont();
1547 font.SetStyle (wxFONTSTYLE_ITALIC);
1548 font.SetPointSize (font.GetPointSize() - 1);
1549 restart->SetFont (font);
1550 table->AddSpacer (0);
1552 _allow_any_dcp_frame_rate = new CheckBox (_panel, _("Allow any DCP frame rate"));
1553 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1554 table->AddSpacer (0);
1556 _allow_any_container = new CheckBox (_panel, _("Allow full-frame and non-standard container ratios"));
1557 table->Add (_allow_any_container, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1558 restart = new StaticText (_panel, _("(restart DCP-o-matic to see all ratios)"));
1559 table->Add(restart, 1, wxALIGN_CENTRE_VERTICAL | wxBOTTOM, DCPOMATIC_CHECKBOX_BOTTOM_PAD);
1560 restart->SetFont (font);
1562 _allow_96khz_audio = new CheckBox (_panel, _("Allow creation of DCPs with 96kHz audio"));
1563 table->Add (_allow_96khz_audio, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1564 table->AddSpacer (0);
1566 _use_all_audio_channels = new CheckBox(_panel, _("Allow mapping to all audio channels"));
1567 table->Add(_use_all_audio_channels, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1568 table->AddSpacer(0);
1570 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1571 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1572 table->AddSpacer (0);
1574 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1575 table->Add (_only_servers_encode, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1576 table->AddSpacer (0);
1579 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1580 auto s = new wxBoxSizer (wxHORIZONTAL);
1581 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1582 s->Add (_frames_in_memory_multiplier, 1);
1587 auto format = create_label (_panel, _("DCP metadata filename format"), true);
1588 #ifdef DCPOMATIC_OSX
1589 auto align = new wxBoxSizer (wxHORIZONTAL);
1590 align->Add (format, 0, wxTOP, 2);
1591 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1593 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1595 dcp::NameFormat::Map titles;
1596 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1597 dcp::NameFormat::Map examples;
1598 examples['t'] = "cpl";
1599 _dcp_metadata_filename_format = new NameFormatEditor (
1600 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1602 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1606 auto format = create_label (_panel, _("DCP asset filename format"), true);
1607 #ifdef DCPOMATIC_OSX
1608 auto align = new wxBoxSizer (wxHORIZONTAL);
1609 align->Add (format, 0, wxTOP, 2);
1610 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1612 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1614 dcp::NameFormat::Map titles;
1615 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1616 titles['r'] = wx_to_std (_("reel number"));
1617 titles['n'] = wx_to_std (_("number of reels"));
1618 titles['c'] = wx_to_std (_("content filename"));
1619 dcp::NameFormat::Map examples;
1620 examples['t'] = "j2c";
1621 examples['r'] = "1";
1622 examples['n'] = "4";
1623 examples['c'] = "myfile.mp4";
1624 _dcp_asset_filename_format = new NameFormatEditor (
1625 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1627 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1631 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1632 auto t = new wxFlexGridSizer (2);
1633 _log_general = new CheckBox (_panel, _("General"));
1634 t->Add (_log_general, 1, wxEXPAND | wxALL);
1635 _log_warning = new CheckBox (_panel, _("Warnings"));
1636 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1637 _log_error = new CheckBox (_panel, _("Errors"));
1638 t->Add (_log_error, 1, wxEXPAND | wxALL);
1639 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1640 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1641 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1642 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1643 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1644 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1645 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1646 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1647 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1648 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1649 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1650 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1651 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1652 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1653 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1654 table->Add (t, 0, wxALL, 6);
1657 #ifdef DCPOMATIC_WINDOWS
1658 _win32_console = new CheckBox (_panel, _("Open console window"));
1659 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1660 table->AddSpacer (0);
1663 _maximum_j2k_bandwidth->SetRange (1, 1000);
1664 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1665 _video_display_mode->Append (_("Simple (safer)"));
1666 #if wxCHECK_VERSION(3, 1, 0)
1667 _video_display_mode->Append (_("OpenGL (faster)"));
1669 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1670 _allow_any_dcp_frame_rate->bind(&AdvancedPage::allow_any_dcp_frame_rate_changed, this);
1671 _allow_any_container->bind(&AdvancedPage::allow_any_container_changed, this);
1672 _allow_96khz_audio->bind(&AdvancedPage::allow_96khz_audio_changed, this);
1673 _use_all_audio_channels->bind(&AdvancedPage::use_all_channels_changed, this);
1674 _show_experimental_audio_processors->bind(&AdvancedPage::show_experimental_audio_processors_changed, this);
1675 _only_servers_encode->bind(&AdvancedPage::only_servers_encode_changed, this);
1676 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1677 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1678 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1679 _log_general->bind(&AdvancedPage::log_changed, this);
1680 _log_warning->bind(&AdvancedPage::log_changed, this);
1681 _log_error->bind(&AdvancedPage::log_changed, this);
1682 _log_timing->bind(&AdvancedPage::log_changed, this);
1683 _log_debug_threed->bind(&AdvancedPage::log_changed, this);
1684 _log_debug_encode->bind(&AdvancedPage::log_changed, this);
1685 _log_debug_email->bind(&AdvancedPage::log_changed, this);
1686 _log_debug_video_view->bind(&AdvancedPage::log_changed, this);
1687 _log_debug_player->bind(&AdvancedPage::log_changed, this);
1688 _log_debug_audio_analysis->bind(&AdvancedPage::log_changed, this);
1689 #ifdef DCPOMATIC_WINDOWS
1690 _win32_console->bind(&AdvancedPage::win32_console_changed, this);
1694 void config_changed () override
1696 auto config = Config::instance ();
1698 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1699 switch (config->video_view_type()) {
1700 case Config::VIDEO_VIEW_SIMPLE:
1701 checked_set (_video_display_mode, 0);
1703 case Config::VIDEO_VIEW_OPENGL:
1704 checked_set (_video_display_mode, 1);
1707 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1708 checked_set (_allow_any_container, config->allow_any_container ());
1709 checked_set (_allow_96khz_audio, config->allow_96khz_audio());
1710 checked_set (_use_all_audio_channels, config->use_all_audio_channels());
1711 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1712 checked_set (_only_servers_encode, config->only_servers_encode ());
1713 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1714 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1715 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1716 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1717 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREE_D);
1718 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1719 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1720 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1721 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1722 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1723 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1724 #ifdef DCPOMATIC_WINDOWS
1725 checked_set (_win32_console, config->win32_console());
1729 void maximum_j2k_bandwidth_changed ()
1731 Config::instance()->set_maximum_j2k_bandwidth(_maximum_j2k_bandwidth->GetValue() * 1000000);
1734 void video_display_mode_changed ()
1736 if (_video_display_mode->GetSelection() == 0) {
1737 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_SIMPLE);
1739 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_OPENGL);
1743 void frames_in_memory_multiplier_changed ()
1745 Config::instance()->set_frames_in_memory_multiplier(_frames_in_memory_multiplier->GetValue());
1748 void allow_any_dcp_frame_rate_changed ()
1750 Config::instance()->set_allow_any_dcp_frame_rate(_allow_any_dcp_frame_rate->GetValue());
1753 void allow_any_container_changed ()
1755 Config::instance()->set_allow_any_container(_allow_any_container->GetValue());
1758 void allow_96khz_audio_changed ()
1760 Config::instance()->set_allow_96hhz_audio(_allow_96khz_audio->GetValue());
1763 void use_all_channels_changed ()
1765 Config::instance()->set_use_all_audio_channels(_use_all_audio_channels->GetValue());
1768 void show_experimental_audio_processors_changed ()
1770 Config::instance()->set_show_experimental_audio_processors(_show_experimental_audio_processors->GetValue());
1773 void only_servers_encode_changed ()
1775 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue());
1778 void dcp_metadata_filename_format_changed ()
1780 Config::instance()->set_dcp_metadata_filename_format(_dcp_metadata_filename_format->get());
1783 void dcp_asset_filename_format_changed ()
1785 Config::instance()->set_dcp_asset_filename_format(_dcp_asset_filename_format->get());
1791 if (_log_general->GetValue ()) {
1792 types |= LogEntry::TYPE_GENERAL;
1794 if (_log_warning->GetValue ()) {
1795 types |= LogEntry::TYPE_WARNING;
1797 if (_log_error->GetValue ()) {
1798 types |= LogEntry::TYPE_ERROR;
1800 if (_log_timing->GetValue ()) {
1801 types |= LogEntry::TYPE_TIMING;
1803 if (_log_debug_threed->GetValue ()) {
1804 types |= LogEntry::TYPE_DEBUG_THREE_D;
1806 if (_log_debug_encode->GetValue ()) {
1807 types |= LogEntry::TYPE_DEBUG_ENCODE;
1809 if (_log_debug_email->GetValue ()) {
1810 types |= LogEntry::TYPE_DEBUG_EMAIL;
1812 if (_log_debug_video_view->GetValue()) {
1813 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1815 if (_log_debug_player->GetValue()) {
1816 types |= LogEntry::TYPE_DEBUG_PLAYER;
1818 if (_log_debug_audio_analysis->GetValue()) {
1819 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1821 Config::instance()->set_log_types (types);
1824 #ifdef DCPOMATIC_WINDOWS
1825 void win32_console_changed ()
1827 Config::instance()->set_win32_console(_win32_console->GetValue());
1831 wxSpinCtrl* _maximum_j2k_bandwidth = nullptr;
1832 wxChoice* _video_display_mode = nullptr;
1833 wxSpinCtrl* _frames_in_memory_multiplier = nullptr;
1834 CheckBox* _allow_any_dcp_frame_rate = nullptr;
1835 CheckBox* _allow_any_container = nullptr;
1836 CheckBox* _allow_96khz_audio = nullptr;
1837 CheckBox* _use_all_audio_channels = nullptr;
1838 CheckBox* _show_experimental_audio_processors = nullptr;
1839 CheckBox* _only_servers_encode = nullptr;
1840 NameFormatEditor* _dcp_metadata_filename_format = nullptr;
1841 NameFormatEditor* _dcp_asset_filename_format = nullptr;
1842 CheckBox* _log_general = nullptr;
1843 CheckBox* _log_warning = nullptr;
1844 CheckBox* _log_error = nullptr;
1845 CheckBox* _log_timing = nullptr;
1846 CheckBox* _log_debug_threed = nullptr;
1847 CheckBox* _log_debug_encode = nullptr;
1848 CheckBox* _log_debug_email = nullptr;
1849 CheckBox* _log_debug_video_view = nullptr;
1850 CheckBox* _log_debug_player = nullptr;
1851 CheckBox* _log_debug_audio_analysis = nullptr;
1852 #ifdef DCPOMATIC_WINDOWS
1853 CheckBox* _win32_console = nullptr;
1858 wxPreferencesEditor*
1859 create_full_config_dialog ()
1861 auto e = new wxPreferencesEditor ();
1863 #ifdef DCPOMATIC_OSX
1864 /* Width that we force some of the config panels to be on OSX so that
1865 the containing window doesn't shrink too much when we select those panels.
1866 This is obviously an unpleasant hack.
1868 wxSize ps = wxSize (750, -1);
1869 int const border = 16;
1871 wxSize ps = wxSize (-1, -1);
1872 int const border = 8;
1875 e->AddPage (new FullGeneralPage (ps, border));
1876 e->AddPage (new SoundPage (ps, border));
1877 e->AddPage (new DefaultsPage (ps, border));
1878 e->AddPage (new EncodingServersPage(ps, border));
1879 e->AddPage (new KeysPage (ps, border));
1880 e->AddPage (new TMSPage (ps, border));
1881 e->AddPage (new EmailPage (ps, border));
1882 e->AddPage (new KDMEmailPage (ps, border));
1883 e->AddPage (new NotificationsPage (ps, border));
1884 e->AddPage (new CoverSheetPage (ps, border));
1885 e->AddPage (new IdentifiersPage (ps, border));
1886 e->AddPage (new AdvancedPage (ps, border));