2 Copyright (C) 2012-2019 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/>.
21 /** @file src/full_config_dialog.cc
22 * @brief A dialogue to edit all DCP-o-matic configuration.
25 #include "full_config_dialog.h"
27 #include "editable_list.h"
28 #include "filter_dialog.h"
29 #include "dir_picker_ctrl.h"
30 #include "file_picker_ctrl.h"
31 #include "server_dialog.h"
32 #include "make_chain_dialog.h"
33 #include "email_dialog.h"
34 #include "name_format_editor.h"
35 #include "nag_dialog.h"
36 #include "config_move_dialog.h"
37 #include "config_dialog.h"
38 #include "static_text.h"
39 #include "check_box.h"
40 #include "dcpomatic_button.h"
41 #include "password_entry.h"
42 #include "lib/config.h"
43 #include "lib/ratio.h"
44 #include "lib/filter.h"
45 #include "lib/dcp_content_type.h"
48 #include "lib/cross.h"
49 #include "lib/exceptions.h"
50 #include <dcp/locale_convert.h>
51 #include <dcp/exceptions.h>
52 #include <dcp/certificate_chain.h>
53 #include <wx/stdpaths.h>
54 #include <wx/preferences.h>
55 #include <wx/spinctrl.h>
56 #include <wx/filepicker.h>
58 #include <boost/filesystem.hpp>
69 using std::shared_ptr;
70 using boost::function;
71 using boost::optional;
72 #if BOOST_VERSION >= 106100
73 using namespace boost::placeholders;
75 using dcp::locale_convert;
77 class FullGeneralPage : public GeneralPage
80 FullGeneralPage (wxSize panel_size, int border)
81 : GeneralPage (panel_size, border)
87 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
88 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
91 add_language_controls (table, r);
93 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
94 _master_encoding_threads = new wxSpinCtrl (_panel);
95 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
98 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
99 _server_encoding_threads = new wxSpinCtrl (_panel);
100 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
103 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
104 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, false);
105 table->Add (_config_file, wxGBPosition (r, 1));
108 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
109 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, false);
110 table->Add (_cinemas_file, wxGBPosition (r, 1));
111 Button* export_cinemas = new Button (_panel, _("Export..."));
112 table->Add (export_cinemas, wxGBPosition (r, 2));
115 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
116 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
117 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
121 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
122 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
125 add_update_controls (table, r);
127 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::config_file_changed, this));
128 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::cinemas_file_changed, this));
130 _master_encoding_threads->SetRange (1, 128);
131 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
132 _server_encoding_threads->SetRange (1, 128);
133 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
134 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
136 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
137 _analyse_ebur128->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::analyse_ebur128_changed, this));
139 _automatic_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::automatic_audio_analysis_changed, this));
142 void config_changed ()
144 Config* config = Config::instance ();
146 checked_set (_master_encoding_threads, config->master_encoding_threads ());
147 checked_set (_server_encoding_threads, config->server_encoding_threads ());
148 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
149 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
151 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
152 checked_set (_config_file, config->config_file());
153 checked_set (_cinemas_file, config->cinemas_file());
155 GeneralPage::config_changed ();
158 void export_cinemas_file ()
160 wxFileDialog* d = new wxFileDialog (
161 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT ("XML files (*.xml)|*.xml"),
162 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
165 if (d->ShowModal () == wxID_OK) {
166 boost::filesystem::copy_file (Config::instance()->cinemas_file(), wx_to_std(d->GetPath()));
171 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
172 void analyse_ebur128_changed ()
174 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
178 void automatic_audio_analysis_changed ()
180 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
183 void master_encoding_threads_changed ()
185 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue ());
188 void server_encoding_threads_changed ()
190 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue ());
193 void config_file_changed ()
195 Config* config = Config::instance();
196 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
197 if (new_file == config->config_file()) {
200 bool copy_and_link = true;
201 if (boost::filesystem::exists(new_file)) {
202 ConfigMoveDialog* d = new ConfigMoveDialog (_panel, new_file);
203 if (d->ShowModal() == wxID_OK) {
204 copy_and_link = false;
211 if (new_file != config->config_file()) {
212 config->copy_and_link (new_file);
215 config->link (new_file);
219 void cinemas_file_changed ()
221 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
224 wxSpinCtrl* _master_encoding_threads;
225 wxSpinCtrl* _server_encoding_threads;
226 FilePickerCtrl* _config_file;
227 FilePickerCtrl* _cinemas_file;
228 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
229 wxCheckBox* _analyse_ebur128;
231 wxCheckBox* _automatic_audio_analysis;
234 class DefaultsPage : public Page
237 DefaultsPage (wxSize panel_size, int border)
238 : Page (panel_size, border)
241 wxString GetName () const
243 return _("Defaults");
247 wxBitmap GetLargeIcon () const
249 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
256 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
257 table->AddGrowableCol (1, 1);
258 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
261 add_label_to_sizer (table, _panel, _("Default duration of still images"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
262 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
263 _still_length = new wxSpinCtrl (_panel);
264 s->Add (_still_length);
265 add_label_to_sizer (s, _panel, _("s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
269 add_label_to_sizer (table, _panel, _("Default directory for new films"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
270 #ifdef DCPOMATIC_USE_OWN_PICKER
271 _directory = new DirPickerCtrl (_panel);
273 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
275 table->Add (_directory, 1, wxEXPAND);
277 add_label_to_sizer (table, _panel, _("Default container"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
278 _container = new wxChoice (_panel, wxID_ANY);
279 table->Add (_container);
281 add_label_to_sizer (table, _panel, _("Default content type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
282 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
283 table->Add (_dcp_content_type);
285 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
286 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
287 table->Add (_dcp_audio_channels);
290 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
291 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
292 _j2k_bandwidth = new wxSpinCtrl (_panel);
293 s->Add (_j2k_bandwidth);
294 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
299 add_label_to_sizer (table, _panel, _("Default audio delay"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
300 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
301 _audio_delay = new wxSpinCtrl (_panel);
302 s->Add (_audio_delay);
303 add_label_to_sizer (s, _panel, _("ms"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
307 add_label_to_sizer (table, _panel, _("Default standard"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
308 _standard = new wxChoice (_panel, wxID_ANY);
309 table->Add (_standard);
311 add_label_to_sizer (table, _panel, _("Default KDM directory"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
312 #ifdef DCPOMATIC_USE_OWN_PICKER
313 _kdm_directory = new DirPickerCtrl (_panel);
315 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
318 table->Add (_kdm_directory, 1, wxEXPAND);
320 _still_length->SetRange (1, 3600);
321 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
323 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
324 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
326 for (auto i: Ratio::containers()) {
327 _container->Append (std_to_wx(i->container_nickname()));
330 _container->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::container_changed, this));
332 for (auto i: DCPContentType::all()) {
333 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
336 setup_audio_channels_choice (_dcp_audio_channels, 2);
338 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
339 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
341 _j2k_bandwidth->SetRange (50, 250);
342 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
344 _audio_delay->SetRange (-1000, 1000);
345 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
347 _standard->Append (_("SMPTE"));
348 _standard->Append (_("Interop"));
349 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
352 void config_changed ()
354 Config* config = Config::instance ();
356 vector<Ratio const *> containers = Ratio::containers ();
357 for (size_t i = 0; i < containers.size(); ++i) {
358 if (containers[i] == config->default_container ()) {
359 _container->SetSelection (i);
363 vector<DCPContentType const *> const ct = DCPContentType::all ();
364 for (size_t i = 0; i < ct.size(); ++i) {
365 if (ct[i] == config->default_dcp_content_type ()) {
366 _dcp_content_type->SetSelection (i);
370 checked_set (_still_length, config->default_still_length ());
371 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
372 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
373 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
374 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
375 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
376 checked_set (_audio_delay, config->default_audio_delay ());
377 checked_set (_standard, config->default_interop() ? 1 : 0);
380 void j2k_bandwidth_changed ()
382 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
385 void audio_delay_changed ()
387 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
390 void dcp_audio_channels_changed ()
392 int const s = _dcp_audio_channels->GetSelection ();
393 if (s != wxNOT_FOUND) {
394 Config::instance()->set_default_dcp_audio_channels (
395 locale_convert<int> (string_client_data (_dcp_audio_channels->GetClientObject (s)))
400 void directory_changed ()
402 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
405 void kdm_directory_changed ()
407 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
410 void still_length_changed ()
412 Config::instance()->set_default_still_length (_still_length->GetValue ());
415 void container_changed ()
417 vector<Ratio const *> ratio = Ratio::containers ();
418 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
421 void dcp_content_type_changed ()
423 vector<DCPContentType const *> ct = DCPContentType::all ();
424 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
427 void standard_changed ()
429 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
432 wxSpinCtrl* _j2k_bandwidth;
433 wxSpinCtrl* _audio_delay;
434 wxSpinCtrl* _still_length;
435 #ifdef DCPOMATIC_USE_OWN_PICKER
436 DirPickerCtrl* _directory;
437 DirPickerCtrl* _kdm_directory;
439 wxDirPickerCtrl* _directory;
440 wxDirPickerCtrl* _kdm_directory;
442 wxChoice* _container;
443 wxChoice* _dcp_content_type;
444 wxChoice* _dcp_audio_channels;
448 class EncodingServersPage : public Page
451 EncodingServersPage (wxSize panel_size, int border)
452 : Page (panel_size, border)
455 wxString GetName () const
461 wxBitmap GetLargeIcon () const
463 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
470 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
471 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
473 vector<EditableListColumn> columns;
474 columns.push_back (EditableListColumn(_("IP address / host name")));
475 _servers_list = new EditableList<string, ServerDialog> (
478 boost::bind (&Config::servers, Config::instance()),
479 boost::bind (&Config::set_servers, Config::instance(), _1),
480 boost::bind (&EncodingServersPage::server_column, this, _1)
483 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
485 _use_any_servers->Bind (wxEVT_CHECKBOX, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
488 void config_changed ()
490 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
491 _servers_list->refresh ();
494 void use_any_servers_changed ()
496 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
499 string server_column (string s)
504 wxCheckBox* _use_any_servers;
505 EditableList<string, ServerDialog>* _servers_list;
508 class TMSPage : public Page
511 TMSPage (wxSize panel_size, int border)
512 : Page (panel_size, border)
515 wxString GetName () const
521 wxBitmap GetLargeIcon () const
523 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
530 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
531 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
533 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
534 table->AddGrowableCol (1, 1);
535 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
537 add_label_to_sizer (table, _panel, _("Protocol"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
538 _tms_protocol = new wxChoice (_panel, wxID_ANY);
539 table->Add (_tms_protocol, 1, wxEXPAND);
541 add_label_to_sizer (table, _panel, _("IP address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
542 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
543 table->Add (_tms_ip, 1, wxEXPAND);
545 add_label_to_sizer (table, _panel, _("Target path"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
546 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
547 table->Add (_tms_path, 1, wxEXPAND);
549 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
550 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
551 table->Add (_tms_user, 1, wxEXPAND);
553 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
554 _tms_password = new PasswordEntry (_panel);
555 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
557 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
558 _tms_protocol->Append (_("FTP (for Dolby)"));
560 _upload->Bind (wxEVT_CHECKBOX, boost::bind(&TMSPage::upload_changed, this));
561 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
562 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
563 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
564 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
565 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
568 void config_changed ()
570 Config* config = Config::instance ();
572 checked_set (_upload, config->upload_after_make_dcp());
573 checked_set (_tms_protocol, static_cast<int>(config->tms_protocol()));
574 checked_set (_tms_ip, config->tms_ip ());
575 checked_set (_tms_path, config->tms_path ());
576 checked_set (_tms_user, config->tms_user ());
577 checked_set (_tms_password, config->tms_password ());
580 void upload_changed ()
582 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
585 void tms_protocol_changed ()
587 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
590 void tms_ip_changed ()
592 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
595 void tms_path_changed ()
597 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
600 void tms_user_changed ()
602 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
605 void tms_password_changed ()
607 Config::instance()->set_tms_password (_tms_password->get());
611 wxChoice* _tms_protocol;
613 wxTextCtrl* _tms_path;
614 wxTextCtrl* _tms_user;
615 PasswordEntry* _tms_password;
624 class EmailPage : public Page
627 EmailPage (wxSize panel_size, int border)
628 : Page (panel_size, border)
631 wxString GetName () const
637 wxBitmap GetLargeIcon () const
639 return wxBitmap ("email", wxBITMAP_TYPE_PNG_RESOURCE);
646 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
647 table->AddGrowableCol (1, 1);
648 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
650 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
652 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
653 _server = new wxTextCtrl (_panel, wxID_ANY);
654 s->Add (_server, 1, wxEXPAND | wxALL);
655 add_label_to_sizer (s, _panel, _("port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
656 _port = new wxSpinCtrl (_panel, wxID_ANY);
657 _port->SetRange (0, 65535);
659 add_label_to_sizer (s, _panel, _("protocol"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
660 _protocol = new wxChoice (_panel, wxID_ANY);
661 /* Make sure this matches the switches in config_changed and port_changed below */
662 _protocol->Append (_("Auto"));
663 _protocol->Append (_("Plain"));
664 _protocol->Append (_("STARTTLS"));
665 _protocol->Append (_("SSL"));
667 table->Add (s, 1, wxEXPAND | wxALL);
670 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
671 _user = new wxTextCtrl (_panel, wxID_ANY);
672 table->Add (_user, 1, wxEXPAND | wxALL);
674 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
675 _password = new PasswordEntry (_panel);
676 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
678 _server->Bind (wxEVT_TEXT, boost::bind (&EmailPage::server_changed, this));
679 _port->Bind (wxEVT_SPINCTRL, boost::bind (&EmailPage::port_changed, this));
680 _protocol->Bind (wxEVT_CHOICE, boost::bind (&EmailPage::protocol_changed, this));
681 _user->Bind (wxEVT_TEXT, boost::bind (&EmailPage::user_changed, this));
682 _password->Changed.connect (boost::bind (&EmailPage::password_changed, this));
685 void config_changed ()
687 auto config = Config::instance ();
689 checked_set (_server, config->mail_server ());
690 checked_set (_port, config->mail_port ());
691 switch (config->mail_protocol()) {
692 case EmailProtocol::AUTO:
693 checked_set (_protocol, 0);
695 case EmailProtocol::PLAIN:
696 checked_set (_protocol, 1);
698 case EmailProtocol::STARTTLS:
699 checked_set (_protocol, 2);
701 case EmailProtocol::SSL:
702 checked_set (_protocol, 3);
705 checked_set (_user, config->mail_user ());
706 checked_set (_password, config->mail_password());
709 void server_changed ()
711 Config::instance()->set_mail_server (wx_to_std (_server->GetValue ()));
716 Config::instance()->set_mail_port (_port->GetValue ());
719 void protocol_changed ()
721 switch (_protocol->GetSelection()) {
723 Config::instance()->set_mail_protocol(EmailProtocol::AUTO);
726 Config::instance()->set_mail_protocol(EmailProtocol::PLAIN);
729 Config::instance()->set_mail_protocol(EmailProtocol::STARTTLS);
732 Config::instance()->set_mail_protocol(EmailProtocol::SSL);
739 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
742 void password_changed ()
744 Config::instance()->set_mail_password(_password->get());
751 PasswordEntry* _password;
754 class KDMEmailPage : public Page
758 KDMEmailPage (wxSize panel_size, int border)
760 /* We have to force both width and height of this one */
761 : Page (wxSize (panel_size.GetWidth(), 128), border)
763 : Page (panel_size, border)
767 wxString GetName () const
769 return _("KDM Email");
773 wxBitmap GetLargeIcon () const
775 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
782 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
783 table->AddGrowableCol (1, 1);
784 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
786 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
787 _subject = new wxTextCtrl (_panel, wxID_ANY);
788 table->Add (_subject, 1, wxEXPAND | wxALL);
790 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
791 _from = new wxTextCtrl (_panel, wxID_ANY);
792 table->Add (_from, 1, wxEXPAND | wxALL);
794 vector<EditableListColumn> columns;
795 columns.push_back (EditableListColumn(_("Address")));
796 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
797 _cc = new EditableList<string, EmailDialog> (
800 bind (&Config::kdm_cc, Config::instance()),
801 bind (&Config::set_kdm_cc, Config::instance(), _1),
804 table->Add (_cc, 1, wxEXPAND | wxALL);
806 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
807 _bcc = new wxTextCtrl (_panel, wxID_ANY);
808 table->Add (_bcc, 1, wxEXPAND | wxALL);
810 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
811 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
813 _reset_email = new Button (_panel, _("Reset to default subject and text"));
814 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
818 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
819 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
820 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
821 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
822 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
825 void config_changed ()
827 Config* config = Config::instance ();
829 checked_set (_subject, config->kdm_subject ());
830 checked_set (_from, config->kdm_from ());
831 checked_set (_bcc, config->kdm_bcc ());
832 checked_set (_email, Config::instance()->kdm_email ());
835 void kdm_subject_changed ()
837 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
840 void kdm_from_changed ()
842 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
845 void kdm_bcc_changed ()
847 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
850 void kdm_email_changed ()
852 if (_email->GetValue().IsEmpty ()) {
853 /* Sometimes we get sent an erroneous notification that the email
854 is empty; I don't know why.
858 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
863 Config::instance()->reset_kdm_email ();
864 checked_set (_email, Config::instance()->kdm_email ());
867 wxTextCtrl* _subject;
869 EditableList<string, EmailDialog>* _cc;
872 wxButton* _reset_email;
875 class NotificationsPage : public Page
878 NotificationsPage (wxSize panel_size, int border)
880 /* We have to force both width and height of this one */
881 : Page (wxSize (panel_size.GetWidth(), 128), border)
883 : Page (panel_size, border)
887 wxString GetName () const
889 return _("Notifications");
893 wxBitmap GetLargeIcon () const
895 return wxBitmap ("notifications", wxBITMAP_TYPE_PNG_RESOURCE);
902 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
903 table->AddGrowableCol (1, 1);
904 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
906 _enable_message_box = new CheckBox (_panel, _("Message box"));
907 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
908 table->AddSpacer (0);
910 _enable_email = new CheckBox (_panel, _("Email"));
911 table->Add (_enable_email, 1, wxEXPAND | wxALL);
912 table->AddSpacer (0);
914 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
915 _subject = new wxTextCtrl (_panel, wxID_ANY);
916 table->Add (_subject, 1, wxEXPAND | wxALL);
918 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
919 _from = new wxTextCtrl (_panel, wxID_ANY);
920 table->Add (_from, 1, wxEXPAND | wxALL);
922 add_label_to_sizer (table, _panel, _("To address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
923 _to = new wxTextCtrl (_panel, wxID_ANY);
924 table->Add (_to, 1, wxEXPAND | wxALL);
926 vector<EditableListColumn> columns;
927 columns.push_back (EditableListColumn(_("Address")));
928 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
929 _cc = new EditableList<string, EmailDialog> (
932 bind (&Config::notification_cc, Config::instance()),
933 bind (&Config::set_notification_cc, Config::instance(), _1),
936 table->Add (_cc, 1, wxEXPAND | wxALL);
938 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
939 _bcc = new wxTextCtrl (_panel, wxID_ANY);
940 table->Add (_bcc, 1, wxEXPAND | wxALL);
942 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
943 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
945 _reset_email = new Button (_panel, _("Reset to default subject and text"));
946 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
950 _enable_message_box->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX));
951 _enable_email->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL));
953 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
954 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
955 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
956 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
957 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
958 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
960 update_sensitivity ();
963 void update_sensitivity ()
965 bool const s = _enable_email->GetValue();
972 _reset_email->Enable(s);
975 void config_changed ()
977 Config* config = Config::instance ();
979 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
980 checked_set (_enable_email, config->notification(Config::EMAIL));
981 checked_set (_subject, config->notification_subject ());
982 checked_set (_from, config->notification_from ());
983 checked_set (_to, config->notification_to ());
984 checked_set (_bcc, config->notification_bcc ());
985 checked_set (_email, Config::instance()->notification_email ());
987 update_sensitivity ();
990 void notification_subject_changed ()
992 Config::instance()->set_notification_subject (wx_to_std (_subject->GetValue ()));
995 void notification_from_changed ()
997 Config::instance()->set_notification_from (wx_to_std (_from->GetValue ()));
1000 void notification_to_changed ()
1002 Config::instance()->set_notification_to (wx_to_std (_to->GetValue ()));
1005 void notification_bcc_changed ()
1007 Config::instance()->set_notification_bcc (wx_to_std (_bcc->GetValue ()));
1010 void notification_email_changed ()
1012 if (_email->GetValue().IsEmpty ()) {
1013 /* Sometimes we get sent an erroneous notification that the email
1014 is empty; I don't know why.
1018 Config::instance()->set_notification_email (wx_to_std (_email->GetValue ()));
1023 Config::instance()->reset_notification_email ();
1024 checked_set (_email, Config::instance()->notification_email ());
1027 void type_changed (wxCheckBox* b, Config::Notification n)
1029 Config::instance()->set_notification(n, b->GetValue());
1030 update_sensitivity ();
1033 wxCheckBox* _enable_message_box;
1034 wxCheckBox* _enable_email;
1036 wxTextCtrl* _subject;
1039 EditableList<string, EmailDialog>* _cc;
1042 wxButton* _reset_email;
1045 class CoverSheetPage : public Page
1049 CoverSheetPage (wxSize panel_size, int border)
1050 #ifdef DCPOMATIC_OSX
1051 /* We have to force both width and height of this one */
1052 : Page (wxSize (panel_size.GetWidth(), 128), border)
1054 : Page (panel_size, border)
1058 wxString GetName () const
1060 return _("Cover Sheet");
1063 #ifdef DCPOMATIC_OSX
1064 wxBitmap GetLargeIcon () const
1066 return wxBitmap ("cover_sheet", wxBITMAP_TYPE_PNG_RESOURCE);
1073 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1074 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1076 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1077 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1079 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1080 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1083 void config_changed ()
1085 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
1088 void cover_sheet_changed ()
1090 if (_cover_sheet->GetValue().IsEmpty ()) {
1091 /* Sometimes we get sent an erroneous notification that the cover sheet
1092 is empty; I don't know why.
1096 Config::instance()->set_cover_sheet (wx_to_std (_cover_sheet->GetValue ()));
1099 void reset_cover_sheet ()
1101 Config::instance()->reset_cover_sheet ();
1102 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
1105 wxTextCtrl* _cover_sheet;
1106 wxButton* _reset_cover_sheet;
1110 class IdentifiersPage : public Page
1113 IdentifiersPage (wxSize panel_size, int border)
1114 : Page (panel_size, border)
1117 wxString GetName () const
1119 return _("Identifiers");
1122 #ifdef DCPOMATIC_OSX
1123 wxBitmap GetLargeIcon () const
1125 return wxBitmap ("identifiers", wxBITMAP_TYPE_PNG_RESOURCE);
1132 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1133 table->AddGrowableCol (1, 1);
1135 add_label_to_sizer (table, _panel, _("Issuer"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1136 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1137 _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."));
1138 table->Add (_issuer, 1, wxALL | wxEXPAND);
1140 add_label_to_sizer (table, _panel, _("Creator"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1141 _creator = new wxTextCtrl (_panel, wxID_ANY);
1142 _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."));
1143 table->Add (_creator, 1, wxALL | wxEXPAND);
1145 add_label_to_sizer (table, _panel, _("Company name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1146 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1147 _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."));
1148 table->Add (_company_name, 1, wxALL | wxEXPAND);
1150 add_label_to_sizer (table, _panel, _("Product name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1151 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1152 _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."));
1153 table->Add (_product_name, 1, wxALL | wxEXPAND);
1155 add_label_to_sizer (table, _panel, _("Product version"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1156 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1157 _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."));
1158 table->Add (_product_version, 1, wxALL | wxEXPAND);
1160 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1161 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1162 _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."));
1163 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1165 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1167 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1168 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1169 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1170 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1171 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1172 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1175 void config_changed ()
1177 Config* config = Config::instance ();
1178 checked_set (_issuer, config->dcp_issuer ());
1179 checked_set (_creator, config->dcp_creator ());
1180 checked_set (_company_name, config->dcp_company_name ());
1181 checked_set (_product_name, config->dcp_product_name ());
1182 checked_set (_product_version, config->dcp_product_version ());
1183 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1186 void issuer_changed ()
1188 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
1191 void creator_changed ()
1193 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
1196 void company_name_changed ()
1198 Config::instance()->set_dcp_company_name (wx_to_std(_company_name->GetValue()));
1201 void product_name_changed ()
1203 Config::instance()->set_dcp_product_name (wx_to_std(_product_name->GetValue()));
1206 void product_version_changed ()
1208 Config::instance()->set_dcp_product_version (wx_to_std(_product_version->GetValue()));
1211 void j2k_comment_changed ()
1213 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1216 wxTextCtrl* _issuer;
1217 wxTextCtrl* _creator;
1218 wxTextCtrl* _company_name;
1219 wxTextCtrl* _product_name;
1220 wxTextCtrl* _product_version;
1221 wxTextCtrl* _j2k_comment;
1225 /** @class AdvancedPage
1226 * @brief Advanced page of the preferences dialog.
1228 class AdvancedPage : public Page
1231 AdvancedPage (wxSize panel_size, int border)
1232 : Page (panel_size, border)
1233 , _maximum_j2k_bandwidth (0)
1234 , _allow_any_dcp_frame_rate (0)
1235 , _allow_any_container (0)
1236 , _show_experimental_audio_processors (0)
1237 , _only_servers_encode (0)
1242 , _log_debug_threed (0)
1243 , _log_debug_encode (0)
1244 , _log_debug_email (0)
1245 , _log_debug_video_view (0)
1246 , _log_debug_player (0)
1247 , _log_debug_audio_analysis (0)
1250 wxString GetName () const
1252 return _("Advanced");
1255 #ifdef DCPOMATIC_OSX
1256 wxBitmap GetLargeIcon () const
1258 return wxBitmap ("advanced", wxBITMAP_TYPE_PNG_RESOURCE);
1263 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1265 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1267 flags |= wxALIGN_RIGHT;
1270 wxStaticText* m = new StaticText (parent, text);
1271 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1276 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1277 table->AddGrowableCol (1, 1);
1278 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1281 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1282 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1283 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1284 s->Add (_maximum_j2k_bandwidth, 1);
1285 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1289 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1290 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1291 table->Add (_video_display_mode);
1293 wxStaticText* restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1294 wxFont font = restart->GetFont();
1295 font.SetStyle (wxFONTSTYLE_ITALIC);
1296 font.SetPointSize (font.GetPointSize() - 1);
1297 restart->SetFont (font);
1298 table->AddSpacer (0);
1300 _allow_any_dcp_frame_rate = new CheckBox (_panel, _("Allow any DCP frame rate"));
1301 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1302 table->AddSpacer (0);
1304 _allow_any_container = new CheckBox (_panel, _("Allow full-frame and non-standard container ratios"));
1305 table->Add (_allow_any_container, 1, wxEXPAND | wxALL);
1306 table->AddSpacer (0);
1308 restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to see all ratios)"), false);
1309 restart->SetFont (font);
1310 table->AddSpacer (0);
1312 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1313 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxALL);
1314 table->AddSpacer (0);
1316 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1317 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1318 table->AddSpacer (0);
1321 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1322 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1323 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1324 s->Add (_frames_in_memory_multiplier, 1);
1329 add_top_aligned_label_to_sizer (table, _panel, _("DCP metadata filename format"));
1330 dcp::NameFormat::Map titles;
1331 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1332 dcp::NameFormat::Map examples;
1333 examples['t'] = "cpl";
1334 _dcp_metadata_filename_format = new NameFormatEditor (
1335 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1337 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1341 add_top_aligned_label_to_sizer (table, _panel, _("DCP asset filename format"));
1342 dcp::NameFormat::Map titles;
1343 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1344 titles['r'] = wx_to_std (_("reel number"));
1345 titles['n'] = wx_to_std (_("number of reels"));
1346 titles['c'] = wx_to_std (_("content filename"));
1347 dcp::NameFormat::Map examples;
1348 examples['t'] = "j2c";
1349 examples['r'] = "1";
1350 examples['n'] = "4";
1351 examples['c'] = "myfile.mp4";
1352 _dcp_asset_filename_format = new NameFormatEditor (
1353 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1355 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1359 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1360 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1361 _log_general = new CheckBox (_panel, _("General"));
1362 t->Add (_log_general, 1, wxEXPAND | wxALL);
1363 _log_warning = new CheckBox (_panel, _("Warnings"));
1364 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1365 _log_error = new CheckBox (_panel, _("Errors"));
1366 t->Add (_log_error, 1, wxEXPAND | wxALL);
1367 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1368 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1369 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1370 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1371 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1372 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1373 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1374 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1375 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1376 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1377 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1378 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1379 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1380 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1381 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1382 table->Add (t, 0, wxALL, 6);
1385 #ifdef DCPOMATIC_WINDOWS
1386 _win32_console = new CheckBox (_panel, _("Open console window"));
1387 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1388 table->AddSpacer (0);
1391 _maximum_j2k_bandwidth->SetRange (1, 1000);
1392 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1393 _video_display_mode->Append (_("Simple (safer)"));
1394 _video_display_mode->Append (_("OpenGL (faster)"));
1395 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1396 _allow_any_dcp_frame_rate->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1397 _allow_any_container->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_container_changed, this));
1398 _show_experimental_audio_processors->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::show_experimental_audio_processors_changed, this));
1399 _only_servers_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1400 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1401 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1402 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1403 _log_general->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1404 _log_warning->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1405 _log_error->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1406 _log_timing->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1407 _log_debug_threed->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1408 _log_debug_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1409 _log_debug_email->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1410 _log_debug_video_view->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1411 _log_debug_player->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1412 _log_debug_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1413 #ifdef DCPOMATIC_WINDOWS
1414 _win32_console->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::win32_console_changed, this));
1418 void config_changed ()
1420 Config* config = Config::instance ();
1422 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1423 switch (config->video_view_type()) {
1424 case Config::VIDEO_VIEW_SIMPLE:
1425 checked_set (_video_display_mode, 0);
1427 case Config::VIDEO_VIEW_OPENGL:
1428 checked_set (_video_display_mode, 1);
1431 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1432 checked_set (_allow_any_container, config->allow_any_container ());
1433 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1434 checked_set (_only_servers_encode, config->only_servers_encode ());
1435 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1436 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1437 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1438 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1439 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREE_D);
1440 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1441 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1442 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1443 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1444 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1445 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1446 #ifdef DCPOMATIC_WINDOWS
1447 checked_set (_win32_console, config->win32_console());
1451 void maximum_j2k_bandwidth_changed ()
1453 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1456 void video_display_mode_changed ()
1458 if (_video_display_mode->GetSelection() == 0) {
1459 Config::instance()->set_video_view_type (Config::VIDEO_VIEW_SIMPLE);
1461 Config::instance()->set_video_view_type (Config::VIDEO_VIEW_OPENGL);
1465 void frames_in_memory_multiplier_changed ()
1467 Config::instance()->set_frames_in_memory_multiplier (_frames_in_memory_multiplier->GetValue());
1470 void allow_any_dcp_frame_rate_changed ()
1472 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1475 void allow_any_container_changed ()
1477 Config::instance()->set_allow_any_container (_allow_any_container->GetValue ());
1480 void show_experimental_audio_processors_changed ()
1482 Config::instance()->set_show_experimental_audio_processors (_show_experimental_audio_processors->GetValue ());
1485 void only_servers_encode_changed ()
1487 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1490 void dcp_metadata_filename_format_changed ()
1492 Config::instance()->set_dcp_metadata_filename_format (_dcp_metadata_filename_format->get ());
1495 void dcp_asset_filename_format_changed ()
1497 Config::instance()->set_dcp_asset_filename_format (_dcp_asset_filename_format->get ());
1503 if (_log_general->GetValue ()) {
1504 types |= LogEntry::TYPE_GENERAL;
1506 if (_log_warning->GetValue ()) {
1507 types |= LogEntry::TYPE_WARNING;
1509 if (_log_error->GetValue ()) {
1510 types |= LogEntry::TYPE_ERROR;
1512 if (_log_timing->GetValue ()) {
1513 types |= LogEntry::TYPE_TIMING;
1515 if (_log_debug_threed->GetValue ()) {
1516 types |= LogEntry::TYPE_DEBUG_THREE_D;
1518 if (_log_debug_encode->GetValue ()) {
1519 types |= LogEntry::TYPE_DEBUG_ENCODE;
1521 if (_log_debug_email->GetValue ()) {
1522 types |= LogEntry::TYPE_DEBUG_EMAIL;
1524 if (_log_debug_video_view->GetValue()) {
1525 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1527 if (_log_debug_player->GetValue()) {
1528 types |= LogEntry::TYPE_DEBUG_PLAYER;
1530 if (_log_debug_audio_analysis->GetValue()) {
1531 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1533 Config::instance()->set_log_types (types);
1536 #ifdef DCPOMATIC_WINDOWS
1537 void win32_console_changed ()
1539 Config::instance()->set_win32_console (_win32_console->GetValue ());
1543 wxSpinCtrl* _maximum_j2k_bandwidth;
1544 wxChoice* _video_display_mode;
1545 wxSpinCtrl* _frames_in_memory_multiplier;
1546 wxCheckBox* _allow_any_dcp_frame_rate;
1547 wxCheckBox* _allow_any_container;
1548 wxCheckBox* _show_experimental_audio_processors;
1549 wxCheckBox* _only_servers_encode;
1550 NameFormatEditor* _dcp_metadata_filename_format;
1551 NameFormatEditor* _dcp_asset_filename_format;
1552 wxCheckBox* _log_general;
1553 wxCheckBox* _log_warning;
1554 wxCheckBox* _log_error;
1555 wxCheckBox* _log_timing;
1556 wxCheckBox* _log_debug_threed;
1557 wxCheckBox* _log_debug_encode;
1558 wxCheckBox* _log_debug_email;
1559 wxCheckBox* _log_debug_video_view;
1560 wxCheckBox* _log_debug_player;
1561 wxCheckBox* _log_debug_audio_analysis;
1562 #ifdef DCPOMATIC_WINDOWS
1563 wxCheckBox* _win32_console;
1567 wxPreferencesEditor*
1568 create_full_config_dialog ()
1570 wxPreferencesEditor* e = new wxPreferencesEditor ();
1572 #ifdef DCPOMATIC_OSX
1573 /* Width that we force some of the config panels to be on OSX so that
1574 the containing window doesn't shrink too much when we select those panels.
1575 This is obviously an unpleasant hack.
1577 wxSize ps = wxSize (700, -1);
1578 int const border = 16;
1580 wxSize ps = wxSize (-1, -1);
1581 int const border = 8;
1584 e->AddPage (new FullGeneralPage (ps, border));
1585 e->AddPage (new SoundPage (ps, border));
1586 e->AddPage (new DefaultsPage (ps, border));
1587 e->AddPage (new EncodingServersPage (ps, border));
1588 e->AddPage (new KeysPage (ps, border));
1589 e->AddPage (new TMSPage (ps, border));
1590 e->AddPage (new EmailPage (ps, border));
1591 e->AddPage (new KDMEmailPage (ps, border));
1592 e->AddPage (new NotificationsPage (ps, border));
1593 e->AddPage (new CoverSheetPage (ps, border));
1594 e->AddPage (new IdentifiersPage (ps, border));
1595 e->AddPage (new AdvancedPage (ps, border));