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>
58 using boost::shared_ptr;
59 using boost::function;
60 using boost::optional;
65 Page (wxSize panel_size, int border)
68 , _panel_size (panel_size)
69 , _window_exists (false)
71 _config_connection = Config::instance()->Changed.connect (boost::bind (&Page::config_changed_wrapper, this));
77 wxWindow* create_window (wxWindow* parent)
79 _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size);
80 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
84 _window_exists = true;
87 _panel->Bind (wxEVT_DESTROY, boost::bind (&Page::window_destroyed, this));
96 virtual void config_changed () = 0;
97 virtual void setup () = 0;
99 void config_changed_wrapper ()
101 if (_window_exists) {
106 void window_destroyed ()
108 _window_exists = false;
112 boost::signals2::scoped_connection _config_connection;
116 class StockPage : public wxStockPreferencesPage, public Page
119 StockPage (Kind kind, wxSize panel_size, int border)
120 : wxStockPreferencesPage (kind)
121 , Page (panel_size, border)
124 wxWindow* CreateWindow (wxWindow* parent)
126 return create_window (parent);
130 class StandardPage : public wxPreferencesPage, public Page
133 StandardPage (wxSize panel_size, int border)
134 : Page (panel_size, border)
137 wxWindow* CreateWindow (wxWindow* parent)
139 return create_window (parent);
143 class GeneralPage : public StockPage
146 GeneralPage (wxSize panel_size, int border)
147 : StockPage (Kind_General, panel_size, border)
153 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
154 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
157 _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language"));
158 table->Add (_set_language, wxGBPosition (r, 0));
159 _language = new wxChoice (_panel, wxID_ANY);
160 _language->Append (wxT ("Deutsch"));
161 _language->Append (wxT ("English"));
162 _language->Append (wxT ("Español"));
163 _language->Append (wxT ("Français"));
164 _language->Append (wxT ("Italiano"));
165 _language->Append (wxT ("Nederlands"));
166 _language->Append (wxT ("Svenska"));
167 _language->Append (wxT ("Русский"));
168 _language->Append (wxT ("Polski"));
169 _language->Append (wxT ("Dansk"));
170 _language->Append (wxT ("Português europeu"));
171 _language->Append (wxT ("Slovenský jazyk"));
172 _language->Append (wxT ("Čeština"));
173 _language->Append (wxT ("українська мова"));
174 table->Add (_language, wxGBPosition (r, 1));
177 wxStaticText* restart = add_label_to_sizer (
178 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
180 wxFont font = restart->GetFont();
181 font.SetStyle (wxFONTSTYLE_ITALIC);
182 font.SetPointSize (font.GetPointSize() - 1);
183 restart->SetFont (font);
186 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
187 _num_local_encoding_threads = new wxSpinCtrl (_panel);
188 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
191 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
192 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml");
193 table->Add (_cinemas_file, wxGBPosition (r, 1));
196 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
197 _analyse_ebur128 = new wxCheckBox (_panel, wxID_ANY, _("Find integrated loudness, true peak and loudness range when analysing audio"));
198 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
202 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
203 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
206 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
207 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
210 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
211 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
214 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
215 bottom_table->AddGrowableCol (1, 1);
217 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
218 _issuer = new wxTextCtrl (_panel, wxID_ANY);
219 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
221 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
222 _creator = new wxTextCtrl (_panel, wxID_ANY);
223 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
225 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
228 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
229 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
230 _cinemas_file->Bind (wxEVT_COMMAND_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
232 _num_local_encoding_threads->SetRange (1, 128);
233 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
235 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
236 _analyse_ebur128->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::analyse_ebur128_changed, this));
238 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
239 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
240 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
242 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
243 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
246 void config_changed ()
248 Config* config = Config::instance ();
250 checked_set (_set_language, static_cast<bool>(config->language()));
252 if (config->language().get_value_or ("") == "fr") {
253 checked_set (_language, 3);
254 } else if (config->language().get_value_or ("") == "it") {
255 checked_set (_language, 4);
256 } else if (config->language().get_value_or ("") == "es") {
257 checked_set (_language, 2);
258 } else if (config->language().get_value_or ("") == "sv") {
259 checked_set (_language, 6);
260 } else if (config->language().get_value_or ("") == "de") {
261 checked_set (_language, 0);
262 } else if (config->language().get_value_or ("") == "nl") {
263 checked_set (_language, 5);
264 } else if (config->language().get_value_or ("") == "ru") {
265 checked_set (_language, 7);
266 } else if (config->language().get_value_or ("") == "pl") {
267 checked_set (_language, 8);
268 } else if (config->language().get_value_or ("") == "da") {
269 checked_set (_language, 9);
270 } else if (config->language().get_value_or ("") == "pt") {
271 checked_set (_language, 10);
272 } else if (config->language().get_value_or ("") == "sk") {
273 checked_set (_language, 11);
274 } else if (config->language().get_value_or ("") == "cs") {
275 checked_set (_language, 12);
276 } else if (config->language().get_value_or ("") == "uk") {
277 checked_set (_language, 13);
279 _language->SetSelection (1);
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 switch (_language->GetSelection ()) {
316 Config::instance()->set_language ("de");
319 Config::instance()->set_language ("en");
322 Config::instance()->set_language ("es");
325 Config::instance()->set_language ("fr");
328 Config::instance()->set_language ("it");
331 Config::instance()->set_language ("nl");
334 Config::instance()->set_language ("sv");
337 Config::instance()->set_language ("ru");
340 Config::instance()->set_language ("pl");
343 Config::instance()->set_language ("da");
346 Config::instance()->set_language ("pt");
349 Config::instance()->set_language ("sk");
352 Config::instance()->set_language ("cs");
355 Config::instance()->set_language ("uk");
360 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
361 void analyse_ebur128_changed ()
363 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
367 void automatic_audio_analysis_changed ()
369 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
372 void check_for_updates_changed ()
374 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
377 void check_for_test_updates_changed ()
379 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
382 void num_local_encoding_threads_changed ()
384 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
387 void issuer_changed ()
389 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
392 void creator_changed ()
394 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
397 void cinemas_file_changed ()
399 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
402 wxCheckBox* _set_language;
404 wxSpinCtrl* _num_local_encoding_threads;
405 FilePickerCtrl* _cinemas_file;
406 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
407 wxCheckBox* _analyse_ebur128;
409 wxCheckBox* _automatic_audio_analysis;
410 wxCheckBox* _check_for_updates;
411 wxCheckBox* _check_for_test_updates;
413 wxTextCtrl* _creator;
416 class DefaultsPage : public StandardPage
419 DefaultsPage (wxSize panel_size, int border)
420 : StandardPage (panel_size, border)
423 wxString GetName () const
425 return _("Defaults");
429 wxBitmap GetLargeIcon () const
431 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
438 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
439 table->AddGrowableCol (1, 1);
440 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
443 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
444 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
445 _still_length = new wxSpinCtrl (_panel);
446 s->Add (_still_length);
447 add_label_to_sizer (s, _panel, _("s"), false);
451 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
452 #ifdef DCPOMATIC_USE_OWN_PICKER
453 _directory = new DirPickerCtrl (_panel);
455 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
457 table->Add (_directory, 1, wxEXPAND);
459 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
460 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
461 table->Add (_isdcf_metadata_button);
463 add_label_to_sizer (table, _panel, _("Default container"), true);
464 _container = new wxChoice (_panel, wxID_ANY);
465 table->Add (_container);
467 add_label_to_sizer (table, _panel, _("Default content type"), true);
468 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
469 table->Add (_dcp_content_type);
472 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
473 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
474 _j2k_bandwidth = new wxSpinCtrl (_panel);
475 s->Add (_j2k_bandwidth);
476 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
481 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
482 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
483 _audio_delay = new wxSpinCtrl (_panel);
484 s->Add (_audio_delay);
485 add_label_to_sizer (s, _panel, _("ms"), false);
489 add_label_to_sizer (table, _panel, _("Default standard"), true);
490 _standard = new wxChoice (_panel, wxID_ANY);
491 table->Add (_standard);
493 _still_length->SetRange (1, 3600);
494 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
496 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
498 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
500 vector<Ratio const *> ratios = Ratio::all ();
501 for (size_t i = 0; i < ratios.size(); ++i) {
502 _container->Append (std_to_wx (ratios[i]->nickname ()));
505 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
507 vector<DCPContentType const *> const ct = DCPContentType::all ();
508 for (size_t i = 0; i < ct.size(); ++i) {
509 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
512 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
514 _j2k_bandwidth->SetRange (50, 250);
515 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
517 _audio_delay->SetRange (-1000, 1000);
518 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
520 _standard->Append (_("SMPTE"));
521 _standard->Append (_("Interop"));
522 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
525 void config_changed ()
527 Config* config = Config::instance ();
529 vector<Ratio const *> ratios = Ratio::all ();
530 for (size_t i = 0; i < ratios.size(); ++i) {
531 if (ratios[i] == config->default_container ()) {
532 _container->SetSelection (i);
536 vector<DCPContentType const *> const ct = DCPContentType::all ();
537 for (size_t i = 0; i < ct.size(); ++i) {
538 if (ct[i] == config->default_dcp_content_type ()) {
539 _dcp_content_type->SetSelection (i);
543 checked_set (_still_length, config->default_still_length ());
544 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
545 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
546 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
547 checked_set (_audio_delay, config->default_audio_delay ());
548 checked_set (_standard, config->default_interop() ? 1 : 0);
551 void j2k_bandwidth_changed ()
553 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
556 void audio_delay_changed ()
558 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
561 void directory_changed ()
563 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
566 void edit_isdcf_metadata_clicked ()
568 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
570 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
574 void still_length_changed ()
576 Config::instance()->set_default_still_length (_still_length->GetValue ());
579 void container_changed ()
581 vector<Ratio const *> ratio = Ratio::all ();
582 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
585 void dcp_content_type_changed ()
587 vector<DCPContentType const *> ct = DCPContentType::all ();
588 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
591 void standard_changed ()
593 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
596 wxSpinCtrl* _j2k_bandwidth;
597 wxSpinCtrl* _audio_delay;
598 wxButton* _isdcf_metadata_button;
599 wxSpinCtrl* _still_length;
600 #ifdef DCPOMATIC_USE_OWN_PICKER
601 DirPickerCtrl* _directory;
603 wxDirPickerCtrl* _directory;
605 wxChoice* _container;
606 wxChoice* _dcp_content_type;
610 class EncodingServersPage : public StandardPage
613 EncodingServersPage (wxSize panel_size, int border)
614 : StandardPage (panel_size, border)
617 wxString GetName () const
623 wxBitmap GetLargeIcon () const
625 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
632 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
633 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
635 vector<string> columns;
636 columns.push_back (wx_to_std (_("IP address / host name")));
637 _servers_list = new EditableList<string, ServerDialog> (
640 boost::bind (&Config::servers, Config::instance()),
641 boost::bind (&Config::set_servers, Config::instance(), _1),
642 boost::bind (&always_valid),
643 boost::bind (&EncodingServersPage::server_column, this, _1)
646 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
648 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
651 void config_changed ()
653 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
654 _servers_list->refresh ();
657 void use_any_servers_changed ()
659 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
662 string server_column (string s)
667 wxCheckBox* _use_any_servers;
668 EditableList<string, ServerDialog>* _servers_list;
671 class CertificateChainEditor : public wxPanel
674 CertificateChainEditor (
678 function<void (shared_ptr<dcp::CertificateChain>)> set,
679 function<shared_ptr<const dcp::CertificateChain> (void)> get
685 wxFont subheading_font (*wxNORMAL_FONT);
686 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
688 _sizer = new wxBoxSizer (wxVERTICAL);
691 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
692 m->SetFont (subheading_font);
693 _sizer->Add (m, 0, wxALL, border);
696 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
697 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
699 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
704 ip.SetText (_("Type"));
706 _certificates->InsertColumn (0, ip);
712 ip.SetText (_("Thumbprint"));
715 wxFont font = ip.GetFont ();
716 font.SetFamily (wxFONTFAMILY_TELETYPE);
719 _certificates->InsertColumn (1, ip);
722 certificates_sizer->Add (_certificates, 1, wxEXPAND);
725 wxSizer* s = new wxBoxSizer (wxVERTICAL);
726 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
727 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
728 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
729 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
730 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
731 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
732 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
735 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
736 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
739 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
740 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
741 wxFont font = _private_key->GetFont ();
742 font.SetFamily (wxFONTFAMILY_TELETYPE);
743 _private_key->SetFont (font);
744 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
745 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
746 table->Add (_load_private_key, wxGBPosition (r, 2));
747 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
748 table->Add (_export_private_key, wxGBPosition (r, 3));
751 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
752 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
753 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
754 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
757 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
758 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
759 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
760 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
761 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
762 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
763 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
764 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
766 SetSizerAndFit (_sizer);
769 void config_changed ()
771 _chain.reset (new dcp::CertificateChain (*_get().get ()));
773 update_certificate_list ();
774 update_private_key ();
775 update_sensitivity ();
778 void add_button (wxWindow* button)
780 _button_sizer->Add (button);
785 void add_certificate ()
787 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
789 if (d->ShowModal() == wxID_OK) {
791 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
794 update_certificate_list ();
795 } catch (dcp::MiscError& e) {
796 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
802 update_sensitivity ();
805 void remove_certificate ()
807 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
812 _certificates->DeleteItem (i);
816 update_sensitivity ();
819 void export_certificate ()
821 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
826 wxFileDialog* d = new wxFileDialog (
827 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
828 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
831 dcp::CertificateChain::List all = _chain->root_to_leaf ();
832 dcp::CertificateChain::List::iterator j = all.begin ();
833 for (int k = 0; k < i; ++k) {
837 if (d->ShowModal () == wxID_OK) {
838 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
840 throw OpenFileError (wx_to_std (d->GetPath ()));
843 string const s = j->certificate (true);
844 fwrite (s.c_str(), 1, s.length(), f);
850 void update_certificate_list ()
852 _certificates->DeleteAllItems ();
854 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
855 BOOST_FOREACH (dcp::Certificate const & i, certs) {
858 _certificates->InsertItem (item);
859 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
862 _certificates->SetItem (n, 0, _("Root"));
863 } else if (n == (certs.size() - 1)) {
864 _certificates->SetItem (n, 0, _("Leaf"));
866 _certificates->SetItem (n, 0, _("Intermediate"));
873 void remake_certificates ()
875 shared_ptr<const dcp::CertificateChain> chain = _get ();
877 string subject_organization_name;
878 string subject_organizational_unit_name;
879 string root_common_name;
880 string intermediate_common_name;
881 string leaf_common_name;
883 dcp::CertificateChain::List all = chain->root_to_leaf ();
885 if (all.size() >= 1) {
887 subject_organization_name = chain->root().subject_organization_name ();
888 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
889 root_common_name = chain->root().subject_common_name ();
892 if (all.size() >= 2) {
894 leaf_common_name = chain->leaf().subject_common_name ();
897 if (all.size() >= 3) {
898 /* Have an intermediate */
899 dcp::CertificateChain::List::iterator i = all.begin ();
901 intermediate_common_name = i->subject_common_name ();
904 MakeChainDialog* d = new MakeChainDialog (
906 subject_organization_name,
907 subject_organizational_unit_name,
909 intermediate_common_name,
913 if (d->ShowModal () == wxID_OK) {
915 new dcp::CertificateChain (
918 d->organisational_unit (),
919 d->root_common_name (),
920 d->intermediate_common_name (),
921 d->leaf_common_name ()
926 update_certificate_list ();
927 update_private_key ();
933 void update_sensitivity ()
935 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
936 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
939 void update_private_key ()
941 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
945 void load_private_key ()
947 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
949 if (d->ShowModal() == wxID_OK) {
951 boost::filesystem::path p (wx_to_std (d->GetPath ()));
952 if (boost::filesystem::file_size (p) > 1024) {
953 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
957 _chain->set_key (dcp::file_to_string (p));
959 update_private_key ();
960 } catch (dcp::MiscError& e) {
961 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
967 update_sensitivity ();
970 void export_private_key ()
972 optional<string> key = _chain->key ();
977 wxFileDialog* d = new wxFileDialog (
978 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
979 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
982 if (d->ShowModal () == wxID_OK) {
983 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
985 throw OpenFileError (wx_to_std (d->GetPath ()));
988 string const s = _chain->key().get ();
989 fwrite (s.c_str(), 1, s.length(), f);
995 wxListCtrl* _certificates;
996 wxButton* _add_certificate;
997 wxButton* _export_certificate;
998 wxButton* _remove_certificate;
999 wxButton* _remake_certificates;
1000 wxStaticText* _private_key;
1001 wxButton* _load_private_key;
1002 wxButton* _export_private_key;
1004 wxBoxSizer* _button_sizer;
1005 shared_ptr<dcp::CertificateChain> _chain;
1006 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
1007 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
1010 class KeysPage : public StandardPage
1013 KeysPage (wxSize panel_size, int border)
1014 : StandardPage (panel_size, border)
1017 wxString GetName () const
1022 #ifdef DCPOMATIC_OSX
1023 wxBitmap GetLargeIcon () const
1025 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
1033 _signer = new CertificateChainEditor (
1034 _panel, _("Signing DCPs and KDMs"), _border,
1035 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
1036 boost::bind (&Config::signer_chain, Config::instance ())
1039 _panel->GetSizer()->Add (_signer);
1041 _decryption = new CertificateChainEditor (
1042 _panel, _("Decrypting DCPs"), _border,
1043 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1044 boost::bind (&Config::decryption_chain, Config::instance ())
1047 _panel->GetSizer()->Add (_decryption);
1049 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1050 _decryption->add_button (_export_decryption_certificate);
1052 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1055 void export_decryption_certificate ()
1057 wxFileDialog* d = new wxFileDialog (
1058 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1059 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1062 if (d->ShowModal () == wxID_OK) {
1063 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1065 throw OpenFileError (wx_to_std (d->GetPath ()));
1068 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1069 fwrite (s.c_str(), 1, s.length(), f);
1075 void config_changed ()
1077 _signer->config_changed ();
1078 _decryption->config_changed ();
1081 CertificateChainEditor* _signer;
1082 CertificateChainEditor* _decryption;
1083 wxButton* _export_decryption_certificate;
1086 class TMSPage : public StandardPage
1089 TMSPage (wxSize panel_size, int border)
1090 : StandardPage (panel_size, border)
1093 wxString GetName () const
1098 #ifdef DCPOMATIC_OSX
1099 wxBitmap GetLargeIcon () const
1101 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1108 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1109 table->AddGrowableCol (1, 1);
1110 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1112 add_label_to_sizer (table, _panel, _("Protocol"), true);
1113 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1114 table->Add (_tms_protocol, 1, wxEXPAND);
1116 add_label_to_sizer (table, _panel, _("IP address"), true);
1117 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1118 table->Add (_tms_ip, 1, wxEXPAND);
1120 add_label_to_sizer (table, _panel, _("Target path"), true);
1121 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1122 table->Add (_tms_path, 1, wxEXPAND);
1124 add_label_to_sizer (table, _panel, _("User name"), true);
1125 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1126 table->Add (_tms_user, 1, wxEXPAND);
1128 add_label_to_sizer (table, _panel, _("Password"), true);
1129 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1130 table->Add (_tms_password, 1, wxEXPAND);
1132 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1133 _tms_protocol->Append (_("FTP (for Dolby)"));
1135 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1136 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1137 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1138 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1139 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1142 void config_changed ()
1144 Config* config = Config::instance ();
1146 checked_set (_tms_protocol, config->tms_protocol ());
1147 checked_set (_tms_ip, config->tms_ip ());
1148 checked_set (_tms_path, config->tms_path ());
1149 checked_set (_tms_user, config->tms_user ());
1150 checked_set (_tms_password, config->tms_password ());
1153 void tms_protocol_changed ()
1155 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1158 void tms_ip_changed ()
1160 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1163 void tms_path_changed ()
1165 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1168 void tms_user_changed ()
1170 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1173 void tms_password_changed ()
1175 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1178 wxChoice* _tms_protocol;
1179 wxTextCtrl* _tms_ip;
1180 wxTextCtrl* _tms_path;
1181 wxTextCtrl* _tms_user;
1182 wxTextCtrl* _tms_password;
1191 class KDMEmailPage : public StandardPage
1195 KDMEmailPage (wxSize panel_size, int border)
1196 #ifdef DCPOMATIC_OSX
1197 /* We have to force both width and height of this one */
1198 : StandardPage (wxSize (480, 128), border)
1200 : StandardPage (panel_size, border)
1204 wxString GetName () const
1206 return _("KDM Email");
1209 #ifdef DCPOMATIC_OSX
1210 wxBitmap GetLargeIcon () const
1212 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1219 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1220 table->AddGrowableCol (1, 1);
1221 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1223 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1225 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1226 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1227 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1228 add_label_to_sizer (s, _panel, _("port"), false);
1229 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1230 _mail_port->SetRange (0, 65535);
1231 s->Add (_mail_port);
1232 table->Add (s, 1, wxEXPAND | wxALL);
1235 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1236 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1237 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1239 add_label_to_sizer (table, _panel, _("Mail password"), true);
1240 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1241 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1243 add_label_to_sizer (table, _panel, _("Subject"), true);
1244 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1245 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1247 add_label_to_sizer (table, _panel, _("From address"), true);
1248 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1249 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1251 vector<string> columns;
1252 columns.push_back (wx_to_std (_("Address")));
1253 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1254 _kdm_cc = new EditableList<string, EmailDialog> (
1257 bind (&Config::kdm_cc, Config::instance()),
1258 bind (&Config::set_kdm_cc, Config::instance(), _1),
1259 bind (&string_not_empty, _1),
1262 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1264 add_label_to_sizer (table, _panel, _("BCC address"), true);
1265 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1266 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1268 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1269 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1271 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1272 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1276 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1277 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1278 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1279 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1280 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1281 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1282 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1283 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1284 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1287 void config_changed ()
1289 Config* config = Config::instance ();
1291 checked_set (_mail_server, config->mail_server ());
1292 checked_set (_mail_port, config->mail_port ());
1293 checked_set (_mail_user, config->mail_user ());
1294 checked_set (_mail_password, config->mail_password ());
1295 checked_set (_kdm_subject, config->kdm_subject ());
1296 checked_set (_kdm_from, config->kdm_from ());
1297 checked_set (_kdm_bcc, config->kdm_bcc ());
1298 checked_set (_kdm_email, Config::instance()->kdm_email ());
1301 void mail_server_changed ()
1303 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1306 void mail_port_changed ()
1308 Config::instance()->set_mail_port (_mail_port->GetValue ());
1311 void mail_user_changed ()
1313 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1316 void mail_password_changed ()
1318 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1321 void kdm_subject_changed ()
1323 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1326 void kdm_from_changed ()
1328 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1331 void kdm_bcc_changed ()
1333 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1336 void kdm_email_changed ()
1338 if (_kdm_email->GetValue().IsEmpty ()) {
1339 /* Sometimes we get sent an erroneous notification that the email
1340 is empty; I don't know why.
1344 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1347 void reset_kdm_email ()
1349 Config::instance()->reset_kdm_email ();
1350 checked_set (_kdm_email, Config::instance()->kdm_email ());
1353 wxTextCtrl* _mail_server;
1354 wxSpinCtrl* _mail_port;
1355 wxTextCtrl* _mail_user;
1356 wxTextCtrl* _mail_password;
1357 wxTextCtrl* _kdm_subject;
1358 wxTextCtrl* _kdm_from;
1359 EditableList<string, EmailDialog>* _kdm_cc;
1360 wxTextCtrl* _kdm_bcc;
1361 wxTextCtrl* _kdm_email;
1362 wxButton* _reset_kdm_email;
1365 /** @class AdvancedPage
1366 * @brief Advanced page of the preferences dialog.
1368 class AdvancedPage : public StockPage
1371 AdvancedPage (wxSize panel_size, int border)
1372 : StockPage (Kind_Advanced, panel_size, border)
1373 , _maximum_j2k_bandwidth (0)
1374 , _allow_any_dcp_frame_rate (0)
1375 , _only_servers_encode (0)
1380 , _log_debug_decode (0)
1381 , _log_debug_encode (0)
1382 , _log_debug_email (0)
1388 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1389 table->AddGrowableCol (1, 1);
1390 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1393 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1394 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1395 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1396 s->Add (_maximum_j2k_bandwidth, 1);
1397 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1401 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1402 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1403 table->AddSpacer (0);
1405 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1406 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1407 table->AddSpacer (0);
1410 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1411 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1413 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1414 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1418 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1419 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1420 t->Add (_log_general, 1, wxEXPAND | wxALL);
1421 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1422 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1423 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1424 t->Add (_log_error, 1, wxEXPAND | wxALL);
1425 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1426 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1427 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1428 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1429 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1430 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1431 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1432 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1433 table->Add (t, 0, wxALL, 6);
1436 #ifdef DCPOMATIC_WINDOWS
1437 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1438 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1439 table->AddSpacer (0);
1442 _maximum_j2k_bandwidth->SetRange (1, 1000);
1443 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1444 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1445 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1446 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1447 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1448 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1449 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1450 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1451 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1452 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1453 #ifdef DCPOMATIC_WINDOWS
1454 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1458 void config_changed ()
1460 Config* config = Config::instance ();
1462 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1463 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1464 checked_set (_only_servers_encode, config->only_servers_encode ());
1465 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1466 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1467 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1468 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1469 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1470 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1471 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1472 #ifdef DCPOMATIC_WINDOWS
1473 checked_set (_win32_console, config->win32_console());
1477 void maximum_j2k_bandwidth_changed ()
1479 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1482 void allow_any_dcp_frame_rate_changed ()
1484 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1487 void only_servers_encode_changed ()
1489 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1495 if (_log_general->GetValue ()) {
1496 types |= LogEntry::TYPE_GENERAL;
1498 if (_log_warning->GetValue ()) {
1499 types |= LogEntry::TYPE_WARNING;
1501 if (_log_error->GetValue ()) {
1502 types |= LogEntry::TYPE_ERROR;
1504 if (_log_timing->GetValue ()) {
1505 types |= LogEntry::TYPE_TIMING;
1507 if (_log_debug_decode->GetValue ()) {
1508 types |= LogEntry::TYPE_DEBUG_DECODE;
1510 if (_log_debug_encode->GetValue ()) {
1511 types |= LogEntry::TYPE_DEBUG_ENCODE;
1513 if (_log_debug_email->GetValue ()) {
1514 types |= LogEntry::TYPE_DEBUG_EMAIL;
1516 Config::instance()->set_log_types (types);
1519 #ifdef DCPOMATIC_WINDOWS
1520 void win32_console_changed ()
1522 Config::instance()->set_win32_console (_win32_console->GetValue ());
1526 wxSpinCtrl* _maximum_j2k_bandwidth;
1527 wxCheckBox* _allow_any_dcp_frame_rate;
1528 wxCheckBox* _only_servers_encode;
1529 wxCheckBox* _log_general;
1530 wxCheckBox* _log_warning;
1531 wxCheckBox* _log_error;
1532 wxCheckBox* _log_timing;
1533 wxCheckBox* _log_debug_decode;
1534 wxCheckBox* _log_debug_encode;
1535 wxCheckBox* _log_debug_email;
1536 #ifdef DCPOMATIC_WINDOWS
1537 wxCheckBox* _win32_console;
1541 wxPreferencesEditor*
1542 create_config_dialog ()
1544 wxPreferencesEditor* e = new wxPreferencesEditor ();
1546 #ifdef DCPOMATIC_OSX
1547 /* Width that we force some of the config panels to be on OSX so that
1548 the containing window doesn't shrink too much when we select those panels.
1549 This is obviously an unpleasant hack.
1551 wxSize ps = wxSize (520, -1);
1552 int const border = 16;
1554 wxSize ps = wxSize (-1, -1);
1555 int const border = 8;
1558 e->AddPage (new GeneralPage (ps, border));
1559 e->AddPage (new DefaultsPage (ps, border));
1560 e->AddPage (new EncodingServersPage (ps, border));
1561 e->AddPage (new KeysPage (ps, border));
1562 e->AddPage (new TMSPage (ps, border));
1563 e->AddPage (new KDMEmailPage (ps, border));
1564 e->AddPage (new AdvancedPage (ps, border));