2 Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
22 /** @file src/full_config_dialog.cc
23 * @brief A dialogue to edit all DCP-o-matic configuration.
27 #include "check_box.h"
28 #include "config_dialog.h"
29 #include "config_move_dialog.h"
30 #include "dcpomatic_button.h"
31 #include "dir_picker_ctrl.h"
32 #include "editable_list.h"
33 #include "email_dialog.h"
34 #include "file_picker_ctrl.h"
35 #include "filter_dialog.h"
36 #include "full_config_dialog.h"
37 #include "kdm_choice.h"
38 #include "make_chain_dialog.h"
39 #include "nag_dialog.h"
40 #include "name_format_editor.h"
41 #include "password_entry.h"
42 #include "send_test_email_dialog.h"
43 #include "server_dialog.h"
44 #include "static_text.h"
46 #include "lib/config.h"
47 #include "lib/cross.h"
48 #include "lib/dcp_content_type.h"
49 #include "lib/emailer.h"
50 #include "lib/exceptions.h"
51 #include "lib/filter.h"
53 #include "lib/ratio.h"
55 #include <dcp/certificate_chain.h>
56 #include <dcp/exceptions.h>
57 #include <dcp/locale_convert.h>
58 #include <dcp/warnings.h>
59 LIBDCP_DISABLE_WARNINGS
60 #include <wx/filepicker.h>
61 #include <wx/preferences.h>
62 #include <wx/spinctrl.h>
63 #include <wx/stdpaths.h>
64 LIBDCP_ENABLE_WARNINGS
66 #include <boost/filesystem.hpp>
76 using std::shared_ptr;
80 using boost::optional;
81 #if BOOST_VERSION >= 106100
82 using namespace boost::placeholders;
84 using dcp::locale_convert;
87 class FullGeneralPage : public GeneralPage
90 FullGeneralPage (wxSize panel_size, int border)
91 : GeneralPage (panel_size, border)
95 void setup () override
97 auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
98 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
101 add_language_controls (table, r);
103 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
104 _master_encoding_threads = new wxSpinCtrl (_panel);
105 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
108 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
109 _server_encoding_threads = new wxSpinCtrl (_panel);
110 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
113 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
114 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, false);
115 table->Add (_config_file, wxGBPosition (r, 1));
118 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
119 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, false);
120 table->Add (_cinemas_file, wxGBPosition (r, 1));
121 Button* export_cinemas = new Button (_panel, _("Export..."));
122 table->Add (export_cinemas, wxGBPosition (r, 2));
125 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
126 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
127 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
131 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
132 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
135 add_update_controls (table, r);
137 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::config_file_changed, this));
138 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::cinemas_file_changed, this));
140 _master_encoding_threads->SetRange (1, 128);
141 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
142 _server_encoding_threads->SetRange (1, 128);
143 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
144 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
146 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
147 _analyse_ebur128->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::analyse_ebur128_changed, this));
149 _automatic_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::automatic_audio_analysis_changed, this));
152 void config_changed () override
154 auto config = Config::instance ();
156 checked_set (_master_encoding_threads, config->master_encoding_threads ());
157 checked_set (_server_encoding_threads, config->server_encoding_threads ());
158 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
159 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
161 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
162 checked_set (_config_file, config->config_read_file());
163 checked_set (_cinemas_file, config->cinemas_file());
165 GeneralPage::config_changed ();
168 void export_cinemas_file ()
170 auto d = new wxFileDialog (
171 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT("XML files (*.xml)|*.xml"),
172 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
175 if (d->ShowModal () == wxID_OK) {
176 boost::filesystem::copy_file (Config::instance()->cinemas_file(), wx_to_std(d->GetPath()));
181 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
182 void analyse_ebur128_changed ()
184 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue());
188 void automatic_audio_analysis_changed ()
190 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue());
193 void master_encoding_threads_changed ()
195 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue());
198 void server_encoding_threads_changed ()
200 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue());
203 void config_file_changed ()
205 auto config = Config::instance();
206 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
207 if (new_file == config->config_read_file()) {
210 bool copy_and_link = true;
211 if (boost::filesystem::exists(new_file)) {
212 auto d = new ConfigMoveDialog (_panel, new_file);
213 if (d->ShowModal() == wxID_OK) {
214 copy_and_link = false;
221 if (new_file != config->config_read_file()) {
222 config->copy_and_link (new_file);
225 config->link (new_file);
229 void cinemas_file_changed ()
231 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
234 wxSpinCtrl* _master_encoding_threads;
235 wxSpinCtrl* _server_encoding_threads;
236 FilePickerCtrl* _config_file;
237 FilePickerCtrl* _cinemas_file;
238 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
239 wxCheckBox* _analyse_ebur128;
241 wxCheckBox* _automatic_audio_analysis;
245 class DefaultsPage : public Page
248 DefaultsPage (wxSize panel_size, int border)
249 : Page (panel_size, border)
252 wxString GetName () const override
254 return _("Defaults");
258 wxBitmap GetLargeIcon () const override
260 return wxBitmap(bitmap_path("defaults"), wxBITMAP_TYPE_PNG);
265 void setup () override
267 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
268 table->AddGrowableCol (1, 1);
269 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
272 add_label_to_sizer (table, _panel, _("Default duration of still images"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
273 auto s = new wxBoxSizer (wxHORIZONTAL);
274 _still_length = new wxSpinCtrl (_panel);
275 s->Add (_still_length);
276 add_label_to_sizer (s, _panel, _("s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
280 add_label_to_sizer (table, _panel, _("Default directory for new films"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
281 #ifdef DCPOMATIC_USE_OWN_PICKER
282 _directory = new DirPickerCtrl (_panel);
284 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
286 table->Add (_directory, 1, wxEXPAND);
288 add_label_to_sizer (table, _panel, _("Default container"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
289 _container = new wxChoice (_panel, wxID_ANY);
290 table->Add (_container);
292 add_label_to_sizer (table, _panel, _("Default content type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
293 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
294 table->Add (_dcp_content_type);
296 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
297 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
298 table->Add (_dcp_audio_channels);
301 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
302 auto s = new wxBoxSizer (wxHORIZONTAL);
303 _j2k_bandwidth = new wxSpinCtrl (_panel);
304 s->Add (_j2k_bandwidth);
305 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
310 add_label_to_sizer (table, _panel, _("Default audio delay"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
311 auto s = new wxBoxSizer (wxHORIZONTAL);
312 _audio_delay = new wxSpinCtrl (_panel);
313 s->Add (_audio_delay);
314 add_label_to_sizer (s, _panel, _("ms"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
318 add_label_to_sizer (table, _panel, _("Default standard"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
319 _standard = new wxChoice (_panel, wxID_ANY);
320 table->Add (_standard);
322 table->Add (_enable_metadata["facility"] = new CheckBox (_panel, _("Default facility")), 0, wxALIGN_CENTRE_VERTICAL);
323 table->Add (_metadata["facility"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
325 table->Add (_enable_metadata["studio"] = new CheckBox (_panel, _("Default studio")), 0, wxALIGN_CENTRE_VERTICAL);
326 table->Add (_metadata["studio"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
328 table->Add (_enable_metadata["chain"] = new CheckBox (_panel, _("Default chain")), 0, wxALIGN_CENTRE_VERTICAL);
329 table->Add (_metadata["chain"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
331 table->Add (_enable_metadata["distributor"] = new CheckBox (_panel, _("Default distributor")), 0, wxALIGN_CENTRE_VERTICAL);
332 table->Add (_metadata["distributor"] = new wxTextCtrl (_panel, wxID_ANY, wxT("")), 0, wxEXPAND);
334 add_label_to_sizer (table, _panel, _("Default KDM directory"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
335 #ifdef DCPOMATIC_USE_OWN_PICKER
336 _kdm_directory = new DirPickerCtrl (_panel);
338 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
340 table->Add (_kdm_directory, 1, wxEXPAND);
342 add_label_to_sizer (table, _panel, _("Default KDM type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
343 _kdm_type = new KDMChoice (_panel);
344 table->Add (_kdm_type, 1, wxEXPAND);
346 add_label_to_sizer (table, _panel, _("Default KDM duration"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
347 _kdm_duration = new wxSpinCtrl (_panel);
348 _kdm_duration_unit = new wxChoice (_panel, wxID_ANY);
349 auto kdm_duration_sizer = new wxBoxSizer (wxHORIZONTAL);
350 kdm_duration_sizer->Add (_kdm_duration, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
351 kdm_duration_sizer->Add (_kdm_duration_unit, 0, wxEXPAND | wxRIGHT, DCPOMATIC_SIZER_GAP);
352 table->Add (kdm_duration_sizer, 1, wxEXPAND);
354 table->Add (_use_isdcf_name_by_default = new CheckBox(_panel, _("Use ISDCF name by default")), 0, wxALIGN_CENTRE_VERTICAL);
356 _still_length->SetRange (1, 3600);
357 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
359 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
360 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
361 _kdm_type->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_type_changed, this));
362 _kdm_duration_unit->Append (_("days"));
363 _kdm_duration_unit->Append (_("weeks"));
364 _kdm_duration_unit->Append (_("months"));
365 _kdm_duration_unit->Append (_("years"));
367 _kdm_duration->Bind (wxEVT_SPINCTRL, boost::bind(&DefaultsPage::kdm_duration_changed, this));
368 _kdm_duration_unit->Bind (wxEVT_CHOICE, boost::bind(&DefaultsPage::kdm_duration_changed, this));
370 _use_isdcf_name_by_default->Bind (wxEVT_CHECKBOX, boost::bind(&DefaultsPage::use_isdcf_name_by_default_changed, this));
372 for (auto i: Ratio::containers()) {
373 _container->Append (std_to_wx(i->container_nickname()));
376 _container->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::container_changed, this));
378 for (auto i: DCPContentType::all()) {
379 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
382 setup_audio_channels_choice (_dcp_audio_channels, 2);
384 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
385 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
387 _j2k_bandwidth->SetRange (50, 250);
388 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
390 _audio_delay->SetRange (-1000, 1000);
391 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
393 _standard->Append (_("SMPTE"));
394 _standard->Append (_("Interop"));
395 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
397 for (auto const& i: _enable_metadata) {
398 i.second->Bind (wxEVT_CHECKBOX, boost::bind(&DefaultsPage::metadata_changed, this));
401 for (auto const& i: _metadata) {
402 i.second->Bind (wxEVT_TEXT, boost::bind(&DefaultsPage::metadata_changed, this));
406 void config_changed () override
408 auto config = Config::instance ();
410 auto containers = Ratio::containers ();
411 for (size_t i = 0; i < containers.size(); ++i) {
412 if (containers[i] == config->default_container()) {
413 _container->SetSelection (i);
417 auto const ct = DCPContentType::all ();
418 for (size_t i = 0; i < ct.size(); ++i) {
419 if (ct[i] == config->default_dcp_content_type()) {
420 _dcp_content_type->SetSelection (i);
424 checked_set (_still_length, config->default_still_length ());
425 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
426 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
427 _kdm_type->set (config->default_kdm_type());
428 checked_set (_use_isdcf_name_by_default, config->use_isdcf_name_by_default());
429 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
430 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
431 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
432 checked_set (_audio_delay, config->default_audio_delay ());
433 checked_set (_standard, config->default_interop() ? 1 : 0);
435 auto metadata = config->default_metadata();
437 for (auto const& i: metadata) {
438 _enable_metadata[i.first]->SetValue(true);
439 checked_set (_metadata[i.first], i.second);
442 for (auto const& i: _enable_metadata) {
443 if (metadata.find(i.first) == metadata.end()) {
444 checked_set (i.second, false);
448 for (auto const& i: _metadata) {
449 if (metadata.find(i.first) == metadata.end()) {
450 checked_set (i.second, wxT(""));
454 checked_set (_kdm_duration, config->default_kdm_duration().duration);
455 switch (config->default_kdm_duration().unit) {
456 case RoughDuration::Unit::DAYS:
457 _kdm_duration->SetRange(1, 365);
458 checked_set (_kdm_duration_unit, 0);
460 case RoughDuration::Unit::WEEKS:
461 _kdm_duration->SetRange(1, 52);
462 checked_set (_kdm_duration_unit, 1);
464 case RoughDuration::Unit::MONTHS:
465 _kdm_duration->SetRange(1, 12);
466 checked_set (_kdm_duration_unit, 2);
468 case RoughDuration::Unit::YEARS:
469 _kdm_duration->SetRange(1, 40);
470 checked_set (_kdm_duration_unit, 3);
474 setup_sensitivity ();
477 void kdm_duration_changed ()
479 auto config = Config::instance();
480 auto duration = _kdm_duration->GetValue();
481 RoughDuration::Unit unit = RoughDuration::Unit::DAYS;
482 switch (_kdm_duration_unit->GetSelection()) {
484 unit = RoughDuration::Unit::DAYS;
487 unit = RoughDuration::Unit::WEEKS;
490 unit = RoughDuration::Unit::MONTHS;
493 unit = RoughDuration::Unit::YEARS;
496 config->set_default_kdm_duration (RoughDuration(duration, unit));
499 void j2k_bandwidth_changed ()
501 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
504 void audio_delay_changed ()
506 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
509 void dcp_audio_channels_changed ()
511 int const s = _dcp_audio_channels->GetSelection ();
512 if (s != wxNOT_FOUND) {
513 Config::instance()->set_default_dcp_audio_channels (
514 locale_convert<int>(string_client_data(_dcp_audio_channels->GetClientObject(s)))
519 void directory_changed ()
521 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
524 void kdm_directory_changed ()
526 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
529 void kdm_type_changed ()
531 Config::instance()->set_default_kdm_type(_kdm_type->get());
534 void use_isdcf_name_by_default_changed ()
536 Config::instance()->set_use_isdcf_name_by_default (_use_isdcf_name_by_default->GetValue());
539 void still_length_changed ()
541 Config::instance()->set_default_still_length (_still_length->GetValue ());
544 void container_changed ()
546 auto ratio = Ratio::containers ();
547 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
550 void dcp_content_type_changed ()
552 auto ct = DCPContentType::all ();
553 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
556 void standard_changed ()
558 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
561 void metadata_changed ()
563 map<string, string> metadata;
564 for (auto const& i: _enable_metadata) {
565 if (i.second->GetValue()) {
566 metadata[i.first] = wx_to_std(_metadata[i.first]->GetValue());
569 Config::instance()->set_default_metadata (metadata);
570 setup_sensitivity ();
573 void setup_sensitivity ()
575 for (auto const& i: _enable_metadata) {
576 _metadata[i.first]->Enable(i.second->GetValue());
580 wxSpinCtrl* _j2k_bandwidth;
581 wxSpinCtrl* _audio_delay;
582 wxSpinCtrl* _still_length;
583 #ifdef DCPOMATIC_USE_OWN_PICKER
584 DirPickerCtrl* _directory;
585 DirPickerCtrl* _kdm_directory;
587 wxDirPickerCtrl* _directory;
588 wxDirPickerCtrl* _kdm_directory;
590 KDMChoice* _kdm_type;
591 wxSpinCtrl* _kdm_duration;
592 wxChoice* _kdm_duration_unit;
593 wxCheckBox* _use_isdcf_name_by_default;
594 wxChoice* _container;
595 wxChoice* _dcp_content_type;
596 wxChoice* _dcp_audio_channels;
598 map<string, CheckBox*> _enable_metadata;
599 map<string, wxTextCtrl*> _metadata;
603 class EncodingServersPage : public Page
606 EncodingServersPage (wxSize panel_size, int border)
607 : Page (panel_size, border)
610 wxString GetName () const override
616 wxBitmap GetLargeIcon () const override
618 return wxBitmap(bitmap_path("servers"), wxBITMAP_TYPE_PNG);
623 void setup () override
625 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
626 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
628 vector<EditableListColumn> columns;
629 columns.push_back (EditableListColumn(_("IP address / host name")));
630 _servers_list = new EditableList<string, ServerDialog> (
633 boost::bind (&Config::servers, Config::instance()),
634 boost::bind (&Config::set_servers, Config::instance(), _1),
635 boost::bind (&EncodingServersPage::server_column, this, _1),
637 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
640 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
642 _use_any_servers->Bind (wxEVT_CHECKBOX, boost::bind(&EncodingServersPage::use_any_servers_changed, this));
645 void config_changed () override
647 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
648 _servers_list->refresh ();
651 void use_any_servers_changed ()
653 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
656 string server_column (string s)
661 wxCheckBox* _use_any_servers;
662 EditableList<string, ServerDialog>* _servers_list;
666 class TMSPage : public Page
669 TMSPage (wxSize panel_size, int border)
670 : Page (panel_size, border)
673 wxString GetName () const override
679 wxBitmap GetLargeIcon () const override
681 return wxBitmap(bitmap_path("tms"), wxBITMAP_TYPE_PNG);
686 void setup () override
688 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
689 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
691 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
692 table->AddGrowableCol (1, 1);
693 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
695 add_label_to_sizer (table, _panel, _("Protocol"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
696 _tms_protocol = new wxChoice (_panel, wxID_ANY);
697 table->Add (_tms_protocol, 1, wxEXPAND);
699 add_label_to_sizer (table, _panel, _("IP address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
700 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
701 table->Add (_tms_ip, 1, wxEXPAND);
703 add_label_to_sizer (table, _panel, _("Target path"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
704 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
705 table->Add (_tms_path, 1, wxEXPAND);
707 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
708 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
709 table->Add (_tms_user, 1, wxEXPAND);
711 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
712 _tms_password = new PasswordEntry (_panel);
713 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
715 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
716 _tms_protocol->Append (_("FTP (for Dolby)"));
718 _upload->Bind (wxEVT_CHECKBOX, boost::bind(&TMSPage::upload_changed, this));
719 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
720 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
721 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
722 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
723 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
726 void config_changed () override
728 auto config = Config::instance ();
730 checked_set (_upload, config->upload_after_make_dcp());
731 checked_set (_tms_protocol, static_cast<int>(config->tms_protocol()));
732 checked_set (_tms_ip, config->tms_ip ());
733 checked_set (_tms_path, config->tms_path ());
734 checked_set (_tms_user, config->tms_user ());
735 checked_set (_tms_password, config->tms_password ());
738 void upload_changed ()
740 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
743 void tms_protocol_changed ()
745 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
748 void tms_ip_changed ()
750 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
753 void tms_path_changed ()
755 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
758 void tms_user_changed ()
760 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
763 void tms_password_changed ()
765 Config::instance()->set_tms_password (_tms_password->get());
769 wxChoice* _tms_protocol;
771 wxTextCtrl* _tms_path;
772 wxTextCtrl* _tms_user;
773 PasswordEntry* _tms_password;
777 class EmailPage : public Page
780 EmailPage (wxSize panel_size, int border)
781 : Page (panel_size, border)
784 wxString GetName () const override
790 wxBitmap GetLargeIcon () const override
792 return wxBitmap(bitmap_path("email"), wxBITMAP_TYPE_PNG);
797 void setup () override
799 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
800 table->AddGrowableCol (1, 1);
801 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
803 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
805 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
806 _server = new wxTextCtrl (_panel, wxID_ANY);
807 s->Add (_server, 1, wxEXPAND | wxALL);
808 add_label_to_sizer (s, _panel, _("port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
809 _port = new wxSpinCtrl (_panel, wxID_ANY);
810 _port->SetRange (0, 65535);
812 add_label_to_sizer (s, _panel, _("protocol"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
813 _protocol = new wxChoice (_panel, wxID_ANY);
814 /* Make sure this matches the switches in config_changed and port_changed below */
815 _protocol->Append (_("Auto"));
816 _protocol->Append (_("Plain"));
817 _protocol->Append (_("STARTTLS"));
818 _protocol->Append (_("SSL"));
819 s->Add (_protocol, 1, wxALIGN_CENTER_VERTICAL);
820 table->Add (s, 1, wxEXPAND | wxALL);
823 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
824 _user = new wxTextCtrl (_panel, wxID_ANY);
825 table->Add (_user, 1, wxEXPAND | wxALL);
827 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
828 _password = new PasswordEntry (_panel);
829 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
831 table->AddSpacer (0);
832 _send_test_email = new Button (_panel, _("Send test email..."));
833 table->Add (_send_test_email);
835 _server->Bind (wxEVT_TEXT, boost::bind(&EmailPage::server_changed, this));
836 _port->Bind (wxEVT_SPINCTRL, boost::bind(&EmailPage::port_changed, this));
837 _protocol->Bind (wxEVT_CHOICE, boost::bind(&EmailPage::protocol_changed, this));
838 _user->Bind (wxEVT_TEXT, boost::bind(&EmailPage::user_changed, this));
839 _password->Changed.connect (boost::bind(&EmailPage::password_changed, this));
840 _send_test_email->Bind (wxEVT_BUTTON, boost::bind(&EmailPage::send_test_email_clicked, this));
843 void config_changed () override
845 auto config = Config::instance ();
847 checked_set (_server, config->mail_server());
848 checked_set (_port, config->mail_port());
849 switch (config->mail_protocol()) {
850 case EmailProtocol::AUTO:
851 checked_set (_protocol, 0);
853 case EmailProtocol::PLAIN:
854 checked_set (_protocol, 1);
856 case EmailProtocol::STARTTLS:
857 checked_set (_protocol, 2);
859 case EmailProtocol::SSL:
860 checked_set (_protocol, 3);
863 checked_set (_user, config->mail_user());
864 checked_set (_password, config->mail_password());
867 void server_changed ()
869 Config::instance()->set_mail_server(wx_to_std(_server->GetValue()));
874 Config::instance()->set_mail_port(_port->GetValue());
877 void protocol_changed ()
879 switch (_protocol->GetSelection()) {
881 Config::instance()->set_mail_protocol(EmailProtocol::AUTO);
884 Config::instance()->set_mail_protocol(EmailProtocol::PLAIN);
887 Config::instance()->set_mail_protocol(EmailProtocol::STARTTLS);
890 Config::instance()->set_mail_protocol(EmailProtocol::SSL);
897 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
900 void password_changed ()
902 Config::instance()->set_mail_password(_password->get());
905 void send_test_email_clicked ()
907 auto dialog = new SendTestEmailDialog(_panel);
908 auto result = dialog->ShowModal();
910 if (result == wxID_OK) {
912 wx_to_std(dialog->from()),
913 { wx_to_std(dialog->to()) },
914 wx_to_std(_("DCP-o-matic test email")),
915 wx_to_std(_("This is a test email from DCP-o-matic."))
917 auto config = Config::instance();
919 emailer.send (config->mail_server(), config->mail_port(), config->mail_protocol(), config->mail_user(), config->mail_password());
920 } catch (NetworkError& e) {
921 error_dialog (_panel, std_to_wx(e.summary()), std_to_wx(e.detail().get_value_or("")));
923 } catch (std::exception& e) {
924 error_dialog (_panel, _("Test email sending failed."), std_to_wx(e.what()));
927 error_dialog (_panel, _("Test email sending failed."));
930 message_dialog (_panel, _("Test email sent."));
938 PasswordEntry* _password;
939 Button* _send_test_email;
943 class KDMEmailPage : public Page
947 KDMEmailPage (wxSize panel_size, int border)
949 /* We have to force both width and height of this one */
950 : Page (wxSize (panel_size.GetWidth(), 128), border)
952 : Page (panel_size, border)
956 wxString GetName () const override
958 return _("KDM Email");
962 wxBitmap GetLargeIcon () const override
964 return wxBitmap(bitmap_path("kdm_email"), wxBITMAP_TYPE_PNG);
969 void setup () override
971 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
972 table->AddGrowableCol (1, 1);
973 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
975 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
976 _subject = new wxTextCtrl (_panel, wxID_ANY);
977 table->Add (_subject, 1, wxEXPAND | wxALL);
979 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
980 _from = new wxTextCtrl (_panel, wxID_ANY);
981 table->Add (_from, 1, wxEXPAND | wxALL);
983 vector<EditableListColumn> columns;
984 columns.push_back (EditableListColumn(_("Address")));
985 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
986 _cc = new EditableList<string, EmailDialog> (
989 bind (&Config::kdm_cc, Config::instance()),
990 bind (&Config::set_kdm_cc, Config::instance(), _1),
995 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
997 table->Add (_cc, 1, wxEXPAND | wxALL);
999 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1000 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1001 table->Add (_bcc, 1, wxEXPAND | wxALL);
1003 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1004 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1006 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1007 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1011 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1012 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1013 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1014 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1015 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
1018 void config_changed () override
1020 auto config = Config::instance ();
1022 checked_set (_subject, config->kdm_subject ());
1023 checked_set (_from, config->kdm_from ());
1024 checked_set (_bcc, config->kdm_bcc ());
1025 checked_set (_email, Config::instance()->kdm_email ());
1028 void kdm_subject_changed ()
1030 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
1033 void kdm_from_changed ()
1035 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
1038 void kdm_bcc_changed ()
1040 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
1043 void kdm_email_changed ()
1045 if (_email->GetValue().IsEmpty ()) {
1046 /* Sometimes we get sent an erroneous notification that the email
1047 is empty; I don't know why.
1051 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
1056 Config::instance()->reset_kdm_email ();
1057 checked_set (_email, Config::instance()->kdm_email ());
1060 wxTextCtrl* _subject;
1062 EditableList<string, EmailDialog>* _cc;
1065 wxButton* _reset_email;
1069 class NotificationsPage : public Page
1072 NotificationsPage (wxSize panel_size, int border)
1073 #ifdef DCPOMATIC_OSX
1074 /* We have to force both width and height of this one */
1075 : Page (wxSize (panel_size.GetWidth(), 128), border)
1077 : Page (panel_size, border)
1081 wxString GetName () const override
1083 return _("Notifications");
1086 #ifdef DCPOMATIC_OSX
1087 wxBitmap GetLargeIcon () const override
1089 return wxBitmap(bitmap_path("notifications"), wxBITMAP_TYPE_PNG);
1094 void setup () override
1096 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1097 table->AddGrowableCol (1, 1);
1098 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1100 _enable_message_box = new CheckBox (_panel, _("Message box"));
1101 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
1102 table->AddSpacer (0);
1104 _enable_email = new CheckBox (_panel, _("Email"));
1105 table->Add (_enable_email, 1, wxEXPAND | wxALL);
1106 table->AddSpacer (0);
1108 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1109 _subject = new wxTextCtrl (_panel, wxID_ANY);
1110 table->Add (_subject, 1, wxEXPAND | wxALL);
1112 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1113 _from = new wxTextCtrl (_panel, wxID_ANY);
1114 table->Add (_from, 1, wxEXPAND | wxALL);
1116 add_label_to_sizer (table, _panel, _("To address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1117 _to = new wxTextCtrl (_panel, wxID_ANY);
1118 table->Add (_to, 1, wxEXPAND | wxALL);
1120 vector<EditableListColumn> columns;
1121 columns.push_back (EditableListColumn(_("Address")));
1122 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1123 _cc = new EditableList<string, EmailDialog> (
1126 bind (&Config::notification_cc, Config::instance()),
1127 bind (&Config::set_notification_cc, Config::instance(), _1),
1128 [] (string s, int) {
1132 EditableListButton::NEW | EditableListButton::EDIT | EditableListButton::REMOVE
1134 table->Add (_cc, 1, wxEXPAND | wxALL);
1136 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1137 _bcc = new wxTextCtrl (_panel, wxID_ANY);
1138 table->Add (_bcc, 1, wxEXPAND | wxALL);
1140 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1141 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
1143 _reset_email = new Button (_panel, _("Reset to default subject and text"));
1144 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
1148 _enable_message_box->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX));
1149 _enable_email->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL));
1151 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
1152 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
1153 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
1154 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
1155 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
1156 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
1158 setup_sensitivity ();
1161 void setup_sensitivity ()
1163 bool const s = _enable_email->GetValue();
1164 _subject->Enable(s);
1170 _reset_email->Enable(s);
1173 void config_changed () override
1175 auto config = Config::instance ();
1177 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
1178 checked_set (_enable_email, config->notification(Config::EMAIL));
1179 checked_set (_subject, config->notification_subject ());
1180 checked_set (_from, config->notification_from ());
1181 checked_set (_to, config->notification_to ());
1182 checked_set (_bcc, config->notification_bcc ());
1183 checked_set (_email, Config::instance()->notification_email ());
1185 setup_sensitivity ();
1188 void notification_subject_changed ()
1190 Config::instance()->set_notification_subject(wx_to_std(_subject->GetValue()));
1193 void notification_from_changed ()
1195 Config::instance()->set_notification_from(wx_to_std(_from->GetValue()));
1198 void notification_to_changed ()
1200 Config::instance()->set_notification_to(wx_to_std(_to->GetValue()));
1203 void notification_bcc_changed ()
1205 Config::instance()->set_notification_bcc(wx_to_std(_bcc->GetValue()));
1208 void notification_email_changed ()
1210 if (_email->GetValue().IsEmpty()) {
1211 /* Sometimes we get sent an erroneous notification that the email
1212 is empty; I don't know why.
1216 Config::instance()->set_notification_email(wx_to_std(_email->GetValue()));
1221 Config::instance()->reset_notification_email();
1222 checked_set (_email, Config::instance()->notification_email());
1225 void type_changed (wxCheckBox* b, Config::Notification n)
1227 Config::instance()->set_notification(n, b->GetValue());
1228 setup_sensitivity ();
1231 wxCheckBox* _enable_message_box;
1232 wxCheckBox* _enable_email;
1234 wxTextCtrl* _subject;
1237 EditableList<string, EmailDialog>* _cc;
1240 wxButton* _reset_email;
1244 class CoverSheetPage : public Page
1248 CoverSheetPage (wxSize panel_size, int border)
1249 #ifdef DCPOMATIC_OSX
1250 /* We have to force both width and height of this one */
1251 : Page (wxSize (panel_size.GetWidth(), 128), border)
1253 : Page (panel_size, border)
1257 wxString GetName () const override
1259 return _("Cover Sheet");
1262 #ifdef DCPOMATIC_OSX
1263 wxBitmap GetLargeIcon () const override
1265 return wxBitmap(bitmap_path("cover_sheet"), wxBITMAP_TYPE_PNG);
1270 void setup () override
1272 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1273 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1275 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1276 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1278 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1279 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1282 void config_changed () override
1284 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1287 void cover_sheet_changed ()
1289 if (_cover_sheet->GetValue().IsEmpty ()) {
1290 /* Sometimes we get sent an erroneous notification that the cover sheet
1291 is empty; I don't know why.
1295 Config::instance()->set_cover_sheet(wx_to_std(_cover_sheet->GetValue()));
1298 void reset_cover_sheet ()
1300 Config::instance()->reset_cover_sheet();
1301 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1304 wxTextCtrl* _cover_sheet;
1305 wxButton* _reset_cover_sheet;
1309 class IdentifiersPage : public Page
1312 IdentifiersPage (wxSize panel_size, int border)
1313 : Page (panel_size, border)
1316 wxString GetName () const override
1318 return _("Identifiers");
1321 #ifdef DCPOMATIC_OSX
1322 wxBitmap GetLargeIcon () const override
1324 return wxBitmap(bitmap_path("identifiers"), wxBITMAP_TYPE_PNG);
1329 void setup () override
1331 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1332 table->AddGrowableCol (1, 1);
1334 add_label_to_sizer (table, _panel, _("Issuer"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1335 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1336 _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."));
1337 table->Add (_issuer, 1, wxALL | wxEXPAND);
1339 add_label_to_sizer (table, _panel, _("Creator"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1340 _creator = new wxTextCtrl (_panel, wxID_ANY);
1341 _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."));
1342 table->Add (_creator, 1, wxALL | wxEXPAND);
1344 add_label_to_sizer (table, _panel, _("Company name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1345 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1346 _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."));
1347 table->Add (_company_name, 1, wxALL | wxEXPAND);
1349 add_label_to_sizer (table, _panel, _("Product name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1350 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1351 _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."));
1352 table->Add (_product_name, 1, wxALL | wxEXPAND);
1354 add_label_to_sizer (table, _panel, _("Product version"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1355 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1356 _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."));
1357 table->Add (_product_version, 1, wxALL | wxEXPAND);
1359 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1360 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1361 _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."));
1362 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1364 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1366 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1367 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1368 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1369 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1370 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1371 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1374 void config_changed () override
1376 auto config = Config::instance ();
1377 checked_set (_issuer, config->dcp_issuer ());
1378 checked_set (_creator, config->dcp_creator ());
1379 checked_set (_company_name, config->dcp_company_name ());
1380 checked_set (_product_name, config->dcp_product_name ());
1381 checked_set (_product_version, config->dcp_product_version ());
1382 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1385 void issuer_changed ()
1387 Config::instance()->set_dcp_issuer(wx_to_std(_issuer->GetValue()));
1390 void creator_changed ()
1392 Config::instance()->set_dcp_creator(wx_to_std(_creator->GetValue()));
1395 void company_name_changed ()
1397 Config::instance()->set_dcp_company_name(wx_to_std(_company_name->GetValue()));
1400 void product_name_changed ()
1402 Config::instance()->set_dcp_product_name(wx_to_std(_product_name->GetValue()));
1405 void product_version_changed ()
1407 Config::instance()->set_dcp_product_version(wx_to_std(_product_version->GetValue()));
1410 void j2k_comment_changed ()
1412 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1415 wxTextCtrl* _issuer;
1416 wxTextCtrl* _creator;
1417 wxTextCtrl* _company_name;
1418 wxTextCtrl* _product_name;
1419 wxTextCtrl* _product_version;
1420 wxTextCtrl* _j2k_comment;
1424 /** @class AdvancedPage
1425 * @brief Advanced page of the preferences dialog.
1427 class AdvancedPage : public Page
1430 AdvancedPage (wxSize panel_size, int border)
1431 : Page (panel_size, border)
1434 wxString GetName () const override
1436 return _("Advanced");
1439 #ifdef DCPOMATIC_OSX
1440 wxBitmap GetLargeIcon () const override
1442 return wxBitmap(bitmap_path("advanced"), wxBITMAP_TYPE_PNG);
1447 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1449 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1451 flags |= wxALIGN_RIGHT;
1454 wxStaticText* m = new StaticText (parent, text);
1455 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1458 void setup () override
1460 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1461 table->AddGrowableCol (1, 1);
1462 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1465 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1466 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1467 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1468 s->Add (_maximum_j2k_bandwidth, 1);
1469 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxALIGN_CENTRE_VERTICAL);
1473 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1474 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1475 table->Add (_video_display_mode);
1477 auto restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1478 auto font = restart->GetFont();
1479 font.SetStyle (wxFONTSTYLE_ITALIC);
1480 font.SetPointSize (font.GetPointSize() - 1);
1481 restart->SetFont (font);
1482 table->AddSpacer (0);
1484 _allow_any_dcp_frame_rate = new CheckBox (_panel, _("Allow any DCP frame rate"));
1485 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1486 table->AddSpacer (0);
1488 _allow_any_container = new CheckBox (_panel, _("Allow full-frame and non-standard container ratios"));
1489 table->Add (_allow_any_container, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1490 restart = new StaticText (_panel, _("(restart DCP-o-matic to see all ratios)"));
1491 table->Add (restart, 1, wxEXPAND | wxALL | wxALIGN_CENTRE_VERTICAL);
1492 restart->SetFont (font);
1494 _allow_96khz_audio = new CheckBox (_panel, _("Allow creation of DCPs with 96kHz audio"));
1495 table->Add (_allow_96khz_audio, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1496 table->AddSpacer (0);
1498 _use_all_audio_channels = new CheckBox(_panel, _("Allow mapping to all audio channels"));
1499 table->Add(_use_all_audio_channels, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1500 table->AddSpacer(0);
1502 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1503 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1504 table->AddSpacer (0);
1506 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1507 table->Add (_only_servers_encode, 1, wxEXPAND | wxLEFT, DCPOMATIC_SIZER_GAP);
1508 table->AddSpacer (0);
1511 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1512 auto s = new wxBoxSizer (wxHORIZONTAL);
1513 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1514 s->Add (_frames_in_memory_multiplier, 1);
1519 auto format = create_label (_panel, _("DCP metadata filename format"), true);
1520 #ifdef DCPOMATIC_OSX
1521 auto align = new wxBoxSizer (wxHORIZONTAL);
1522 align->Add (format, 0, wxTOP, 2);
1523 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1525 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1527 dcp::NameFormat::Map titles;
1528 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1529 dcp::NameFormat::Map examples;
1530 examples['t'] = "cpl";
1531 _dcp_metadata_filename_format = new NameFormatEditor (
1532 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1534 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1538 auto format = create_label (_panel, _("DCP asset filename format"), true);
1539 #ifdef DCPOMATIC_OSX
1540 auto align = new wxBoxSizer (wxHORIZONTAL);
1541 align->Add (format, 0, wxTOP, 2);
1542 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1544 table->Add (format, 0, wxTOP | wxLEFT | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1546 dcp::NameFormat::Map titles;
1547 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1548 titles['r'] = wx_to_std (_("reel number"));
1549 titles['n'] = wx_to_std (_("number of reels"));
1550 titles['c'] = wx_to_std (_("content filename"));
1551 dcp::NameFormat::Map examples;
1552 examples['t'] = "j2c";
1553 examples['r'] = "1";
1554 examples['n'] = "4";
1555 examples['c'] = "myfile.mp4";
1556 _dcp_asset_filename_format = new NameFormatEditor (
1557 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1559 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1563 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1564 auto t = new wxFlexGridSizer (2);
1565 _log_general = new CheckBox (_panel, _("General"));
1566 t->Add (_log_general, 1, wxEXPAND | wxALL);
1567 _log_warning = new CheckBox (_panel, _("Warnings"));
1568 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1569 _log_error = new CheckBox (_panel, _("Errors"));
1570 t->Add (_log_error, 1, wxEXPAND | wxALL);
1571 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1572 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1573 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1574 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1575 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1576 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1577 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1578 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1579 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1580 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1581 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1582 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1583 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1584 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1585 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1586 table->Add (t, 0, wxALL, 6);
1589 #ifdef DCPOMATIC_WINDOWS
1590 _win32_console = new CheckBox (_panel, _("Open console window"));
1591 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1592 table->AddSpacer (0);
1595 _maximum_j2k_bandwidth->SetRange (1, 1000);
1596 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1597 _video_display_mode->Append (_("Simple (safer)"));
1598 #if wxCHECK_VERSION(3, 1, 0)
1599 _video_display_mode->Append (_("OpenGL (faster)"));
1601 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1602 _allow_any_dcp_frame_rate->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1603 _allow_any_container->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_container_changed, this));
1604 _allow_96khz_audio->Bind (wxEVT_CHECKBOX, boost::bind(&AdvancedPage::allow_96khz_audio_changed, this));
1605 _use_all_audio_channels->Bind(wxEVT_CHECKBOX, boost::bind(&AdvancedPage::use_all_channels_changed, this));
1606 _show_experimental_audio_processors->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::show_experimental_audio_processors_changed, this));
1607 _only_servers_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1608 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1609 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1610 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1611 _log_general->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1612 _log_warning->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1613 _log_error->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1614 _log_timing->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1615 _log_debug_threed->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1616 _log_debug_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1617 _log_debug_email->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1618 _log_debug_video_view->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1619 _log_debug_player->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1620 _log_debug_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1621 #ifdef DCPOMATIC_WINDOWS
1622 _win32_console->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::win32_console_changed, this));
1626 void config_changed () override
1628 auto config = Config::instance ();
1630 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1631 switch (config->video_view_type()) {
1632 case Config::VIDEO_VIEW_SIMPLE:
1633 checked_set (_video_display_mode, 0);
1635 case Config::VIDEO_VIEW_OPENGL:
1636 checked_set (_video_display_mode, 1);
1639 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1640 checked_set (_allow_any_container, config->allow_any_container ());
1641 checked_set (_allow_96khz_audio, config->allow_96khz_audio());
1642 checked_set (_use_all_audio_channels, config->use_all_audio_channels());
1643 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1644 checked_set (_only_servers_encode, config->only_servers_encode ());
1645 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1646 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1647 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1648 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1649 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREE_D);
1650 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1651 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1652 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1653 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1654 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1655 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1656 #ifdef DCPOMATIC_WINDOWS
1657 checked_set (_win32_console, config->win32_console());
1661 void maximum_j2k_bandwidth_changed ()
1663 Config::instance()->set_maximum_j2k_bandwidth(_maximum_j2k_bandwidth->GetValue() * 1000000);
1666 void video_display_mode_changed ()
1668 if (_video_display_mode->GetSelection() == 0) {
1669 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_SIMPLE);
1671 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_OPENGL);
1675 void frames_in_memory_multiplier_changed ()
1677 Config::instance()->set_frames_in_memory_multiplier(_frames_in_memory_multiplier->GetValue());
1680 void allow_any_dcp_frame_rate_changed ()
1682 Config::instance()->set_allow_any_dcp_frame_rate(_allow_any_dcp_frame_rate->GetValue());
1685 void allow_any_container_changed ()
1687 Config::instance()->set_allow_any_container(_allow_any_container->GetValue());
1690 void allow_96khz_audio_changed ()
1692 Config::instance()->set_allow_96hhz_audio(_allow_96khz_audio->GetValue());
1695 void use_all_channels_changed ()
1697 Config::instance()->set_use_all_audio_channels(_use_all_audio_channels->GetValue());
1700 void show_experimental_audio_processors_changed ()
1702 Config::instance()->set_show_experimental_audio_processors(_show_experimental_audio_processors->GetValue());
1705 void only_servers_encode_changed ()
1707 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue());
1710 void dcp_metadata_filename_format_changed ()
1712 Config::instance()->set_dcp_metadata_filename_format(_dcp_metadata_filename_format->get());
1715 void dcp_asset_filename_format_changed ()
1717 Config::instance()->set_dcp_asset_filename_format(_dcp_asset_filename_format->get());
1723 if (_log_general->GetValue ()) {
1724 types |= LogEntry::TYPE_GENERAL;
1726 if (_log_warning->GetValue ()) {
1727 types |= LogEntry::TYPE_WARNING;
1729 if (_log_error->GetValue ()) {
1730 types |= LogEntry::TYPE_ERROR;
1732 if (_log_timing->GetValue ()) {
1733 types |= LogEntry::TYPE_TIMING;
1735 if (_log_debug_threed->GetValue ()) {
1736 types |= LogEntry::TYPE_DEBUG_THREE_D;
1738 if (_log_debug_encode->GetValue ()) {
1739 types |= LogEntry::TYPE_DEBUG_ENCODE;
1741 if (_log_debug_email->GetValue ()) {
1742 types |= LogEntry::TYPE_DEBUG_EMAIL;
1744 if (_log_debug_video_view->GetValue()) {
1745 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1747 if (_log_debug_player->GetValue()) {
1748 types |= LogEntry::TYPE_DEBUG_PLAYER;
1750 if (_log_debug_audio_analysis->GetValue()) {
1751 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1753 Config::instance()->set_log_types (types);
1756 #ifdef DCPOMATIC_WINDOWS
1757 void win32_console_changed ()
1759 Config::instance()->set_win32_console(_win32_console->GetValue());
1763 wxSpinCtrl* _maximum_j2k_bandwidth = nullptr;
1764 wxChoice* _video_display_mode = nullptr;
1765 wxSpinCtrl* _frames_in_memory_multiplier = nullptr;
1766 wxCheckBox* _allow_any_dcp_frame_rate = nullptr;
1767 wxCheckBox* _allow_any_container = nullptr;
1768 wxCheckBox* _allow_96khz_audio = nullptr;
1769 wxCheckBox* _use_all_audio_channels = nullptr;
1770 wxCheckBox* _show_experimental_audio_processors = nullptr;
1771 wxCheckBox* _only_servers_encode = nullptr;
1772 NameFormatEditor* _dcp_metadata_filename_format = nullptr;
1773 NameFormatEditor* _dcp_asset_filename_format = nullptr;
1774 wxCheckBox* _log_general = nullptr;
1775 wxCheckBox* _log_warning = nullptr;
1776 wxCheckBox* _log_error = nullptr;
1777 wxCheckBox* _log_timing = nullptr;
1778 wxCheckBox* _log_debug_threed = nullptr;
1779 wxCheckBox* _log_debug_encode = nullptr;
1780 wxCheckBox* _log_debug_email = nullptr;
1781 wxCheckBox* _log_debug_video_view = nullptr;
1782 wxCheckBox* _log_debug_player = nullptr;
1783 wxCheckBox* _log_debug_audio_analysis = nullptr;
1784 #ifdef DCPOMATIC_WINDOWS
1785 wxCheckBox* _win32_console = nullptr;
1790 wxPreferencesEditor*
1791 create_full_config_dialog ()
1793 auto e = new wxPreferencesEditor ();
1795 #ifdef DCPOMATIC_OSX
1796 /* Width that we force some of the config panels to be on OSX so that
1797 the containing window doesn't shrink too much when we select those panels.
1798 This is obviously an unpleasant hack.
1800 wxSize ps = wxSize (750, -1);
1801 int const border = 16;
1803 wxSize ps = wxSize (-1, -1);
1804 int const border = 8;
1807 e->AddPage (new FullGeneralPage (ps, border));
1808 e->AddPage (new SoundPage (ps, border));
1809 e->AddPage (new DefaultsPage (ps, border));
1810 e->AddPage (new EncodingServersPage(ps, border));
1811 e->AddPage (new KeysPage (ps, border));
1812 e->AddPage (new TMSPage (ps, border));
1813 e->AddPage (new EmailPage (ps, border));
1814 e->AddPage (new KDMEmailPage (ps, border));
1815 e->AddPage (new NotificationsPage (ps, border));
1816 e->AddPage (new CoverSheetPage (ps, border));
1817 e->AddPage (new IdentifiersPage (ps, border));
1818 e->AddPage (new AdvancedPage (ps, border));