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 "make_chain_dialog.h"
38 #include "nag_dialog.h"
39 #include "name_format_editor.h"
40 #include "password_entry.h"
41 #include "server_dialog.h"
42 #include "static_text.h"
44 #include "lib/config.h"
45 #include "lib/cross.h"
46 #include "lib/dcp_content_type.h"
47 #include "lib/exceptions.h"
48 #include "lib/filter.h"
50 #include "lib/ratio.h"
52 #include <dcp/certificate_chain.h>
53 #include <dcp/exceptions.h>
54 #include <dcp/locale_convert.h>
55 #include <wx/filepicker.h>
56 #include <wx/preferences.h>
57 #include <wx/spinctrl.h>
58 #include <wx/stdpaths.h>
60 #include <boost/filesystem.hpp>
70 using std::shared_ptr;
74 using boost::optional;
75 #if BOOST_VERSION >= 106100
76 using namespace boost::placeholders;
78 using dcp::locale_convert;
81 class FullGeneralPage : public GeneralPage
84 FullGeneralPage (wxSize panel_size, int border)
85 : GeneralPage (panel_size, border)
91 auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
92 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
95 add_language_controls (table, r);
97 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
98 _master_encoding_threads = new wxSpinCtrl (_panel);
99 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
102 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
103 _server_encoding_threads = new wxSpinCtrl (_panel);
104 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
107 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
108 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, false);
109 table->Add (_config_file, wxGBPosition (r, 1));
112 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
113 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, false);
114 table->Add (_cinemas_file, wxGBPosition (r, 1));
115 Button* export_cinemas = new Button (_panel, _("Export..."));
116 table->Add (export_cinemas, wxGBPosition (r, 2));
119 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
120 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
121 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
125 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
126 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
129 add_update_controls (table, r);
131 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::config_file_changed, this));
132 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind(&FullGeneralPage::cinemas_file_changed, this));
134 _master_encoding_threads->SetRange (1, 128);
135 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
136 _server_encoding_threads->SetRange (1, 128);
137 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
138 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
140 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
141 _analyse_ebur128->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::analyse_ebur128_changed, this));
143 _automatic_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::automatic_audio_analysis_changed, this));
146 void config_changed ()
148 auto config = Config::instance ();
150 checked_set (_master_encoding_threads, config->master_encoding_threads ());
151 checked_set (_server_encoding_threads, config->server_encoding_threads ());
152 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
153 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
155 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
156 checked_set (_config_file, config->config_file());
157 checked_set (_cinemas_file, config->cinemas_file());
159 GeneralPage::config_changed ();
162 void export_cinemas_file ()
164 auto d = new wxFileDialog (
165 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT("XML files (*.xml)|*.xml"),
166 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
169 if (d->ShowModal () == wxID_OK) {
170 boost::filesystem::copy_file (Config::instance()->cinemas_file(), wx_to_std(d->GetPath()));
175 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
176 void analyse_ebur128_changed ()
178 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue());
182 void automatic_audio_analysis_changed ()
184 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue());
187 void master_encoding_threads_changed ()
189 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue());
192 void server_encoding_threads_changed ()
194 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue());
197 void config_file_changed ()
199 auto config = Config::instance();
200 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
201 if (new_file == config->config_file()) {
204 bool copy_and_link = true;
205 if (boost::filesystem::exists(new_file)) {
206 auto d = new ConfigMoveDialog (_panel, new_file);
207 if (d->ShowModal() == wxID_OK) {
208 copy_and_link = false;
215 if (new_file != config->config_file()) {
216 config->copy_and_link (new_file);
219 config->link (new_file);
223 void cinemas_file_changed ()
225 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
228 wxSpinCtrl* _master_encoding_threads;
229 wxSpinCtrl* _server_encoding_threads;
230 FilePickerCtrl* _config_file;
231 FilePickerCtrl* _cinemas_file;
232 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
233 wxCheckBox* _analyse_ebur128;
235 wxCheckBox* _automatic_audio_analysis;
239 class DefaultsPage : public Page
242 DefaultsPage (wxSize panel_size, int border)
243 : Page (panel_size, border)
246 wxString GetName () const
248 return _("Defaults");
252 wxBitmap GetLargeIcon () const
254 return wxBitmap(bitmap_path("defaults"), wxBITMAP_TYPE_PNG);
261 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
262 table->AddGrowableCol (1, 1);
263 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
266 add_label_to_sizer (table, _panel, _("Default duration of still images"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
267 auto s = new wxBoxSizer (wxHORIZONTAL);
268 _still_length = new wxSpinCtrl (_panel);
269 s->Add (_still_length);
270 add_label_to_sizer (s, _panel, _("s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
274 add_label_to_sizer (table, _panel, _("Default directory for new films"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
275 #ifdef DCPOMATIC_USE_OWN_PICKER
276 _directory = new DirPickerCtrl (_panel);
278 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
280 table->Add (_directory, 1, wxEXPAND);
282 add_label_to_sizer (table, _panel, _("Default container"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
283 _container = new wxChoice (_panel, wxID_ANY);
284 table->Add (_container);
286 add_label_to_sizer (table, _panel, _("Default content type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
287 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
288 table->Add (_dcp_content_type);
290 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
291 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
292 table->Add (_dcp_audio_channels);
295 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
296 auto s = new wxBoxSizer (wxHORIZONTAL);
297 _j2k_bandwidth = new wxSpinCtrl (_panel);
298 s->Add (_j2k_bandwidth);
299 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
304 add_label_to_sizer (table, _panel, _("Default audio delay"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
305 auto s = new wxBoxSizer (wxHORIZONTAL);
306 _audio_delay = new wxSpinCtrl (_panel);
307 s->Add (_audio_delay);
308 add_label_to_sizer (s, _panel, _("ms"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
312 add_label_to_sizer (table, _panel, _("Default standard"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
313 _standard = new wxChoice (_panel, wxID_ANY);
314 table->Add (_standard);
316 add_label_to_sizer (table, _panel, _("Default KDM directory"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
317 #ifdef DCPOMATIC_USE_OWN_PICKER
318 _kdm_directory = new DirPickerCtrl (_panel);
320 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
323 table->Add (_kdm_directory, 1, wxEXPAND);
325 _still_length->SetRange (1, 3600);
326 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
328 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
329 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
331 for (auto i: Ratio::containers()) {
332 _container->Append (std_to_wx(i->container_nickname()));
335 _container->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::container_changed, this));
337 for (auto i: DCPContentType::all()) {
338 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
341 setup_audio_channels_choice (_dcp_audio_channels, 2);
343 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
344 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
346 _j2k_bandwidth->SetRange (50, 250);
347 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
349 _audio_delay->SetRange (-1000, 1000);
350 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
352 _standard->Append (_("SMPTE"));
353 _standard->Append (_("Interop"));
354 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
357 void config_changed ()
359 auto config = Config::instance ();
361 auto containers = Ratio::containers ();
362 for (size_t i = 0; i < containers.size(); ++i) {
363 if (containers[i] == config->default_container()) {
364 _container->SetSelection (i);
368 auto const ct = DCPContentType::all ();
369 for (size_t i = 0; i < ct.size(); ++i) {
370 if (ct[i] == config->default_dcp_content_type()) {
371 _dcp_content_type->SetSelection (i);
375 checked_set (_still_length, config->default_still_length ());
376 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
377 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
378 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
379 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
380 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
381 checked_set (_audio_delay, config->default_audio_delay ());
382 checked_set (_standard, config->default_interop() ? 1 : 0);
385 void j2k_bandwidth_changed ()
387 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
390 void audio_delay_changed ()
392 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
395 void dcp_audio_channels_changed ()
397 int const s = _dcp_audio_channels->GetSelection ();
398 if (s != wxNOT_FOUND) {
399 Config::instance()->set_default_dcp_audio_channels (
400 locale_convert<int>(string_client_data(_dcp_audio_channels->GetClientObject(s)))
405 void directory_changed ()
407 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
410 void kdm_directory_changed ()
412 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
415 void still_length_changed ()
417 Config::instance()->set_default_still_length (_still_length->GetValue ());
420 void container_changed ()
422 auto ratio = Ratio::containers ();
423 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
426 void dcp_content_type_changed ()
428 auto ct = DCPContentType::all ();
429 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
432 void standard_changed ()
434 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
437 wxSpinCtrl* _j2k_bandwidth;
438 wxSpinCtrl* _audio_delay;
439 wxSpinCtrl* _still_length;
440 #ifdef DCPOMATIC_USE_OWN_PICKER
441 DirPickerCtrl* _directory;
442 DirPickerCtrl* _kdm_directory;
444 wxDirPickerCtrl* _directory;
445 wxDirPickerCtrl* _kdm_directory;
447 wxChoice* _container;
448 wxChoice* _dcp_content_type;
449 wxChoice* _dcp_audio_channels;
454 class EncodingServersPage : public Page
457 EncodingServersPage (wxSize panel_size, int border)
458 : Page (panel_size, border)
461 wxString GetName () const
467 wxBitmap GetLargeIcon () const
469 return wxBitmap(bitmap_path("servers"), wxBITMAP_TYPE_PNG);
476 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
477 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
479 vector<EditableListColumn> columns;
480 columns.push_back (EditableListColumn(_("IP address / host name")));
481 _servers_list = new EditableList<string, ServerDialog> (
484 boost::bind (&Config::servers, Config::instance()),
485 boost::bind (&Config::set_servers, Config::instance(), _1),
486 boost::bind (&EncodingServersPage::server_column, this, _1)
489 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
491 _use_any_servers->Bind (wxEVT_CHECKBOX, boost::bind(&EncodingServersPage::use_any_servers_changed, this));
494 void config_changed ()
496 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
497 _servers_list->refresh ();
500 void use_any_servers_changed ()
502 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
505 string server_column (string s)
510 wxCheckBox* _use_any_servers;
511 EditableList<string, ServerDialog>* _servers_list;
515 class TMSPage : public Page
518 TMSPage (wxSize panel_size, int border)
519 : Page (panel_size, border)
522 wxString GetName () const
528 wxBitmap GetLargeIcon () const
530 return wxBitmap(bitmap_path("tms"), wxBITMAP_TYPE_PNG);
537 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
538 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
540 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
541 table->AddGrowableCol (1, 1);
542 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
544 add_label_to_sizer (table, _panel, _("Protocol"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
545 _tms_protocol = new wxChoice (_panel, wxID_ANY);
546 table->Add (_tms_protocol, 1, wxEXPAND);
548 add_label_to_sizer (table, _panel, _("IP address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
549 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
550 table->Add (_tms_ip, 1, wxEXPAND);
552 add_label_to_sizer (table, _panel, _("Target path"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
553 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
554 table->Add (_tms_path, 1, wxEXPAND);
556 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
557 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
558 table->Add (_tms_user, 1, wxEXPAND);
560 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
561 _tms_password = new PasswordEntry (_panel);
562 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
564 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
565 _tms_protocol->Append (_("FTP (for Dolby)"));
567 _upload->Bind (wxEVT_CHECKBOX, boost::bind(&TMSPage::upload_changed, this));
568 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
569 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
570 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
571 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
572 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
575 void config_changed ()
577 auto config = Config::instance ();
579 checked_set (_upload, config->upload_after_make_dcp());
580 checked_set (_tms_protocol, static_cast<int>(config->tms_protocol()));
581 checked_set (_tms_ip, config->tms_ip ());
582 checked_set (_tms_path, config->tms_path ());
583 checked_set (_tms_user, config->tms_user ());
584 checked_set (_tms_password, config->tms_password ());
587 void upload_changed ()
589 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
592 void tms_protocol_changed ()
594 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
597 void tms_ip_changed ()
599 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
602 void tms_path_changed ()
604 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
607 void tms_user_changed ()
609 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
612 void tms_password_changed ()
614 Config::instance()->set_tms_password (_tms_password->get());
618 wxChoice* _tms_protocol;
620 wxTextCtrl* _tms_path;
621 wxTextCtrl* _tms_user;
622 PasswordEntry* _tms_password;
626 class EmailPage : public Page
629 EmailPage (wxSize panel_size, int border)
630 : Page (panel_size, border)
633 wxString GetName () const
639 wxBitmap GetLargeIcon () const
641 return wxBitmap(bitmap_path("email"), wxBITMAP_TYPE_PNG);
648 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
649 table->AddGrowableCol (1, 1);
650 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
652 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
654 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
655 _server = new wxTextCtrl (_panel, wxID_ANY);
656 s->Add (_server, 1, wxEXPAND | wxALL);
657 add_label_to_sizer (s, _panel, _("port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
658 _port = new wxSpinCtrl (_panel, wxID_ANY);
659 _port->SetRange (0, 65535);
661 add_label_to_sizer (s, _panel, _("protocol"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
662 _protocol = new wxChoice (_panel, wxID_ANY);
663 /* Make sure this matches the switches in config_changed and port_changed below */
664 _protocol->Append (_("Auto"));
665 _protocol->Append (_("Plain"));
666 _protocol->Append (_("STARTTLS"));
667 _protocol->Append (_("SSL"));
668 s->Add (_protocol, 1, wxALIGN_CENTER_VERTICAL);
669 table->Add (s, 1, wxEXPAND | wxALL);
672 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
673 _user = new wxTextCtrl (_panel, wxID_ANY);
674 table->Add (_user, 1, wxEXPAND | wxALL);
676 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
677 _password = new PasswordEntry (_panel);
678 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
680 _server->Bind (wxEVT_TEXT, boost::bind(&EmailPage::server_changed, this));
681 _port->Bind (wxEVT_SPINCTRL, boost::bind(&EmailPage::port_changed, this));
682 _protocol->Bind (wxEVT_CHOICE, boost::bind(&EmailPage::protocol_changed, this));
683 _user->Bind (wxEVT_TEXT, boost::bind(&EmailPage::user_changed, this));
684 _password->Changed.connect (boost::bind(&EmailPage::password_changed, this));
687 void config_changed ()
689 auto config = Config::instance ();
691 checked_set (_server, config->mail_server());
692 checked_set (_port, config->mail_port());
693 switch (config->mail_protocol()) {
694 case EmailProtocol::AUTO:
695 checked_set (_protocol, 0);
697 case EmailProtocol::PLAIN:
698 checked_set (_protocol, 1);
700 case EmailProtocol::STARTTLS:
701 checked_set (_protocol, 2);
703 case EmailProtocol::SSL:
704 checked_set (_protocol, 3);
707 checked_set (_user, config->mail_user());
708 checked_set (_password, config->mail_password());
711 void server_changed ()
713 Config::instance()->set_mail_server(wx_to_std(_server->GetValue()));
718 Config::instance()->set_mail_port(_port->GetValue());
721 void protocol_changed ()
723 switch (_protocol->GetSelection()) {
725 Config::instance()->set_mail_protocol(EmailProtocol::AUTO);
728 Config::instance()->set_mail_protocol(EmailProtocol::PLAIN);
731 Config::instance()->set_mail_protocol(EmailProtocol::STARTTLS);
734 Config::instance()->set_mail_protocol(EmailProtocol::SSL);
741 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
744 void password_changed ()
746 Config::instance()->set_mail_password(_password->get());
753 PasswordEntry* _password;
757 class KDMEmailPage : public Page
761 KDMEmailPage (wxSize panel_size, int border)
763 /* We have to force both width and height of this one */
764 : Page (wxSize (panel_size.GetWidth(), 128), border)
766 : Page (panel_size, border)
770 wxString GetName () const
772 return _("KDM Email");
776 wxBitmap GetLargeIcon () const
778 return wxBitmap(bitmap_path("kdm_email"), wxBITMAP_TYPE_PNG);
785 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
786 table->AddGrowableCol (1, 1);
787 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
789 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
790 _subject = new wxTextCtrl (_panel, wxID_ANY);
791 table->Add (_subject, 1, wxEXPAND | wxALL);
793 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
794 _from = new wxTextCtrl (_panel, wxID_ANY);
795 table->Add (_from, 1, wxEXPAND | wxALL);
797 vector<EditableListColumn> columns;
798 columns.push_back (EditableListColumn(_("Address")));
799 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
800 _cc = new EditableList<string, EmailDialog> (
803 bind (&Config::kdm_cc, Config::instance()),
804 bind (&Config::set_kdm_cc, Config::instance(), _1),
808 table->Add (_cc, 1, wxEXPAND | wxALL);
810 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
811 _bcc = new wxTextCtrl (_panel, wxID_ANY);
812 table->Add (_bcc, 1, wxEXPAND | wxALL);
814 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
815 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
817 _reset_email = new Button (_panel, _("Reset to default subject and text"));
818 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
822 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
823 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
824 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
825 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
826 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
829 void config_changed ()
831 Config* config = Config::instance ();
833 checked_set (_subject, config->kdm_subject ());
834 checked_set (_from, config->kdm_from ());
835 checked_set (_bcc, config->kdm_bcc ());
836 checked_set (_email, Config::instance()->kdm_email ());
839 void kdm_subject_changed ()
841 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
844 void kdm_from_changed ()
846 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
849 void kdm_bcc_changed ()
851 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
854 void kdm_email_changed ()
856 if (_email->GetValue().IsEmpty ()) {
857 /* Sometimes we get sent an erroneous notification that the email
858 is empty; I don't know why.
862 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
867 Config::instance()->reset_kdm_email ();
868 checked_set (_email, Config::instance()->kdm_email ());
871 wxTextCtrl* _subject;
873 EditableList<string, EmailDialog>* _cc;
876 wxButton* _reset_email;
880 class NotificationsPage : public Page
883 NotificationsPage (wxSize panel_size, int border)
885 /* We have to force both width and height of this one */
886 : Page (wxSize (panel_size.GetWidth(), 128), border)
888 : Page (panel_size, border)
892 wxString GetName () const
894 return _("Notifications");
898 wxBitmap GetLargeIcon () const
900 return wxBitmap(bitmap_path("notifications"), wxBITMAP_TYPE_PNG);
907 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
908 table->AddGrowableCol (1, 1);
909 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
911 _enable_message_box = new CheckBox (_panel, _("Message box"));
912 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
913 table->AddSpacer (0);
915 _enable_email = new CheckBox (_panel, _("Email"));
916 table->Add (_enable_email, 1, wxEXPAND | wxALL);
917 table->AddSpacer (0);
919 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
920 _subject = new wxTextCtrl (_panel, wxID_ANY);
921 table->Add (_subject, 1, wxEXPAND | wxALL);
923 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
924 _from = new wxTextCtrl (_panel, wxID_ANY);
925 table->Add (_from, 1, wxEXPAND | wxALL);
927 add_label_to_sizer (table, _panel, _("To address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
928 _to = new wxTextCtrl (_panel, wxID_ANY);
929 table->Add (_to, 1, wxEXPAND | wxALL);
931 vector<EditableListColumn> columns;
932 columns.push_back (EditableListColumn(_("Address")));
933 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
934 _cc = new EditableList<string, EmailDialog> (
937 bind (&Config::notification_cc, Config::instance()),
938 bind (&Config::set_notification_cc, Config::instance(), _1),
942 table->Add (_cc, 1, wxEXPAND | wxALL);
944 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
945 _bcc = new wxTextCtrl (_panel, wxID_ANY);
946 table->Add (_bcc, 1, wxEXPAND | wxALL);
948 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
949 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
951 _reset_email = new Button (_panel, _("Reset to default subject and text"));
952 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
956 _enable_message_box->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX));
957 _enable_email->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL));
959 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
960 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
961 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
962 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
963 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
964 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
966 update_sensitivity ();
969 void update_sensitivity ()
971 bool const s = _enable_email->GetValue();
978 _reset_email->Enable(s);
981 void config_changed ()
983 auto config = Config::instance ();
985 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
986 checked_set (_enable_email, config->notification(Config::EMAIL));
987 checked_set (_subject, config->notification_subject ());
988 checked_set (_from, config->notification_from ());
989 checked_set (_to, config->notification_to ());
990 checked_set (_bcc, config->notification_bcc ());
991 checked_set (_email, Config::instance()->notification_email ());
993 update_sensitivity ();
996 void notification_subject_changed ()
998 Config::instance()->set_notification_subject(wx_to_std(_subject->GetValue()));
1001 void notification_from_changed ()
1003 Config::instance()->set_notification_from(wx_to_std(_from->GetValue()));
1006 void notification_to_changed ()
1008 Config::instance()->set_notification_to(wx_to_std(_to->GetValue()));
1011 void notification_bcc_changed ()
1013 Config::instance()->set_notification_bcc(wx_to_std(_bcc->GetValue()));
1016 void notification_email_changed ()
1018 if (_email->GetValue().IsEmpty()) {
1019 /* Sometimes we get sent an erroneous notification that the email
1020 is empty; I don't know why.
1024 Config::instance()->set_notification_email(wx_to_std(_email->GetValue()));
1029 Config::instance()->reset_notification_email();
1030 checked_set (_email, Config::instance()->notification_email());
1033 void type_changed (wxCheckBox* b, Config::Notification n)
1035 Config::instance()->set_notification(n, b->GetValue());
1036 update_sensitivity ();
1039 wxCheckBox* _enable_message_box;
1040 wxCheckBox* _enable_email;
1042 wxTextCtrl* _subject;
1045 EditableList<string, EmailDialog>* _cc;
1048 wxButton* _reset_email;
1052 class CoverSheetPage : public Page
1056 CoverSheetPage (wxSize panel_size, int border)
1057 #ifdef DCPOMATIC_OSX
1058 /* We have to force both width and height of this one */
1059 : Page (wxSize (panel_size.GetWidth(), 128), border)
1061 : Page (panel_size, border)
1065 wxString GetName () const
1067 return _("Cover Sheet");
1070 #ifdef DCPOMATIC_OSX
1071 wxBitmap GetLargeIcon () const
1073 return wxBitmap(bitmap_path("cover_sheet"), wxBITMAP_TYPE_PNG);
1080 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1081 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1083 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1084 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1086 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1087 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1090 void config_changed ()
1092 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1095 void cover_sheet_changed ()
1097 if (_cover_sheet->GetValue().IsEmpty ()) {
1098 /* Sometimes we get sent an erroneous notification that the cover sheet
1099 is empty; I don't know why.
1103 Config::instance()->set_cover_sheet(wx_to_std(_cover_sheet->GetValue()));
1106 void reset_cover_sheet ()
1108 Config::instance()->reset_cover_sheet();
1109 checked_set (_cover_sheet, Config::instance()->cover_sheet());
1112 wxTextCtrl* _cover_sheet;
1113 wxButton* _reset_cover_sheet;
1117 class IdentifiersPage : public Page
1120 IdentifiersPage (wxSize panel_size, int border)
1121 : Page (panel_size, border)
1124 wxString GetName () const
1126 return _("Identifiers");
1129 #ifdef DCPOMATIC_OSX
1130 wxBitmap GetLargeIcon () const
1132 return wxBitmap(bitmap_path("identifiers"), wxBITMAP_TYPE_PNG);
1139 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1140 table->AddGrowableCol (1, 1);
1142 add_label_to_sizer (table, _panel, _("Issuer"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1143 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1144 _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."));
1145 table->Add (_issuer, 1, wxALL | wxEXPAND);
1147 add_label_to_sizer (table, _panel, _("Creator"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1148 _creator = new wxTextCtrl (_panel, wxID_ANY);
1149 _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."));
1150 table->Add (_creator, 1, wxALL | wxEXPAND);
1152 add_label_to_sizer (table, _panel, _("Company name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1153 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1154 _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."));
1155 table->Add (_company_name, 1, wxALL | wxEXPAND);
1157 add_label_to_sizer (table, _panel, _("Product name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1158 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1159 _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."));
1160 table->Add (_product_name, 1, wxALL | wxEXPAND);
1162 add_label_to_sizer (table, _panel, _("Product version"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1163 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1164 _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."));
1165 table->Add (_product_version, 1, wxALL | wxEXPAND);
1167 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1168 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1169 _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."));
1170 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1172 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1174 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1175 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1176 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1177 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1178 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1179 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1182 void config_changed ()
1184 auto config = Config::instance ();
1185 checked_set (_issuer, config->dcp_issuer ());
1186 checked_set (_creator, config->dcp_creator ());
1187 checked_set (_company_name, config->dcp_company_name ());
1188 checked_set (_product_name, config->dcp_product_name ());
1189 checked_set (_product_version, config->dcp_product_version ());
1190 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1193 void issuer_changed ()
1195 Config::instance()->set_dcp_issuer(wx_to_std(_issuer->GetValue()));
1198 void creator_changed ()
1200 Config::instance()->set_dcp_creator(wx_to_std(_creator->GetValue()));
1203 void company_name_changed ()
1205 Config::instance()->set_dcp_company_name(wx_to_std(_company_name->GetValue()));
1208 void product_name_changed ()
1210 Config::instance()->set_dcp_product_name(wx_to_std(_product_name->GetValue()));
1213 void product_version_changed ()
1215 Config::instance()->set_dcp_product_version(wx_to_std(_product_version->GetValue()));
1218 void j2k_comment_changed ()
1220 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1223 wxTextCtrl* _issuer;
1224 wxTextCtrl* _creator;
1225 wxTextCtrl* _company_name;
1226 wxTextCtrl* _product_name;
1227 wxTextCtrl* _product_version;
1228 wxTextCtrl* _j2k_comment;
1232 /** @class AdvancedPage
1233 * @brief Advanced page of the preferences dialog.
1235 class AdvancedPage : public Page
1238 AdvancedPage (wxSize panel_size, int border)
1239 : Page (panel_size, border)
1242 wxString GetName () const
1244 return _("Advanced");
1247 #ifdef DCPOMATIC_OSX
1248 wxBitmap GetLargeIcon () const
1250 return wxBitmap(bitmap_path("advanced"), wxBITMAP_TYPE_PNG);
1255 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1257 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1259 flags |= wxALIGN_RIGHT;
1262 wxStaticText* m = new StaticText (parent, text);
1263 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1268 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1269 table->AddGrowableCol (1, 1);
1270 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1273 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1274 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1275 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1276 s->Add (_maximum_j2k_bandwidth, 1);
1277 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxALIGN_CENTRE_VERTICAL);
1281 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1282 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1283 table->Add (_video_display_mode);
1285 auto restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1286 auto font = restart->GetFont();
1287 font.SetStyle (wxFONTSTYLE_ITALIC);
1288 font.SetPointSize (font.GetPointSize() - 1);
1289 restart->SetFont (font);
1290 table->AddSpacer (0);
1292 _allow_any_dcp_frame_rate = new CheckBox (_panel, _("Allow any DCP frame rate"));
1293 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1294 table->AddSpacer (0);
1296 _allow_any_container = new CheckBox (_panel, _("Allow full-frame and non-standard container ratios"));
1297 table->Add (_allow_any_container, 1, wxEXPAND | wxALL);
1298 table->AddSpacer (0);
1300 restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to see all ratios)"), false);
1301 restart->SetFont (font);
1302 table->AddSpacer (0);
1304 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1305 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxALL);
1306 table->AddSpacer (0);
1308 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1309 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1310 table->AddSpacer (0);
1313 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1314 auto s = new wxBoxSizer (wxHORIZONTAL);
1315 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1316 s->Add (_frames_in_memory_multiplier, 1);
1321 auto format = create_label (_panel, _("DCP metadata filename format"), true);
1322 #ifdef DCPOMATIC_OSX
1323 auto align = new wxBoxSizer (wxHORIZONTAL);
1324 align->Add (format, 0, wxTOP, 2);
1325 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1327 table->Add (format, 0, wxTOP | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1329 dcp::NameFormat::Map titles;
1330 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1331 dcp::NameFormat::Map examples;
1332 examples['t'] = "cpl";
1333 _dcp_metadata_filename_format = new NameFormatEditor (
1334 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1336 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1340 auto format = create_label (_panel, _("DCP asset filename format"), true);
1341 #ifdef DCPOMATIC_OSX
1342 auto align = new wxBoxSizer (wxHORIZONTAL);
1343 align->Add (format, 0, wxTOP, 2);
1344 table->Add (align, 0, wxALIGN_RIGHT | wxRIGHT, DCPOMATIC_SIZER_GAP - 2);
1346 table->Add (format, 0, wxTOP | wxRIGHT | wxALIGN_TOP, DCPOMATIC_SIZER_GAP);
1348 dcp::NameFormat::Map titles;
1349 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1350 titles['r'] = wx_to_std (_("reel number"));
1351 titles['n'] = wx_to_std (_("number of reels"));
1352 titles['c'] = wx_to_std (_("content filename"));
1353 dcp::NameFormat::Map examples;
1354 examples['t'] = "j2c";
1355 examples['r'] = "1";
1356 examples['n'] = "4";
1357 examples['c'] = "myfile.mp4";
1358 _dcp_asset_filename_format = new NameFormatEditor (
1359 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1361 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1365 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1366 auto t = new wxBoxSizer (wxVERTICAL);
1367 _log_general = new CheckBox (_panel, _("General"));
1368 t->Add (_log_general, 1, wxEXPAND | wxALL);
1369 _log_warning = new CheckBox (_panel, _("Warnings"));
1370 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1371 _log_error = new CheckBox (_panel, _("Errors"));
1372 t->Add (_log_error, 1, wxEXPAND | wxALL);
1373 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1374 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1375 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1376 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1377 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1378 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1379 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1380 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1381 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1382 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1383 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1384 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1385 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1386 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1387 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1388 table->Add (t, 0, wxALL, 6);
1391 #ifdef DCPOMATIC_WINDOWS
1392 _win32_console = new CheckBox (_panel, _("Open console window"));
1393 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1394 table->AddSpacer (0);
1397 _maximum_j2k_bandwidth->SetRange (1, 1000);
1398 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1399 _video_display_mode->Append (_("Simple (safer)"));
1400 _video_display_mode->Append (_("OpenGL (faster)"));
1401 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1402 _allow_any_dcp_frame_rate->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1403 _allow_any_container->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_container_changed, this));
1404 _show_experimental_audio_processors->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::show_experimental_audio_processors_changed, this));
1405 _only_servers_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1406 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1407 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1408 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1409 _log_general->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1410 _log_warning->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1411 _log_error->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1412 _log_timing->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1413 _log_debug_threed->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1414 _log_debug_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1415 _log_debug_email->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1416 _log_debug_video_view->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1417 _log_debug_player->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1418 _log_debug_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1419 #ifdef DCPOMATIC_WINDOWS
1420 _win32_console->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::win32_console_changed, this));
1424 void config_changed ()
1426 auto config = Config::instance ();
1428 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1429 switch (config->video_view_type()) {
1430 case Config::VIDEO_VIEW_SIMPLE:
1431 checked_set (_video_display_mode, 0);
1433 case Config::VIDEO_VIEW_OPENGL:
1434 checked_set (_video_display_mode, 1);
1437 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1438 checked_set (_allow_any_container, config->allow_any_container ());
1439 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1440 checked_set (_only_servers_encode, config->only_servers_encode ());
1441 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1442 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1443 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1444 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1445 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREE_D);
1446 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1447 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1448 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1449 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1450 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1451 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1452 #ifdef DCPOMATIC_WINDOWS
1453 checked_set (_win32_console, config->win32_console());
1457 void maximum_j2k_bandwidth_changed ()
1459 Config::instance()->set_maximum_j2k_bandwidth(_maximum_j2k_bandwidth->GetValue() * 1000000);
1462 void video_display_mode_changed ()
1464 if (_video_display_mode->GetSelection() == 0) {
1465 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_SIMPLE);
1467 Config::instance()->set_video_view_type(Config::VIDEO_VIEW_OPENGL);
1471 void frames_in_memory_multiplier_changed ()
1473 Config::instance()->set_frames_in_memory_multiplier(_frames_in_memory_multiplier->GetValue());
1476 void allow_any_dcp_frame_rate_changed ()
1478 Config::instance()->set_allow_any_dcp_frame_rate(_allow_any_dcp_frame_rate->GetValue());
1481 void allow_any_container_changed ()
1483 Config::instance()->set_allow_any_container(_allow_any_container->GetValue());
1486 void show_experimental_audio_processors_changed ()
1488 Config::instance()->set_show_experimental_audio_processors(_show_experimental_audio_processors->GetValue());
1491 void only_servers_encode_changed ()
1493 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue());
1496 void dcp_metadata_filename_format_changed ()
1498 Config::instance()->set_dcp_metadata_filename_format(_dcp_metadata_filename_format->get());
1501 void dcp_asset_filename_format_changed ()
1503 Config::instance()->set_dcp_asset_filename_format(_dcp_asset_filename_format->get());
1509 if (_log_general->GetValue ()) {
1510 types |= LogEntry::TYPE_GENERAL;
1512 if (_log_warning->GetValue ()) {
1513 types |= LogEntry::TYPE_WARNING;
1515 if (_log_error->GetValue ()) {
1516 types |= LogEntry::TYPE_ERROR;
1518 if (_log_timing->GetValue ()) {
1519 types |= LogEntry::TYPE_TIMING;
1521 if (_log_debug_threed->GetValue ()) {
1522 types |= LogEntry::TYPE_DEBUG_THREE_D;
1524 if (_log_debug_encode->GetValue ()) {
1525 types |= LogEntry::TYPE_DEBUG_ENCODE;
1527 if (_log_debug_email->GetValue ()) {
1528 types |= LogEntry::TYPE_DEBUG_EMAIL;
1530 if (_log_debug_video_view->GetValue()) {
1531 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1533 if (_log_debug_player->GetValue()) {
1534 types |= LogEntry::TYPE_DEBUG_PLAYER;
1536 if (_log_debug_audio_analysis->GetValue()) {
1537 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1539 Config::instance()->set_log_types (types);
1542 #ifdef DCPOMATIC_WINDOWS
1543 void win32_console_changed ()
1545 Config::instance()->set_win32_console(_win32_console->GetValue());
1549 wxSpinCtrl* _maximum_j2k_bandwidth = nullptr;
1550 wxChoice* _video_display_mode = nullptr;
1551 wxSpinCtrl* _frames_in_memory_multiplier = nullptr;
1552 wxCheckBox* _allow_any_dcp_frame_rate = nullptr;
1553 wxCheckBox* _allow_any_container = nullptr;
1554 wxCheckBox* _show_experimental_audio_processors = nullptr;
1555 wxCheckBox* _only_servers_encode = nullptr;
1556 NameFormatEditor* _dcp_metadata_filename_format = nullptr;
1557 NameFormatEditor* _dcp_asset_filename_format = nullptr;
1558 wxCheckBox* _log_general = nullptr;
1559 wxCheckBox* _log_warning = nullptr;
1560 wxCheckBox* _log_error = nullptr;
1561 wxCheckBox* _log_timing = nullptr;
1562 wxCheckBox* _log_debug_threed = nullptr;
1563 wxCheckBox* _log_debug_encode = nullptr;
1564 wxCheckBox* _log_debug_email = nullptr;
1565 wxCheckBox* _log_debug_video_view = nullptr;
1566 wxCheckBox* _log_debug_player = nullptr;
1567 wxCheckBox* _log_debug_audio_analysis = nullptr;
1568 #ifdef DCPOMATIC_WINDOWS
1569 wxCheckBox* _win32_console = nullptr;
1574 wxPreferencesEditor*
1575 create_full_config_dialog ()
1577 auto e = new wxPreferencesEditor ();
1579 #ifdef DCPOMATIC_OSX
1580 /* Width that we force some of the config panels to be on OSX so that
1581 the containing window doesn't shrink too much when we select those panels.
1582 This is obviously an unpleasant hack.
1584 wxSize ps = wxSize (700, -1);
1585 int const border = 16;
1587 wxSize ps = wxSize (-1, -1);
1588 int const border = 8;
1591 e->AddPage (new FullGeneralPage (ps, border));
1592 e->AddPage (new SoundPage (ps, border));
1593 e->AddPage (new DefaultsPage (ps, border));
1594 e->AddPage (new EncodingServersPage(ps, border));
1595 e->AddPage (new KeysPage (ps, border));
1596 e->AddPage (new TMSPage (ps, border));
1597 e->AddPage (new EmailPage (ps, border));
1598 e->AddPage (new KDMEmailPage (ps, border));
1599 e->AddPage (new NotificationsPage (ps, border));
1600 e->AddPage (new CoverSheetPage (ps, border));
1601 e->AddPage (new IdentifiersPage (ps, border));
1602 e->AddPage (new AdvancedPage (ps, border));