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 ("Dansk", "da_DK"));
166 languages.push_back (make_pair ("Deutsch", "de_DE"));
167 languages.push_back (make_pair ("English", "en_GB"));
168 languages.push_back (make_pair ("Español", "es_ES"));
169 languages.push_back (make_pair ("Français", "fr_FR"));
170 languages.push_back (make_pair ("Italiano", "it_IT"));
171 languages.push_back (make_pair ("Nederlands", "nl_NL"));
172 languages.push_back (make_pair ("Русский", "ru_RU"));
173 languages.push_back (make_pair ("Polski", "pl_PL"));
174 languages.push_back (make_pair ("Português europeu", "pt_PT"));
175 languages.push_back (make_pair ("Português do Brasil", "pt_BR"));
176 languages.push_back (make_pair ("Svenska", "sv_SE"));
177 languages.push_back (make_pair ("Slovenský jazyk", "sk_SK"));
178 languages.push_back (make_pair ("українська мова", "uk_UA"));
179 checked_set (_language, languages);
180 table->Add (_language, wxGBPosition (r, 1));
183 wxStaticText* restart = add_label_to_sizer (
184 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
186 wxFont font = restart->GetFont();
187 font.SetStyle (wxFONTSTYLE_ITALIC);
188 font.SetPointSize (font.GetPointSize() - 1);
189 restart->SetFont (font);
192 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
193 _num_local_encoding_threads = new wxSpinCtrl (_panel);
194 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
197 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
198 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml");
199 table->Add (_cinemas_file, wxGBPosition (r, 1));
202 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
203 _analyse_ebur128 = new wxCheckBox (_panel, wxID_ANY, _("Find integrated loudness, true peak and loudness range when analysing audio"));
204 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
208 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
209 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
212 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
213 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
216 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
217 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
220 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
221 bottom_table->AddGrowableCol (1, 1);
223 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
224 _issuer = new wxTextCtrl (_panel, wxID_ANY);
225 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
227 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
228 _creator = new wxTextCtrl (_panel, wxID_ANY);
229 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
231 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
234 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
235 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
236 _cinemas_file->Bind (wxEVT_COMMAND_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
238 _num_local_encoding_threads->SetRange (1, 128);
239 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
241 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
242 _analyse_ebur128->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::analyse_ebur128_changed, this));
244 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
245 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
246 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
248 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
249 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
252 void config_changed ()
254 Config* config = Config::instance ();
256 checked_set (_set_language, static_cast<bool>(config->language()));
258 /* Backwards compatibility of config file */
260 map<string, string> compat_map;
261 compat_map["fr"] = "fr_FR";
262 compat_map["it"] = "it_IT";
263 compat_map["es"] = "es_ES";
264 compat_map["sv"] = "sv_SE";
265 compat_map["de"] = "de_DE";
266 compat_map["nl"] = "nl_NL";
267 compat_map["ru"] = "ru_RU";
268 compat_map["pl"] = "pl_PL";
269 compat_map["da"] = "da_DK";
270 compat_map["pt"] = "pt_PT";
271 compat_map["sk"] = "sk_SK";
272 compat_map["cs"] = "cs_CZ";
273 compat_map["uk"] = "uk_UA";
275 string lang = config->language().get_value_or ("en_GB");
276 if (compat_map.find (lang) != compat_map.end ()) {
277 lang = compat_map[lang];
280 checked_set (_language, lang);
282 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
283 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
284 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
286 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
287 checked_set (_check_for_updates, config->check_for_updates ());
288 checked_set (_check_for_test_updates, config->check_for_test_updates ());
289 checked_set (_issuer, config->dcp_issuer ());
290 checked_set (_creator, config->dcp_creator ());
291 checked_set (_cinemas_file, config->cinemas_file());
293 setup_sensitivity ();
296 void setup_sensitivity ()
298 _language->Enable (_set_language->GetValue ());
299 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
302 void set_language_changed ()
304 setup_sensitivity ();
305 if (_set_language->GetValue ()) {
308 Config::instance()->unset_language ();
312 void language_changed ()
314 int const sel = _language->GetSelection ();
316 Config::instance()->set_language (string_client_data (_language->GetClientObject (sel)));
318 Config::instance()->unset_language ();
322 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
323 void analyse_ebur128_changed ()
325 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
329 void automatic_audio_analysis_changed ()
331 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
334 void check_for_updates_changed ()
336 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
339 void check_for_test_updates_changed ()
341 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
344 void num_local_encoding_threads_changed ()
346 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
349 void issuer_changed ()
351 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
354 void creator_changed ()
356 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
359 void cinemas_file_changed ()
361 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
364 wxCheckBox* _set_language;
366 wxSpinCtrl* _num_local_encoding_threads;
367 FilePickerCtrl* _cinemas_file;
368 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
369 wxCheckBox* _analyse_ebur128;
371 wxCheckBox* _automatic_audio_analysis;
372 wxCheckBox* _check_for_updates;
373 wxCheckBox* _check_for_test_updates;
375 wxTextCtrl* _creator;
378 class DefaultsPage : public StandardPage
381 DefaultsPage (wxSize panel_size, int border)
382 : StandardPage (panel_size, border)
385 wxString GetName () const
387 return _("Defaults");
391 wxBitmap GetLargeIcon () const
393 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
400 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
401 table->AddGrowableCol (1, 1);
402 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
405 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
406 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
407 _still_length = new wxSpinCtrl (_panel);
408 s->Add (_still_length);
409 add_label_to_sizer (s, _panel, _("s"), false);
413 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
414 #ifdef DCPOMATIC_USE_OWN_PICKER
415 _directory = new DirPickerCtrl (_panel);
417 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
419 table->Add (_directory, 1, wxEXPAND);
421 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
422 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
423 table->Add (_isdcf_metadata_button);
425 add_label_to_sizer (table, _panel, _("Default container"), true);
426 _container = new wxChoice (_panel, wxID_ANY);
427 table->Add (_container);
429 add_label_to_sizer (table, _panel, _("Default content type"), true);
430 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
431 table->Add (_dcp_content_type);
434 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
435 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
436 _j2k_bandwidth = new wxSpinCtrl (_panel);
437 s->Add (_j2k_bandwidth);
438 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
443 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
444 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
445 _audio_delay = new wxSpinCtrl (_panel);
446 s->Add (_audio_delay);
447 add_label_to_sizer (s, _panel, _("ms"), false);
451 add_label_to_sizer (table, _panel, _("Default standard"), true);
452 _standard = new wxChoice (_panel, wxID_ANY);
453 table->Add (_standard);
455 _still_length->SetRange (1, 3600);
456 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
458 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
460 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
462 vector<Ratio const *> ratios = Ratio::all ();
463 for (size_t i = 0; i < ratios.size(); ++i) {
464 _container->Append (std_to_wx (ratios[i]->nickname ()));
467 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
469 vector<DCPContentType const *> const ct = DCPContentType::all ();
470 for (size_t i = 0; i < ct.size(); ++i) {
471 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
474 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
476 _j2k_bandwidth->SetRange (50, 250);
477 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
479 _audio_delay->SetRange (-1000, 1000);
480 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
482 _standard->Append (_("SMPTE"));
483 _standard->Append (_("Interop"));
484 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
487 void config_changed ()
489 Config* config = Config::instance ();
491 vector<Ratio const *> ratios = Ratio::all ();
492 for (size_t i = 0; i < ratios.size(); ++i) {
493 if (ratios[i] == config->default_container ()) {
494 _container->SetSelection (i);
498 vector<DCPContentType const *> const ct = DCPContentType::all ();
499 for (size_t i = 0; i < ct.size(); ++i) {
500 if (ct[i] == config->default_dcp_content_type ()) {
501 _dcp_content_type->SetSelection (i);
505 checked_set (_still_length, config->default_still_length ());
506 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
507 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
508 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
509 checked_set (_audio_delay, config->default_audio_delay ());
510 checked_set (_standard, config->default_interop() ? 1 : 0);
513 void j2k_bandwidth_changed ()
515 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
518 void audio_delay_changed ()
520 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
523 void directory_changed ()
525 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
528 void edit_isdcf_metadata_clicked ()
530 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
532 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
536 void still_length_changed ()
538 Config::instance()->set_default_still_length (_still_length->GetValue ());
541 void container_changed ()
543 vector<Ratio const *> ratio = Ratio::all ();
544 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
547 void dcp_content_type_changed ()
549 vector<DCPContentType const *> ct = DCPContentType::all ();
550 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
553 void standard_changed ()
555 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
558 wxSpinCtrl* _j2k_bandwidth;
559 wxSpinCtrl* _audio_delay;
560 wxButton* _isdcf_metadata_button;
561 wxSpinCtrl* _still_length;
562 #ifdef DCPOMATIC_USE_OWN_PICKER
563 DirPickerCtrl* _directory;
565 wxDirPickerCtrl* _directory;
567 wxChoice* _container;
568 wxChoice* _dcp_content_type;
572 class EncodingServersPage : public StandardPage
575 EncodingServersPage (wxSize panel_size, int border)
576 : StandardPage (panel_size, border)
579 wxString GetName () const
585 wxBitmap GetLargeIcon () const
587 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
594 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
595 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
597 vector<string> columns;
598 columns.push_back (wx_to_std (_("IP address / host name")));
599 _servers_list = new EditableList<string, ServerDialog> (
602 boost::bind (&Config::servers, Config::instance()),
603 boost::bind (&Config::set_servers, Config::instance(), _1),
604 boost::bind (&always_valid),
605 boost::bind (&EncodingServersPage::server_column, this, _1)
608 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
610 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
613 void config_changed ()
615 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
616 _servers_list->refresh ();
619 void use_any_servers_changed ()
621 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
624 string server_column (string s)
629 wxCheckBox* _use_any_servers;
630 EditableList<string, ServerDialog>* _servers_list;
633 class CertificateChainEditor : public wxPanel
636 CertificateChainEditor (
640 function<void (shared_ptr<dcp::CertificateChain>)> set,
641 function<shared_ptr<const dcp::CertificateChain> (void)> get
647 wxFont subheading_font (*wxNORMAL_FONT);
648 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
650 _sizer = new wxBoxSizer (wxVERTICAL);
653 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
654 m->SetFont (subheading_font);
655 _sizer->Add (m, 0, wxALL, border);
658 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
659 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
661 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
666 ip.SetText (_("Type"));
668 _certificates->InsertColumn (0, ip);
674 ip.SetText (_("Thumbprint"));
677 wxFont font = ip.GetFont ();
678 font.SetFamily (wxFONTFAMILY_TELETYPE);
681 _certificates->InsertColumn (1, ip);
684 certificates_sizer->Add (_certificates, 1, wxEXPAND);
687 wxSizer* s = new wxBoxSizer (wxVERTICAL);
688 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
689 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
690 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
691 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
692 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
693 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
694 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
697 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
698 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
701 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
702 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
703 wxFont font = _private_key->GetFont ();
704 font.SetFamily (wxFONTFAMILY_TELETYPE);
705 _private_key->SetFont (font);
706 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
707 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
708 table->Add (_load_private_key, wxGBPosition (r, 2));
709 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
710 table->Add (_export_private_key, wxGBPosition (r, 3));
713 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
714 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
715 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
716 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
719 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
720 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
721 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
722 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
723 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
724 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
725 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
726 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
728 SetSizerAndFit (_sizer);
731 void config_changed ()
733 _chain.reset (new dcp::CertificateChain (*_get().get ()));
735 update_certificate_list ();
736 update_private_key ();
737 update_sensitivity ();
740 void add_button (wxWindow* button)
742 _button_sizer->Add (button);
747 void add_certificate ()
749 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
751 if (d->ShowModal() == wxID_OK) {
753 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
756 update_certificate_list ();
757 } catch (dcp::MiscError& e) {
758 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
764 update_sensitivity ();
767 void remove_certificate ()
769 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
774 _certificates->DeleteItem (i);
778 update_sensitivity ();
781 void export_certificate ()
783 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
788 wxFileDialog* d = new wxFileDialog (
789 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
790 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
793 dcp::CertificateChain::List all = _chain->root_to_leaf ();
794 dcp::CertificateChain::List::iterator j = all.begin ();
795 for (int k = 0; k < i; ++k) {
799 if (d->ShowModal () == wxID_OK) {
800 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
802 throw OpenFileError (wx_to_std (d->GetPath ()));
805 string const s = j->certificate (true);
806 fwrite (s.c_str(), 1, s.length(), f);
812 void update_certificate_list ()
814 _certificates->DeleteAllItems ();
816 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
817 BOOST_FOREACH (dcp::Certificate const & i, certs) {
820 _certificates->InsertItem (item);
821 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
824 _certificates->SetItem (n, 0, _("Root"));
825 } else if (n == (certs.size() - 1)) {
826 _certificates->SetItem (n, 0, _("Leaf"));
828 _certificates->SetItem (n, 0, _("Intermediate"));
835 void remake_certificates ()
837 shared_ptr<const dcp::CertificateChain> chain = _get ();
839 string subject_organization_name;
840 string subject_organizational_unit_name;
841 string root_common_name;
842 string intermediate_common_name;
843 string leaf_common_name;
845 dcp::CertificateChain::List all = chain->root_to_leaf ();
847 if (all.size() >= 1) {
849 subject_organization_name = chain->root().subject_organization_name ();
850 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
851 root_common_name = chain->root().subject_common_name ();
854 if (all.size() >= 2) {
856 leaf_common_name = chain->leaf().subject_common_name ();
859 if (all.size() >= 3) {
860 /* Have an intermediate */
861 dcp::CertificateChain::List::iterator i = all.begin ();
863 intermediate_common_name = i->subject_common_name ();
866 MakeChainDialog* d = new MakeChainDialog (
868 subject_organization_name,
869 subject_organizational_unit_name,
871 intermediate_common_name,
875 if (d->ShowModal () == wxID_OK) {
877 new dcp::CertificateChain (
880 d->organisational_unit (),
881 d->root_common_name (),
882 d->intermediate_common_name (),
883 d->leaf_common_name ()
888 update_certificate_list ();
889 update_private_key ();
895 void update_sensitivity ()
897 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
898 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
901 void update_private_key ()
903 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
907 void load_private_key ()
909 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
911 if (d->ShowModal() == wxID_OK) {
913 boost::filesystem::path p (wx_to_std (d->GetPath ()));
914 if (boost::filesystem::file_size (p) > 1024) {
915 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
919 _chain->set_key (dcp::file_to_string (p));
921 update_private_key ();
922 } catch (dcp::MiscError& e) {
923 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
929 update_sensitivity ();
932 void export_private_key ()
934 optional<string> key = _chain->key ();
939 wxFileDialog* d = new wxFileDialog (
940 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
941 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
944 if (d->ShowModal () == wxID_OK) {
945 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
947 throw OpenFileError (wx_to_std (d->GetPath ()));
950 string const s = _chain->key().get ();
951 fwrite (s.c_str(), 1, s.length(), f);
957 wxListCtrl* _certificates;
958 wxButton* _add_certificate;
959 wxButton* _export_certificate;
960 wxButton* _remove_certificate;
961 wxButton* _remake_certificates;
962 wxStaticText* _private_key;
963 wxButton* _load_private_key;
964 wxButton* _export_private_key;
966 wxBoxSizer* _button_sizer;
967 shared_ptr<dcp::CertificateChain> _chain;
968 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
969 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
972 class KeysPage : public StandardPage
975 KeysPage (wxSize panel_size, int border)
976 : StandardPage (panel_size, border)
979 wxString GetName () const
985 wxBitmap GetLargeIcon () const
987 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
995 _signer = new CertificateChainEditor (
996 _panel, _("Signing DCPs and KDMs"), _border,
997 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
998 boost::bind (&Config::signer_chain, Config::instance ())
1001 _panel->GetSizer()->Add (_signer);
1003 _decryption = new CertificateChainEditor (
1004 _panel, _("Decrypting DCPs"), _border,
1005 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1006 boost::bind (&Config::decryption_chain, Config::instance ())
1009 _panel->GetSizer()->Add (_decryption);
1011 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1012 _decryption->add_button (_export_decryption_certificate);
1014 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1017 void export_decryption_certificate ()
1019 wxFileDialog* d = new wxFileDialog (
1020 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1021 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1024 if (d->ShowModal () == wxID_OK) {
1025 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1027 throw OpenFileError (wx_to_std (d->GetPath ()));
1030 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1031 fwrite (s.c_str(), 1, s.length(), f);
1037 void config_changed ()
1039 _signer->config_changed ();
1040 _decryption->config_changed ();
1043 CertificateChainEditor* _signer;
1044 CertificateChainEditor* _decryption;
1045 wxButton* _export_decryption_certificate;
1048 class TMSPage : public StandardPage
1051 TMSPage (wxSize panel_size, int border)
1052 : StandardPage (panel_size, border)
1055 wxString GetName () const
1060 #ifdef DCPOMATIC_OSX
1061 wxBitmap GetLargeIcon () const
1063 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1070 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1071 table->AddGrowableCol (1, 1);
1072 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1074 add_label_to_sizer (table, _panel, _("Protocol"), true);
1075 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1076 table->Add (_tms_protocol, 1, wxEXPAND);
1078 add_label_to_sizer (table, _panel, _("IP address"), true);
1079 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1080 table->Add (_tms_ip, 1, wxEXPAND);
1082 add_label_to_sizer (table, _panel, _("Target path"), true);
1083 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1084 table->Add (_tms_path, 1, wxEXPAND);
1086 add_label_to_sizer (table, _panel, _("User name"), true);
1087 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1088 table->Add (_tms_user, 1, wxEXPAND);
1090 add_label_to_sizer (table, _panel, _("Password"), true);
1091 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1092 table->Add (_tms_password, 1, wxEXPAND);
1094 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1095 _tms_protocol->Append (_("FTP (for Dolby)"));
1097 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1098 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1099 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1100 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1101 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1104 void config_changed ()
1106 Config* config = Config::instance ();
1108 checked_set (_tms_protocol, config->tms_protocol ());
1109 checked_set (_tms_ip, config->tms_ip ());
1110 checked_set (_tms_path, config->tms_path ());
1111 checked_set (_tms_user, config->tms_user ());
1112 checked_set (_tms_password, config->tms_password ());
1115 void tms_protocol_changed ()
1117 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1120 void tms_ip_changed ()
1122 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1125 void tms_path_changed ()
1127 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1130 void tms_user_changed ()
1132 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1135 void tms_password_changed ()
1137 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1140 wxChoice* _tms_protocol;
1141 wxTextCtrl* _tms_ip;
1142 wxTextCtrl* _tms_path;
1143 wxTextCtrl* _tms_user;
1144 wxTextCtrl* _tms_password;
1153 class KDMEmailPage : public StandardPage
1157 KDMEmailPage (wxSize panel_size, int border)
1158 #ifdef DCPOMATIC_OSX
1159 /* We have to force both width and height of this one */
1160 : StandardPage (wxSize (480, 128), border)
1162 : StandardPage (panel_size, border)
1166 wxString GetName () const
1168 return _("KDM Email");
1171 #ifdef DCPOMATIC_OSX
1172 wxBitmap GetLargeIcon () const
1174 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1181 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1182 table->AddGrowableCol (1, 1);
1183 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1185 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1187 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1188 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1189 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1190 add_label_to_sizer (s, _panel, _("port"), false);
1191 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1192 _mail_port->SetRange (0, 65535);
1193 s->Add (_mail_port);
1194 table->Add (s, 1, wxEXPAND | wxALL);
1197 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1198 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1199 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1201 add_label_to_sizer (table, _panel, _("Mail password"), true);
1202 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1203 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1205 add_label_to_sizer (table, _panel, _("Subject"), true);
1206 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1207 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1209 add_label_to_sizer (table, _panel, _("From address"), true);
1210 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1211 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1213 vector<string> columns;
1214 columns.push_back (wx_to_std (_("Address")));
1215 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1216 _kdm_cc = new EditableList<string, EmailDialog> (
1219 bind (&Config::kdm_cc, Config::instance()),
1220 bind (&Config::set_kdm_cc, Config::instance(), _1),
1221 bind (&string_not_empty, _1),
1224 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1226 add_label_to_sizer (table, _panel, _("BCC address"), true);
1227 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1228 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1230 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1231 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1233 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1234 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1238 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1239 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1240 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1241 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1242 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1243 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1244 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1245 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1246 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1249 void config_changed ()
1251 Config* config = Config::instance ();
1253 checked_set (_mail_server, config->mail_server ());
1254 checked_set (_mail_port, config->mail_port ());
1255 checked_set (_mail_user, config->mail_user ());
1256 checked_set (_mail_password, config->mail_password ());
1257 checked_set (_kdm_subject, config->kdm_subject ());
1258 checked_set (_kdm_from, config->kdm_from ());
1259 checked_set (_kdm_bcc, config->kdm_bcc ());
1260 checked_set (_kdm_email, Config::instance()->kdm_email ());
1263 void mail_server_changed ()
1265 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1268 void mail_port_changed ()
1270 Config::instance()->set_mail_port (_mail_port->GetValue ());
1273 void mail_user_changed ()
1275 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1278 void mail_password_changed ()
1280 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1283 void kdm_subject_changed ()
1285 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1288 void kdm_from_changed ()
1290 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1293 void kdm_bcc_changed ()
1295 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1298 void kdm_email_changed ()
1300 if (_kdm_email->GetValue().IsEmpty ()) {
1301 /* Sometimes we get sent an erroneous notification that the email
1302 is empty; I don't know why.
1306 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1309 void reset_kdm_email ()
1311 Config::instance()->reset_kdm_email ();
1312 checked_set (_kdm_email, Config::instance()->kdm_email ());
1315 wxTextCtrl* _mail_server;
1316 wxSpinCtrl* _mail_port;
1317 wxTextCtrl* _mail_user;
1318 wxTextCtrl* _mail_password;
1319 wxTextCtrl* _kdm_subject;
1320 wxTextCtrl* _kdm_from;
1321 EditableList<string, EmailDialog>* _kdm_cc;
1322 wxTextCtrl* _kdm_bcc;
1323 wxTextCtrl* _kdm_email;
1324 wxButton* _reset_kdm_email;
1327 /** @class AdvancedPage
1328 * @brief Advanced page of the preferences dialog.
1330 class AdvancedPage : public StockPage
1333 AdvancedPage (wxSize panel_size, int border)
1334 : StockPage (Kind_Advanced, panel_size, border)
1335 , _maximum_j2k_bandwidth (0)
1336 , _allow_any_dcp_frame_rate (0)
1337 , _only_servers_encode (0)
1342 , _log_debug_decode (0)
1343 , _log_debug_encode (0)
1344 , _log_debug_email (0)
1350 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1351 table->AddGrowableCol (1, 1);
1352 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1355 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1356 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1357 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1358 s->Add (_maximum_j2k_bandwidth, 1);
1359 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1363 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1364 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1365 table->AddSpacer (0);
1367 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1368 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1369 table->AddSpacer (0);
1372 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1373 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1375 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1376 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1380 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1381 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1382 t->Add (_log_general, 1, wxEXPAND | wxALL);
1383 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1384 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1385 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1386 t->Add (_log_error, 1, wxEXPAND | wxALL);
1387 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1388 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1389 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1390 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1391 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1392 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1393 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1394 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1395 table->Add (t, 0, wxALL, 6);
1398 #ifdef DCPOMATIC_WINDOWS
1399 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1400 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1401 table->AddSpacer (0);
1404 _maximum_j2k_bandwidth->SetRange (1, 1000);
1405 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1406 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1407 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1408 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1409 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1410 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1411 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1412 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1413 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1414 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1415 #ifdef DCPOMATIC_WINDOWS
1416 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1420 void config_changed ()
1422 Config* config = Config::instance ();
1424 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1425 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1426 checked_set (_only_servers_encode, config->only_servers_encode ());
1427 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1428 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1429 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1430 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1431 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1432 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1433 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1434 #ifdef DCPOMATIC_WINDOWS
1435 checked_set (_win32_console, config->win32_console());
1439 void maximum_j2k_bandwidth_changed ()
1441 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1444 void allow_any_dcp_frame_rate_changed ()
1446 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1449 void only_servers_encode_changed ()
1451 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1457 if (_log_general->GetValue ()) {
1458 types |= LogEntry::TYPE_GENERAL;
1460 if (_log_warning->GetValue ()) {
1461 types |= LogEntry::TYPE_WARNING;
1463 if (_log_error->GetValue ()) {
1464 types |= LogEntry::TYPE_ERROR;
1466 if (_log_timing->GetValue ()) {
1467 types |= LogEntry::TYPE_TIMING;
1469 if (_log_debug_decode->GetValue ()) {
1470 types |= LogEntry::TYPE_DEBUG_DECODE;
1472 if (_log_debug_encode->GetValue ()) {
1473 types |= LogEntry::TYPE_DEBUG_ENCODE;
1475 if (_log_debug_email->GetValue ()) {
1476 types |= LogEntry::TYPE_DEBUG_EMAIL;
1478 Config::instance()->set_log_types (types);
1481 #ifdef DCPOMATIC_WINDOWS
1482 void win32_console_changed ()
1484 Config::instance()->set_win32_console (_win32_console->GetValue ());
1488 wxSpinCtrl* _maximum_j2k_bandwidth;
1489 wxCheckBox* _allow_any_dcp_frame_rate;
1490 wxCheckBox* _only_servers_encode;
1491 wxCheckBox* _log_general;
1492 wxCheckBox* _log_warning;
1493 wxCheckBox* _log_error;
1494 wxCheckBox* _log_timing;
1495 wxCheckBox* _log_debug_decode;
1496 wxCheckBox* _log_debug_encode;
1497 wxCheckBox* _log_debug_email;
1498 #ifdef DCPOMATIC_WINDOWS
1499 wxCheckBox* _win32_console;
1503 wxPreferencesEditor*
1504 create_config_dialog ()
1506 wxPreferencesEditor* e = new wxPreferencesEditor ();
1508 #ifdef DCPOMATIC_OSX
1509 /* Width that we force some of the config panels to be on OSX so that
1510 the containing window doesn't shrink too much when we select those panels.
1511 This is obviously an unpleasant hack.
1513 wxSize ps = wxSize (520, -1);
1514 int const border = 16;
1516 wxSize ps = wxSize (-1, -1);
1517 int const border = 8;
1520 e->AddPage (new GeneralPage (ps, border));
1521 e->AddPage (new DefaultsPage (ps, border));
1522 e->AddPage (new EncodingServersPage (ps, border));
1523 e->AddPage (new KeysPage (ps, border));
1524 e->AddPage (new TMSPage (ps, border));
1525 e->AddPage (new KDMEmailPage (ps, border));
1526 e->AddPage (new AdvancedPage (ps, border));