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 "isdcf_metadata_dialog.h"
32 #include "server_dialog.h"
33 #include "make_chain_dialog.h"
34 #include "email_dialog.h"
35 #include "name_format_editor.h"
36 #include "nag_dialog.h"
37 #include "config_move_dialog.h"
38 #include "config_dialog.h"
39 #include "static_text.h"
40 #include "check_box.h"
41 #include "dcpomatic_button.h"
42 #include "password_entry.h"
43 #include "lib/config.h"
44 #include "lib/ratio.h"
45 #include "lib/filter.h"
46 #include "lib/dcp_content_type.h"
49 #include "lib/cross.h"
50 #include "lib/exceptions.h"
51 #include <dcp/locale_convert.h>
52 #include <dcp/exceptions.h>
53 #include <dcp/certificate_chain.h>
54 #include <wx/stdpaths.h>
55 #include <wx/preferences.h>
56 #include <wx/spinctrl.h>
57 #include <wx/filepicker.h>
59 #include <boost/filesystem.hpp>
70 using std::shared_ptr;
71 using boost::function;
72 using boost::optional;
73 #if BOOST_VERSION >= 106100
74 using namespace boost::placeholders;
76 using dcp::locale_convert;
78 class FullGeneralPage : public GeneralPage
81 FullGeneralPage (wxSize panel_size, int border)
82 : GeneralPage (panel_size, border)
88 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
89 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
92 add_language_controls (table, r);
94 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
95 _master_encoding_threads = new wxSpinCtrl (_panel);
96 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
99 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
100 _server_encoding_threads = new wxSpinCtrl (_panel);
101 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
104 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
105 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, true);
106 table->Add (_config_file, wxGBPosition (r, 1));
109 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
110 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, true);
111 table->Add (_cinemas_file, wxGBPosition (r, 1));
112 Button* export_cinemas = new Button (_panel, _("Export..."));
113 table->Add (export_cinemas, wxGBPosition (r, 2));
116 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
117 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
118 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
122 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
123 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
126 add_update_controls (table, r);
128 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::config_file_changed, this));
129 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::cinemas_file_changed, this));
131 _master_encoding_threads->SetRange (1, 128);
132 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
133 _server_encoding_threads->SetRange (1, 128);
134 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
135 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
137 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
138 _analyse_ebur128->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::analyse_ebur128_changed, this));
140 _automatic_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::automatic_audio_analysis_changed, this));
143 void config_changed ()
145 Config* config = Config::instance ();
147 checked_set (_master_encoding_threads, config->master_encoding_threads ());
148 checked_set (_server_encoding_threads, config->server_encoding_threads ());
149 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
150 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
152 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
153 checked_set (_config_file, config->config_file());
154 checked_set (_cinemas_file, config->cinemas_file());
156 GeneralPage::config_changed ();
159 void export_cinemas_file ()
161 wxFileDialog* d = new wxFileDialog (
162 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT ("XML files (*.xml)|*.xml"),
163 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
166 if (d->ShowModal () == wxID_OK) {
167 boost::filesystem::copy_file (Config::instance()->cinemas_file(), wx_to_std(d->GetPath()));
172 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
173 void analyse_ebur128_changed ()
175 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
179 void automatic_audio_analysis_changed ()
181 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
184 void master_encoding_threads_changed ()
186 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue ());
189 void server_encoding_threads_changed ()
191 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue ());
194 void config_file_changed ()
196 Config* config = Config::instance();
197 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
198 if (new_file == config->config_file()) {
201 bool copy_and_link = true;
202 if (boost::filesystem::exists(new_file)) {
203 ConfigMoveDialog* d = new ConfigMoveDialog (_panel, new_file);
204 if (d->ShowModal() == wxID_OK) {
205 copy_and_link = false;
212 if (new_file != config->config_file()) {
213 config->copy_and_link (new_file);
216 config->link (new_file);
220 void cinemas_file_changed ()
222 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
225 wxSpinCtrl* _master_encoding_threads;
226 wxSpinCtrl* _server_encoding_threads;
227 FilePickerCtrl* _config_file;
228 FilePickerCtrl* _cinemas_file;
229 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
230 wxCheckBox* _analyse_ebur128;
232 wxCheckBox* _automatic_audio_analysis;
235 class DefaultsPage : public Page
238 DefaultsPage (wxSize panel_size, int border)
239 : Page (panel_size, border)
242 wxString GetName () const
244 return _("Defaults");
248 wxBitmap GetLargeIcon () const
250 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
257 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
258 table->AddGrowableCol (1, 1);
259 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
262 add_label_to_sizer (table, _panel, _("Default duration of still images"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
263 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
264 _still_length = new wxSpinCtrl (_panel);
265 s->Add (_still_length);
266 add_label_to_sizer (s, _panel, _("s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
270 add_label_to_sizer (table, _panel, _("Default directory for new films"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
271 #ifdef DCPOMATIC_USE_OWN_PICKER
272 _directory = new DirPickerCtrl (_panel);
274 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
276 table->Add (_directory, 1, wxEXPAND);
278 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
279 _isdcf_metadata_button = new Button (_panel, _("Edit..."));
280 table->Add (_isdcf_metadata_button);
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 wxBoxSizer* 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 wxBoxSizer* 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 _isdcf_metadata_button->Bind (wxEVT_BUTTON, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
333 for (auto i: Ratio::containers()) {
334 _container->Append (std_to_wx(i->container_nickname()));
337 _container->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::container_changed, this));
339 for (auto i: DCPContentType::all()) {
340 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
343 setup_audio_channels_choice (_dcp_audio_channels, 2);
345 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
346 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
348 _j2k_bandwidth->SetRange (50, 250);
349 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
351 _audio_delay->SetRange (-1000, 1000);
352 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
354 _standard->Append (_("SMPTE"));
355 _standard->Append (_("Interop"));
356 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
359 void config_changed ()
361 Config* config = Config::instance ();
363 vector<Ratio const *> containers = Ratio::containers ();
364 for (size_t i = 0; i < containers.size(); ++i) {
365 if (containers[i] == config->default_container ()) {
366 _container->SetSelection (i);
370 vector<DCPContentType const *> const ct = DCPContentType::all ();
371 for (size_t i = 0; i < ct.size(); ++i) {
372 if (ct[i] == config->default_dcp_content_type ()) {
373 _dcp_content_type->SetSelection (i);
377 checked_set (_still_length, config->default_still_length ());
378 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
379 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
380 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
381 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
382 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
383 checked_set (_audio_delay, config->default_audio_delay ());
384 checked_set (_standard, config->default_interop() ? 1 : 0);
387 void j2k_bandwidth_changed ()
389 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
392 void audio_delay_changed ()
394 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
397 void dcp_audio_channels_changed ()
399 int const s = _dcp_audio_channels->GetSelection ();
400 if (s != wxNOT_FOUND) {
401 Config::instance()->set_default_dcp_audio_channels (
402 locale_convert<int> (string_client_data (_dcp_audio_channels->GetClientObject (s)))
407 void directory_changed ()
409 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
412 void kdm_directory_changed ()
414 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
417 void edit_isdcf_metadata_clicked ()
419 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
421 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
425 void still_length_changed ()
427 Config::instance()->set_default_still_length (_still_length->GetValue ());
430 void container_changed ()
432 vector<Ratio const *> ratio = Ratio::containers ();
433 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
436 void dcp_content_type_changed ()
438 vector<DCPContentType const *> ct = DCPContentType::all ();
439 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
442 void standard_changed ()
444 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
447 wxSpinCtrl* _j2k_bandwidth;
448 wxSpinCtrl* _audio_delay;
449 wxButton* _isdcf_metadata_button;
450 wxSpinCtrl* _still_length;
451 #ifdef DCPOMATIC_USE_OWN_PICKER
452 DirPickerCtrl* _directory;
453 DirPickerCtrl* _kdm_directory;
455 wxDirPickerCtrl* _directory;
456 wxDirPickerCtrl* _kdm_directory;
458 wxChoice* _container;
459 wxChoice* _dcp_content_type;
460 wxChoice* _dcp_audio_channels;
464 class EncodingServersPage : public Page
467 EncodingServersPage (wxSize panel_size, int border)
468 : Page (panel_size, border)
471 wxString GetName () const
477 wxBitmap GetLargeIcon () const
479 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
486 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
487 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
489 vector<EditableListColumn> columns;
490 columns.push_back (EditableListColumn(_("IP address / host name")));
491 _servers_list = new EditableList<string, ServerDialog> (
494 boost::bind (&Config::servers, Config::instance()),
495 boost::bind (&Config::set_servers, Config::instance(), _1),
496 boost::bind (&EncodingServersPage::server_column, this, _1)
499 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
501 _use_any_servers->Bind (wxEVT_CHECKBOX, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
504 void config_changed ()
506 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
507 _servers_list->refresh ();
510 void use_any_servers_changed ()
512 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
515 string server_column (string s)
520 wxCheckBox* _use_any_servers;
521 EditableList<string, ServerDialog>* _servers_list;
524 class TMSPage : public Page
527 TMSPage (wxSize panel_size, int border)
528 : Page (panel_size, border)
531 wxString GetName () const
537 wxBitmap GetLargeIcon () const
539 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
546 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
547 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
549 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
550 table->AddGrowableCol (1, 1);
551 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
553 add_label_to_sizer (table, _panel, _("Protocol"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
554 _tms_protocol = new wxChoice (_panel, wxID_ANY);
555 table->Add (_tms_protocol, 1, wxEXPAND);
557 add_label_to_sizer (table, _panel, _("IP address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
558 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
559 table->Add (_tms_ip, 1, wxEXPAND);
561 add_label_to_sizer (table, _panel, _("Target path"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
562 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
563 table->Add (_tms_path, 1, wxEXPAND);
565 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
566 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
567 table->Add (_tms_user, 1, wxEXPAND);
569 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
570 _tms_password = new PasswordEntry (_panel);
571 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
573 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
574 _tms_protocol->Append (_("FTP (for Dolby)"));
576 _upload->Bind (wxEVT_CHECKBOX, boost::bind(&TMSPage::upload_changed, this));
577 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
578 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
579 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
580 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
581 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
584 void config_changed ()
586 Config* config = Config::instance ();
588 checked_set (_upload, config->upload_after_make_dcp());
589 checked_set (_tms_protocol, static_cast<int>(config->tms_protocol()));
590 checked_set (_tms_ip, config->tms_ip ());
591 checked_set (_tms_path, config->tms_path ());
592 checked_set (_tms_user, config->tms_user ());
593 checked_set (_tms_password, config->tms_password ());
596 void upload_changed ()
598 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
601 void tms_protocol_changed ()
603 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
606 void tms_ip_changed ()
608 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
611 void tms_path_changed ()
613 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
616 void tms_user_changed ()
618 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
621 void tms_password_changed ()
623 Config::instance()->set_tms_password (_tms_password->get());
627 wxChoice* _tms_protocol;
629 wxTextCtrl* _tms_path;
630 wxTextCtrl* _tms_user;
631 PasswordEntry* _tms_password;
640 class EmailPage : public Page
643 EmailPage (wxSize panel_size, int border)
644 : Page (panel_size, border)
647 wxString GetName () const
653 wxBitmap GetLargeIcon () const
655 return wxBitmap ("email", wxBITMAP_TYPE_PNG_RESOURCE);
662 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
663 table->AddGrowableCol (1, 1);
664 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
666 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
668 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
669 _server = new wxTextCtrl (_panel, wxID_ANY);
670 s->Add (_server, 1, wxEXPAND | wxALL);
671 add_label_to_sizer (s, _panel, _("port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
672 _port = new wxSpinCtrl (_panel, wxID_ANY);
673 _port->SetRange (0, 65535);
675 add_label_to_sizer (s, _panel, _("protocol"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
676 _protocol = new wxChoice (_panel, wxID_ANY);
677 /* Make sure this matches the switches in config_changed and port_changed below */
678 _protocol->Append (_("Auto"));
679 _protocol->Append (_("Plain"));
680 _protocol->Append (_("STARTTLS"));
681 _protocol->Append (_("SSL"));
683 table->Add (s, 1, wxEXPAND | wxALL);
686 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
687 _user = new wxTextCtrl (_panel, wxID_ANY);
688 table->Add (_user, 1, wxEXPAND | wxALL);
690 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
691 _password = new PasswordEntry (_panel);
692 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
694 _server->Bind (wxEVT_TEXT, boost::bind (&EmailPage::server_changed, this));
695 _port->Bind (wxEVT_SPINCTRL, boost::bind (&EmailPage::port_changed, this));
696 _protocol->Bind (wxEVT_CHOICE, boost::bind (&EmailPage::protocol_changed, this));
697 _user->Bind (wxEVT_TEXT, boost::bind (&EmailPage::user_changed, this));
698 _password->Changed.connect (boost::bind (&EmailPage::password_changed, this));
701 void config_changed ()
703 auto config = Config::instance ();
705 checked_set (_server, config->mail_server ());
706 checked_set (_port, config->mail_port ());
707 switch (config->mail_protocol()) {
708 case EmailProtocol::AUTO:
709 checked_set (_protocol, 0);
711 case EmailProtocol::PLAIN:
712 checked_set (_protocol, 1);
714 case EmailProtocol::STARTTLS:
715 checked_set (_protocol, 2);
717 case EmailProtocol::SSL:
718 checked_set (_protocol, 3);
721 checked_set (_user, config->mail_user ());
722 checked_set (_password, config->mail_password());
725 void server_changed ()
727 Config::instance()->set_mail_server (wx_to_std (_server->GetValue ()));
732 Config::instance()->set_mail_port (_port->GetValue ());
735 void protocol_changed ()
737 switch (_protocol->GetSelection()) {
739 Config::instance()->set_mail_protocol(EmailProtocol::AUTO);
742 Config::instance()->set_mail_protocol(EmailProtocol::PLAIN);
745 Config::instance()->set_mail_protocol(EmailProtocol::STARTTLS);
748 Config::instance()->set_mail_protocol(EmailProtocol::SSL);
755 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
758 void password_changed ()
760 Config::instance()->set_mail_password(_password->get());
767 PasswordEntry* _password;
770 class KDMEmailPage : public Page
774 KDMEmailPage (wxSize panel_size, int border)
776 /* We have to force both width and height of this one */
777 : Page (wxSize (panel_size.GetWidth(), 128), border)
779 : Page (panel_size, border)
783 wxString GetName () const
785 return _("KDM Email");
789 wxBitmap GetLargeIcon () const
791 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
798 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
799 table->AddGrowableCol (1, 1);
800 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
802 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
803 _subject = new wxTextCtrl (_panel, wxID_ANY);
804 table->Add (_subject, 1, wxEXPAND | wxALL);
806 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
807 _from = new wxTextCtrl (_panel, wxID_ANY);
808 table->Add (_from, 1, wxEXPAND | wxALL);
810 vector<EditableListColumn> columns;
811 columns.push_back (EditableListColumn(_("Address")));
812 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
813 _cc = new EditableList<string, EmailDialog> (
816 bind (&Config::kdm_cc, Config::instance()),
817 bind (&Config::set_kdm_cc, Config::instance(), _1),
820 table->Add (_cc, 1, wxEXPAND | wxALL);
822 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
823 _bcc = new wxTextCtrl (_panel, wxID_ANY);
824 table->Add (_bcc, 1, wxEXPAND | wxALL);
826 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
827 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
829 _reset_email = new Button (_panel, _("Reset to default subject and text"));
830 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
834 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
835 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
836 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
837 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
838 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
841 void config_changed ()
843 Config* config = Config::instance ();
845 checked_set (_subject, config->kdm_subject ());
846 checked_set (_from, config->kdm_from ());
847 checked_set (_bcc, config->kdm_bcc ());
848 checked_set (_email, Config::instance()->kdm_email ());
851 void kdm_subject_changed ()
853 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
856 void kdm_from_changed ()
858 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
861 void kdm_bcc_changed ()
863 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
866 void kdm_email_changed ()
868 if (_email->GetValue().IsEmpty ()) {
869 /* Sometimes we get sent an erroneous notification that the email
870 is empty; I don't know why.
874 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
879 Config::instance()->reset_kdm_email ();
880 checked_set (_email, Config::instance()->kdm_email ());
883 wxTextCtrl* _subject;
885 EditableList<string, EmailDialog>* _cc;
888 wxButton* _reset_email;
891 class NotificationsPage : public Page
894 NotificationsPage (wxSize panel_size, int border)
896 /* We have to force both width and height of this one */
897 : Page (wxSize (panel_size.GetWidth(), 128), border)
899 : Page (panel_size, border)
903 wxString GetName () const
905 return _("Notifications");
909 wxBitmap GetLargeIcon () const
911 return wxBitmap ("notifications", wxBITMAP_TYPE_PNG_RESOURCE);
918 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
919 table->AddGrowableCol (1, 1);
920 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
922 _enable_message_box = new CheckBox (_panel, _("Message box"));
923 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
924 table->AddSpacer (0);
926 _enable_email = new CheckBox (_panel, _("Email"));
927 table->Add (_enable_email, 1, wxEXPAND | wxALL);
928 table->AddSpacer (0);
930 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
931 _subject = new wxTextCtrl (_panel, wxID_ANY);
932 table->Add (_subject, 1, wxEXPAND | wxALL);
934 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
935 _from = new wxTextCtrl (_panel, wxID_ANY);
936 table->Add (_from, 1, wxEXPAND | wxALL);
938 add_label_to_sizer (table, _panel, _("To address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
939 _to = new wxTextCtrl (_panel, wxID_ANY);
940 table->Add (_to, 1, wxEXPAND | wxALL);
942 vector<EditableListColumn> columns;
943 columns.push_back (EditableListColumn(_("Address")));
944 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
945 _cc = new EditableList<string, EmailDialog> (
948 bind (&Config::notification_cc, Config::instance()),
949 bind (&Config::set_notification_cc, Config::instance(), _1),
952 table->Add (_cc, 1, wxEXPAND | wxALL);
954 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
955 _bcc = new wxTextCtrl (_panel, wxID_ANY);
956 table->Add (_bcc, 1, wxEXPAND | wxALL);
958 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
959 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
961 _reset_email = new Button (_panel, _("Reset to default subject and text"));
962 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
966 _enable_message_box->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX));
967 _enable_email->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL));
969 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
970 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
971 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
972 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
973 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
974 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
976 update_sensitivity ();
979 void update_sensitivity ()
981 bool const s = _enable_email->GetValue();
988 _reset_email->Enable(s);
991 void config_changed ()
993 Config* config = Config::instance ();
995 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
996 checked_set (_enable_email, config->notification(Config::EMAIL));
997 checked_set (_subject, config->notification_subject ());
998 checked_set (_from, config->notification_from ());
999 checked_set (_to, config->notification_to ());
1000 checked_set (_bcc, config->notification_bcc ());
1001 checked_set (_email, Config::instance()->notification_email ());
1003 update_sensitivity ();
1006 void notification_subject_changed ()
1008 Config::instance()->set_notification_subject (wx_to_std (_subject->GetValue ()));
1011 void notification_from_changed ()
1013 Config::instance()->set_notification_from (wx_to_std (_from->GetValue ()));
1016 void notification_to_changed ()
1018 Config::instance()->set_notification_to (wx_to_std (_to->GetValue ()));
1021 void notification_bcc_changed ()
1023 Config::instance()->set_notification_bcc (wx_to_std (_bcc->GetValue ()));
1026 void notification_email_changed ()
1028 if (_email->GetValue().IsEmpty ()) {
1029 /* Sometimes we get sent an erroneous notification that the email
1030 is empty; I don't know why.
1034 Config::instance()->set_notification_email (wx_to_std (_email->GetValue ()));
1039 Config::instance()->reset_notification_email ();
1040 checked_set (_email, Config::instance()->notification_email ());
1043 void type_changed (wxCheckBox* b, Config::Notification n)
1045 Config::instance()->set_notification(n, b->GetValue());
1046 update_sensitivity ();
1049 wxCheckBox* _enable_message_box;
1050 wxCheckBox* _enable_email;
1052 wxTextCtrl* _subject;
1055 EditableList<string, EmailDialog>* _cc;
1058 wxButton* _reset_email;
1061 class CoverSheetPage : public Page
1065 CoverSheetPage (wxSize panel_size, int border)
1066 #ifdef DCPOMATIC_OSX
1067 /* We have to force both width and height of this one */
1068 : Page (wxSize (panel_size.GetWidth(), 128), border)
1070 : Page (panel_size, border)
1074 wxString GetName () const
1076 return _("Cover Sheet");
1079 #ifdef DCPOMATIC_OSX
1080 wxBitmap GetLargeIcon () const
1082 return wxBitmap ("cover_sheet", wxBITMAP_TYPE_PNG_RESOURCE);
1089 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1090 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1092 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1093 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1095 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1096 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1099 void config_changed ()
1101 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
1104 void cover_sheet_changed ()
1106 if (_cover_sheet->GetValue().IsEmpty ()) {
1107 /* Sometimes we get sent an erroneous notification that the cover sheet
1108 is empty; I don't know why.
1112 Config::instance()->set_cover_sheet (wx_to_std (_cover_sheet->GetValue ()));
1115 void reset_cover_sheet ()
1117 Config::instance()->reset_cover_sheet ();
1118 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
1121 wxTextCtrl* _cover_sheet;
1122 wxButton* _reset_cover_sheet;
1126 class IdentifiersPage : public Page
1129 IdentifiersPage (wxSize panel_size, int border)
1130 : Page (panel_size, border)
1133 wxString GetName () const
1135 return _("Identifiers");
1138 #ifdef DCPOMATIC_OSX
1139 wxBitmap GetLargeIcon () const
1141 return wxBitmap ("identifiers", wxBITMAP_TYPE_PNG_RESOURCE);
1148 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1149 table->AddGrowableCol (1, 1);
1151 add_label_to_sizer (table, _panel, _("Issuer"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1152 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1153 _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."));
1154 table->Add (_issuer, 1, wxALL | wxEXPAND);
1156 add_label_to_sizer (table, _panel, _("Creator"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1157 _creator = new wxTextCtrl (_panel, wxID_ANY);
1158 _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."));
1159 table->Add (_creator, 1, wxALL | wxEXPAND);
1161 add_label_to_sizer (table, _panel, _("Company name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1162 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1163 _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."));
1164 table->Add (_company_name, 1, wxALL | wxEXPAND);
1166 add_label_to_sizer (table, _panel, _("Product name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1167 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1168 _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."));
1169 table->Add (_product_name, 1, wxALL | wxEXPAND);
1171 add_label_to_sizer (table, _panel, _("Product version"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1172 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1173 _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."));
1174 table->Add (_product_version, 1, wxALL | wxEXPAND);
1176 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1177 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1178 _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."));
1179 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1181 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1183 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1184 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1185 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1186 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1187 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1188 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1191 void config_changed ()
1193 Config* config = Config::instance ();
1194 checked_set (_issuer, config->dcp_issuer ());
1195 checked_set (_creator, config->dcp_creator ());
1196 checked_set (_company_name, config->dcp_company_name ());
1197 checked_set (_product_name, config->dcp_product_name ());
1198 checked_set (_product_version, config->dcp_product_version ());
1199 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1202 void issuer_changed ()
1204 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
1207 void creator_changed ()
1209 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
1212 void company_name_changed ()
1214 Config::instance()->set_dcp_company_name (wx_to_std(_company_name->GetValue()));
1217 void product_name_changed ()
1219 Config::instance()->set_dcp_product_name (wx_to_std(_product_name->GetValue()));
1222 void product_version_changed ()
1224 Config::instance()->set_dcp_product_version (wx_to_std(_product_version->GetValue()));
1227 void j2k_comment_changed ()
1229 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1232 wxTextCtrl* _issuer;
1233 wxTextCtrl* _creator;
1234 wxTextCtrl* _company_name;
1235 wxTextCtrl* _product_name;
1236 wxTextCtrl* _product_version;
1237 wxTextCtrl* _j2k_comment;
1241 /** @class AdvancedPage
1242 * @brief Advanced page of the preferences dialog.
1244 class AdvancedPage : public Page
1247 AdvancedPage (wxSize panel_size, int border)
1248 : Page (panel_size, border)
1249 , _maximum_j2k_bandwidth (0)
1250 , _allow_any_dcp_frame_rate (0)
1251 , _allow_any_container (0)
1252 , _show_experimental_audio_processors (0)
1253 , _only_servers_encode (0)
1258 , _log_debug_threed (0)
1259 , _log_debug_encode (0)
1260 , _log_debug_email (0)
1261 , _log_debug_video_view (0)
1262 , _log_debug_player (0)
1263 , _log_debug_audio_analysis (0)
1266 wxString GetName () const
1268 return _("Advanced");
1271 #ifdef DCPOMATIC_OSX
1272 wxBitmap GetLargeIcon () const
1274 return wxBitmap ("advanced", wxBITMAP_TYPE_PNG_RESOURCE);
1279 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1281 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1283 flags |= wxALIGN_RIGHT;
1286 wxStaticText* m = new StaticText (parent, text);
1287 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1292 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1293 table->AddGrowableCol (1, 1);
1294 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1297 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1298 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1299 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1300 s->Add (_maximum_j2k_bandwidth, 1);
1301 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1305 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1306 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1307 table->Add (_video_display_mode);
1309 wxStaticText* restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1310 wxFont font = restart->GetFont();
1311 font.SetStyle (wxFONTSTYLE_ITALIC);
1312 font.SetPointSize (font.GetPointSize() - 1);
1313 restart->SetFont (font);
1314 table->AddSpacer (0);
1316 _allow_any_dcp_frame_rate = new CheckBox (_panel, _("Allow any DCP frame rate"));
1317 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1318 table->AddSpacer (0);
1320 _allow_any_container = new CheckBox (_panel, _("Allow full-frame and non-standard container ratios"));
1321 table->Add (_allow_any_container, 1, wxEXPAND | wxALL);
1322 table->AddSpacer (0);
1324 restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to see all ratios)"), false);
1325 restart->SetFont (font);
1326 table->AddSpacer (0);
1328 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1329 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxALL);
1330 table->AddSpacer (0);
1332 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1333 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1334 table->AddSpacer (0);
1337 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1338 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1339 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1340 s->Add (_frames_in_memory_multiplier, 1);
1345 add_top_aligned_label_to_sizer (table, _panel, _("DCP metadata filename format"));
1346 dcp::NameFormat::Map titles;
1347 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1348 dcp::NameFormat::Map examples;
1349 examples['t'] = "cpl";
1350 _dcp_metadata_filename_format = new NameFormatEditor (
1351 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1353 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1357 add_top_aligned_label_to_sizer (table, _panel, _("DCP asset filename format"));
1358 dcp::NameFormat::Map titles;
1359 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1360 titles['r'] = wx_to_std (_("reel number"));
1361 titles['n'] = wx_to_std (_("number of reels"));
1362 titles['c'] = wx_to_std (_("content filename"));
1363 dcp::NameFormat::Map examples;
1364 examples['t'] = "j2c";
1365 examples['r'] = "1";
1366 examples['n'] = "4";
1367 examples['c'] = "myfile.mp4";
1368 _dcp_asset_filename_format = new NameFormatEditor (
1369 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1371 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1375 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1376 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1377 _log_general = new CheckBox (_panel, _("General"));
1378 t->Add (_log_general, 1, wxEXPAND | wxALL);
1379 _log_warning = new CheckBox (_panel, _("Warnings"));
1380 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1381 _log_error = new CheckBox (_panel, _("Errors"));
1382 t->Add (_log_error, 1, wxEXPAND | wxALL);
1383 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1384 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1385 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1386 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1387 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1388 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1389 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1390 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1391 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1392 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1393 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1394 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1395 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1396 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1397 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1398 table->Add (t, 0, wxALL, 6);
1401 #ifdef DCPOMATIC_WINDOWS
1402 _win32_console = new CheckBox (_panel, _("Open console window"));
1403 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1404 table->AddSpacer (0);
1407 _maximum_j2k_bandwidth->SetRange (1, 1000);
1408 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1409 _video_display_mode->Append (_("Simple (safer)"));
1410 _video_display_mode->Append (_("OpenGL (faster)"));
1411 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1412 _allow_any_dcp_frame_rate->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1413 _allow_any_container->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_container_changed, this));
1414 _show_experimental_audio_processors->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::show_experimental_audio_processors_changed, this));
1415 _only_servers_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1416 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1417 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1418 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1419 _log_general->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1420 _log_warning->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1421 _log_error->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1422 _log_timing->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1423 _log_debug_threed->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1424 _log_debug_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1425 _log_debug_email->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1426 _log_debug_video_view->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1427 _log_debug_player->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1428 _log_debug_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1429 #ifdef DCPOMATIC_WINDOWS
1430 _win32_console->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::win32_console_changed, this));
1434 void config_changed ()
1436 Config* config = Config::instance ();
1438 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1439 switch (config->video_view_type()) {
1440 case Config::VIDEO_VIEW_SIMPLE:
1441 checked_set (_video_display_mode, 0);
1443 case Config::VIDEO_VIEW_OPENGL:
1444 checked_set (_video_display_mode, 1);
1447 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1448 checked_set (_allow_any_container, config->allow_any_container ());
1449 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1450 checked_set (_only_servers_encode, config->only_servers_encode ());
1451 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1452 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1453 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1454 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1455 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREE_D);
1456 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1457 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1458 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1459 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1460 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1461 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1462 #ifdef DCPOMATIC_WINDOWS
1463 checked_set (_win32_console, config->win32_console());
1467 void maximum_j2k_bandwidth_changed ()
1469 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1472 void video_display_mode_changed ()
1474 if (_video_display_mode->GetSelection() == 0) {
1475 Config::instance()->set_video_view_type (Config::VIDEO_VIEW_SIMPLE);
1477 Config::instance()->set_video_view_type (Config::VIDEO_VIEW_OPENGL);
1481 void frames_in_memory_multiplier_changed ()
1483 Config::instance()->set_frames_in_memory_multiplier (_frames_in_memory_multiplier->GetValue());
1486 void allow_any_dcp_frame_rate_changed ()
1488 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1491 void allow_any_container_changed ()
1493 Config::instance()->set_allow_any_container (_allow_any_container->GetValue ());
1496 void show_experimental_audio_processors_changed ()
1498 Config::instance()->set_show_experimental_audio_processors (_show_experimental_audio_processors->GetValue ());
1501 void only_servers_encode_changed ()
1503 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1506 void dcp_metadata_filename_format_changed ()
1508 Config::instance()->set_dcp_metadata_filename_format (_dcp_metadata_filename_format->get ());
1511 void dcp_asset_filename_format_changed ()
1513 Config::instance()->set_dcp_asset_filename_format (_dcp_asset_filename_format->get ());
1519 if (_log_general->GetValue ()) {
1520 types |= LogEntry::TYPE_GENERAL;
1522 if (_log_warning->GetValue ()) {
1523 types |= LogEntry::TYPE_WARNING;
1525 if (_log_error->GetValue ()) {
1526 types |= LogEntry::TYPE_ERROR;
1528 if (_log_timing->GetValue ()) {
1529 types |= LogEntry::TYPE_TIMING;
1531 if (_log_debug_threed->GetValue ()) {
1532 types |= LogEntry::TYPE_DEBUG_THREE_D;
1534 if (_log_debug_encode->GetValue ()) {
1535 types |= LogEntry::TYPE_DEBUG_ENCODE;
1537 if (_log_debug_email->GetValue ()) {
1538 types |= LogEntry::TYPE_DEBUG_EMAIL;
1540 if (_log_debug_video_view->GetValue()) {
1541 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1543 if (_log_debug_player->GetValue()) {
1544 types |= LogEntry::TYPE_DEBUG_PLAYER;
1546 if (_log_debug_audio_analysis->GetValue()) {
1547 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1549 Config::instance()->set_log_types (types);
1552 #ifdef DCPOMATIC_WINDOWS
1553 void win32_console_changed ()
1555 Config::instance()->set_win32_console (_win32_console->GetValue ());
1559 wxSpinCtrl* _maximum_j2k_bandwidth;
1560 wxChoice* _video_display_mode;
1561 wxSpinCtrl* _frames_in_memory_multiplier;
1562 wxCheckBox* _allow_any_dcp_frame_rate;
1563 wxCheckBox* _allow_any_container;
1564 wxCheckBox* _show_experimental_audio_processors;
1565 wxCheckBox* _only_servers_encode;
1566 NameFormatEditor* _dcp_metadata_filename_format;
1567 NameFormatEditor* _dcp_asset_filename_format;
1568 wxCheckBox* _log_general;
1569 wxCheckBox* _log_warning;
1570 wxCheckBox* _log_error;
1571 wxCheckBox* _log_timing;
1572 wxCheckBox* _log_debug_threed;
1573 wxCheckBox* _log_debug_encode;
1574 wxCheckBox* _log_debug_email;
1575 wxCheckBox* _log_debug_video_view;
1576 wxCheckBox* _log_debug_player;
1577 wxCheckBox* _log_debug_audio_analysis;
1578 #ifdef DCPOMATIC_WINDOWS
1579 wxCheckBox* _win32_console;
1583 wxPreferencesEditor*
1584 create_full_config_dialog ()
1586 wxPreferencesEditor* e = new wxPreferencesEditor ();
1588 #ifdef DCPOMATIC_OSX
1589 /* Width that we force some of the config panels to be on OSX so that
1590 the containing window doesn't shrink too much when we select those panels.
1591 This is obviously an unpleasant hack.
1593 wxSize ps = wxSize (700, -1);
1594 int const border = 16;
1596 wxSize ps = wxSize (-1, -1);
1597 int const border = 8;
1600 e->AddPage (new FullGeneralPage (ps, border));
1601 e->AddPage (new SoundPage (ps, border));
1602 e->AddPage (new DefaultsPage (ps, border));
1603 e->AddPage (new EncodingServersPage (ps, border));
1604 e->AddPage (new KeysPage (ps, border));
1605 e->AddPage (new TMSPage (ps, border));
1606 e->AddPage (new EmailPage (ps, border));
1607 e->AddPage (new KDMEmailPage (ps, border));
1608 e->AddPage (new NotificationsPage (ps, border));
1609 e->AddPage (new CoverSheetPage (ps, border));
1610 e->AddPage (new IdentifiersPage (ps, border));
1611 e->AddPage (new AdvancedPage (ps, border));