2 Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /** @file src/config_dialog.cc
21 * @brief A dialogue to edit DCP-o-matic configuration.
24 #include "config_dialog.h"
26 #include "editable_list.h"
27 #include "filter_dialog.h"
28 #include "dir_picker_ctrl.h"
29 #include "file_picker_ctrl.h"
30 #include "isdcf_metadata_dialog.h"
31 #include "server_dialog.h"
32 #include "make_chain_dialog.h"
33 #include "email_dialog.h"
34 #include "lib/config.h"
35 #include "lib/ratio.h"
36 #include "lib/filter.h"
37 #include "lib/dcp_content_type.h"
40 #include "lib/raw_convert.h"
41 #include "lib/cross.h"
42 #include "lib/exceptions.h"
43 #include <dcp/exceptions.h>
44 #include <dcp/certificate_chain.h>
45 #include <wx/stdpaths.h>
46 #include <wx/preferences.h>
47 #include <wx/spinctrl.h>
48 #include <wx/filepicker.h>
49 #include <boost/filesystem.hpp>
50 #include <boost/foreach.hpp>
61 using boost::shared_ptr;
62 using boost::function;
63 using boost::optional;
68 Page (wxSize panel_size, int border)
71 , _panel_size (panel_size)
72 , _window_exists (false)
74 _config_connection = Config::instance()->Changed.connect (boost::bind (&Page::config_changed_wrapper, this));
80 wxWindow* create_window (wxWindow* parent)
82 _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size);
83 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
87 _window_exists = true;
90 _panel->Bind (wxEVT_DESTROY, boost::bind (&Page::window_destroyed, this));
99 virtual void config_changed () = 0;
100 virtual void setup () = 0;
102 void config_changed_wrapper ()
104 if (_window_exists) {
109 void window_destroyed ()
111 _window_exists = false;
115 boost::signals2::scoped_connection _config_connection;
119 class StockPage : public wxStockPreferencesPage, public Page
122 StockPage (Kind kind, wxSize panel_size, int border)
123 : wxStockPreferencesPage (kind)
124 , Page (panel_size, border)
127 wxWindow* CreateWindow (wxWindow* parent)
129 return create_window (parent);
133 class StandardPage : public wxPreferencesPage, public Page
136 StandardPage (wxSize panel_size, int border)
137 : Page (panel_size, border)
140 wxWindow* CreateWindow (wxWindow* parent)
142 return create_window (parent);
146 class GeneralPage : public StockPage
149 GeneralPage (wxSize panel_size, int border)
150 : StockPage (Kind_General, panel_size, border)
156 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
157 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
160 _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language"));
161 table->Add (_set_language, wxGBPosition (r, 0));
162 _language = new wxChoice (_panel, wxID_ANY);
163 vector<pair<string, string> > languages;
164 languages.push_back (make_pair ("Čeština", "cs_CZ"));
165 languages.push_back (make_pair ("汉语/漢語", "zh_CN"));
166 languages.push_back (make_pair ("Dansk", "da_DK"));
167 languages.push_back (make_pair ("Deutsch", "de_DE"));
168 languages.push_back (make_pair ("English", "en_GB"));
169 languages.push_back (make_pair ("Español", "es_ES"));
170 languages.push_back (make_pair ("Français", "fr_FR"));
171 languages.push_back (make_pair ("Italiano", "it_IT"));
172 languages.push_back (make_pair ("Nederlands", "nl_NL"));
173 languages.push_back (make_pair ("Русский", "ru_RU"));
174 languages.push_back (make_pair ("Polski", "pl_PL"));
175 languages.push_back (make_pair ("Português europeu", "pt_PT"));
176 languages.push_back (make_pair ("Português do Brasil", "pt_BR"));
177 languages.push_back (make_pair ("Svenska", "sv_SE"));
178 languages.push_back (make_pair ("Slovenský jazyk", "sk_SK"));
179 languages.push_back (make_pair ("українська мова", "uk_UA"));
180 checked_set (_language, languages);
181 table->Add (_language, wxGBPosition (r, 1));
184 wxStaticText* restart = add_label_to_sizer (
185 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
187 wxFont font = restart->GetFont();
188 font.SetStyle (wxFONTSTYLE_ITALIC);
189 font.SetPointSize (font.GetPointSize() - 1);
190 restart->SetFont (font);
193 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
194 _num_local_encoding_threads = new wxSpinCtrl (_panel);
195 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
198 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
199 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml");
200 table->Add (_cinemas_file, wxGBPosition (r, 1));
203 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
204 _analyse_ebur128 = new wxCheckBox (_panel, wxID_ANY, _("Find integrated loudness, true peak and loudness range when analysing audio"));
205 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
209 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
210 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
213 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
214 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
217 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
218 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
221 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
222 bottom_table->AddGrowableCol (1, 1);
224 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
225 _issuer = new wxTextCtrl (_panel, wxID_ANY);
226 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
228 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
229 _creator = new wxTextCtrl (_panel, wxID_ANY);
230 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
232 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
235 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
236 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
237 _cinemas_file->Bind (wxEVT_COMMAND_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
239 _num_local_encoding_threads->SetRange (1, 128);
240 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
242 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
243 _analyse_ebur128->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::analyse_ebur128_changed, this));
245 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
246 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
247 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
249 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
250 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
253 void config_changed ()
255 Config* config = Config::instance ();
257 checked_set (_set_language, static_cast<bool>(config->language()));
259 /* Backwards compatibility of config file */
261 map<string, string> compat_map;
262 compat_map["fr"] = "fr_FR";
263 compat_map["it"] = "it_IT";
264 compat_map["es"] = "es_ES";
265 compat_map["sv"] = "sv_SE";
266 compat_map["de"] = "de_DE";
267 compat_map["nl"] = "nl_NL";
268 compat_map["ru"] = "ru_RU";
269 compat_map["pl"] = "pl_PL";
270 compat_map["da"] = "da_DK";
271 compat_map["pt"] = "pt_PT";
272 compat_map["sk"] = "sk_SK";
273 compat_map["cs"] = "cs_CZ";
274 compat_map["uk"] = "uk_UA";
276 string lang = config->language().get_value_or ("en_GB");
277 if (compat_map.find (lang) != compat_map.end ()) {
278 lang = compat_map[lang];
281 checked_set (_language, lang);
283 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
284 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
285 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
287 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
288 checked_set (_check_for_updates, config->check_for_updates ());
289 checked_set (_check_for_test_updates, config->check_for_test_updates ());
290 checked_set (_issuer, config->dcp_issuer ());
291 checked_set (_creator, config->dcp_creator ());
292 checked_set (_cinemas_file, config->cinemas_file());
294 setup_sensitivity ();
297 void setup_sensitivity ()
299 _language->Enable (_set_language->GetValue ());
300 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
303 void set_language_changed ()
305 setup_sensitivity ();
306 if (_set_language->GetValue ()) {
309 Config::instance()->unset_language ();
313 void language_changed ()
315 int const sel = _language->GetSelection ();
317 Config::instance()->set_language (string_client_data (_language->GetClientObject (sel)));
319 Config::instance()->unset_language ();
323 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
324 void analyse_ebur128_changed ()
326 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
330 void automatic_audio_analysis_changed ()
332 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
335 void check_for_updates_changed ()
337 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
340 void check_for_test_updates_changed ()
342 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
345 void num_local_encoding_threads_changed ()
347 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
350 void issuer_changed ()
352 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
355 void creator_changed ()
357 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
360 void cinemas_file_changed ()
362 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
365 wxCheckBox* _set_language;
367 wxSpinCtrl* _num_local_encoding_threads;
368 FilePickerCtrl* _cinemas_file;
369 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
370 wxCheckBox* _analyse_ebur128;
372 wxCheckBox* _automatic_audio_analysis;
373 wxCheckBox* _check_for_updates;
374 wxCheckBox* _check_for_test_updates;
376 wxTextCtrl* _creator;
379 class DefaultsPage : public StandardPage
382 DefaultsPage (wxSize panel_size, int border)
383 : StandardPage (panel_size, border)
386 wxString GetName () const
388 return _("Defaults");
392 wxBitmap GetLargeIcon () const
394 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
401 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
402 table->AddGrowableCol (1, 1);
403 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
406 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
407 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
408 _still_length = new wxSpinCtrl (_panel);
409 s->Add (_still_length);
410 add_label_to_sizer (s, _panel, _("s"), false);
414 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
415 #ifdef DCPOMATIC_USE_OWN_PICKER
416 _directory = new DirPickerCtrl (_panel);
418 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
420 table->Add (_directory, 1, wxEXPAND);
422 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
423 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
424 table->Add (_isdcf_metadata_button);
426 add_label_to_sizer (table, _panel, _("Default container"), true);
427 _container = new wxChoice (_panel, wxID_ANY);
428 table->Add (_container);
430 add_label_to_sizer (table, _panel, _("Default content type"), true);
431 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
432 table->Add (_dcp_content_type);
435 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
436 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
437 _j2k_bandwidth = new wxSpinCtrl (_panel);
438 s->Add (_j2k_bandwidth);
439 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
444 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
445 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
446 _audio_delay = new wxSpinCtrl (_panel);
447 s->Add (_audio_delay);
448 add_label_to_sizer (s, _panel, _("ms"), false);
452 add_label_to_sizer (table, _panel, _("Default standard"), true);
453 _standard = new wxChoice (_panel, wxID_ANY);
454 table->Add (_standard);
456 _still_length->SetRange (1, 3600);
457 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
459 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
461 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
463 vector<Ratio const *> ratios = Ratio::all ();
464 for (size_t i = 0; i < ratios.size(); ++i) {
465 _container->Append (std_to_wx (ratios[i]->nickname ()));
468 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
470 vector<DCPContentType const *> const ct = DCPContentType::all ();
471 for (size_t i = 0; i < ct.size(); ++i) {
472 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
475 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
477 _j2k_bandwidth->SetRange (50, 250);
478 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
480 _audio_delay->SetRange (-1000, 1000);
481 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
483 _standard->Append (_("SMPTE"));
484 _standard->Append (_("Interop"));
485 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
488 void config_changed ()
490 Config* config = Config::instance ();
492 vector<Ratio const *> ratios = Ratio::all ();
493 for (size_t i = 0; i < ratios.size(); ++i) {
494 if (ratios[i] == config->default_container ()) {
495 _container->SetSelection (i);
499 vector<DCPContentType const *> const ct = DCPContentType::all ();
500 for (size_t i = 0; i < ct.size(); ++i) {
501 if (ct[i] == config->default_dcp_content_type ()) {
502 _dcp_content_type->SetSelection (i);
506 checked_set (_still_length, config->default_still_length ());
507 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
508 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
509 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
510 checked_set (_audio_delay, config->default_audio_delay ());
511 checked_set (_standard, config->default_interop() ? 1 : 0);
514 void j2k_bandwidth_changed ()
516 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
519 void audio_delay_changed ()
521 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
524 void directory_changed ()
526 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
529 void edit_isdcf_metadata_clicked ()
531 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
533 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
537 void still_length_changed ()
539 Config::instance()->set_default_still_length (_still_length->GetValue ());
542 void container_changed ()
544 vector<Ratio const *> ratio = Ratio::all ();
545 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
548 void dcp_content_type_changed ()
550 vector<DCPContentType const *> ct = DCPContentType::all ();
551 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
554 void standard_changed ()
556 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
559 wxSpinCtrl* _j2k_bandwidth;
560 wxSpinCtrl* _audio_delay;
561 wxButton* _isdcf_metadata_button;
562 wxSpinCtrl* _still_length;
563 #ifdef DCPOMATIC_USE_OWN_PICKER
564 DirPickerCtrl* _directory;
566 wxDirPickerCtrl* _directory;
568 wxChoice* _container;
569 wxChoice* _dcp_content_type;
573 class EncodingServersPage : public StandardPage
576 EncodingServersPage (wxSize panel_size, int border)
577 : StandardPage (panel_size, border)
580 wxString GetName () const
586 wxBitmap GetLargeIcon () const
588 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
595 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
596 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
598 vector<string> columns;
599 columns.push_back (wx_to_std (_("IP address / host name")));
600 _servers_list = new EditableList<string, ServerDialog> (
603 boost::bind (&Config::servers, Config::instance()),
604 boost::bind (&Config::set_servers, Config::instance(), _1),
605 boost::bind (&always_valid),
606 boost::bind (&EncodingServersPage::server_column, this, _1)
609 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
611 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
614 void config_changed ()
616 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
617 _servers_list->refresh ();
620 void use_any_servers_changed ()
622 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
625 string server_column (string s)
630 wxCheckBox* _use_any_servers;
631 EditableList<string, ServerDialog>* _servers_list;
634 class CertificateChainEditor : public wxPanel
637 CertificateChainEditor (
641 function<void (shared_ptr<dcp::CertificateChain>)> set,
642 function<shared_ptr<const dcp::CertificateChain> (void)> get
648 wxFont subheading_font (*wxNORMAL_FONT);
649 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
651 _sizer = new wxBoxSizer (wxVERTICAL);
654 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
655 m->SetFont (subheading_font);
656 _sizer->Add (m, 0, wxALL, border);
659 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
660 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
662 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
667 ip.SetText (_("Type"));
669 _certificates->InsertColumn (0, ip);
675 ip.SetText (_("Thumbprint"));
678 wxFont font = ip.GetFont ();
679 font.SetFamily (wxFONTFAMILY_TELETYPE);
682 _certificates->InsertColumn (1, ip);
685 certificates_sizer->Add (_certificates, 1, wxEXPAND);
688 wxSizer* s = new wxBoxSizer (wxVERTICAL);
689 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
690 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
691 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
692 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
693 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
694 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
695 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
698 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
699 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
702 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
703 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
704 wxFont font = _private_key->GetFont ();
705 font.SetFamily (wxFONTFAMILY_TELETYPE);
706 _private_key->SetFont (font);
707 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
708 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
709 table->Add (_load_private_key, wxGBPosition (r, 2));
710 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
711 table->Add (_export_private_key, wxGBPosition (r, 3));
714 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
715 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
716 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
717 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
720 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
721 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
722 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
723 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
724 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
725 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
726 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
727 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
729 SetSizerAndFit (_sizer);
732 void config_changed ()
734 _chain.reset (new dcp::CertificateChain (*_get().get ()));
736 update_certificate_list ();
737 update_private_key ();
738 update_sensitivity ();
741 void add_button (wxWindow* button)
743 _button_sizer->Add (button);
748 void add_certificate ()
750 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
752 if (d->ShowModal() == wxID_OK) {
754 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
755 if (c.extra_data ()) {
758 _("This file contains other certificates (or other data) after its first certificate. "
759 "Only the first certificate will be used.")
764 update_certificate_list ();
765 } catch (dcp::MiscError& e) {
766 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
772 update_sensitivity ();
775 void remove_certificate ()
777 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
782 _certificates->DeleteItem (i);
786 update_sensitivity ();
789 void export_certificate ()
791 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
796 wxFileDialog* d = new wxFileDialog (
797 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
798 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
801 dcp::CertificateChain::List all = _chain->root_to_leaf ();
802 dcp::CertificateChain::List::iterator j = all.begin ();
803 for (int k = 0; k < i; ++k) {
807 if (d->ShowModal () == wxID_OK) {
808 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
810 throw OpenFileError (wx_to_std (d->GetPath ()));
813 string const s = j->certificate (true);
814 fwrite (s.c_str(), 1, s.length(), f);
820 void update_certificate_list ()
822 _certificates->DeleteAllItems ();
824 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
825 BOOST_FOREACH (dcp::Certificate const & i, certs) {
828 _certificates->InsertItem (item);
829 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
832 _certificates->SetItem (n, 0, _("Root"));
833 } else if (n == (certs.size() - 1)) {
834 _certificates->SetItem (n, 0, _("Leaf"));
836 _certificates->SetItem (n, 0, _("Intermediate"));
843 void remake_certificates ()
845 shared_ptr<const dcp::CertificateChain> chain = _get ();
847 string subject_organization_name;
848 string subject_organizational_unit_name;
849 string root_common_name;
850 string intermediate_common_name;
851 string leaf_common_name;
853 dcp::CertificateChain::List all = chain->root_to_leaf ();
855 if (all.size() >= 1) {
857 subject_organization_name = chain->root().subject_organization_name ();
858 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
859 root_common_name = chain->root().subject_common_name ();
862 if (all.size() >= 2) {
864 leaf_common_name = chain->leaf().subject_common_name ();
867 if (all.size() >= 3) {
868 /* Have an intermediate */
869 dcp::CertificateChain::List::iterator i = all.begin ();
871 intermediate_common_name = i->subject_common_name ();
874 MakeChainDialog* d = new MakeChainDialog (
876 subject_organization_name,
877 subject_organizational_unit_name,
879 intermediate_common_name,
883 if (d->ShowModal () == wxID_OK) {
885 new dcp::CertificateChain (
888 d->organisational_unit (),
889 d->root_common_name (),
890 d->intermediate_common_name (),
891 d->leaf_common_name ()
896 update_certificate_list ();
897 update_private_key ();
903 void update_sensitivity ()
905 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
906 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
909 void update_private_key ()
911 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
915 void load_private_key ()
917 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
919 if (d->ShowModal() == wxID_OK) {
921 boost::filesystem::path p (wx_to_std (d->GetPath ()));
922 if (boost::filesystem::file_size (p) > 8192) {
925 wxString::Format (_("Could not read key file; file is too long (%s)"), std_to_wx (p.string ()))
930 _chain->set_key (dcp::file_to_string (p));
932 update_private_key ();
933 } catch (dcp::MiscError& e) {
934 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
940 update_sensitivity ();
943 void export_private_key ()
945 optional<string> key = _chain->key ();
950 wxFileDialog* d = new wxFileDialog (
951 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
952 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
955 if (d->ShowModal () == wxID_OK) {
956 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
958 throw OpenFileError (wx_to_std (d->GetPath ()));
961 string const s = _chain->key().get ();
962 fwrite (s.c_str(), 1, s.length(), f);
968 wxListCtrl* _certificates;
969 wxButton* _add_certificate;
970 wxButton* _export_certificate;
971 wxButton* _remove_certificate;
972 wxButton* _remake_certificates;
973 wxStaticText* _private_key;
974 wxButton* _load_private_key;
975 wxButton* _export_private_key;
977 wxBoxSizer* _button_sizer;
978 shared_ptr<dcp::CertificateChain> _chain;
979 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
980 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
983 class KeysPage : public StandardPage
986 KeysPage (wxSize panel_size, int border)
987 : StandardPage (panel_size, border)
990 wxString GetName () const
996 wxBitmap GetLargeIcon () const
998 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
1006 _signer = new CertificateChainEditor (
1007 _panel, _("Signing DCPs and KDMs"), _border,
1008 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
1009 boost::bind (&Config::signer_chain, Config::instance ())
1012 _panel->GetSizer()->Add (_signer);
1014 _decryption = new CertificateChainEditor (
1015 _panel, _("Decrypting DCPs"), _border,
1016 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1017 boost::bind (&Config::decryption_chain, Config::instance ())
1020 _panel->GetSizer()->Add (_decryption);
1022 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1023 _decryption->add_button (_export_decryption_certificate);
1025 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1028 void export_decryption_certificate ()
1030 wxFileDialog* d = new wxFileDialog (
1031 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1032 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1035 if (d->ShowModal () == wxID_OK) {
1036 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1038 throw OpenFileError (wx_to_std (d->GetPath ()));
1041 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1042 fwrite (s.c_str(), 1, s.length(), f);
1048 void config_changed ()
1050 _signer->config_changed ();
1051 _decryption->config_changed ();
1054 CertificateChainEditor* _signer;
1055 CertificateChainEditor* _decryption;
1056 wxButton* _export_decryption_certificate;
1059 class TMSPage : public StandardPage
1062 TMSPage (wxSize panel_size, int border)
1063 : StandardPage (panel_size, border)
1066 wxString GetName () const
1071 #ifdef DCPOMATIC_OSX
1072 wxBitmap GetLargeIcon () const
1074 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1081 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1082 table->AddGrowableCol (1, 1);
1083 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1085 add_label_to_sizer (table, _panel, _("Protocol"), true);
1086 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1087 table->Add (_tms_protocol, 1, wxEXPAND);
1089 add_label_to_sizer (table, _panel, _("IP address"), true);
1090 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1091 table->Add (_tms_ip, 1, wxEXPAND);
1093 add_label_to_sizer (table, _panel, _("Target path"), true);
1094 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1095 table->Add (_tms_path, 1, wxEXPAND);
1097 add_label_to_sizer (table, _panel, _("User name"), true);
1098 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1099 table->Add (_tms_user, 1, wxEXPAND);
1101 add_label_to_sizer (table, _panel, _("Password"), true);
1102 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1103 table->Add (_tms_password, 1, wxEXPAND);
1105 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1106 _tms_protocol->Append (_("FTP (for Dolby)"));
1108 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1109 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1110 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1111 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1112 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1115 void config_changed ()
1117 Config* config = Config::instance ();
1119 checked_set (_tms_protocol, config->tms_protocol ());
1120 checked_set (_tms_ip, config->tms_ip ());
1121 checked_set (_tms_path, config->tms_path ());
1122 checked_set (_tms_user, config->tms_user ());
1123 checked_set (_tms_password, config->tms_password ());
1126 void tms_protocol_changed ()
1128 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1131 void tms_ip_changed ()
1133 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1136 void tms_path_changed ()
1138 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1141 void tms_user_changed ()
1143 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1146 void tms_password_changed ()
1148 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1151 wxChoice* _tms_protocol;
1152 wxTextCtrl* _tms_ip;
1153 wxTextCtrl* _tms_path;
1154 wxTextCtrl* _tms_user;
1155 wxTextCtrl* _tms_password;
1164 class KDMEmailPage : public StandardPage
1168 KDMEmailPage (wxSize panel_size, int border)
1169 #ifdef DCPOMATIC_OSX
1170 /* We have to force both width and height of this one */
1171 : StandardPage (wxSize (480, 128), border)
1173 : StandardPage (panel_size, border)
1177 wxString GetName () const
1179 return _("KDM Email");
1182 #ifdef DCPOMATIC_OSX
1183 wxBitmap GetLargeIcon () const
1185 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1192 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1193 table->AddGrowableCol (1, 1);
1194 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1196 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1198 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1199 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1200 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1201 add_label_to_sizer (s, _panel, _("port"), false);
1202 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1203 _mail_port->SetRange (0, 65535);
1204 s->Add (_mail_port);
1205 table->Add (s, 1, wxEXPAND | wxALL);
1208 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1209 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1210 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1212 add_label_to_sizer (table, _panel, _("Mail password"), true);
1213 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1214 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1216 add_label_to_sizer (table, _panel, _("Subject"), true);
1217 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1218 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1220 add_label_to_sizer (table, _panel, _("From address"), true);
1221 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1222 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1224 vector<string> columns;
1225 columns.push_back (wx_to_std (_("Address")));
1226 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1227 _kdm_cc = new EditableList<string, EmailDialog> (
1230 bind (&Config::kdm_cc, Config::instance()),
1231 bind (&Config::set_kdm_cc, Config::instance(), _1),
1232 bind (&string_not_empty, _1),
1235 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1237 add_label_to_sizer (table, _panel, _("BCC address"), true);
1238 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1239 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1241 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1242 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1244 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1245 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1249 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1250 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1251 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1252 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1253 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1254 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1255 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1256 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1257 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1260 void config_changed ()
1262 Config* config = Config::instance ();
1264 checked_set (_mail_server, config->mail_server ());
1265 checked_set (_mail_port, config->mail_port ());
1266 checked_set (_mail_user, config->mail_user ());
1267 checked_set (_mail_password, config->mail_password ());
1268 checked_set (_kdm_subject, config->kdm_subject ());
1269 checked_set (_kdm_from, config->kdm_from ());
1270 checked_set (_kdm_bcc, config->kdm_bcc ());
1271 checked_set (_kdm_email, Config::instance()->kdm_email ());
1274 void mail_server_changed ()
1276 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1279 void mail_port_changed ()
1281 Config::instance()->set_mail_port (_mail_port->GetValue ());
1284 void mail_user_changed ()
1286 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1289 void mail_password_changed ()
1291 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1294 void kdm_subject_changed ()
1296 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1299 void kdm_from_changed ()
1301 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1304 void kdm_bcc_changed ()
1306 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1309 void kdm_email_changed ()
1311 if (_kdm_email->GetValue().IsEmpty ()) {
1312 /* Sometimes we get sent an erroneous notification that the email
1313 is empty; I don't know why.
1317 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1320 void reset_kdm_email ()
1322 Config::instance()->reset_kdm_email ();
1323 checked_set (_kdm_email, Config::instance()->kdm_email ());
1326 wxTextCtrl* _mail_server;
1327 wxSpinCtrl* _mail_port;
1328 wxTextCtrl* _mail_user;
1329 wxTextCtrl* _mail_password;
1330 wxTextCtrl* _kdm_subject;
1331 wxTextCtrl* _kdm_from;
1332 EditableList<string, EmailDialog>* _kdm_cc;
1333 wxTextCtrl* _kdm_bcc;
1334 wxTextCtrl* _kdm_email;
1335 wxButton* _reset_kdm_email;
1338 /** @class AdvancedPage
1339 * @brief Advanced page of the preferences dialog.
1341 class AdvancedPage : public StockPage
1344 AdvancedPage (wxSize panel_size, int border)
1345 : StockPage (Kind_Advanced, panel_size, border)
1346 , _maximum_j2k_bandwidth (0)
1347 , _allow_any_dcp_frame_rate (0)
1348 , _only_servers_encode (0)
1353 , _log_debug_decode (0)
1354 , _log_debug_encode (0)
1355 , _log_debug_email (0)
1361 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1362 table->AddGrowableCol (1, 1);
1363 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1366 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1367 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1368 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1369 s->Add (_maximum_j2k_bandwidth, 1);
1370 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1374 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1375 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1376 table->AddSpacer (0);
1378 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1379 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1380 table->AddSpacer (0);
1383 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1384 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1386 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1387 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1391 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1392 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1393 t->Add (_log_general, 1, wxEXPAND | wxALL);
1394 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1395 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1396 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1397 t->Add (_log_error, 1, wxEXPAND | wxALL);
1398 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1399 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1400 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1401 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1402 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1403 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1404 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1405 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1406 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1407 table->Add (t, 0, wxALL, 6);
1410 #ifdef DCPOMATIC_WINDOWS
1411 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1412 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1413 table->AddSpacer (0);
1416 _maximum_j2k_bandwidth->SetRange (1, 1000);
1417 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1418 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1419 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1420 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1421 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1422 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1423 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1424 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1425 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1426 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1427 #ifdef DCPOMATIC_WINDOWS
1428 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1432 void config_changed ()
1434 Config* config = Config::instance ();
1436 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1437 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1438 checked_set (_only_servers_encode, config->only_servers_encode ());
1439 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1440 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1441 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1442 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1443 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1444 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1445 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1446 #ifdef DCPOMATIC_WINDOWS
1447 checked_set (_win32_console, config->win32_console());
1451 void maximum_j2k_bandwidth_changed ()
1453 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1456 void allow_any_dcp_frame_rate_changed ()
1458 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1461 void only_servers_encode_changed ()
1463 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1469 if (_log_general->GetValue ()) {
1470 types |= LogEntry::TYPE_GENERAL;
1472 if (_log_warning->GetValue ()) {
1473 types |= LogEntry::TYPE_WARNING;
1475 if (_log_error->GetValue ()) {
1476 types |= LogEntry::TYPE_ERROR;
1478 if (_log_timing->GetValue ()) {
1479 types |= LogEntry::TYPE_TIMING;
1481 if (_log_debug_decode->GetValue ()) {
1482 types |= LogEntry::TYPE_DEBUG_DECODE;
1484 if (_log_debug_encode->GetValue ()) {
1485 types |= LogEntry::TYPE_DEBUG_ENCODE;
1487 if (_log_debug_email->GetValue ()) {
1488 types |= LogEntry::TYPE_DEBUG_EMAIL;
1490 Config::instance()->set_log_types (types);
1493 #ifdef DCPOMATIC_WINDOWS
1494 void win32_console_changed ()
1496 Config::instance()->set_win32_console (_win32_console->GetValue ());
1500 wxSpinCtrl* _maximum_j2k_bandwidth;
1501 wxCheckBox* _allow_any_dcp_frame_rate;
1502 wxCheckBox* _only_servers_encode;
1503 wxCheckBox* _log_general;
1504 wxCheckBox* _log_warning;
1505 wxCheckBox* _log_error;
1506 wxCheckBox* _log_timing;
1507 wxCheckBox* _log_debug_decode;
1508 wxCheckBox* _log_debug_encode;
1509 wxCheckBox* _log_debug_email;
1510 #ifdef DCPOMATIC_WINDOWS
1511 wxCheckBox* _win32_console;
1515 wxPreferencesEditor*
1516 create_config_dialog ()
1518 wxPreferencesEditor* e = new wxPreferencesEditor ();
1520 #ifdef DCPOMATIC_OSX
1521 /* Width that we force some of the config panels to be on OSX so that
1522 the containing window doesn't shrink too much when we select those panels.
1523 This is obviously an unpleasant hack.
1525 wxSize ps = wxSize (520, -1);
1526 int const border = 16;
1528 wxSize ps = wxSize (-1, -1);
1529 int const border = 8;
1532 e->AddPage (new GeneralPage (ps, border));
1533 e->AddPage (new DefaultsPage (ps, border));
1534 e->AddPage (new EncodingServersPage (ps, border));
1535 e->AddPage (new KeysPage (ps, border));
1536 e->AddPage (new TMSPage (ps, border));
1537 e->AddPage (new KDMEmailPage (ps, border));
1538 e->AddPage (new AdvancedPage (ps, border));