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 "lib/jpeg2000_encoder.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_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 add_label_to_sizer (table, _panel, _("JPEG2000 encoder"), true, wxGBPosition (r, 0));
237 _encoder = new wxChoice (_panel, wxID_ANY);
238 BOOST_FOREACH (shared_ptr<JPEG2000Encoder> i, JPEG2000Encoder::all()) {
239 _encoder->Append (std_to_wx (i->name ()));
241 table->Add (_encoder, wxGBPosition (r, 1));
244 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
245 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
246 _cinemas_file->Bind (wxEVT_COMMAND_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
248 _num_local_encoding_threads->SetRange (1, 128);
249 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
251 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
252 _analyse_ebur128->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::analyse_ebur128_changed, this));
254 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
255 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
256 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
258 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
259 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
262 void config_changed ()
264 Config* config = Config::instance ();
266 checked_set (_set_language, static_cast<bool>(config->language()));
268 /* Backwards compatibility of config file */
270 map<string, string> compat_map;
271 compat_map["fr"] = "fr_FR";
272 compat_map["it"] = "it_IT";
273 compat_map["es"] = "es_ES";
274 compat_map["sv"] = "sv_SE";
275 compat_map["de"] = "de_DE";
276 compat_map["nl"] = "nl_NL";
277 compat_map["ru"] = "ru_RU";
278 compat_map["pl"] = "pl_PL";
279 compat_map["da"] = "da_DK";
280 compat_map["pt"] = "pt_PT";
281 compat_map["sk"] = "sk_SK";
282 compat_map["cs"] = "cs_CZ";
283 compat_map["uk"] = "uk_UA";
285 string lang = config->language().get_value_or ("en_GB");
286 if (compat_map.find (lang) != compat_map.end ()) {
287 lang = compat_map[lang];
290 checked_set (_language, lang);
292 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
293 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
294 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
296 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
297 checked_set (_check_for_updates, config->check_for_updates ());
298 checked_set (_check_for_test_updates, config->check_for_test_updates ());
299 checked_set (_issuer, config->dcp_issuer ());
300 checked_set (_creator, config->dcp_creator ());
301 checked_set (_cinemas_file, config->cinemas_file());
303 setup_sensitivity ();
305 if (!config->encoder ()) {
306 checked_set (_encoder, 0);
308 vector<shared_ptr<JPEG2000Encoder> > encoders = JPEG2000Encoder::all ();
309 for (size_t i = 0; i < encoders.size(); ++i) {
310 if (encoders[i]->id() == config->encoder().get ()) {
311 checked_set (_encoder, i);
317 void setup_sensitivity ()
319 _language->Enable (_set_language->GetValue ());
320 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
323 void set_language_changed ()
325 setup_sensitivity ();
326 if (_set_language->GetValue ()) {
329 Config::instance()->unset_language ();
333 void language_changed ()
335 int const sel = _language->GetSelection ();
337 Config::instance()->set_language (string_client_data (_language->GetClientObject (sel)));
339 Config::instance()->unset_language ();
343 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
344 void analyse_ebur128_changed ()
346 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
350 void automatic_audio_analysis_changed ()
352 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
355 void check_for_updates_changed ()
357 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
360 void check_for_test_updates_changed ()
362 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
365 void num_local_encoding_threads_changed ()
367 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
370 void issuer_changed ()
372 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
375 void creator_changed ()
377 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
380 void cinemas_file_changed ()
382 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
385 wxCheckBox* _set_language;
387 wxSpinCtrl* _num_local_encoding_threads;
388 FilePickerCtrl* _cinemas_file;
389 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
390 wxCheckBox* _analyse_ebur128;
392 wxCheckBox* _automatic_audio_analysis;
393 wxCheckBox* _check_for_updates;
394 wxCheckBox* _check_for_test_updates;
396 wxTextCtrl* _creator;
400 class DefaultsPage : public StandardPage
403 DefaultsPage (wxSize panel_size, int border)
404 : StandardPage (panel_size, border)
407 wxString GetName () const
409 return _("Defaults");
413 wxBitmap GetLargeIcon () const
415 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
422 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
423 table->AddGrowableCol (1, 1);
424 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
427 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
428 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
429 _still_length = new wxSpinCtrl (_panel);
430 s->Add (_still_length);
431 add_label_to_sizer (s, _panel, _("s"), false);
435 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
436 #ifdef DCPOMATIC_USE_OWN_PICKER
437 _directory = new DirPickerCtrl (_panel);
439 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
441 table->Add (_directory, 1, wxEXPAND);
443 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
444 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
445 table->Add (_isdcf_metadata_button);
447 add_label_to_sizer (table, _panel, _("Default container"), true);
448 _container = new wxChoice (_panel, wxID_ANY);
449 table->Add (_container);
451 add_label_to_sizer (table, _panel, _("Default content type"), true);
452 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
453 table->Add (_dcp_content_type);
456 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
457 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
458 _j2k_bandwidth = new wxSpinCtrl (_panel);
459 s->Add (_j2k_bandwidth);
460 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
465 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
466 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
467 _audio_delay = new wxSpinCtrl (_panel);
468 s->Add (_audio_delay);
469 add_label_to_sizer (s, _panel, _("ms"), false);
473 add_label_to_sizer (table, _panel, _("Default standard"), true);
474 _standard = new wxChoice (_panel, wxID_ANY);
475 table->Add (_standard);
477 _still_length->SetRange (1, 3600);
478 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
480 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
482 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
484 vector<Ratio const *> ratios = Ratio::all ();
485 for (size_t i = 0; i < ratios.size(); ++i) {
486 _container->Append (std_to_wx (ratios[i]->nickname ()));
489 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
491 vector<DCPContentType const *> const ct = DCPContentType::all ();
492 for (size_t i = 0; i < ct.size(); ++i) {
493 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
496 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
498 _j2k_bandwidth->SetRange (50, 250);
499 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
501 _audio_delay->SetRange (-1000, 1000);
502 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
504 _standard->Append (_("SMPTE"));
505 _standard->Append (_("Interop"));
506 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
509 void config_changed ()
511 Config* config = Config::instance ();
513 vector<Ratio const *> ratios = Ratio::all ();
514 for (size_t i = 0; i < ratios.size(); ++i) {
515 if (ratios[i] == config->default_container ()) {
516 _container->SetSelection (i);
520 vector<DCPContentType const *> const ct = DCPContentType::all ();
521 for (size_t i = 0; i < ct.size(); ++i) {
522 if (ct[i] == config->default_dcp_content_type ()) {
523 _dcp_content_type->SetSelection (i);
527 checked_set (_still_length, config->default_still_length ());
528 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
529 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
530 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
531 checked_set (_audio_delay, config->default_audio_delay ());
532 checked_set (_standard, config->default_interop() ? 1 : 0);
535 void j2k_bandwidth_changed ()
537 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
540 void audio_delay_changed ()
542 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
545 void directory_changed ()
547 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
550 void edit_isdcf_metadata_clicked ()
552 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
554 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
558 void still_length_changed ()
560 Config::instance()->set_default_still_length (_still_length->GetValue ());
563 void container_changed ()
565 vector<Ratio const *> ratio = Ratio::all ();
566 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
569 void dcp_content_type_changed ()
571 vector<DCPContentType const *> ct = DCPContentType::all ();
572 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
575 void standard_changed ()
577 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
580 wxSpinCtrl* _j2k_bandwidth;
581 wxSpinCtrl* _audio_delay;
582 wxButton* _isdcf_metadata_button;
583 wxSpinCtrl* _still_length;
584 #ifdef DCPOMATIC_USE_OWN_PICKER
585 DirPickerCtrl* _directory;
587 wxDirPickerCtrl* _directory;
589 wxChoice* _container;
590 wxChoice* _dcp_content_type;
594 class EncodingServersPage : public StandardPage
597 EncodingServersPage (wxSize panel_size, int border)
598 : StandardPage (panel_size, border)
601 wxString GetName () const
607 wxBitmap GetLargeIcon () const
609 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
616 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
617 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
619 vector<string> columns;
620 columns.push_back (wx_to_std (_("IP address / host name")));
621 _servers_list = new EditableList<string, ServerDialog> (
624 boost::bind (&Config::servers, Config::instance()),
625 boost::bind (&Config::set_servers, Config::instance(), _1),
626 boost::bind (&always_valid),
627 boost::bind (&EncodingServersPage::server_column, this, _1)
630 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
632 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
635 void config_changed ()
637 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
638 _servers_list->refresh ();
641 void use_any_servers_changed ()
643 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
646 string server_column (string s)
651 wxCheckBox* _use_any_servers;
652 EditableList<string, ServerDialog>* _servers_list;
655 class CertificateChainEditor : public wxPanel
658 CertificateChainEditor (
662 function<void (shared_ptr<dcp::CertificateChain>)> set,
663 function<shared_ptr<const dcp::CertificateChain> (void)> get
669 wxFont subheading_font (*wxNORMAL_FONT);
670 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
672 _sizer = new wxBoxSizer (wxVERTICAL);
675 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
676 m->SetFont (subheading_font);
677 _sizer->Add (m, 0, wxALL, border);
680 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
681 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
683 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
688 ip.SetText (_("Type"));
690 _certificates->InsertColumn (0, ip);
696 ip.SetText (_("Thumbprint"));
699 wxFont font = ip.GetFont ();
700 font.SetFamily (wxFONTFAMILY_TELETYPE);
703 _certificates->InsertColumn (1, ip);
706 certificates_sizer->Add (_certificates, 1, wxEXPAND);
709 wxSizer* s = new wxBoxSizer (wxVERTICAL);
710 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
711 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
712 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
713 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
714 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
715 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
716 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
719 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
720 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
723 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
724 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
725 wxFont font = _private_key->GetFont ();
726 font.SetFamily (wxFONTFAMILY_TELETYPE);
727 _private_key->SetFont (font);
728 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
729 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
730 table->Add (_load_private_key, wxGBPosition (r, 2));
731 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
732 table->Add (_export_private_key, wxGBPosition (r, 3));
735 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
736 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
737 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
738 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
741 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
742 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
743 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
744 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
745 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
746 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
747 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
748 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
750 SetSizerAndFit (_sizer);
753 void config_changed ()
755 _chain.reset (new dcp::CertificateChain (*_get().get ()));
757 update_certificate_list ();
758 update_private_key ();
759 update_sensitivity ();
762 void add_button (wxWindow* button)
764 _button_sizer->Add (button);
769 void add_certificate ()
771 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
773 if (d->ShowModal() == wxID_OK) {
775 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
778 update_certificate_list ();
779 } catch (dcp::MiscError& e) {
780 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
786 update_sensitivity ();
789 void remove_certificate ()
791 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
796 _certificates->DeleteItem (i);
800 update_sensitivity ();
803 void export_certificate ()
805 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
810 wxFileDialog* d = new wxFileDialog (
811 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
812 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
815 dcp::CertificateChain::List all = _chain->root_to_leaf ();
816 dcp::CertificateChain::List::iterator j = all.begin ();
817 for (int k = 0; k < i; ++k) {
821 if (d->ShowModal () == wxID_OK) {
822 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
824 throw OpenFileError (wx_to_std (d->GetPath ()));
827 string const s = j->certificate (true);
828 fwrite (s.c_str(), 1, s.length(), f);
834 void update_certificate_list ()
836 _certificates->DeleteAllItems ();
838 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
839 BOOST_FOREACH (dcp::Certificate const & i, certs) {
842 _certificates->InsertItem (item);
843 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
846 _certificates->SetItem (n, 0, _("Root"));
847 } else if (n == (certs.size() - 1)) {
848 _certificates->SetItem (n, 0, _("Leaf"));
850 _certificates->SetItem (n, 0, _("Intermediate"));
857 void remake_certificates ()
859 shared_ptr<const dcp::CertificateChain> chain = _get ();
861 string subject_organization_name;
862 string subject_organizational_unit_name;
863 string root_common_name;
864 string intermediate_common_name;
865 string leaf_common_name;
867 dcp::CertificateChain::List all = chain->root_to_leaf ();
869 if (all.size() >= 1) {
871 subject_organization_name = chain->root().subject_organization_name ();
872 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
873 root_common_name = chain->root().subject_common_name ();
876 if (all.size() >= 2) {
878 leaf_common_name = chain->leaf().subject_common_name ();
881 if (all.size() >= 3) {
882 /* Have an intermediate */
883 dcp::CertificateChain::List::iterator i = all.begin ();
885 intermediate_common_name = i->subject_common_name ();
888 MakeChainDialog* d = new MakeChainDialog (
890 subject_organization_name,
891 subject_organizational_unit_name,
893 intermediate_common_name,
897 if (d->ShowModal () == wxID_OK) {
899 new dcp::CertificateChain (
902 d->organisational_unit (),
903 d->root_common_name (),
904 d->intermediate_common_name (),
905 d->leaf_common_name ()
910 update_certificate_list ();
911 update_private_key ();
917 void update_sensitivity ()
919 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
920 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
923 void update_private_key ()
925 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
929 void load_private_key ()
931 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
933 if (d->ShowModal() == wxID_OK) {
935 boost::filesystem::path p (wx_to_std (d->GetPath ()));
936 if (boost::filesystem::file_size (p) > 1024) {
937 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
941 _chain->set_key (dcp::file_to_string (p));
943 update_private_key ();
944 } catch (dcp::MiscError& e) {
945 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
951 update_sensitivity ();
954 void export_private_key ()
956 optional<string> key = _chain->key ();
961 wxFileDialog* d = new wxFileDialog (
962 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
963 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
966 if (d->ShowModal () == wxID_OK) {
967 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
969 throw OpenFileError (wx_to_std (d->GetPath ()));
972 string const s = _chain->key().get ();
973 fwrite (s.c_str(), 1, s.length(), f);
979 wxListCtrl* _certificates;
980 wxButton* _add_certificate;
981 wxButton* _export_certificate;
982 wxButton* _remove_certificate;
983 wxButton* _remake_certificates;
984 wxStaticText* _private_key;
985 wxButton* _load_private_key;
986 wxButton* _export_private_key;
988 wxBoxSizer* _button_sizer;
989 shared_ptr<dcp::CertificateChain> _chain;
990 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
991 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
994 class KeysPage : public StandardPage
997 KeysPage (wxSize panel_size, int border)
998 : StandardPage (panel_size, border)
1001 wxString GetName () const
1006 #ifdef DCPOMATIC_OSX
1007 wxBitmap GetLargeIcon () const
1009 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
1017 _signer = new CertificateChainEditor (
1018 _panel, _("Signing DCPs and KDMs"), _border,
1019 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
1020 boost::bind (&Config::signer_chain, Config::instance ())
1023 _panel->GetSizer()->Add (_signer);
1025 _decryption = new CertificateChainEditor (
1026 _panel, _("Decrypting DCPs"), _border,
1027 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1028 boost::bind (&Config::decryption_chain, Config::instance ())
1031 _panel->GetSizer()->Add (_decryption);
1033 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1034 _decryption->add_button (_export_decryption_certificate);
1036 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1039 void export_decryption_certificate ()
1041 wxFileDialog* d = new wxFileDialog (
1042 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1043 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1046 if (d->ShowModal () == wxID_OK) {
1047 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1049 throw OpenFileError (wx_to_std (d->GetPath ()));
1052 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1053 fwrite (s.c_str(), 1, s.length(), f);
1059 void config_changed ()
1061 _signer->config_changed ();
1062 _decryption->config_changed ();
1065 CertificateChainEditor* _signer;
1066 CertificateChainEditor* _decryption;
1067 wxButton* _export_decryption_certificate;
1070 class TMSPage : public StandardPage
1073 TMSPage (wxSize panel_size, int border)
1074 : StandardPage (panel_size, border)
1077 wxString GetName () const
1082 #ifdef DCPOMATIC_OSX
1083 wxBitmap GetLargeIcon () const
1085 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1092 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1093 table->AddGrowableCol (1, 1);
1094 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1096 add_label_to_sizer (table, _panel, _("Protocol"), true);
1097 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1098 table->Add (_tms_protocol, 1, wxEXPAND);
1100 add_label_to_sizer (table, _panel, _("IP address"), true);
1101 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1102 table->Add (_tms_ip, 1, wxEXPAND);
1104 add_label_to_sizer (table, _panel, _("Target path"), true);
1105 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1106 table->Add (_tms_path, 1, wxEXPAND);
1108 add_label_to_sizer (table, _panel, _("User name"), true);
1109 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1110 table->Add (_tms_user, 1, wxEXPAND);
1112 add_label_to_sizer (table, _panel, _("Password"), true);
1113 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1114 table->Add (_tms_password, 1, wxEXPAND);
1116 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1117 _tms_protocol->Append (_("FTP (for Dolby)"));
1119 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1120 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1121 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1122 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1123 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1126 void config_changed ()
1128 Config* config = Config::instance ();
1130 checked_set (_tms_protocol, config->tms_protocol ());
1131 checked_set (_tms_ip, config->tms_ip ());
1132 checked_set (_tms_path, config->tms_path ());
1133 checked_set (_tms_user, config->tms_user ());
1134 checked_set (_tms_password, config->tms_password ());
1137 void tms_protocol_changed ()
1139 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1142 void tms_ip_changed ()
1144 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1147 void tms_path_changed ()
1149 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1152 void tms_user_changed ()
1154 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1157 void tms_password_changed ()
1159 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1162 wxChoice* _tms_protocol;
1163 wxTextCtrl* _tms_ip;
1164 wxTextCtrl* _tms_path;
1165 wxTextCtrl* _tms_user;
1166 wxTextCtrl* _tms_password;
1175 class KDMEmailPage : public StandardPage
1179 KDMEmailPage (wxSize panel_size, int border)
1180 #ifdef DCPOMATIC_OSX
1181 /* We have to force both width and height of this one */
1182 : StandardPage (wxSize (480, 128), border)
1184 : StandardPage (panel_size, border)
1188 wxString GetName () const
1190 return _("KDM Email");
1193 #ifdef DCPOMATIC_OSX
1194 wxBitmap GetLargeIcon () const
1196 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1203 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1204 table->AddGrowableCol (1, 1);
1205 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1207 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1209 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1210 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1211 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1212 add_label_to_sizer (s, _panel, _("port"), false);
1213 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1214 _mail_port->SetRange (0, 65535);
1215 s->Add (_mail_port);
1216 table->Add (s, 1, wxEXPAND | wxALL);
1219 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1220 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1221 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1223 add_label_to_sizer (table, _panel, _("Mail password"), true);
1224 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1225 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1227 add_label_to_sizer (table, _panel, _("Subject"), true);
1228 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1229 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1231 add_label_to_sizer (table, _panel, _("From address"), true);
1232 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1233 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1235 vector<string> columns;
1236 columns.push_back (wx_to_std (_("Address")));
1237 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1238 _kdm_cc = new EditableList<string, EmailDialog> (
1241 bind (&Config::kdm_cc, Config::instance()),
1242 bind (&Config::set_kdm_cc, Config::instance(), _1),
1243 bind (&string_not_empty, _1),
1246 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1248 add_label_to_sizer (table, _panel, _("BCC address"), true);
1249 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1250 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1252 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1253 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1255 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1256 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1260 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1261 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1262 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1263 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1264 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1265 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1266 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1267 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1268 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1271 void config_changed ()
1273 Config* config = Config::instance ();
1275 checked_set (_mail_server, config->mail_server ());
1276 checked_set (_mail_port, config->mail_port ());
1277 checked_set (_mail_user, config->mail_user ());
1278 checked_set (_mail_password, config->mail_password ());
1279 checked_set (_kdm_subject, config->kdm_subject ());
1280 checked_set (_kdm_from, config->kdm_from ());
1281 checked_set (_kdm_bcc, config->kdm_bcc ());
1282 checked_set (_kdm_email, Config::instance()->kdm_email ());
1285 void mail_server_changed ()
1287 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1290 void mail_port_changed ()
1292 Config::instance()->set_mail_port (_mail_port->GetValue ());
1295 void mail_user_changed ()
1297 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1300 void mail_password_changed ()
1302 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1305 void kdm_subject_changed ()
1307 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1310 void kdm_from_changed ()
1312 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1315 void kdm_bcc_changed ()
1317 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1320 void kdm_email_changed ()
1322 if (_kdm_email->GetValue().IsEmpty ()) {
1323 /* Sometimes we get sent an erroneous notification that the email
1324 is empty; I don't know why.
1328 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1331 void reset_kdm_email ()
1333 Config::instance()->reset_kdm_email ();
1334 checked_set (_kdm_email, Config::instance()->kdm_email ());
1337 wxTextCtrl* _mail_server;
1338 wxSpinCtrl* _mail_port;
1339 wxTextCtrl* _mail_user;
1340 wxTextCtrl* _mail_password;
1341 wxTextCtrl* _kdm_subject;
1342 wxTextCtrl* _kdm_from;
1343 EditableList<string, EmailDialog>* _kdm_cc;
1344 wxTextCtrl* _kdm_bcc;
1345 wxTextCtrl* _kdm_email;
1346 wxButton* _reset_kdm_email;
1349 /** @class AdvancedPage
1350 * @brief Advanced page of the preferences dialog.
1352 class AdvancedPage : public StockPage
1355 AdvancedPage (wxSize panel_size, int border)
1356 : StockPage (Kind_Advanced, panel_size, border)
1357 , _maximum_j2k_bandwidth (0)
1358 , _allow_any_dcp_frame_rate (0)
1359 , _only_servers_encode (0)
1364 , _log_debug_decode (0)
1365 , _log_debug_encode (0)
1366 , _log_debug_email (0)
1372 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1373 table->AddGrowableCol (1, 1);
1374 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1377 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1378 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1379 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1380 s->Add (_maximum_j2k_bandwidth, 1);
1381 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1385 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1386 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1387 table->AddSpacer (0);
1389 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1390 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1391 table->AddSpacer (0);
1394 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1395 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1397 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1398 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1402 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1403 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1404 t->Add (_log_general, 1, wxEXPAND | wxALL);
1405 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1406 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1407 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1408 t->Add (_log_error, 1, wxEXPAND | wxALL);
1409 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1410 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1411 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1412 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1413 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1414 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1415 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1416 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1417 table->Add (t, 0, wxALL, 6);
1420 #ifdef DCPOMATIC_WINDOWS
1421 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1422 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1423 table->AddSpacer (0);
1426 _maximum_j2k_bandwidth->SetRange (1, 1000);
1427 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1428 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1429 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1430 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1431 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1432 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1433 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1434 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1435 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1436 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1437 #ifdef DCPOMATIC_WINDOWS
1438 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1442 void config_changed ()
1444 Config* config = Config::instance ();
1446 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1447 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1448 checked_set (_only_servers_encode, config->only_servers_encode ());
1449 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1450 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1451 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1452 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1453 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1454 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1455 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1456 #ifdef DCPOMATIC_WINDOWS
1457 checked_set (_win32_console, config->win32_console());
1461 void maximum_j2k_bandwidth_changed ()
1463 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1466 void allow_any_dcp_frame_rate_changed ()
1468 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1471 void only_servers_encode_changed ()
1473 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1479 if (_log_general->GetValue ()) {
1480 types |= LogEntry::TYPE_GENERAL;
1482 if (_log_warning->GetValue ()) {
1483 types |= LogEntry::TYPE_WARNING;
1485 if (_log_error->GetValue ()) {
1486 types |= LogEntry::TYPE_ERROR;
1488 if (_log_timing->GetValue ()) {
1489 types |= LogEntry::TYPE_TIMING;
1491 if (_log_debug_decode->GetValue ()) {
1492 types |= LogEntry::TYPE_DEBUG_DECODE;
1494 if (_log_debug_encode->GetValue ()) {
1495 types |= LogEntry::TYPE_DEBUG_ENCODE;
1497 if (_log_debug_email->GetValue ()) {
1498 types |= LogEntry::TYPE_DEBUG_EMAIL;
1500 Config::instance()->set_log_types (types);
1503 #ifdef DCPOMATIC_WINDOWS
1504 void win32_console_changed ()
1506 Config::instance()->set_win32_console (_win32_console->GetValue ());
1510 wxSpinCtrl* _maximum_j2k_bandwidth;
1511 wxCheckBox* _allow_any_dcp_frame_rate;
1512 wxCheckBox* _only_servers_encode;
1513 wxCheckBox* _log_general;
1514 wxCheckBox* _log_warning;
1515 wxCheckBox* _log_error;
1516 wxCheckBox* _log_timing;
1517 wxCheckBox* _log_debug_decode;
1518 wxCheckBox* _log_debug_encode;
1519 wxCheckBox* _log_debug_email;
1520 #ifdef DCPOMATIC_WINDOWS
1521 wxCheckBox* _win32_console;
1525 wxPreferencesEditor*
1526 create_config_dialog ()
1528 wxPreferencesEditor* e = new wxPreferencesEditor ();
1530 #ifdef DCPOMATIC_OSX
1531 /* Width that we force some of the config panels to be on OSX so that
1532 the containing window doesn't shrink too much when we select those panels.
1533 This is obviously an unpleasant hack.
1535 wxSize ps = wxSize (520, -1);
1536 int const border = 16;
1538 wxSize ps = wxSize (-1, -1);
1539 int const border = 8;
1542 e->AddPage (new GeneralPage (ps, border));
1543 e->AddPage (new DefaultsPage (ps, border));
1544 e->AddPage (new EncodingServersPage (ps, border));
1545 e->AddPage (new KeysPage (ps, border));
1546 e->AddPage (new TMSPage (ps, border));
1547 e->AddPage (new KDMEmailPage (ps, border));
1548 e->AddPage (new AdvancedPage (ps, border));