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/lexical_cast.hpp>
50 #include <boost/filesystem.hpp>
51 #include <boost/foreach.hpp>
59 using boost::shared_ptr;
60 using boost::lexical_cast;
61 using boost::function;
62 using boost::optional;
67 Page (wxSize panel_size, int border)
70 , _panel_size (panel_size)
71 , _window_exists (false)
73 _config_connection = Config::instance()->Changed.connect (boost::bind (&Page::config_changed_wrapper, this));
79 wxWindow* create_window (wxWindow* parent)
81 _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size);
82 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
86 _window_exists = true;
89 _panel->Bind (wxEVT_DESTROY, boost::bind (&Page::window_destroyed, this));
98 virtual void config_changed () = 0;
99 virtual void setup () = 0;
101 void config_changed_wrapper ()
103 if (_window_exists) {
108 void window_destroyed ()
110 _window_exists = false;
114 boost::signals2::scoped_connection _config_connection;
118 class StockPage : public wxStockPreferencesPage, public Page
121 StockPage (Kind kind, wxSize panel_size, int border)
122 : wxStockPreferencesPage (kind)
123 , Page (panel_size, border)
126 wxWindow* CreateWindow (wxWindow* parent)
128 return create_window (parent);
132 class StandardPage : public wxPreferencesPage, public Page
135 StandardPage (wxSize panel_size, int border)
136 : Page (panel_size, border)
139 wxWindow* CreateWindow (wxWindow* parent)
141 return create_window (parent);
145 class GeneralPage : public StockPage
148 GeneralPage (wxSize panel_size, int border)
149 : StockPage (Kind_General, panel_size, border)
155 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
156 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
159 _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language"));
160 table->Add (_set_language, wxGBPosition (r, 0));
161 _language = new wxChoice (_panel, wxID_ANY);
162 _language->Append (wxT ("Deutsch"));
163 _language->Append (wxT ("English"));
164 _language->Append (wxT ("Español"));
165 _language->Append (wxT ("Français"));
166 _language->Append (wxT ("Italiano"));
167 _language->Append (wxT ("Nederlands"));
168 _language->Append (wxT ("Svenska"));
169 _language->Append (wxT ("Русский"));
170 _language->Append (wxT ("Polski"));
171 _language->Append (wxT ("Dansk"));
172 _language->Append (wxT ("Português europeu"));
173 _language->Append (wxT ("Slovenský jazyk"));
174 _language->Append (wxT ("Čeština"));
175 table->Add (_language, wxGBPosition (r, 1));
178 wxStaticText* restart = add_label_to_sizer (
179 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
181 wxFont font = restart->GetFont();
182 font.SetStyle (wxFONTSTYLE_ITALIC);
183 font.SetPointSize (font.GetPointSize() - 1);
184 restart->SetFont (font);
187 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
188 _num_local_encoding_threads = new wxSpinCtrl (_panel);
189 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
192 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
193 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml");
194 table->Add (_cinemas_file, wxGBPosition (r, 1));
197 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
198 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
201 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
202 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
205 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
206 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
209 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
210 bottom_table->AddGrowableCol (1, 1);
212 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
213 _issuer = new wxTextCtrl (_panel, wxID_ANY);
214 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
216 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
217 _creator = new wxTextCtrl (_panel, wxID_ANY);
218 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
220 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
223 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
224 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
225 _cinemas_file->Bind (wxEVT_COMMAND_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
227 _num_local_encoding_threads->SetRange (1, 128);
228 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
230 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
231 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
232 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
234 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
235 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
238 void config_changed ()
240 Config* config = Config::instance ();
242 checked_set (_set_language, static_cast<bool>(config->language()));
244 if (config->language().get_value_or ("") == "fr") {
245 checked_set (_language, 3);
246 } else if (config->language().get_value_or ("") == "it") {
247 checked_set (_language, 4);
248 } else if (config->language().get_value_or ("") == "es") {
249 checked_set (_language, 2);
250 } else if (config->language().get_value_or ("") == "sv") {
251 checked_set (_language, 6);
252 } else if (config->language().get_value_or ("") == "de") {
253 checked_set (_language, 0);
254 } else if (config->language().get_value_or ("") == "nl") {
255 checked_set (_language, 5);
256 } else if (config->language().get_value_or ("") == "ru") {
257 checked_set (_language, 7);
258 } else if (config->language().get_value_or ("") == "pl") {
259 checked_set (_language, 8);
260 } else if (config->language().get_value_or ("") == "da") {
261 checked_set (_language, 9);
262 } else if (config->language().get_value_or ("") == "pt") {
263 checked_set (_language, 10);
264 } else if (config->language().get_value_or ("") == "sk") {
265 checked_set (_language, 11);
266 } else if (config->language().get_value_or ("") == "cs") {
267 checked_set (_language, 12);
269 _language->SetSelection (1);
272 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
273 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
274 checked_set (_check_for_updates, config->check_for_updates ());
275 checked_set (_check_for_test_updates, config->check_for_test_updates ());
276 checked_set (_issuer, config->dcp_issuer ());
277 checked_set (_creator, config->dcp_creator ());
278 checked_set (_cinemas_file, config->cinemas_file());
280 setup_sensitivity ();
283 void setup_sensitivity ()
285 _language->Enable (_set_language->GetValue ());
286 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
289 void set_language_changed ()
291 setup_sensitivity ();
292 if (_set_language->GetValue ()) {
295 Config::instance()->unset_language ();
299 void language_changed ()
301 switch (_language->GetSelection ()) {
303 Config::instance()->set_language ("de");
306 Config::instance()->set_language ("en");
309 Config::instance()->set_language ("es");
312 Config::instance()->set_language ("fr");
315 Config::instance()->set_language ("it");
318 Config::instance()->set_language ("nl");
321 Config::instance()->set_language ("sv");
324 Config::instance()->set_language ("ru");
327 Config::instance()->set_language ("pl");
330 Config::instance()->set_language ("da");
333 Config::instance()->set_language ("pt");
336 Config::instance()->set_language ("sk");
339 Config::instance()->set_language ("cs");
344 void automatic_audio_analysis_changed ()
346 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
349 void check_for_updates_changed ()
351 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
354 void check_for_test_updates_changed ()
356 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
359 void num_local_encoding_threads_changed ()
361 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
364 void issuer_changed ()
366 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
369 void creator_changed ()
371 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
374 void cinemas_file_changed ()
376 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
379 wxCheckBox* _set_language;
381 wxSpinCtrl* _num_local_encoding_threads;
382 FilePickerCtrl* _cinemas_file;
383 wxCheckBox* _automatic_audio_analysis;
384 wxCheckBox* _check_for_updates;
385 wxCheckBox* _check_for_test_updates;
387 wxTextCtrl* _creator;
390 class DefaultsPage : public StandardPage
393 DefaultsPage (wxSize panel_size, int border)
394 : StandardPage (panel_size, border)
397 wxString GetName () const
399 return _("Defaults");
403 wxBitmap GetLargeIcon () const
405 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
412 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
413 table->AddGrowableCol (1, 1);
414 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
417 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
418 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
419 _still_length = new wxSpinCtrl (_panel);
420 s->Add (_still_length);
421 add_label_to_sizer (s, _panel, _("s"), false);
425 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
426 #ifdef DCPOMATIC_USE_OWN_PICKER
427 _directory = new DirPickerCtrl (_panel);
429 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
431 table->Add (_directory, 1, wxEXPAND);
433 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
434 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
435 table->Add (_isdcf_metadata_button);
437 add_label_to_sizer (table, _panel, _("Default container"), true);
438 _container = new wxChoice (_panel, wxID_ANY);
439 table->Add (_container);
441 add_label_to_sizer (table, _panel, _("Default content type"), true);
442 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
443 table->Add (_dcp_content_type);
446 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
447 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
448 _j2k_bandwidth = new wxSpinCtrl (_panel);
449 s->Add (_j2k_bandwidth);
450 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
455 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
456 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
457 _audio_delay = new wxSpinCtrl (_panel);
458 s->Add (_audio_delay);
459 add_label_to_sizer (s, _panel, _("ms"), false);
463 add_label_to_sizer (table, _panel, _("Default standard"), true);
464 _standard = new wxChoice (_panel, wxID_ANY);
465 table->Add (_standard);
467 _still_length->SetRange (1, 3600);
468 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
470 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
472 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
474 vector<Ratio const *> ratios = Ratio::all ();
475 for (size_t i = 0; i < ratios.size(); ++i) {
476 _container->Append (std_to_wx (ratios[i]->nickname ()));
479 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
481 vector<DCPContentType const *> const ct = DCPContentType::all ();
482 for (size_t i = 0; i < ct.size(); ++i) {
483 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
486 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
488 _j2k_bandwidth->SetRange (50, 250);
489 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
491 _audio_delay->SetRange (-1000, 1000);
492 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
494 _standard->Append (_("SMPTE"));
495 _standard->Append (_("Interop"));
496 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
499 void config_changed ()
501 Config* config = Config::instance ();
503 vector<Ratio const *> ratios = Ratio::all ();
504 for (size_t i = 0; i < ratios.size(); ++i) {
505 if (ratios[i] == config->default_container ()) {
506 _container->SetSelection (i);
510 vector<DCPContentType const *> const ct = DCPContentType::all ();
511 for (size_t i = 0; i < ct.size(); ++i) {
512 if (ct[i] == config->default_dcp_content_type ()) {
513 _dcp_content_type->SetSelection (i);
517 checked_set (_still_length, config->default_still_length ());
518 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
519 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
520 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
521 checked_set (_audio_delay, config->default_audio_delay ());
522 checked_set (_standard, config->default_interop() ? 1 : 0);
525 void j2k_bandwidth_changed ()
527 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
530 void audio_delay_changed ()
532 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
535 void directory_changed ()
537 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
540 void edit_isdcf_metadata_clicked ()
542 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
544 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
548 void still_length_changed ()
550 Config::instance()->set_default_still_length (_still_length->GetValue ());
553 void container_changed ()
555 vector<Ratio const *> ratio = Ratio::all ();
556 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
559 void dcp_content_type_changed ()
561 vector<DCPContentType const *> ct = DCPContentType::all ();
562 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
565 void standard_changed ()
567 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
570 wxSpinCtrl* _j2k_bandwidth;
571 wxSpinCtrl* _audio_delay;
572 wxButton* _isdcf_metadata_button;
573 wxSpinCtrl* _still_length;
574 #ifdef DCPOMATIC_USE_OWN_PICKER
575 DirPickerCtrl* _directory;
577 wxDirPickerCtrl* _directory;
579 wxChoice* _container;
580 wxChoice* _dcp_content_type;
584 class EncodingServersPage : public StandardPage
587 EncodingServersPage (wxSize panel_size, int border)
588 : StandardPage (panel_size, border)
591 wxString GetName () const
597 wxBitmap GetLargeIcon () const
599 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
606 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
607 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
609 vector<string> columns;
610 columns.push_back (wx_to_std (_("IP address / host name")));
611 _servers_list = new EditableList<string, ServerDialog> (
614 boost::bind (&Config::servers, Config::instance()),
615 boost::bind (&Config::set_servers, Config::instance(), _1),
616 boost::bind (&EncodingServersPage::server_column, this, _1)
619 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
621 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
624 void config_changed ()
626 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
627 _servers_list->refresh ();
630 void use_any_servers_changed ()
632 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
635 string server_column (string s)
640 wxCheckBox* _use_any_servers;
641 EditableList<string, ServerDialog>* _servers_list;
644 class CertificateChainEditor : public wxPanel
647 CertificateChainEditor (
651 function<void (shared_ptr<dcp::CertificateChain>)> set,
652 function<shared_ptr<const dcp::CertificateChain> (void)> get
658 wxFont subheading_font (*wxNORMAL_FONT);
659 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
661 _sizer = new wxBoxSizer (wxVERTICAL);
664 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
665 m->SetFont (subheading_font);
666 _sizer->Add (m, 0, wxALL, border);
669 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
670 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
672 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
677 ip.SetText (_("Type"));
679 _certificates->InsertColumn (0, ip);
685 ip.SetText (_("Thumbprint"));
688 wxFont font = ip.GetFont ();
689 font.SetFamily (wxFONTFAMILY_TELETYPE);
692 _certificates->InsertColumn (1, ip);
695 certificates_sizer->Add (_certificates, 1, wxEXPAND);
698 wxSizer* s = new wxBoxSizer (wxVERTICAL);
699 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
700 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
701 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
702 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
703 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
704 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
705 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
708 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
709 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
712 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
713 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
714 wxFont font = _private_key->GetFont ();
715 font.SetFamily (wxFONTFAMILY_TELETYPE);
716 _private_key->SetFont (font);
717 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
718 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
719 table->Add (_load_private_key, wxGBPosition (r, 2));
720 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
721 table->Add (_export_private_key, wxGBPosition (r, 3));
724 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
725 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
726 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
727 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
730 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
731 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
732 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
733 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
734 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
735 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
736 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
737 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
739 SetSizerAndFit (_sizer);
742 void config_changed ()
744 _chain.reset (new dcp::CertificateChain (*_get().get ()));
746 update_certificate_list ();
747 update_private_key ();
748 update_sensitivity ();
751 void add_button (wxWindow* button)
753 _button_sizer->Add (button);
758 void add_certificate ()
760 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
762 if (d->ShowModal() == wxID_OK) {
764 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
767 update_certificate_list ();
768 } catch (dcp::MiscError& e) {
769 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
775 update_sensitivity ();
778 void remove_certificate ()
780 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
785 _certificates->DeleteItem (i);
789 update_sensitivity ();
792 void export_certificate ()
794 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
799 wxFileDialog* d = new wxFileDialog (
800 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
801 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
804 dcp::CertificateChain::List all = _chain->root_to_leaf ();
805 dcp::CertificateChain::List::iterator j = all.begin ();
806 for (int k = 0; k < i; ++k) {
810 if (d->ShowModal () == wxID_OK) {
811 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
813 throw OpenFileError (wx_to_std (d->GetPath ()));
816 string const s = j->certificate (true);
817 fwrite (s.c_str(), 1, s.length(), f);
823 void update_certificate_list ()
825 _certificates->DeleteAllItems ();
827 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
828 BOOST_FOREACH (dcp::Certificate const & i, certs) {
831 _certificates->InsertItem (item);
832 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
835 _certificates->SetItem (n, 0, _("Root"));
836 } else if (n == (certs.size() - 1)) {
837 _certificates->SetItem (n, 0, _("Leaf"));
839 _certificates->SetItem (n, 0, _("Intermediate"));
846 void remake_certificates ()
848 shared_ptr<const dcp::CertificateChain> chain = _get ();
850 string subject_organization_name;
851 string subject_organizational_unit_name;
852 string root_common_name;
853 string intermediate_common_name;
854 string leaf_common_name;
856 dcp::CertificateChain::List all = chain->root_to_leaf ();
858 if (all.size() >= 1) {
860 subject_organization_name = chain->root().subject_organization_name ();
861 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
862 root_common_name = chain->root().subject_common_name ();
865 if (all.size() >= 2) {
867 leaf_common_name = chain->leaf().subject_common_name ();
870 if (all.size() >= 3) {
871 /* Have an intermediate */
872 dcp::CertificateChain::List::iterator i = all.begin ();
874 intermediate_common_name = i->subject_common_name ();
877 MakeChainDialog* d = new MakeChainDialog (
879 subject_organization_name,
880 subject_organizational_unit_name,
882 intermediate_common_name,
886 if (d->ShowModal () == wxID_OK) {
888 new dcp::CertificateChain (
891 d->organisational_unit (),
892 d->root_common_name (),
893 d->intermediate_common_name (),
894 d->leaf_common_name ()
899 update_certificate_list ();
900 update_private_key ();
906 void update_sensitivity ()
908 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
909 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
912 void update_private_key ()
914 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
918 void load_private_key ()
920 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
922 if (d->ShowModal() == wxID_OK) {
924 boost::filesystem::path p (wx_to_std (d->GetPath ()));
925 if (boost::filesystem::file_size (p) > 1024) {
926 error_dialog (this, wxString::Format (_("Could not read key file (%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> (
1228 _panel, columns, bind (&Config::kdm_cc, Config::instance()), bind (&Config::set_kdm_cc, Config::instance(), _1), bind (&column, _1)
1230 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1232 add_label_to_sizer (table, _panel, _("BCC address"), true);
1233 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1234 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1236 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1237 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1239 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1240 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1242 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1243 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1244 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1245 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1246 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1247 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1248 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1249 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1250 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1253 void config_changed ()
1255 Config* config = Config::instance ();
1257 checked_set (_mail_server, config->mail_server ());
1258 checked_set (_mail_port, config->mail_port ());
1259 checked_set (_mail_user, config->mail_user ());
1260 checked_set (_mail_password, config->mail_password ());
1261 checked_set (_kdm_subject, config->kdm_subject ());
1262 checked_set (_kdm_from, config->kdm_from ());
1263 checked_set (_kdm_bcc, config->kdm_bcc ());
1264 checked_set (_kdm_email, Config::instance()->kdm_email ());
1267 void mail_server_changed ()
1269 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1272 void mail_port_changed ()
1274 Config::instance()->set_mail_port (_mail_port->GetValue ());
1277 void mail_user_changed ()
1279 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1282 void mail_password_changed ()
1284 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1287 void kdm_subject_changed ()
1289 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1292 void kdm_from_changed ()
1294 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1297 void kdm_bcc_changed ()
1299 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1302 void kdm_email_changed ()
1304 if (_kdm_email->GetValue().IsEmpty ()) {
1305 /* Sometimes we get sent an erroneous notification that the email
1306 is empty; I don't know why.
1310 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1313 void reset_kdm_email ()
1315 Config::instance()->reset_kdm_email ();
1316 checked_set (_kdm_email, Config::instance()->kdm_email ());
1319 wxTextCtrl* _mail_server;
1320 wxSpinCtrl* _mail_port;
1321 wxTextCtrl* _mail_user;
1322 wxTextCtrl* _mail_password;
1323 wxTextCtrl* _kdm_subject;
1324 wxTextCtrl* _kdm_from;
1325 EditableList<string, EmailDialog>* _kdm_cc;
1326 wxTextCtrl* _kdm_bcc;
1327 wxTextCtrl* _kdm_email;
1328 wxButton* _reset_kdm_email;
1331 /** @class AdvancedPage
1332 * @brief Advanced page of the preferences dialog.
1334 class AdvancedPage : public StockPage
1337 AdvancedPage (wxSize panel_size, int border)
1338 : StockPage (Kind_Advanced, panel_size, border)
1339 , _maximum_j2k_bandwidth (0)
1340 , _allow_any_dcp_frame_rate (0)
1341 , _only_servers_encode (0)
1346 , _log_debug_decode (0)
1347 , _log_debug_encode (0)
1348 , _log_debug_email (0)
1354 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1355 table->AddGrowableCol (1, 1);
1356 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1359 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1360 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1361 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1362 s->Add (_maximum_j2k_bandwidth, 1);
1363 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1367 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1368 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1369 table->AddSpacer (0);
1371 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1372 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1373 table->AddSpacer (0);
1376 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1377 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1379 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1380 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1384 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1385 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1386 t->Add (_log_general, 1, wxEXPAND | wxALL);
1387 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1388 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1389 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1390 t->Add (_log_error, 1, wxEXPAND | wxALL);
1391 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1392 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1393 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1394 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1395 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1396 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1397 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1398 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1399 table->Add (t, 0, wxALL, 6);
1402 #ifdef DCPOMATIC_WINDOWS
1403 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1404 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1405 table->AddSpacer (0);
1408 _maximum_j2k_bandwidth->SetRange (1, 1000);
1409 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1410 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1411 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1412 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1413 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1414 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1415 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1416 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1417 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1418 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1419 #ifdef DCPOMATIC_WINDOWS
1420 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1424 void config_changed ()
1426 Config* config = Config::instance ();
1428 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1429 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1430 checked_set (_only_servers_encode, config->only_servers_encode ());
1431 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1432 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1433 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1434 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1435 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1436 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1437 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1438 #ifdef DCPOMATIC_WINDOWS
1439 checked_set (_win32_console, config->win32_console());
1443 void maximum_j2k_bandwidth_changed ()
1445 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1448 void allow_any_dcp_frame_rate_changed ()
1450 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1453 void only_servers_encode_changed ()
1455 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1461 if (_log_general->GetValue ()) {
1462 types |= LogEntry::TYPE_GENERAL;
1464 if (_log_warning->GetValue ()) {
1465 types |= LogEntry::TYPE_WARNING;
1467 if (_log_error->GetValue ()) {
1468 types |= LogEntry::TYPE_ERROR;
1470 if (_log_timing->GetValue ()) {
1471 types |= LogEntry::TYPE_TIMING;
1473 if (_log_debug_decode->GetValue ()) {
1474 types |= LogEntry::TYPE_DEBUG_DECODE;
1476 if (_log_debug_encode->GetValue ()) {
1477 types |= LogEntry::TYPE_DEBUG_ENCODE;
1479 if (_log_debug_email->GetValue ()) {
1480 types |= LogEntry::TYPE_DEBUG_EMAIL;
1482 Config::instance()->set_log_types (types);
1485 #ifdef DCPOMATIC_WINDOWS
1486 void win32_console_changed ()
1488 Config::instance()->set_win32_console (_win32_console->GetValue ());
1492 wxSpinCtrl* _maximum_j2k_bandwidth;
1493 wxCheckBox* _allow_any_dcp_frame_rate;
1494 wxCheckBox* _only_servers_encode;
1495 wxCheckBox* _log_general;
1496 wxCheckBox* _log_warning;
1497 wxCheckBox* _log_error;
1498 wxCheckBox* _log_timing;
1499 wxCheckBox* _log_debug_decode;
1500 wxCheckBox* _log_debug_encode;
1501 wxCheckBox* _log_debug_email;
1502 #ifdef DCPOMATIC_WINDOWS
1503 wxCheckBox* _win32_console;
1507 wxPreferencesEditor*
1508 create_config_dialog ()
1510 wxPreferencesEditor* e = new wxPreferencesEditor ();
1512 #ifdef DCPOMATIC_OSX
1513 /* Width that we force some of the config panels to be on OSX so that
1514 the containing window doesn't shrink too much when we select those panels.
1515 This is obviously an unpleasant hack.
1517 wxSize ps = wxSize (520, -1);
1518 int const border = 16;
1520 wxSize ps = wxSize (-1, -1);
1521 int const border = 8;
1524 e->AddPage (new GeneralPage (ps, border));
1525 e->AddPage (new DefaultsPage (ps, border));
1526 e->AddPage (new EncodingServersPage (ps, border));
1527 e->AddPage (new KeysPage (ps, border));
1528 e->AddPage (new TMSPage (ps, border));
1529 e->AddPage (new KDMEmailPage (ps, border));
1530 e->AddPage (new AdvancedPage (ps, border));