2 Copyright (C) 2012-2017 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 "lib/config.h"
40 #include "lib/ratio.h"
41 #include "lib/filter.h"
42 #include "lib/dcp_content_type.h"
45 #include "lib/cross.h"
46 #include "lib/exceptions.h"
47 #include <dcp/locale_convert.h>
48 #include <dcp/exceptions.h>
49 #include <dcp/certificate_chain.h>
50 #include <wx/stdpaths.h>
51 #include <wx/preferences.h>
52 #include <wx/spinctrl.h>
53 #include <wx/filepicker.h>
55 #include <boost/filesystem.hpp>
56 #include <boost/foreach.hpp>
67 using boost::shared_ptr;
68 using boost::function;
69 using boost::optional;
70 using dcp::locale_convert;
72 class FullGeneralPage : public GeneralPage
75 FullGeneralPage (wxSize panel_size, int border)
76 : GeneralPage (panel_size, border)
82 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
83 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
86 add_language_controls (table, r);
88 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
89 _master_encoding_threads = new wxSpinCtrl (_panel);
90 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
93 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
94 _server_encoding_threads = new wxSpinCtrl (_panel);
95 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
98 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
99 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true);
100 table->Add (_config_file, wxGBPosition (r, 1));
103 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
104 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true);
105 table->Add (_cinemas_file, wxGBPosition (r, 1));
108 add_play_sound_controls (table, r);
110 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
111 _analyse_ebur128 = new wxCheckBox (_panel, wxID_ANY, _("Find integrated loudness, true peak and loudness range when analysing audio"));
112 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
116 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
117 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
120 add_update_controls (table, r);
122 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
123 bottom_table->AddGrowableCol (1, 1);
125 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
126 _issuer = new wxTextCtrl (_panel, wxID_ANY);
127 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
129 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
130 _creator = new wxTextCtrl (_panel, wxID_ANY);
131 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
133 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
136 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::config_file_changed, this));
137 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::cinemas_file_changed, this));
139 _master_encoding_threads->SetRange (1, 128);
140 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
141 _server_encoding_threads->SetRange (1, 128);
142 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
144 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
145 _analyse_ebur128->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::analyse_ebur128_changed, this));
147 _automatic_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::automatic_audio_analysis_changed, this));
149 _issuer->Bind (wxEVT_TEXT, boost::bind (&FullGeneralPage::issuer_changed, this));
150 _creator->Bind (wxEVT_TEXT, boost::bind (&FullGeneralPage::creator_changed, this));
153 void config_changed ()
155 Config* config = Config::instance ();
157 checked_set (_master_encoding_threads, config->master_encoding_threads ());
158 checked_set (_server_encoding_threads, config->server_encoding_threads ());
159 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
160 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
162 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
163 checked_set (_issuer, config->dcp_issuer ());
164 checked_set (_creator, config->dcp_creator ());
165 checked_set (_config_file, config->config_file());
166 checked_set (_cinemas_file, config->cinemas_file());
168 GeneralPage::config_changed ();
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 issuer_changed ()
196 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
199 void creator_changed ()
201 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
204 void config_file_changed ()
206 Config* config = Config::instance();
207 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
208 if (new_file == config->config_file()) {
211 bool copy_and_link = true;
212 if (boost::filesystem::exists(new_file)) {
213 ConfigMoveDialog* d = new ConfigMoveDialog (_panel, new_file);
214 if (d->ShowModal() == wxID_OK) {
215 copy_and_link = false;
222 if (new_file != config->config_file()) {
223 config->copy_and_link (new_file);
226 config->link (new_file);
230 void cinemas_file_changed ()
232 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
235 wxSpinCtrl* _master_encoding_threads;
236 wxSpinCtrl* _server_encoding_threads;
237 FilePickerCtrl* _config_file;
238 FilePickerCtrl* _cinemas_file;
239 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
240 wxCheckBox* _analyse_ebur128;
242 wxCheckBox* _automatic_audio_analysis;
244 wxTextCtrl* _creator;
247 class DefaultsPage : public StandardPage
250 DefaultsPage (wxSize panel_size, int border)
251 : StandardPage (panel_size, border)
254 wxString GetName () const
256 return _("Defaults");
260 wxBitmap GetLargeIcon () const
262 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
269 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
270 table->AddGrowableCol (1, 1);
271 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
274 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
275 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
276 _still_length = new wxSpinCtrl (_panel);
277 s->Add (_still_length);
278 add_label_to_sizer (s, _panel, _("s"), false);
282 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
283 #ifdef DCPOMATIC_USE_OWN_PICKER
284 _directory = new DirPickerCtrl (_panel);
286 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
288 table->Add (_directory, 1, wxEXPAND);
290 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
291 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
292 table->Add (_isdcf_metadata_button);
294 add_label_to_sizer (table, _panel, _("Default container"), true);
295 _container = new wxChoice (_panel, wxID_ANY);
296 table->Add (_container);
298 add_label_to_sizer (table, _panel, _("Default scale-to"), true);
299 _scale_to = new wxChoice (_panel, wxID_ANY);
300 table->Add (_scale_to);
302 add_label_to_sizer (table, _panel, _("Default content type"), true);
303 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
304 table->Add (_dcp_content_type);
306 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true);
307 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
308 table->Add (_dcp_audio_channels);
311 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
312 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
313 _j2k_bandwidth = new wxSpinCtrl (_panel);
314 s->Add (_j2k_bandwidth);
315 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
320 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
321 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
322 _audio_delay = new wxSpinCtrl (_panel);
323 s->Add (_audio_delay);
324 add_label_to_sizer (s, _panel, _("ms"), false);
328 add_label_to_sizer (table, _panel, _("Default standard"), true);
329 _standard = new wxChoice (_panel, wxID_ANY);
330 table->Add (_standard);
332 add_label_to_sizer (table, _panel, _("Default KDM directory"), true);
333 #ifdef DCPOMATIC_USE_OWN_PICKER
334 _kdm_directory = new DirPickerCtrl (_panel);
336 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
338 table->Add (_kdm_directory, 1, wxEXPAND);
340 _still_length->SetRange (1, 3600);
341 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
343 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
344 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
346 _isdcf_metadata_button->Bind (wxEVT_BUTTON, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
348 BOOST_FOREACH (Ratio const * i, Ratio::containers()) {
349 _container->Append (std_to_wx(i->container_nickname()));
352 _container->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::container_changed, this));
354 _scale_to->Append (_("Guess from content"));
356 BOOST_FOREACH (Ratio const * i, Ratio::all()) {
357 _scale_to->Append (std_to_wx(i->image_nickname()));
360 _scale_to->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::scale_to_changed, this));
362 BOOST_FOREACH (DCPContentType const * i, DCPContentType::all()) {
363 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
366 setup_audio_channels_choice (_dcp_audio_channels, 2);
368 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
369 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
371 _j2k_bandwidth->SetRange (50, 250);
372 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
374 _audio_delay->SetRange (-1000, 1000);
375 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
377 _standard->Append (_("SMPTE"));
378 _standard->Append (_("Interop"));
379 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
382 void config_changed ()
384 Config* config = Config::instance ();
386 vector<Ratio const *> containers = Ratio::containers ();
387 for (size_t i = 0; i < containers.size(); ++i) {
388 if (containers[i] == config->default_container ()) {
389 _container->SetSelection (i);
393 vector<Ratio const *> ratios = Ratio::all ();
394 for (size_t i = 0; i < ratios.size(); ++i) {
395 if (ratios[i] == config->default_scale_to ()) {
396 _scale_to->SetSelection (i + 1);
400 if (!config->default_scale_to()) {
401 _scale_to->SetSelection (0);
404 vector<DCPContentType const *> const ct = DCPContentType::all ();
405 for (size_t i = 0; i < ct.size(); ++i) {
406 if (ct[i] == config->default_dcp_content_type ()) {
407 _dcp_content_type->SetSelection (i);
411 checked_set (_still_length, config->default_still_length ());
412 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
413 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
414 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
415 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
416 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
417 checked_set (_audio_delay, config->default_audio_delay ());
418 checked_set (_standard, config->default_interop() ? 1 : 0);
421 void j2k_bandwidth_changed ()
423 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
426 void audio_delay_changed ()
428 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
431 void dcp_audio_channels_changed ()
433 int const s = _dcp_audio_channels->GetSelection ();
434 if (s != wxNOT_FOUND) {
435 Config::instance()->set_default_dcp_audio_channels (
436 locale_convert<int> (string_client_data (_dcp_audio_channels->GetClientObject (s)))
441 void directory_changed ()
443 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
446 void kdm_directory_changed ()
448 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
451 void edit_isdcf_metadata_clicked ()
453 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
455 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
459 void still_length_changed ()
461 Config::instance()->set_default_still_length (_still_length->GetValue ());
464 void container_changed ()
466 vector<Ratio const *> ratio = Ratio::containers ();
467 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
470 void scale_to_changed ()
472 int const s = _scale_to->GetSelection ();
474 Config::instance()->set_default_scale_to (0);
476 vector<Ratio const *> ratio = Ratio::all ();
477 Config::instance()->set_default_scale_to (ratio[s - 1]);
481 void dcp_content_type_changed ()
483 vector<DCPContentType const *> ct = DCPContentType::all ();
484 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
487 void standard_changed ()
489 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
492 wxSpinCtrl* _j2k_bandwidth;
493 wxSpinCtrl* _audio_delay;
494 wxButton* _isdcf_metadata_button;
495 wxSpinCtrl* _still_length;
496 #ifdef DCPOMATIC_USE_OWN_PICKER
497 DirPickerCtrl* _directory;
498 DirPickerCtrl* _kdm_directory;
500 wxDirPickerCtrl* _directory;
501 wxDirPickerCtrl* _kdm_directory;
503 wxChoice* _container;
505 wxChoice* _dcp_content_type;
506 wxChoice* _dcp_audio_channels;
510 class EncodingServersPage : public StandardPage
513 EncodingServersPage (wxSize panel_size, int border)
514 : StandardPage (panel_size, border)
517 wxString GetName () const
523 wxBitmap GetLargeIcon () const
525 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
532 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
533 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
535 vector<string> columns;
536 columns.push_back (wx_to_std (_("IP address / host name")));
537 _servers_list = new EditableList<string, ServerDialog> (
540 boost::bind (&Config::servers, Config::instance()),
541 boost::bind (&Config::set_servers, Config::instance(), _1),
542 boost::bind (&EncodingServersPage::server_column, this, _1)
545 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
547 _use_any_servers->Bind (wxEVT_CHECKBOX, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
550 void config_changed ()
552 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
553 _servers_list->refresh ();
556 void use_any_servers_changed ()
558 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
561 string server_column (string s)
566 wxCheckBox* _use_any_servers;
567 EditableList<string, ServerDialog>* _servers_list;
570 class TMSPage : public StandardPage
573 TMSPage (wxSize panel_size, int border)
574 : StandardPage (panel_size, border)
577 wxString GetName () const
583 wxBitmap GetLargeIcon () const
585 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
592 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
593 table->AddGrowableCol (1, 1);
594 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
596 add_label_to_sizer (table, _panel, _("Protocol"), true);
597 _tms_protocol = new wxChoice (_panel, wxID_ANY);
598 table->Add (_tms_protocol, 1, wxEXPAND);
600 add_label_to_sizer (table, _panel, _("IP address"), true);
601 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
602 table->Add (_tms_ip, 1, wxEXPAND);
604 add_label_to_sizer (table, _panel, _("Target path"), true);
605 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
606 table->Add (_tms_path, 1, wxEXPAND);
608 add_label_to_sizer (table, _panel, _("User name"), true);
609 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
610 table->Add (_tms_user, 1, wxEXPAND);
612 add_label_to_sizer (table, _panel, _("Password"), true);
613 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
614 table->Add (_tms_password, 1, wxEXPAND);
616 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
617 _tms_protocol->Append (_("FTP (for Dolby)"));
619 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
620 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
621 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
622 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
623 _tms_password->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_password_changed, this));
626 void config_changed ()
628 Config* config = Config::instance ();
630 checked_set (_tms_protocol, config->tms_protocol ());
631 checked_set (_tms_ip, config->tms_ip ());
632 checked_set (_tms_path, config->tms_path ());
633 checked_set (_tms_user, config->tms_user ());
634 checked_set (_tms_password, config->tms_password ());
637 void tms_protocol_changed ()
639 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
642 void tms_ip_changed ()
644 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
647 void tms_path_changed ()
649 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
652 void tms_user_changed ()
654 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
657 void tms_password_changed ()
659 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
662 wxChoice* _tms_protocol;
664 wxTextCtrl* _tms_path;
665 wxTextCtrl* _tms_user;
666 wxTextCtrl* _tms_password;
675 class KDMEmailPage : public StandardPage
679 KDMEmailPage (wxSize panel_size, int border)
681 /* We have to force both width and height of this one */
682 : StandardPage (wxSize (480, 128), border)
684 : StandardPage (panel_size, border)
688 wxString GetName () const
690 return _("KDM Email");
694 wxBitmap GetLargeIcon () const
696 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
703 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
704 table->AddGrowableCol (1, 1);
705 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
707 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
709 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
710 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
711 s->Add (_mail_server, 1, wxEXPAND | wxALL);
712 add_label_to_sizer (s, _panel, _("port"), false);
713 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
714 _mail_port->SetRange (0, 65535);
716 table->Add (s, 1, wxEXPAND | wxALL);
719 add_label_to_sizer (table, _panel, _("Mail user name"), true);
720 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
721 table->Add (_mail_user, 1, wxEXPAND | wxALL);
723 add_label_to_sizer (table, _panel, _("Mail password"), true);
724 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
725 table->Add (_mail_password, 1, wxEXPAND | wxALL);
727 add_label_to_sizer (table, _panel, _("Subject"), true);
728 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
729 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
731 add_label_to_sizer (table, _panel, _("From address"), true);
732 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
733 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
735 vector<string> columns;
736 columns.push_back (wx_to_std (_("Address")));
737 add_label_to_sizer (table, _panel, _("CC addresses"), true);
738 _kdm_cc = new EditableList<string, EmailDialog> (
741 bind (&Config::kdm_cc, Config::instance()),
742 bind (&Config::set_kdm_cc, Config::instance(), _1),
745 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
747 add_label_to_sizer (table, _panel, _("BCC address"), true);
748 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
749 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
751 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
752 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
754 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
755 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
759 _mail_server->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::mail_server_changed, this));
760 _mail_port->Bind (wxEVT_SPINCTRL, boost::bind (&KDMEmailPage::mail_port_changed, this));
761 _mail_user->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::mail_user_changed, this));
762 _mail_password->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::mail_password_changed, this));
763 _kdm_subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
764 _kdm_from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
765 _kdm_bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
766 _kdm_email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
767 _reset_kdm_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_kdm_email, this));
770 void config_changed ()
772 Config* config = Config::instance ();
774 checked_set (_mail_server, config->mail_server ());
775 checked_set (_mail_port, config->mail_port ());
776 checked_set (_mail_user, config->mail_user ());
777 checked_set (_mail_password, config->mail_password ());
778 checked_set (_kdm_subject, config->kdm_subject ());
779 checked_set (_kdm_from, config->kdm_from ());
780 checked_set (_kdm_bcc, config->kdm_bcc ());
781 checked_set (_kdm_email, Config::instance()->kdm_email ());
784 void mail_server_changed ()
786 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
789 void mail_port_changed ()
791 Config::instance()->set_mail_port (_mail_port->GetValue ());
794 void mail_user_changed ()
796 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
799 void mail_password_changed ()
801 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
804 void kdm_subject_changed ()
806 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
809 void kdm_from_changed ()
811 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
814 void kdm_bcc_changed ()
816 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
819 void kdm_email_changed ()
821 if (_kdm_email->GetValue().IsEmpty ()) {
822 /* Sometimes we get sent an erroneous notification that the email
823 is empty; I don't know why.
827 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
830 void reset_kdm_email ()
832 Config::instance()->reset_kdm_email ();
833 checked_set (_kdm_email, Config::instance()->kdm_email ());
836 wxTextCtrl* _mail_server;
837 wxSpinCtrl* _mail_port;
838 wxTextCtrl* _mail_user;
839 wxTextCtrl* _mail_password;
840 wxTextCtrl* _kdm_subject;
841 wxTextCtrl* _kdm_from;
842 EditableList<string, EmailDialog>* _kdm_cc;
843 wxTextCtrl* _kdm_bcc;
844 wxTextCtrl* _kdm_email;
845 wxButton* _reset_kdm_email;
848 class CoverSheetPage : public StandardPage
852 CoverSheetPage (wxSize panel_size, int border)
854 /* We have to force both width and height of this one */
855 : StandardPage (wxSize (480, 128), border)
857 : StandardPage (panel_size, border)
861 wxString GetName () const
863 return _("Cover Sheet");
867 wxBitmap GetLargeIcon () const
869 return wxBitmap ("cover_sheet", wxBITMAP_TYPE_PNG_RESOURCE);
876 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
877 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
879 _reset_cover_sheet = new wxButton (_panel, wxID_ANY, _("Reset to default text"));
880 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
882 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
883 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
886 void config_changed ()
888 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
891 void cover_sheet_changed ()
893 if (_cover_sheet->GetValue().IsEmpty ()) {
894 /* Sometimes we get sent an erroneous notification that the cover sheet
895 is empty; I don't know why.
899 Config::instance()->set_cover_sheet (wx_to_std (_cover_sheet->GetValue ()));
902 void reset_cover_sheet ()
904 Config::instance()->reset_cover_sheet ();
905 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
908 wxTextCtrl* _cover_sheet;
909 wxButton* _reset_cover_sheet;
913 /** @class AdvancedPage
914 * @brief Advanced page of the preferences dialog.
916 class AdvancedPage : public StockPage
919 AdvancedPage (wxSize panel_size, int border)
920 : StockPage (Kind_Advanced, panel_size, border)
921 , _maximum_j2k_bandwidth (0)
922 , _allow_any_dcp_frame_rate (0)
923 , _only_servers_encode (0)
928 , _log_debug_decode (0)
929 , _log_debug_encode (0)
930 , _log_debug_email (0)
934 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
936 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
938 flags |= wxALIGN_RIGHT;
941 wxStaticText* m = new wxStaticText (parent, wxID_ANY, text);
942 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
947 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
948 table->AddGrowableCol (1, 1);
949 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
952 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
953 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
954 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
955 s->Add (_maximum_j2k_bandwidth, 1);
956 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
960 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
961 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
962 table->AddSpacer (0);
964 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
965 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
966 table->AddSpacer (0);
969 add_top_aligned_label_to_sizer (table, _panel, _("DCP metadata filename format"));
970 dcp::NameFormat::Map titles;
971 titles['t'] = "type (cpl/pkl)";
972 dcp::NameFormat::Map examples;
973 examples['t'] = "cpl";
974 _dcp_metadata_filename_format = new NameFormatEditor (
975 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
977 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
981 add_top_aligned_label_to_sizer (table, _panel, _("DCP asset filename format"));
982 dcp::NameFormat::Map titles;
983 titles['t'] = "type (j2c/pcm/sub)";
984 titles['r'] = "reel number";
985 titles['n'] = "number of reels";
986 titles['c'] = "content filename";
987 dcp::NameFormat::Map examples;
988 examples['t'] = "j2c";
991 examples['c'] = "myfile.mp4";
992 _dcp_asset_filename_format = new NameFormatEditor (
993 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
995 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
999 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1000 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1001 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1002 t->Add (_log_general, 1, wxEXPAND | wxALL);
1003 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1004 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1005 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1006 t->Add (_log_error, 1, wxEXPAND | wxALL);
1007 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1008 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1009 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1010 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1011 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1012 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1013 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1014 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1015 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1016 table->Add (t, 0, wxALL, 6);
1019 #ifdef DCPOMATIC_WINDOWS
1020 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1021 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1022 table->AddSpacer (0);
1025 _maximum_j2k_bandwidth->SetRange (1, 1000);
1026 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1027 _allow_any_dcp_frame_rate->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1028 _only_servers_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1029 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1030 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1031 _log_general->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1032 _log_warning->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1033 _log_error->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1034 _log_timing->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1035 _log_debug_decode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1036 _log_debug_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1037 _log_debug_email->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1038 #ifdef DCPOMATIC_WINDOWS
1039 _win32_console->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::win32_console_changed, this));
1043 void config_changed ()
1045 Config* config = Config::instance ();
1047 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1048 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1049 checked_set (_only_servers_encode, config->only_servers_encode ());
1050 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1051 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1052 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1053 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1054 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1055 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1056 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1057 #ifdef DCPOMATIC_WINDOWS
1058 checked_set (_win32_console, config->win32_console());
1062 void maximum_j2k_bandwidth_changed ()
1064 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1067 void allow_any_dcp_frame_rate_changed ()
1069 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1072 void only_servers_encode_changed ()
1074 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1077 void dcp_metadata_filename_format_changed ()
1079 Config::instance()->set_dcp_metadata_filename_format (_dcp_metadata_filename_format->get ());
1082 void dcp_asset_filename_format_changed ()
1084 Config::instance()->set_dcp_asset_filename_format (_dcp_asset_filename_format->get ());
1090 if (_log_general->GetValue ()) {
1091 types |= LogEntry::TYPE_GENERAL;
1093 if (_log_warning->GetValue ()) {
1094 types |= LogEntry::TYPE_WARNING;
1096 if (_log_error->GetValue ()) {
1097 types |= LogEntry::TYPE_ERROR;
1099 if (_log_timing->GetValue ()) {
1100 types |= LogEntry::TYPE_TIMING;
1102 if (_log_debug_decode->GetValue ()) {
1103 types |= LogEntry::TYPE_DEBUG_DECODE;
1105 if (_log_debug_encode->GetValue ()) {
1106 types |= LogEntry::TYPE_DEBUG_ENCODE;
1108 if (_log_debug_email->GetValue ()) {
1109 types |= LogEntry::TYPE_DEBUG_EMAIL;
1111 Config::instance()->set_log_types (types);
1114 #ifdef DCPOMATIC_WINDOWS
1115 void win32_console_changed ()
1117 Config::instance()->set_win32_console (_win32_console->GetValue ());
1121 wxSpinCtrl* _maximum_j2k_bandwidth;
1122 wxCheckBox* _allow_any_dcp_frame_rate;
1123 wxCheckBox* _only_servers_encode;
1124 NameFormatEditor* _dcp_metadata_filename_format;
1125 NameFormatEditor* _dcp_asset_filename_format;
1126 wxCheckBox* _log_general;
1127 wxCheckBox* _log_warning;
1128 wxCheckBox* _log_error;
1129 wxCheckBox* _log_timing;
1130 wxCheckBox* _log_debug_decode;
1131 wxCheckBox* _log_debug_encode;
1132 wxCheckBox* _log_debug_email;
1133 #ifdef DCPOMATIC_WINDOWS
1134 wxCheckBox* _win32_console;
1138 wxPreferencesEditor*
1139 create_full_config_dialog ()
1141 wxPreferencesEditor* e = new wxPreferencesEditor ();
1143 #ifdef DCPOMATIC_OSX
1144 /* Width that we force some of the config panels to be on OSX so that
1145 the containing window doesn't shrink too much when we select those panels.
1146 This is obviously an unpleasant hack.
1148 wxSize ps = wxSize (520, -1);
1149 int const border = 16;
1151 wxSize ps = wxSize (-1, -1);
1152 int const border = 8;
1155 e->AddPage (new FullGeneralPage (ps, border));
1156 e->AddPage (new DefaultsPage (ps, border));
1157 e->AddPage (new EncodingServersPage (ps, border));
1158 e->AddPage (new KeysPage (ps, border, true));
1159 e->AddPage (new TMSPage (ps, border));
1160 e->AddPage (new KDMEmailPage (ps, border));
1161 e->AddPage (new CoverSheetPage (ps, border));
1162 e->AddPage (new AdvancedPage (ps, border));