2 Copyright (C) 2012-2016 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/config_dialog.cc
22 * @brief A dialogue to edit DCP-o-matic configuration.
25 #include "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 "lib/config.h"
36 #include "lib/ratio.h"
37 #include "lib/filter.h"
38 #include "lib/dcp_content_type.h"
41 #include "lib/raw_convert.h"
42 #include "lib/cross.h"
43 #include "lib/exceptions.h"
44 #include <dcp/exceptions.h>
45 #include <dcp/certificate_chain.h>
46 #include <wx/stdpaths.h>
47 #include <wx/preferences.h>
48 #include <wx/spinctrl.h>
49 #include <wx/filepicker.h>
50 #include <boost/filesystem.hpp>
51 #include <boost/foreach.hpp>
62 using boost::shared_ptr;
63 using boost::function;
64 using boost::optional;
69 Page (wxSize panel_size, int border)
72 , _panel_size (panel_size)
73 , _window_exists (false)
75 _config_connection = Config::instance()->Changed.connect (boost::bind (&Page::config_changed_wrapper, this));
81 wxWindow* create_window (wxWindow* parent)
83 _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size);
84 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
88 _window_exists = true;
91 _panel->Bind (wxEVT_DESTROY, boost::bind (&Page::window_destroyed, this));
100 virtual void config_changed () = 0;
101 virtual void setup () = 0;
103 void config_changed_wrapper ()
105 if (_window_exists) {
110 void window_destroyed ()
112 _window_exists = false;
116 boost::signals2::scoped_connection _config_connection;
120 class StockPage : public wxStockPreferencesPage, public Page
123 StockPage (Kind kind, wxSize panel_size, int border)
124 : wxStockPreferencesPage (kind)
125 , Page (panel_size, border)
128 wxWindow* CreateWindow (wxWindow* parent)
130 return create_window (parent);
134 class StandardPage : public wxPreferencesPage, public Page
137 StandardPage (wxSize panel_size, int border)
138 : Page (panel_size, border)
141 wxWindow* CreateWindow (wxWindow* parent)
143 return create_window (parent);
147 class GeneralPage : public StockPage
150 GeneralPage (wxSize panel_size, int border)
151 : StockPage (Kind_General, panel_size, border)
157 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
158 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
161 _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language"));
162 table->Add (_set_language, wxGBPosition (r, 0));
163 _language = new wxChoice (_panel, wxID_ANY);
164 vector<pair<string, string> > languages;
165 languages.push_back (make_pair ("Čeština", "cs_CZ"));
166 languages.push_back (make_pair ("汉语/漢語", "zh_CN"));
167 languages.push_back (make_pair ("Dansk", "da_DK"));
168 languages.push_back (make_pair ("Deutsch", "de_DE"));
169 languages.push_back (make_pair ("English", "en_GB"));
170 languages.push_back (make_pair ("Español", "es_ES"));
171 languages.push_back (make_pair ("Français", "fr_FR"));
172 languages.push_back (make_pair ("Italiano", "it_IT"));
173 languages.push_back (make_pair ("Nederlands", "nl_NL"));
174 languages.push_back (make_pair ("Русский", "ru_RU"));
175 languages.push_back (make_pair ("Polski", "pl_PL"));
176 languages.push_back (make_pair ("Português europeu", "pt_PT"));
177 languages.push_back (make_pair ("Português do Brasil", "pt_BR"));
178 languages.push_back (make_pair ("Svenska", "sv_SE"));
179 languages.push_back (make_pair ("Slovenský jazyk", "sk_SK"));
180 languages.push_back (make_pair ("українська мова", "uk_UA"));
181 checked_set (_language, languages);
182 table->Add (_language, wxGBPosition (r, 1));
185 wxStaticText* restart = add_label_to_sizer (
186 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
188 wxFont font = restart->GetFont();
189 font.SetStyle (wxFONTSTYLE_ITALIC);
190 font.SetPointSize (font.GetPointSize() - 1);
191 restart->SetFont (font);
194 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
195 _num_local_encoding_threads = new wxSpinCtrl (_panel);
196 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
199 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
200 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml");
201 table->Add (_cinemas_file, wxGBPosition (r, 1));
204 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
205 _analyse_ebur128 = new wxCheckBox (_panel, wxID_ANY, _("Find integrated loudness, true peak and loudness range when analysing audio"));
206 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
210 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
211 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
214 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
215 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
218 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
219 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
222 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
223 bottom_table->AddGrowableCol (1, 1);
225 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
226 _issuer = new wxTextCtrl (_panel, wxID_ANY);
227 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
229 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
230 _creator = new wxTextCtrl (_panel, wxID_ANY);
231 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
233 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
236 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
237 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
238 _cinemas_file->Bind (wxEVT_COMMAND_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
240 _num_local_encoding_threads->SetRange (1, 128);
241 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
243 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
244 _analyse_ebur128->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::analyse_ebur128_changed, this));
246 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
247 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
248 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
250 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
251 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
254 void config_changed ()
256 Config* config = Config::instance ();
258 checked_set (_set_language, static_cast<bool>(config->language()));
260 /* Backwards compatibility of config file */
262 map<string, string> compat_map;
263 compat_map["fr"] = "fr_FR";
264 compat_map["it"] = "it_IT";
265 compat_map["es"] = "es_ES";
266 compat_map["sv"] = "sv_SE";
267 compat_map["de"] = "de_DE";
268 compat_map["nl"] = "nl_NL";
269 compat_map["ru"] = "ru_RU";
270 compat_map["pl"] = "pl_PL";
271 compat_map["da"] = "da_DK";
272 compat_map["pt"] = "pt_PT";
273 compat_map["sk"] = "sk_SK";
274 compat_map["cs"] = "cs_CZ";
275 compat_map["uk"] = "uk_UA";
277 string lang = config->language().get_value_or ("en_GB");
278 if (compat_map.find (lang) != compat_map.end ()) {
279 lang = compat_map[lang];
282 checked_set (_language, lang);
284 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
285 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
286 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
288 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
289 checked_set (_check_for_updates, config->check_for_updates ());
290 checked_set (_check_for_test_updates, config->check_for_test_updates ());
291 checked_set (_issuer, config->dcp_issuer ());
292 checked_set (_creator, config->dcp_creator ());
293 checked_set (_cinemas_file, config->cinemas_file());
295 setup_sensitivity ();
298 void setup_sensitivity ()
300 _language->Enable (_set_language->GetValue ());
301 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
304 void set_language_changed ()
306 setup_sensitivity ();
307 if (_set_language->GetValue ()) {
310 Config::instance()->unset_language ();
314 void language_changed ()
316 int const sel = _language->GetSelection ();
318 Config::instance()->set_language (string_client_data (_language->GetClientObject (sel)));
320 Config::instance()->unset_language ();
324 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
325 void analyse_ebur128_changed ()
327 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
331 void automatic_audio_analysis_changed ()
333 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
336 void check_for_updates_changed ()
338 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
341 void check_for_test_updates_changed ()
343 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
346 void num_local_encoding_threads_changed ()
348 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
351 void issuer_changed ()
353 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
356 void creator_changed ()
358 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
361 void cinemas_file_changed ()
363 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
366 wxCheckBox* _set_language;
368 wxSpinCtrl* _num_local_encoding_threads;
369 FilePickerCtrl* _cinemas_file;
370 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
371 wxCheckBox* _analyse_ebur128;
373 wxCheckBox* _automatic_audio_analysis;
374 wxCheckBox* _check_for_updates;
375 wxCheckBox* _check_for_test_updates;
377 wxTextCtrl* _creator;
380 class DefaultsPage : public StandardPage
383 DefaultsPage (wxSize panel_size, int border)
384 : StandardPage (panel_size, border)
387 wxString GetName () const
389 return _("Defaults");
393 wxBitmap GetLargeIcon () const
395 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
402 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
403 table->AddGrowableCol (1, 1);
404 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
407 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
408 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
409 _still_length = new wxSpinCtrl (_panel);
410 s->Add (_still_length);
411 add_label_to_sizer (s, _panel, _("s"), false);
415 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
416 #ifdef DCPOMATIC_USE_OWN_PICKER
417 _directory = new DirPickerCtrl (_panel);
419 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
421 table->Add (_directory, 1, wxEXPAND);
423 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
424 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
425 table->Add (_isdcf_metadata_button);
427 add_label_to_sizer (table, _panel, _("Default container"), true);
428 _container = new wxChoice (_panel, wxID_ANY);
429 table->Add (_container);
431 add_label_to_sizer (table, _panel, _("Default content type"), true);
432 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
433 table->Add (_dcp_content_type);
436 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
437 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
438 _j2k_bandwidth = new wxSpinCtrl (_panel);
439 s->Add (_j2k_bandwidth);
440 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
445 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
446 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
447 _audio_delay = new wxSpinCtrl (_panel);
448 s->Add (_audio_delay);
449 add_label_to_sizer (s, _panel, _("ms"), false);
453 add_label_to_sizer (table, _panel, _("Default standard"), true);
454 _standard = new wxChoice (_panel, wxID_ANY);
455 table->Add (_standard);
457 _still_length->SetRange (1, 3600);
458 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
460 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
462 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
464 vector<Ratio const *> ratios = Ratio::all ();
465 for (size_t i = 0; i < ratios.size(); ++i) {
466 _container->Append (std_to_wx (ratios[i]->nickname ()));
469 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
471 vector<DCPContentType const *> const ct = DCPContentType::all ();
472 for (size_t i = 0; i < ct.size(); ++i) {
473 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
476 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
478 _j2k_bandwidth->SetRange (50, 250);
479 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
481 _audio_delay->SetRange (-1000, 1000);
482 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
484 _standard->Append (_("SMPTE"));
485 _standard->Append (_("Interop"));
486 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
489 void config_changed ()
491 Config* config = Config::instance ();
493 vector<Ratio const *> ratios = Ratio::all ();
494 for (size_t i = 0; i < ratios.size(); ++i) {
495 if (ratios[i] == config->default_container ()) {
496 _container->SetSelection (i);
500 vector<DCPContentType const *> const ct = DCPContentType::all ();
501 for (size_t i = 0; i < ct.size(); ++i) {
502 if (ct[i] == config->default_dcp_content_type ()) {
503 _dcp_content_type->SetSelection (i);
507 checked_set (_still_length, config->default_still_length ());
508 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
509 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
510 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
511 checked_set (_audio_delay, config->default_audio_delay ());
512 checked_set (_standard, config->default_interop() ? 1 : 0);
515 void j2k_bandwidth_changed ()
517 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
520 void audio_delay_changed ()
522 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
525 void directory_changed ()
527 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
530 void edit_isdcf_metadata_clicked ()
532 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
534 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
538 void still_length_changed ()
540 Config::instance()->set_default_still_length (_still_length->GetValue ());
543 void container_changed ()
545 vector<Ratio const *> ratio = Ratio::all ();
546 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
549 void dcp_content_type_changed ()
551 vector<DCPContentType const *> ct = DCPContentType::all ();
552 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
555 void standard_changed ()
557 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
560 wxSpinCtrl* _j2k_bandwidth;
561 wxSpinCtrl* _audio_delay;
562 wxButton* _isdcf_metadata_button;
563 wxSpinCtrl* _still_length;
564 #ifdef DCPOMATIC_USE_OWN_PICKER
565 DirPickerCtrl* _directory;
567 wxDirPickerCtrl* _directory;
569 wxChoice* _container;
570 wxChoice* _dcp_content_type;
574 class EncodingServersPage : public StandardPage
577 EncodingServersPage (wxSize panel_size, int border)
578 : StandardPage (panel_size, border)
581 wxString GetName () const
587 wxBitmap GetLargeIcon () const
589 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
596 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
597 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
599 vector<string> columns;
600 columns.push_back (wx_to_std (_("IP address / host name")));
601 _servers_list = new EditableList<string, ServerDialog> (
604 boost::bind (&Config::servers, Config::instance()),
605 boost::bind (&Config::set_servers, Config::instance(), _1),
606 boost::bind (&always_valid),
607 boost::bind (&EncodingServersPage::server_column, this, _1)
610 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
612 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
615 void config_changed ()
617 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
618 _servers_list->refresh ();
621 void use_any_servers_changed ()
623 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
626 string server_column (string s)
631 wxCheckBox* _use_any_servers;
632 EditableList<string, ServerDialog>* _servers_list;
635 class CertificateChainEditor : public wxPanel
638 CertificateChainEditor (
642 function<void (shared_ptr<dcp::CertificateChain>)> set,
643 function<shared_ptr<const dcp::CertificateChain> (void)> get
649 wxFont subheading_font (*wxNORMAL_FONT);
650 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
652 _sizer = new wxBoxSizer (wxVERTICAL);
655 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
656 m->SetFont (subheading_font);
657 _sizer->Add (m, 0, wxALL, border);
660 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
661 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
663 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
668 ip.SetText (_("Type"));
670 _certificates->InsertColumn (0, ip);
676 ip.SetText (_("Thumbprint"));
679 wxFont font = ip.GetFont ();
680 font.SetFamily (wxFONTFAMILY_TELETYPE);
683 _certificates->InsertColumn (1, ip);
686 certificates_sizer->Add (_certificates, 1, wxEXPAND);
689 wxSizer* s = new wxBoxSizer (wxVERTICAL);
690 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
691 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
692 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
693 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
694 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
695 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
696 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
699 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
700 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
703 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
704 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
705 wxFont font = _private_key->GetFont ();
706 font.SetFamily (wxFONTFAMILY_TELETYPE);
707 _private_key->SetFont (font);
708 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
709 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
710 table->Add (_load_private_key, wxGBPosition (r, 2));
711 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
712 table->Add (_export_private_key, wxGBPosition (r, 3));
715 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
716 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
717 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
718 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
721 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
722 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
723 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
724 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
725 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
726 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
727 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
728 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
730 SetSizerAndFit (_sizer);
733 void config_changed ()
735 _chain.reset (new dcp::CertificateChain (*_get().get ()));
737 update_certificate_list ();
738 update_private_key ();
739 update_sensitivity ();
742 void add_button (wxWindow* button)
744 _button_sizer->Add (button);
749 void add_certificate ()
751 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
753 if (d->ShowModal() == wxID_OK) {
755 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
756 if (c.extra_data ()) {
759 _("This file contains other certificates (or other data) after its first certificate. "
760 "Only the first certificate will be used.")
765 update_certificate_list ();
766 } catch (dcp::MiscError& e) {
767 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
773 update_sensitivity ();
776 void remove_certificate ()
778 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
783 _certificates->DeleteItem (i);
787 update_sensitivity ();
790 void export_certificate ()
792 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
797 wxFileDialog* d = new wxFileDialog (
798 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
799 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
802 dcp::CertificateChain::List all = _chain->root_to_leaf ();
803 dcp::CertificateChain::List::iterator j = all.begin ();
804 for (int k = 0; k < i; ++k) {
808 if (d->ShowModal () == wxID_OK) {
809 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
811 throw OpenFileError (wx_to_std (d->GetPath ()));
814 string const s = j->certificate (true);
815 fwrite (s.c_str(), 1, s.length(), f);
821 void update_certificate_list ()
823 _certificates->DeleteAllItems ();
825 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
826 BOOST_FOREACH (dcp::Certificate const & i, certs) {
829 _certificates->InsertItem (item);
830 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
833 _certificates->SetItem (n, 0, _("Root"));
834 } else if (n == (certs.size() - 1)) {
835 _certificates->SetItem (n, 0, _("Leaf"));
837 _certificates->SetItem (n, 0, _("Intermediate"));
844 void remake_certificates ()
846 shared_ptr<const dcp::CertificateChain> chain = _get ();
848 string subject_organization_name;
849 string subject_organizational_unit_name;
850 string root_common_name;
851 string intermediate_common_name;
852 string leaf_common_name;
854 dcp::CertificateChain::List all = chain->root_to_leaf ();
856 if (all.size() >= 1) {
858 subject_organization_name = chain->root().subject_organization_name ();
859 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
860 root_common_name = chain->root().subject_common_name ();
863 if (all.size() >= 2) {
865 leaf_common_name = chain->leaf().subject_common_name ();
868 if (all.size() >= 3) {
869 /* Have an intermediate */
870 dcp::CertificateChain::List::iterator i = all.begin ();
872 intermediate_common_name = i->subject_common_name ();
875 MakeChainDialog* d = new MakeChainDialog (
877 subject_organization_name,
878 subject_organizational_unit_name,
880 intermediate_common_name,
884 if (d->ShowModal () == wxID_OK) {
886 new dcp::CertificateChain (
889 d->organisational_unit (),
890 d->root_common_name (),
891 d->intermediate_common_name (),
892 d->leaf_common_name ()
897 update_certificate_list ();
898 update_private_key ();
904 void update_sensitivity ()
906 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
907 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
910 void update_private_key ()
912 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
916 void load_private_key ()
918 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
920 if (d->ShowModal() == wxID_OK) {
922 boost::filesystem::path p (wx_to_std (d->GetPath ()));
923 if (boost::filesystem::file_size (p) > 8192) {
926 wxString::Format (_("Could not read key file; file is too long (%s)"), std_to_wx (p.string ()))
931 _chain->set_key (dcp::file_to_string (p));
933 update_private_key ();
934 } catch (dcp::MiscError& e) {
935 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
941 update_sensitivity ();
944 void export_private_key ()
946 optional<string> key = _chain->key ();
951 wxFileDialog* d = new wxFileDialog (
952 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
953 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
956 if (d->ShowModal () == wxID_OK) {
957 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
959 throw OpenFileError (wx_to_std (d->GetPath ()));
962 string const s = _chain->key().get ();
963 fwrite (s.c_str(), 1, s.length(), f);
969 wxListCtrl* _certificates;
970 wxButton* _add_certificate;
971 wxButton* _export_certificate;
972 wxButton* _remove_certificate;
973 wxButton* _remake_certificates;
974 wxStaticText* _private_key;
975 wxButton* _load_private_key;
976 wxButton* _export_private_key;
978 wxBoxSizer* _button_sizer;
979 shared_ptr<dcp::CertificateChain> _chain;
980 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
981 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
984 class KeysPage : public StandardPage
987 KeysPage (wxSize panel_size, int border)
988 : StandardPage (panel_size, border)
991 wxString GetName () const
997 wxBitmap GetLargeIcon () const
999 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
1007 _signer = new CertificateChainEditor (
1008 _panel, _("Signing DCPs and KDMs"), _border,
1009 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
1010 boost::bind (&Config::signer_chain, Config::instance ())
1013 _panel->GetSizer()->Add (_signer);
1015 _decryption = new CertificateChainEditor (
1016 _panel, _("Decrypting DCPs"), _border,
1017 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1018 boost::bind (&Config::decryption_chain, Config::instance ())
1021 _panel->GetSizer()->Add (_decryption);
1023 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1024 _decryption->add_button (_export_decryption_certificate);
1026 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1029 void export_decryption_certificate ()
1031 wxFileDialog* d = new wxFileDialog (
1032 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1033 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1036 if (d->ShowModal () == wxID_OK) {
1037 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1039 throw OpenFileError (wx_to_std (d->GetPath ()));
1042 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1043 fwrite (s.c_str(), 1, s.length(), f);
1049 void config_changed ()
1051 _signer->config_changed ();
1052 _decryption->config_changed ();
1055 CertificateChainEditor* _signer;
1056 CertificateChainEditor* _decryption;
1057 wxButton* _export_decryption_certificate;
1060 class TMSPage : public StandardPage
1063 TMSPage (wxSize panel_size, int border)
1064 : StandardPage (panel_size, border)
1067 wxString GetName () const
1072 #ifdef DCPOMATIC_OSX
1073 wxBitmap GetLargeIcon () const
1075 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1082 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1083 table->AddGrowableCol (1, 1);
1084 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1086 add_label_to_sizer (table, _panel, _("Protocol"), true);
1087 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1088 table->Add (_tms_protocol, 1, wxEXPAND);
1090 add_label_to_sizer (table, _panel, _("IP address"), true);
1091 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1092 table->Add (_tms_ip, 1, wxEXPAND);
1094 add_label_to_sizer (table, _panel, _("Target path"), true);
1095 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1096 table->Add (_tms_path, 1, wxEXPAND);
1098 add_label_to_sizer (table, _panel, _("User name"), true);
1099 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1100 table->Add (_tms_user, 1, wxEXPAND);
1102 add_label_to_sizer (table, _panel, _("Password"), true);
1103 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1104 table->Add (_tms_password, 1, wxEXPAND);
1106 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1107 _tms_protocol->Append (_("FTP (for Dolby)"));
1109 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1110 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1111 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1112 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1113 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1116 void config_changed ()
1118 Config* config = Config::instance ();
1120 checked_set (_tms_protocol, config->tms_protocol ());
1121 checked_set (_tms_ip, config->tms_ip ());
1122 checked_set (_tms_path, config->tms_path ());
1123 checked_set (_tms_user, config->tms_user ());
1124 checked_set (_tms_password, config->tms_password ());
1127 void tms_protocol_changed ()
1129 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1132 void tms_ip_changed ()
1134 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1137 void tms_path_changed ()
1139 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1142 void tms_user_changed ()
1144 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1147 void tms_password_changed ()
1149 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1152 wxChoice* _tms_protocol;
1153 wxTextCtrl* _tms_ip;
1154 wxTextCtrl* _tms_path;
1155 wxTextCtrl* _tms_user;
1156 wxTextCtrl* _tms_password;
1165 class KDMEmailPage : public StandardPage
1169 KDMEmailPage (wxSize panel_size, int border)
1170 #ifdef DCPOMATIC_OSX
1171 /* We have to force both width and height of this one */
1172 : StandardPage (wxSize (480, 128), border)
1174 : StandardPage (panel_size, border)
1178 wxString GetName () const
1180 return _("KDM Email");
1183 #ifdef DCPOMATIC_OSX
1184 wxBitmap GetLargeIcon () const
1186 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1193 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1194 table->AddGrowableCol (1, 1);
1195 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1197 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1199 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1200 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1201 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1202 add_label_to_sizer (s, _panel, _("port"), false);
1203 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1204 _mail_port->SetRange (0, 65535);
1205 s->Add (_mail_port);
1206 table->Add (s, 1, wxEXPAND | wxALL);
1209 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1210 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1211 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1213 add_label_to_sizer (table, _panel, _("Mail password"), true);
1214 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1215 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1217 add_label_to_sizer (table, _panel, _("Subject"), true);
1218 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1219 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1221 add_label_to_sizer (table, _panel, _("From address"), true);
1222 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1223 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1225 vector<string> columns;
1226 columns.push_back (wx_to_std (_("Address")));
1227 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1228 _kdm_cc = new EditableList<string, EmailDialog> (
1231 bind (&Config::kdm_cc, Config::instance()),
1232 bind (&Config::set_kdm_cc, Config::instance(), _1),
1233 bind (&string_not_empty, _1),
1236 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1238 add_label_to_sizer (table, _panel, _("BCC address"), true);
1239 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1240 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1242 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1243 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1245 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1246 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1250 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1251 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1252 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1253 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1254 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1255 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1256 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1257 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1258 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1261 void config_changed ()
1263 Config* config = Config::instance ();
1265 checked_set (_mail_server, config->mail_server ());
1266 checked_set (_mail_port, config->mail_port ());
1267 checked_set (_mail_user, config->mail_user ());
1268 checked_set (_mail_password, config->mail_password ());
1269 checked_set (_kdm_subject, config->kdm_subject ());
1270 checked_set (_kdm_from, config->kdm_from ());
1271 checked_set (_kdm_bcc, config->kdm_bcc ());
1272 checked_set (_kdm_email, Config::instance()->kdm_email ());
1275 void mail_server_changed ()
1277 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1280 void mail_port_changed ()
1282 Config::instance()->set_mail_port (_mail_port->GetValue ());
1285 void mail_user_changed ()
1287 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1290 void mail_password_changed ()
1292 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1295 void kdm_subject_changed ()
1297 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1300 void kdm_from_changed ()
1302 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1305 void kdm_bcc_changed ()
1307 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1310 void kdm_email_changed ()
1312 if (_kdm_email->GetValue().IsEmpty ()) {
1313 /* Sometimes we get sent an erroneous notification that the email
1314 is empty; I don't know why.
1318 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1321 void reset_kdm_email ()
1323 Config::instance()->reset_kdm_email ();
1324 checked_set (_kdm_email, Config::instance()->kdm_email ());
1327 wxTextCtrl* _mail_server;
1328 wxSpinCtrl* _mail_port;
1329 wxTextCtrl* _mail_user;
1330 wxTextCtrl* _mail_password;
1331 wxTextCtrl* _kdm_subject;
1332 wxTextCtrl* _kdm_from;
1333 EditableList<string, EmailDialog>* _kdm_cc;
1334 wxTextCtrl* _kdm_bcc;
1335 wxTextCtrl* _kdm_email;
1336 wxButton* _reset_kdm_email;
1339 /** @class AdvancedPage
1340 * @brief Advanced page of the preferences dialog.
1342 class AdvancedPage : public StockPage
1345 AdvancedPage (wxSize panel_size, int border)
1346 : StockPage (Kind_Advanced, panel_size, border)
1347 , _maximum_j2k_bandwidth (0)
1348 , _allow_any_dcp_frame_rate (0)
1349 , _only_servers_encode (0)
1354 , _log_debug_decode (0)
1355 , _log_debug_encode (0)
1356 , _log_debug_email (0)
1362 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1363 table->AddGrowableCol (1, 1);
1364 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1367 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1368 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1369 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1370 s->Add (_maximum_j2k_bandwidth, 1);
1371 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1375 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1376 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1377 table->AddSpacer (0);
1379 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1380 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1381 table->AddSpacer (0);
1384 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1385 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1387 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1388 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1392 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1393 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1394 t->Add (_log_general, 1, wxEXPAND | wxALL);
1395 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1396 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1397 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1398 t->Add (_log_error, 1, wxEXPAND | wxALL);
1399 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1400 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1401 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1402 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1403 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1404 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1405 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1406 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1407 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1408 table->Add (t, 0, wxALL, 6);
1411 #ifdef DCPOMATIC_WINDOWS
1412 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1413 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1414 table->AddSpacer (0);
1417 _maximum_j2k_bandwidth->SetRange (1, 1000);
1418 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1419 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1420 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1421 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1422 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1423 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1424 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1425 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1426 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1427 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1428 #ifdef DCPOMATIC_WINDOWS
1429 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1433 void config_changed ()
1435 Config* config = Config::instance ();
1437 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1438 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1439 checked_set (_only_servers_encode, config->only_servers_encode ());
1440 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1441 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1442 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1443 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1444 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1445 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1446 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1447 #ifdef DCPOMATIC_WINDOWS
1448 checked_set (_win32_console, config->win32_console());
1452 void maximum_j2k_bandwidth_changed ()
1454 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1457 void allow_any_dcp_frame_rate_changed ()
1459 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1462 void only_servers_encode_changed ()
1464 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1470 if (_log_general->GetValue ()) {
1471 types |= LogEntry::TYPE_GENERAL;
1473 if (_log_warning->GetValue ()) {
1474 types |= LogEntry::TYPE_WARNING;
1476 if (_log_error->GetValue ()) {
1477 types |= LogEntry::TYPE_ERROR;
1479 if (_log_timing->GetValue ()) {
1480 types |= LogEntry::TYPE_TIMING;
1482 if (_log_debug_decode->GetValue ()) {
1483 types |= LogEntry::TYPE_DEBUG_DECODE;
1485 if (_log_debug_encode->GetValue ()) {
1486 types |= LogEntry::TYPE_DEBUG_ENCODE;
1488 if (_log_debug_email->GetValue ()) {
1489 types |= LogEntry::TYPE_DEBUG_EMAIL;
1491 Config::instance()->set_log_types (types);
1494 #ifdef DCPOMATIC_WINDOWS
1495 void win32_console_changed ()
1497 Config::instance()->set_win32_console (_win32_console->GetValue ());
1501 wxSpinCtrl* _maximum_j2k_bandwidth;
1502 wxCheckBox* _allow_any_dcp_frame_rate;
1503 wxCheckBox* _only_servers_encode;
1504 wxCheckBox* _log_general;
1505 wxCheckBox* _log_warning;
1506 wxCheckBox* _log_error;
1507 wxCheckBox* _log_timing;
1508 wxCheckBox* _log_debug_decode;
1509 wxCheckBox* _log_debug_encode;
1510 wxCheckBox* _log_debug_email;
1511 #ifdef DCPOMATIC_WINDOWS
1512 wxCheckBox* _win32_console;
1516 wxPreferencesEditor*
1517 create_config_dialog ()
1519 wxPreferencesEditor* e = new wxPreferencesEditor ();
1521 #ifdef DCPOMATIC_OSX
1522 /* Width that we force some of the config panels to be on OSX so that
1523 the containing window doesn't shrink too much when we select those panels.
1524 This is obviously an unpleasant hack.
1526 wxSize ps = wxSize (520, -1);
1527 int const border = 16;
1529 wxSize ps = wxSize (-1, -1);
1530 int const border = 8;
1533 e->AddPage (new GeneralPage (ps, border));
1534 e->AddPage (new DefaultsPage (ps, border));
1535 e->AddPage (new EncodingServersPage (ps, border));
1536 e->AddPage (new KeysPage (ps, border));
1537 e->AddPage (new TMSPage (ps, border));
1538 e->AddPage (new KDMEmailPage (ps, border));
1539 e->AddPage (new AdvancedPage (ps, border));