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 (&EncodingServersPage::server_column, this, _1)
645 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
647 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
650 void config_changed ()
652 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
653 _servers_list->refresh ();
656 void use_any_servers_changed ()
658 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
661 string server_column (string s)
666 wxCheckBox* _use_any_servers;
667 EditableList<string, ServerDialog>* _servers_list;
670 class CertificateChainEditor : public wxPanel
673 CertificateChainEditor (
677 function<void (shared_ptr<dcp::CertificateChain>)> set,
678 function<shared_ptr<const dcp::CertificateChain> (void)> get
684 wxFont subheading_font (*wxNORMAL_FONT);
685 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
687 _sizer = new wxBoxSizer (wxVERTICAL);
690 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
691 m->SetFont (subheading_font);
692 _sizer->Add (m, 0, wxALL, border);
695 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
696 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
698 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
703 ip.SetText (_("Type"));
705 _certificates->InsertColumn (0, ip);
711 ip.SetText (_("Thumbprint"));
714 wxFont font = ip.GetFont ();
715 font.SetFamily (wxFONTFAMILY_TELETYPE);
718 _certificates->InsertColumn (1, ip);
721 certificates_sizer->Add (_certificates, 1, wxEXPAND);
724 wxSizer* s = new wxBoxSizer (wxVERTICAL);
725 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
726 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
727 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
728 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
729 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
730 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
731 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
734 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
735 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
738 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
739 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
740 wxFont font = _private_key->GetFont ();
741 font.SetFamily (wxFONTFAMILY_TELETYPE);
742 _private_key->SetFont (font);
743 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
744 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
745 table->Add (_load_private_key, wxGBPosition (r, 2));
746 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
747 table->Add (_export_private_key, wxGBPosition (r, 3));
750 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
751 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
752 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
753 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
756 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
757 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
758 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
759 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
760 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
761 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
762 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
763 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
765 SetSizerAndFit (_sizer);
768 void config_changed ()
770 _chain.reset (new dcp::CertificateChain (*_get().get ()));
772 update_certificate_list ();
773 update_private_key ();
774 update_sensitivity ();
777 void add_button (wxWindow* button)
779 _button_sizer->Add (button);
784 void add_certificate ()
786 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
788 if (d->ShowModal() == wxID_OK) {
790 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
793 update_certificate_list ();
794 } catch (dcp::MiscError& e) {
795 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
801 update_sensitivity ();
804 void remove_certificate ()
806 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
811 _certificates->DeleteItem (i);
815 update_sensitivity ();
818 void export_certificate ()
820 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
825 wxFileDialog* d = new wxFileDialog (
826 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
827 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
830 dcp::CertificateChain::List all = _chain->root_to_leaf ();
831 dcp::CertificateChain::List::iterator j = all.begin ();
832 for (int k = 0; k < i; ++k) {
836 if (d->ShowModal () == wxID_OK) {
837 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
839 throw OpenFileError (wx_to_std (d->GetPath ()));
842 string const s = j->certificate (true);
843 fwrite (s.c_str(), 1, s.length(), f);
849 void update_certificate_list ()
851 _certificates->DeleteAllItems ();
853 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
854 BOOST_FOREACH (dcp::Certificate const & i, certs) {
857 _certificates->InsertItem (item);
858 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
861 _certificates->SetItem (n, 0, _("Root"));
862 } else if (n == (certs.size() - 1)) {
863 _certificates->SetItem (n, 0, _("Leaf"));
865 _certificates->SetItem (n, 0, _("Intermediate"));
872 void remake_certificates ()
874 shared_ptr<const dcp::CertificateChain> chain = _get ();
876 string subject_organization_name;
877 string subject_organizational_unit_name;
878 string root_common_name;
879 string intermediate_common_name;
880 string leaf_common_name;
882 dcp::CertificateChain::List all = chain->root_to_leaf ();
884 if (all.size() >= 1) {
886 subject_organization_name = chain->root().subject_organization_name ();
887 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
888 root_common_name = chain->root().subject_common_name ();
891 if (all.size() >= 2) {
893 leaf_common_name = chain->leaf().subject_common_name ();
896 if (all.size() >= 3) {
897 /* Have an intermediate */
898 dcp::CertificateChain::List::iterator i = all.begin ();
900 intermediate_common_name = i->subject_common_name ();
903 MakeChainDialog* d = new MakeChainDialog (
905 subject_organization_name,
906 subject_organizational_unit_name,
908 intermediate_common_name,
912 if (d->ShowModal () == wxID_OK) {
914 new dcp::CertificateChain (
917 d->organisational_unit (),
918 d->root_common_name (),
919 d->intermediate_common_name (),
920 d->leaf_common_name ()
925 update_certificate_list ();
926 update_private_key ();
932 void update_sensitivity ()
934 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
935 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
938 void update_private_key ()
940 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
944 void load_private_key ()
946 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
948 if (d->ShowModal() == wxID_OK) {
950 boost::filesystem::path p (wx_to_std (d->GetPath ()));
951 if (boost::filesystem::file_size (p) > 1024) {
952 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
956 _chain->set_key (dcp::file_to_string (p));
958 update_private_key ();
959 } catch (dcp::MiscError& e) {
960 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
966 update_sensitivity ();
969 void export_private_key ()
971 optional<string> key = _chain->key ();
976 wxFileDialog* d = new wxFileDialog (
977 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
978 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
981 if (d->ShowModal () == wxID_OK) {
982 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
984 throw OpenFileError (wx_to_std (d->GetPath ()));
987 string const s = _chain->key().get ();
988 fwrite (s.c_str(), 1, s.length(), f);
994 wxListCtrl* _certificates;
995 wxButton* _add_certificate;
996 wxButton* _export_certificate;
997 wxButton* _remove_certificate;
998 wxButton* _remake_certificates;
999 wxStaticText* _private_key;
1000 wxButton* _load_private_key;
1001 wxButton* _export_private_key;
1003 wxBoxSizer* _button_sizer;
1004 shared_ptr<dcp::CertificateChain> _chain;
1005 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
1006 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
1009 class KeysPage : public StandardPage
1012 KeysPage (wxSize panel_size, int border)
1013 : StandardPage (panel_size, border)
1016 wxString GetName () const
1021 #ifdef DCPOMATIC_OSX
1022 wxBitmap GetLargeIcon () const
1024 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
1032 _signer = new CertificateChainEditor (
1033 _panel, _("Signing DCPs and KDMs"), _border,
1034 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
1035 boost::bind (&Config::signer_chain, Config::instance ())
1038 _panel->GetSizer()->Add (_signer);
1040 _decryption = new CertificateChainEditor (
1041 _panel, _("Decrypting DCPs"), _border,
1042 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1043 boost::bind (&Config::decryption_chain, Config::instance ())
1046 _panel->GetSizer()->Add (_decryption);
1048 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1049 _decryption->add_button (_export_decryption_certificate);
1051 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1054 void export_decryption_certificate ()
1056 wxFileDialog* d = new wxFileDialog (
1057 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1058 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1061 if (d->ShowModal () == wxID_OK) {
1062 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1064 throw OpenFileError (wx_to_std (d->GetPath ()));
1067 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1068 fwrite (s.c_str(), 1, s.length(), f);
1074 void config_changed ()
1076 _signer->config_changed ();
1077 _decryption->config_changed ();
1080 CertificateChainEditor* _signer;
1081 CertificateChainEditor* _decryption;
1082 wxButton* _export_decryption_certificate;
1085 class TMSPage : public StandardPage
1088 TMSPage (wxSize panel_size, int border)
1089 : StandardPage (panel_size, border)
1092 wxString GetName () const
1097 #ifdef DCPOMATIC_OSX
1098 wxBitmap GetLargeIcon () const
1100 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1107 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1108 table->AddGrowableCol (1, 1);
1109 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1111 add_label_to_sizer (table, _panel, _("Protocol"), true);
1112 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1113 table->Add (_tms_protocol, 1, wxEXPAND);
1115 add_label_to_sizer (table, _panel, _("IP address"), true);
1116 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1117 table->Add (_tms_ip, 1, wxEXPAND);
1119 add_label_to_sizer (table, _panel, _("Target path"), true);
1120 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1121 table->Add (_tms_path, 1, wxEXPAND);
1123 add_label_to_sizer (table, _panel, _("User name"), true);
1124 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1125 table->Add (_tms_user, 1, wxEXPAND);
1127 add_label_to_sizer (table, _panel, _("Password"), true);
1128 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1129 table->Add (_tms_password, 1, wxEXPAND);
1131 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1132 _tms_protocol->Append (_("FTP (for Dolby)"));
1134 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1135 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1136 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1137 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1138 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1141 void config_changed ()
1143 Config* config = Config::instance ();
1145 checked_set (_tms_protocol, config->tms_protocol ());
1146 checked_set (_tms_ip, config->tms_ip ());
1147 checked_set (_tms_path, config->tms_path ());
1148 checked_set (_tms_user, config->tms_user ());
1149 checked_set (_tms_password, config->tms_password ());
1152 void tms_protocol_changed ()
1154 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1157 void tms_ip_changed ()
1159 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1162 void tms_path_changed ()
1164 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1167 void tms_user_changed ()
1169 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1172 void tms_password_changed ()
1174 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1177 wxChoice* _tms_protocol;
1178 wxTextCtrl* _tms_ip;
1179 wxTextCtrl* _tms_path;
1180 wxTextCtrl* _tms_user;
1181 wxTextCtrl* _tms_password;
1190 class KDMEmailPage : public StandardPage
1194 KDMEmailPage (wxSize panel_size, int border)
1195 #ifdef DCPOMATIC_OSX
1196 /* We have to force both width and height of this one */
1197 : StandardPage (wxSize (480, 128), border)
1199 : StandardPage (panel_size, border)
1203 wxString GetName () const
1205 return _("KDM Email");
1208 #ifdef DCPOMATIC_OSX
1209 wxBitmap GetLargeIcon () const
1211 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1218 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1219 table->AddGrowableCol (1, 1);
1220 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1222 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1224 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1225 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1226 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1227 add_label_to_sizer (s, _panel, _("port"), false);
1228 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1229 _mail_port->SetRange (0, 65535);
1230 s->Add (_mail_port);
1231 table->Add (s, 1, wxEXPAND | wxALL);
1234 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1235 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1236 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1238 add_label_to_sizer (table, _panel, _("Mail password"), true);
1239 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1240 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1242 add_label_to_sizer (table, _panel, _("Subject"), true);
1243 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1244 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1246 add_label_to_sizer (table, _panel, _("From address"), true);
1247 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1248 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1250 vector<string> columns;
1251 columns.push_back (wx_to_std (_("Address")));
1252 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1253 _kdm_cc = new EditableList<string, EmailDialog> (
1254 _panel, columns, bind (&Config::kdm_cc, Config::instance()), bind (&Config::set_kdm_cc, Config::instance(), _1), bind (&column, _1)
1256 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1258 add_label_to_sizer (table, _panel, _("BCC address"), true);
1259 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1260 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1262 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1263 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1265 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1266 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1270 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1271 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1272 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1273 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1274 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1275 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1276 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1277 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1278 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1281 void config_changed ()
1283 Config* config = Config::instance ();
1285 checked_set (_mail_server, config->mail_server ());
1286 checked_set (_mail_port, config->mail_port ());
1287 checked_set (_mail_user, config->mail_user ());
1288 checked_set (_mail_password, config->mail_password ());
1289 checked_set (_kdm_subject, config->kdm_subject ());
1290 checked_set (_kdm_from, config->kdm_from ());
1291 checked_set (_kdm_bcc, config->kdm_bcc ());
1292 checked_set (_kdm_email, Config::instance()->kdm_email ());
1295 void mail_server_changed ()
1297 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1300 void mail_port_changed ()
1302 Config::instance()->set_mail_port (_mail_port->GetValue ());
1305 void mail_user_changed ()
1307 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1310 void mail_password_changed ()
1312 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1315 void kdm_subject_changed ()
1317 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1320 void kdm_from_changed ()
1322 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1325 void kdm_bcc_changed ()
1327 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1330 void kdm_email_changed ()
1332 if (_kdm_email->GetValue().IsEmpty ()) {
1333 /* Sometimes we get sent an erroneous notification that the email
1334 is empty; I don't know why.
1338 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1341 void reset_kdm_email ()
1343 Config::instance()->reset_kdm_email ();
1344 checked_set (_kdm_email, Config::instance()->kdm_email ());
1347 wxTextCtrl* _mail_server;
1348 wxSpinCtrl* _mail_port;
1349 wxTextCtrl* _mail_user;
1350 wxTextCtrl* _mail_password;
1351 wxTextCtrl* _kdm_subject;
1352 wxTextCtrl* _kdm_from;
1353 EditableList<string, EmailDialog>* _kdm_cc;
1354 wxTextCtrl* _kdm_bcc;
1355 wxTextCtrl* _kdm_email;
1356 wxButton* _reset_kdm_email;
1359 /** @class AdvancedPage
1360 * @brief Advanced page of the preferences dialog.
1362 class AdvancedPage : public StockPage
1365 AdvancedPage (wxSize panel_size, int border)
1366 : StockPage (Kind_Advanced, panel_size, border)
1367 , _maximum_j2k_bandwidth (0)
1368 , _allow_any_dcp_frame_rate (0)
1369 , _only_servers_encode (0)
1374 , _log_debug_decode (0)
1375 , _log_debug_encode (0)
1376 , _log_debug_email (0)
1382 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1383 table->AddGrowableCol (1, 1);
1384 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1387 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1388 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1389 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1390 s->Add (_maximum_j2k_bandwidth, 1);
1391 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1395 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1396 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1397 table->AddSpacer (0);
1399 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1400 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1401 table->AddSpacer (0);
1404 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1405 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1407 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1408 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1412 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1413 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1414 t->Add (_log_general, 1, wxEXPAND | wxALL);
1415 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1416 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1417 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1418 t->Add (_log_error, 1, wxEXPAND | wxALL);
1419 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1420 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1421 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1422 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1423 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1424 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1425 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1426 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1427 table->Add (t, 0, wxALL, 6);
1430 #ifdef DCPOMATIC_WINDOWS
1431 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1432 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1433 table->AddSpacer (0);
1436 _maximum_j2k_bandwidth->SetRange (1, 1000);
1437 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1438 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1439 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1440 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1441 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1442 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1443 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1444 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1445 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1446 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1447 #ifdef DCPOMATIC_WINDOWS
1448 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1452 void config_changed ()
1454 Config* config = Config::instance ();
1456 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1457 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1458 checked_set (_only_servers_encode, config->only_servers_encode ());
1459 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1460 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1461 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1462 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1463 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1464 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1465 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1466 #ifdef DCPOMATIC_WINDOWS
1467 checked_set (_win32_console, config->win32_console());
1471 void maximum_j2k_bandwidth_changed ()
1473 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1476 void allow_any_dcp_frame_rate_changed ()
1478 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1481 void only_servers_encode_changed ()
1483 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1489 if (_log_general->GetValue ()) {
1490 types |= LogEntry::TYPE_GENERAL;
1492 if (_log_warning->GetValue ()) {
1493 types |= LogEntry::TYPE_WARNING;
1495 if (_log_error->GetValue ()) {
1496 types |= LogEntry::TYPE_ERROR;
1498 if (_log_timing->GetValue ()) {
1499 types |= LogEntry::TYPE_TIMING;
1501 if (_log_debug_decode->GetValue ()) {
1502 types |= LogEntry::TYPE_DEBUG_DECODE;
1504 if (_log_debug_encode->GetValue ()) {
1505 types |= LogEntry::TYPE_DEBUG_ENCODE;
1507 if (_log_debug_email->GetValue ()) {
1508 types |= LogEntry::TYPE_DEBUG_EMAIL;
1510 Config::instance()->set_log_types (types);
1513 #ifdef DCPOMATIC_WINDOWS
1514 void win32_console_changed ()
1516 Config::instance()->set_win32_console (_win32_console->GetValue ());
1520 wxSpinCtrl* _maximum_j2k_bandwidth;
1521 wxCheckBox* _allow_any_dcp_frame_rate;
1522 wxCheckBox* _only_servers_encode;
1523 wxCheckBox* _log_general;
1524 wxCheckBox* _log_warning;
1525 wxCheckBox* _log_error;
1526 wxCheckBox* _log_timing;
1527 wxCheckBox* _log_debug_decode;
1528 wxCheckBox* _log_debug_encode;
1529 wxCheckBox* _log_debug_email;
1530 #ifdef DCPOMATIC_WINDOWS
1531 wxCheckBox* _win32_console;
1535 wxPreferencesEditor*
1536 create_config_dialog ()
1538 wxPreferencesEditor* e = new wxPreferencesEditor ();
1540 #ifdef DCPOMATIC_OSX
1541 /* Width that we force some of the config panels to be on OSX so that
1542 the containing window doesn't shrink too much when we select those panels.
1543 This is obviously an unpleasant hack.
1545 wxSize ps = wxSize (520, -1);
1546 int const border = 16;
1548 wxSize ps = wxSize (-1, -1);
1549 int const border = 8;
1552 e->AddPage (new GeneralPage (ps, border));
1553 e->AddPage (new DefaultsPage (ps, border));
1554 e->AddPage (new EncodingServersPage (ps, border));
1555 e->AddPage (new KeysPage (ps, border));
1556 e->AddPage (new TMSPage (ps, border));
1557 e->AddPage (new KDMEmailPage (ps, border));
1558 e->AddPage (new AdvancedPage (ps, border));