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 _language->Append (wxT ("українська мова"));
176 table->Add (_language, wxGBPosition (r, 1));
179 wxStaticText* restart = add_label_to_sizer (
180 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
182 wxFont font = restart->GetFont();
183 font.SetStyle (wxFONTSTYLE_ITALIC);
184 font.SetPointSize (font.GetPointSize() - 1);
185 restart->SetFont (font);
188 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
189 _num_local_encoding_threads = new wxSpinCtrl (_panel);
190 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
193 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
194 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml");
195 table->Add (_cinemas_file, wxGBPosition (r, 1));
198 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
199 _analyse_ebur128 = new wxCheckBox (_panel, wxID_ANY, _("Find integrated loudness, true peak and loudness range when analysing audio"));
200 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
204 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
205 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
208 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
209 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
212 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
213 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
216 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
217 bottom_table->AddGrowableCol (1, 1);
219 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
220 _issuer = new wxTextCtrl (_panel, wxID_ANY);
221 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
223 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
224 _creator = new wxTextCtrl (_panel, wxID_ANY);
225 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
227 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
230 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
231 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
232 _cinemas_file->Bind (wxEVT_COMMAND_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
234 _num_local_encoding_threads->SetRange (1, 128);
235 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
237 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
238 _analyse_ebur128->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::analyse_ebur128_changed, this));
240 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
241 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
242 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
244 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
245 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
248 void config_changed ()
250 Config* config = Config::instance ();
252 checked_set (_set_language, static_cast<bool>(config->language()));
254 if (config->language().get_value_or ("") == "fr") {
255 checked_set (_language, 3);
256 } else if (config->language().get_value_or ("") == "it") {
257 checked_set (_language, 4);
258 } else if (config->language().get_value_or ("") == "es") {
259 checked_set (_language, 2);
260 } else if (config->language().get_value_or ("") == "sv") {
261 checked_set (_language, 6);
262 } else if (config->language().get_value_or ("") == "de") {
263 checked_set (_language, 0);
264 } else if (config->language().get_value_or ("") == "nl") {
265 checked_set (_language, 5);
266 } else if (config->language().get_value_or ("") == "ru") {
267 checked_set (_language, 7);
268 } else if (config->language().get_value_or ("") == "pl") {
269 checked_set (_language, 8);
270 } else if (config->language().get_value_or ("") == "da") {
271 checked_set (_language, 9);
272 } else if (config->language().get_value_or ("") == "pt") {
273 checked_set (_language, 10);
274 } else if (config->language().get_value_or ("") == "sk") {
275 checked_set (_language, 11);
276 } else if (config->language().get_value_or ("") == "cs") {
277 checked_set (_language, 12);
278 } else if (config->language().get_value_or ("") == "uk") {
279 checked_set (_language, 13);
281 _language->SetSelection (1);
284 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
285 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
286 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
288 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
289 checked_set (_check_for_updates, config->check_for_updates ());
290 checked_set (_check_for_test_updates, config->check_for_test_updates ());
291 checked_set (_issuer, config->dcp_issuer ());
292 checked_set (_creator, config->dcp_creator ());
293 checked_set (_cinemas_file, config->cinemas_file());
295 setup_sensitivity ();
298 void setup_sensitivity ()
300 _language->Enable (_set_language->GetValue ());
301 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
304 void set_language_changed ()
306 setup_sensitivity ();
307 if (_set_language->GetValue ()) {
310 Config::instance()->unset_language ();
314 void language_changed ()
316 switch (_language->GetSelection ()) {
318 Config::instance()->set_language ("de");
321 Config::instance()->set_language ("en");
324 Config::instance()->set_language ("es");
327 Config::instance()->set_language ("fr");
330 Config::instance()->set_language ("it");
333 Config::instance()->set_language ("nl");
336 Config::instance()->set_language ("sv");
339 Config::instance()->set_language ("ru");
342 Config::instance()->set_language ("pl");
345 Config::instance()->set_language ("da");
348 Config::instance()->set_language ("pt");
351 Config::instance()->set_language ("sk");
354 Config::instance()->set_language ("cs");
357 Config::instance()->set_language ("uk");
362 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
363 void analyse_ebur128_changed ()
365 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
369 void automatic_audio_analysis_changed ()
371 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
374 void check_for_updates_changed ()
376 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
379 void check_for_test_updates_changed ()
381 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
384 void num_local_encoding_threads_changed ()
386 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
389 void issuer_changed ()
391 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
394 void creator_changed ()
396 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
399 void cinemas_file_changed ()
401 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
404 wxCheckBox* _set_language;
406 wxSpinCtrl* _num_local_encoding_threads;
407 FilePickerCtrl* _cinemas_file;
408 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
409 wxCheckBox* _analyse_ebur128;
411 wxCheckBox* _automatic_audio_analysis;
412 wxCheckBox* _check_for_updates;
413 wxCheckBox* _check_for_test_updates;
415 wxTextCtrl* _creator;
418 class DefaultsPage : public StandardPage
421 DefaultsPage (wxSize panel_size, int border)
422 : StandardPage (panel_size, border)
425 wxString GetName () const
427 return _("Defaults");
431 wxBitmap GetLargeIcon () const
433 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
440 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
441 table->AddGrowableCol (1, 1);
442 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
445 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
446 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
447 _still_length = new wxSpinCtrl (_panel);
448 s->Add (_still_length);
449 add_label_to_sizer (s, _panel, _("s"), false);
453 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
454 #ifdef DCPOMATIC_USE_OWN_PICKER
455 _directory = new DirPickerCtrl (_panel);
457 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
459 table->Add (_directory, 1, wxEXPAND);
461 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
462 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
463 table->Add (_isdcf_metadata_button);
465 add_label_to_sizer (table, _panel, _("Default container"), true);
466 _container = new wxChoice (_panel, wxID_ANY);
467 table->Add (_container);
469 add_label_to_sizer (table, _panel, _("Default content type"), true);
470 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
471 table->Add (_dcp_content_type);
474 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
475 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
476 _j2k_bandwidth = new wxSpinCtrl (_panel);
477 s->Add (_j2k_bandwidth);
478 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
483 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
484 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
485 _audio_delay = new wxSpinCtrl (_panel);
486 s->Add (_audio_delay);
487 add_label_to_sizer (s, _panel, _("ms"), false);
491 add_label_to_sizer (table, _panel, _("Default standard"), true);
492 _standard = new wxChoice (_panel, wxID_ANY);
493 table->Add (_standard);
495 _still_length->SetRange (1, 3600);
496 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
498 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
500 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
502 vector<Ratio const *> ratios = Ratio::all ();
503 for (size_t i = 0; i < ratios.size(); ++i) {
504 _container->Append (std_to_wx (ratios[i]->nickname ()));
507 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
509 vector<DCPContentType const *> const ct = DCPContentType::all ();
510 for (size_t i = 0; i < ct.size(); ++i) {
511 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
514 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
516 _j2k_bandwidth->SetRange (50, 250);
517 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
519 _audio_delay->SetRange (-1000, 1000);
520 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
522 _standard->Append (_("SMPTE"));
523 _standard->Append (_("Interop"));
524 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
527 void config_changed ()
529 Config* config = Config::instance ();
531 vector<Ratio const *> ratios = Ratio::all ();
532 for (size_t i = 0; i < ratios.size(); ++i) {
533 if (ratios[i] == config->default_container ()) {
534 _container->SetSelection (i);
538 vector<DCPContentType const *> const ct = DCPContentType::all ();
539 for (size_t i = 0; i < ct.size(); ++i) {
540 if (ct[i] == config->default_dcp_content_type ()) {
541 _dcp_content_type->SetSelection (i);
545 checked_set (_still_length, config->default_still_length ());
546 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
547 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
548 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
549 checked_set (_audio_delay, config->default_audio_delay ());
550 checked_set (_standard, config->default_interop() ? 1 : 0);
553 void j2k_bandwidth_changed ()
555 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
558 void audio_delay_changed ()
560 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
563 void directory_changed ()
565 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
568 void edit_isdcf_metadata_clicked ()
570 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
572 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
576 void still_length_changed ()
578 Config::instance()->set_default_still_length (_still_length->GetValue ());
581 void container_changed ()
583 vector<Ratio const *> ratio = Ratio::all ();
584 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
587 void dcp_content_type_changed ()
589 vector<DCPContentType const *> ct = DCPContentType::all ();
590 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
593 void standard_changed ()
595 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
598 wxSpinCtrl* _j2k_bandwidth;
599 wxSpinCtrl* _audio_delay;
600 wxButton* _isdcf_metadata_button;
601 wxSpinCtrl* _still_length;
602 #ifdef DCPOMATIC_USE_OWN_PICKER
603 DirPickerCtrl* _directory;
605 wxDirPickerCtrl* _directory;
607 wxChoice* _container;
608 wxChoice* _dcp_content_type;
612 class EncodingServersPage : public StandardPage
615 EncodingServersPage (wxSize panel_size, int border)
616 : StandardPage (panel_size, border)
619 wxString GetName () const
625 wxBitmap GetLargeIcon () const
627 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
634 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
635 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
637 vector<string> columns;
638 columns.push_back (wx_to_std (_("IP address / host name")));
639 _servers_list = new EditableList<string, ServerDialog> (
642 boost::bind (&Config::servers, Config::instance()),
643 boost::bind (&Config::set_servers, Config::instance(), _1),
644 boost::bind (&EncodingServersPage::server_column, this, _1)
647 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
649 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
652 void config_changed ()
654 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
655 _servers_list->refresh ();
658 void use_any_servers_changed ()
660 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
663 string server_column (string s)
668 wxCheckBox* _use_any_servers;
669 EditableList<string, ServerDialog>* _servers_list;
672 class CertificateChainEditor : public wxPanel
675 CertificateChainEditor (
679 function<void (shared_ptr<dcp::CertificateChain>)> set,
680 function<shared_ptr<const dcp::CertificateChain> (void)> get
686 wxFont subheading_font (*wxNORMAL_FONT);
687 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
689 _sizer = new wxBoxSizer (wxVERTICAL);
692 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
693 m->SetFont (subheading_font);
694 _sizer->Add (m, 0, wxALL, border);
697 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
698 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
700 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
705 ip.SetText (_("Type"));
707 _certificates->InsertColumn (0, ip);
713 ip.SetText (_("Thumbprint"));
716 wxFont font = ip.GetFont ();
717 font.SetFamily (wxFONTFAMILY_TELETYPE);
720 _certificates->InsertColumn (1, ip);
723 certificates_sizer->Add (_certificates, 1, wxEXPAND);
726 wxSizer* s = new wxBoxSizer (wxVERTICAL);
727 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
728 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
729 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
730 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
731 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
732 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
733 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
736 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
737 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
740 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
741 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
742 wxFont font = _private_key->GetFont ();
743 font.SetFamily (wxFONTFAMILY_TELETYPE);
744 _private_key->SetFont (font);
745 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
746 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
747 table->Add (_load_private_key, wxGBPosition (r, 2));
748 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
749 table->Add (_export_private_key, wxGBPosition (r, 3));
752 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
753 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
754 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
755 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
758 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
759 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
760 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
761 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
762 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
763 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
764 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
765 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
767 SetSizerAndFit (_sizer);
770 void config_changed ()
772 _chain.reset (new dcp::CertificateChain (*_get().get ()));
774 update_certificate_list ();
775 update_private_key ();
776 update_sensitivity ();
779 void add_button (wxWindow* button)
781 _button_sizer->Add (button);
786 void add_certificate ()
788 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
790 if (d->ShowModal() == wxID_OK) {
792 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
795 update_certificate_list ();
796 } catch (dcp::MiscError& e) {
797 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
803 update_sensitivity ();
806 void remove_certificate ()
808 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
813 _certificates->DeleteItem (i);
817 update_sensitivity ();
820 void export_certificate ()
822 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
827 wxFileDialog* d = new wxFileDialog (
828 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
829 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
832 dcp::CertificateChain::List all = _chain->root_to_leaf ();
833 dcp::CertificateChain::List::iterator j = all.begin ();
834 for (int k = 0; k < i; ++k) {
838 if (d->ShowModal () == wxID_OK) {
839 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
841 throw OpenFileError (wx_to_std (d->GetPath ()));
844 string const s = j->certificate (true);
845 fwrite (s.c_str(), 1, s.length(), f);
851 void update_certificate_list ()
853 _certificates->DeleteAllItems ();
855 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
856 BOOST_FOREACH (dcp::Certificate const & i, certs) {
859 _certificates->InsertItem (item);
860 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
863 _certificates->SetItem (n, 0, _("Root"));
864 } else if (n == (certs.size() - 1)) {
865 _certificates->SetItem (n, 0, _("Leaf"));
867 _certificates->SetItem (n, 0, _("Intermediate"));
874 void remake_certificates ()
876 shared_ptr<const dcp::CertificateChain> chain = _get ();
878 string subject_organization_name;
879 string subject_organizational_unit_name;
880 string root_common_name;
881 string intermediate_common_name;
882 string leaf_common_name;
884 dcp::CertificateChain::List all = chain->root_to_leaf ();
886 if (all.size() >= 1) {
888 subject_organization_name = chain->root().subject_organization_name ();
889 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
890 root_common_name = chain->root().subject_common_name ();
893 if (all.size() >= 2) {
895 leaf_common_name = chain->leaf().subject_common_name ();
898 if (all.size() >= 3) {
899 /* Have an intermediate */
900 dcp::CertificateChain::List::iterator i = all.begin ();
902 intermediate_common_name = i->subject_common_name ();
905 MakeChainDialog* d = new MakeChainDialog (
907 subject_organization_name,
908 subject_organizational_unit_name,
910 intermediate_common_name,
914 if (d->ShowModal () == wxID_OK) {
916 new dcp::CertificateChain (
919 d->organisational_unit (),
920 d->root_common_name (),
921 d->intermediate_common_name (),
922 d->leaf_common_name ()
927 update_certificate_list ();
928 update_private_key ();
934 void update_sensitivity ()
936 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
937 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
940 void update_private_key ()
942 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
946 void load_private_key ()
948 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
950 if (d->ShowModal() == wxID_OK) {
952 boost::filesystem::path p (wx_to_std (d->GetPath ()));
953 if (boost::filesystem::file_size (p) > 1024) {
954 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
958 _chain->set_key (dcp::file_to_string (p));
960 update_private_key ();
961 } catch (dcp::MiscError& e) {
962 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
968 update_sensitivity ();
971 void export_private_key ()
973 optional<string> key = _chain->key ();
978 wxFileDialog* d = new wxFileDialog (
979 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
980 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
983 if (d->ShowModal () == wxID_OK) {
984 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
986 throw OpenFileError (wx_to_std (d->GetPath ()));
989 string const s = _chain->key().get ();
990 fwrite (s.c_str(), 1, s.length(), f);
996 wxListCtrl* _certificates;
997 wxButton* _add_certificate;
998 wxButton* _export_certificate;
999 wxButton* _remove_certificate;
1000 wxButton* _remake_certificates;
1001 wxStaticText* _private_key;
1002 wxButton* _load_private_key;
1003 wxButton* _export_private_key;
1005 wxBoxSizer* _button_sizer;
1006 shared_ptr<dcp::CertificateChain> _chain;
1007 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
1008 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
1011 class KeysPage : public StandardPage
1014 KeysPage (wxSize panel_size, int border)
1015 : StandardPage (panel_size, border)
1018 wxString GetName () const
1023 #ifdef DCPOMATIC_OSX
1024 wxBitmap GetLargeIcon () const
1026 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
1034 _signer = new CertificateChainEditor (
1035 _panel, _("Signing DCPs and KDMs"), _border,
1036 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
1037 boost::bind (&Config::signer_chain, Config::instance ())
1040 _panel->GetSizer()->Add (_signer);
1042 _decryption = new CertificateChainEditor (
1043 _panel, _("Decrypting DCPs"), _border,
1044 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1045 boost::bind (&Config::decryption_chain, Config::instance ())
1048 _panel->GetSizer()->Add (_decryption);
1050 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1051 _decryption->add_button (_export_decryption_certificate);
1053 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1056 void export_decryption_certificate ()
1058 wxFileDialog* d = new wxFileDialog (
1059 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1060 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1063 if (d->ShowModal () == wxID_OK) {
1064 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1066 throw OpenFileError (wx_to_std (d->GetPath ()));
1069 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1070 fwrite (s.c_str(), 1, s.length(), f);
1076 void config_changed ()
1078 _signer->config_changed ();
1079 _decryption->config_changed ();
1082 CertificateChainEditor* _signer;
1083 CertificateChainEditor* _decryption;
1084 wxButton* _export_decryption_certificate;
1087 class TMSPage : public StandardPage
1090 TMSPage (wxSize panel_size, int border)
1091 : StandardPage (panel_size, border)
1094 wxString GetName () const
1099 #ifdef DCPOMATIC_OSX
1100 wxBitmap GetLargeIcon () const
1102 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1109 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1110 table->AddGrowableCol (1, 1);
1111 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1113 add_label_to_sizer (table, _panel, _("Protocol"), true);
1114 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1115 table->Add (_tms_protocol, 1, wxEXPAND);
1117 add_label_to_sizer (table, _panel, _("IP address"), true);
1118 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1119 table->Add (_tms_ip, 1, wxEXPAND);
1121 add_label_to_sizer (table, _panel, _("Target path"), true);
1122 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1123 table->Add (_tms_path, 1, wxEXPAND);
1125 add_label_to_sizer (table, _panel, _("User name"), true);
1126 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1127 table->Add (_tms_user, 1, wxEXPAND);
1129 add_label_to_sizer (table, _panel, _("Password"), true);
1130 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1131 table->Add (_tms_password, 1, wxEXPAND);
1133 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1134 _tms_protocol->Append (_("FTP (for Dolby)"));
1136 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1137 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1138 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1139 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1140 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1143 void config_changed ()
1145 Config* config = Config::instance ();
1147 checked_set (_tms_protocol, config->tms_protocol ());
1148 checked_set (_tms_ip, config->tms_ip ());
1149 checked_set (_tms_path, config->tms_path ());
1150 checked_set (_tms_user, config->tms_user ());
1151 checked_set (_tms_password, config->tms_password ());
1154 void tms_protocol_changed ()
1156 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1159 void tms_ip_changed ()
1161 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1164 void tms_path_changed ()
1166 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1169 void tms_user_changed ()
1171 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1174 void tms_password_changed ()
1176 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1179 wxChoice* _tms_protocol;
1180 wxTextCtrl* _tms_ip;
1181 wxTextCtrl* _tms_path;
1182 wxTextCtrl* _tms_user;
1183 wxTextCtrl* _tms_password;
1192 class KDMEmailPage : public StandardPage
1196 KDMEmailPage (wxSize panel_size, int border)
1197 #ifdef DCPOMATIC_OSX
1198 /* We have to force both width and height of this one */
1199 : StandardPage (wxSize (480, 128), border)
1201 : StandardPage (panel_size, border)
1205 wxString GetName () const
1207 return _("KDM Email");
1210 #ifdef DCPOMATIC_OSX
1211 wxBitmap GetLargeIcon () const
1213 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1220 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1221 table->AddGrowableCol (1, 1);
1222 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1224 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1226 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1227 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1228 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1229 add_label_to_sizer (s, _panel, _("port"), false);
1230 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1231 _mail_port->SetRange (0, 65535);
1232 s->Add (_mail_port);
1233 table->Add (s, 1, wxEXPAND | wxALL);
1236 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1237 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1238 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1240 add_label_to_sizer (table, _panel, _("Mail password"), true);
1241 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1242 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1244 add_label_to_sizer (table, _panel, _("Subject"), true);
1245 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1246 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1248 add_label_to_sizer (table, _panel, _("From address"), true);
1249 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1250 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1252 vector<string> columns;
1253 columns.push_back (wx_to_std (_("Address")));
1254 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1255 _kdm_cc = new EditableList<string, EmailDialog> (
1256 _panel, columns, bind (&Config::kdm_cc, Config::instance()), bind (&Config::set_kdm_cc, Config::instance(), _1), bind (&column, _1)
1258 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1260 add_label_to_sizer (table, _panel, _("BCC address"), true);
1261 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1262 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1264 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1265 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1267 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1268 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1272 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1273 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1274 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1275 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1276 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1277 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1278 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1279 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1280 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1283 void config_changed ()
1285 Config* config = Config::instance ();
1287 checked_set (_mail_server, config->mail_server ());
1288 checked_set (_mail_port, config->mail_port ());
1289 checked_set (_mail_user, config->mail_user ());
1290 checked_set (_mail_password, config->mail_password ());
1291 checked_set (_kdm_subject, config->kdm_subject ());
1292 checked_set (_kdm_from, config->kdm_from ());
1293 checked_set (_kdm_bcc, config->kdm_bcc ());
1294 checked_set (_kdm_email, Config::instance()->kdm_email ());
1297 void mail_server_changed ()
1299 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1302 void mail_port_changed ()
1304 Config::instance()->set_mail_port (_mail_port->GetValue ());
1307 void mail_user_changed ()
1309 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1312 void mail_password_changed ()
1314 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1317 void kdm_subject_changed ()
1319 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1322 void kdm_from_changed ()
1324 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1327 void kdm_bcc_changed ()
1329 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1332 void kdm_email_changed ()
1334 if (_kdm_email->GetValue().IsEmpty ()) {
1335 /* Sometimes we get sent an erroneous notification that the email
1336 is empty; I don't know why.
1340 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1343 void reset_kdm_email ()
1345 Config::instance()->reset_kdm_email ();
1346 checked_set (_kdm_email, Config::instance()->kdm_email ());
1349 wxTextCtrl* _mail_server;
1350 wxSpinCtrl* _mail_port;
1351 wxTextCtrl* _mail_user;
1352 wxTextCtrl* _mail_password;
1353 wxTextCtrl* _kdm_subject;
1354 wxTextCtrl* _kdm_from;
1355 EditableList<string, EmailDialog>* _kdm_cc;
1356 wxTextCtrl* _kdm_bcc;
1357 wxTextCtrl* _kdm_email;
1358 wxButton* _reset_kdm_email;
1361 /** @class AdvancedPage
1362 * @brief Advanced page of the preferences dialog.
1364 class AdvancedPage : public StockPage
1367 AdvancedPage (wxSize panel_size, int border)
1368 : StockPage (Kind_Advanced, panel_size, border)
1369 , _maximum_j2k_bandwidth (0)
1370 , _allow_any_dcp_frame_rate (0)
1371 , _only_servers_encode (0)
1376 , _log_debug_decode (0)
1377 , _log_debug_encode (0)
1378 , _log_debug_email (0)
1384 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1385 table->AddGrowableCol (1, 1);
1386 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1389 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1390 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1391 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1392 s->Add (_maximum_j2k_bandwidth, 1);
1393 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1397 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1398 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1399 table->AddSpacer (0);
1401 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1402 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1403 table->AddSpacer (0);
1406 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1407 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1409 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1410 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1414 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1415 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1416 t->Add (_log_general, 1, wxEXPAND | wxALL);
1417 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1418 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1419 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1420 t->Add (_log_error, 1, wxEXPAND | wxALL);
1421 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1422 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1423 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1424 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1425 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1426 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1427 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1428 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1429 table->Add (t, 0, wxALL, 6);
1432 #ifdef DCPOMATIC_WINDOWS
1433 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1434 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1435 table->AddSpacer (0);
1438 _maximum_j2k_bandwidth->SetRange (1, 1000);
1439 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1440 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1441 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1442 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1443 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1444 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1445 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1446 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1447 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1448 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1449 #ifdef DCPOMATIC_WINDOWS
1450 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1454 void config_changed ()
1456 Config* config = Config::instance ();
1458 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1459 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1460 checked_set (_only_servers_encode, config->only_servers_encode ());
1461 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1462 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1463 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1464 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1465 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1466 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1467 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1468 #ifdef DCPOMATIC_WINDOWS
1469 checked_set (_win32_console, config->win32_console());
1473 void maximum_j2k_bandwidth_changed ()
1475 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1478 void allow_any_dcp_frame_rate_changed ()
1480 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1483 void only_servers_encode_changed ()
1485 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1491 if (_log_general->GetValue ()) {
1492 types |= LogEntry::TYPE_GENERAL;
1494 if (_log_warning->GetValue ()) {
1495 types |= LogEntry::TYPE_WARNING;
1497 if (_log_error->GetValue ()) {
1498 types |= LogEntry::TYPE_ERROR;
1500 if (_log_timing->GetValue ()) {
1501 types |= LogEntry::TYPE_TIMING;
1503 if (_log_debug_decode->GetValue ()) {
1504 types |= LogEntry::TYPE_DEBUG_DECODE;
1506 if (_log_debug_encode->GetValue ()) {
1507 types |= LogEntry::TYPE_DEBUG_ENCODE;
1509 if (_log_debug_email->GetValue ()) {
1510 types |= LogEntry::TYPE_DEBUG_EMAIL;
1512 Config::instance()->set_log_types (types);
1515 #ifdef DCPOMATIC_WINDOWS
1516 void win32_console_changed ()
1518 Config::instance()->set_win32_console (_win32_console->GetValue ());
1522 wxSpinCtrl* _maximum_j2k_bandwidth;
1523 wxCheckBox* _allow_any_dcp_frame_rate;
1524 wxCheckBox* _only_servers_encode;
1525 wxCheckBox* _log_general;
1526 wxCheckBox* _log_warning;
1527 wxCheckBox* _log_error;
1528 wxCheckBox* _log_timing;
1529 wxCheckBox* _log_debug_decode;
1530 wxCheckBox* _log_debug_encode;
1531 wxCheckBox* _log_debug_email;
1532 #ifdef DCPOMATIC_WINDOWS
1533 wxCheckBox* _win32_console;
1537 wxPreferencesEditor*
1538 create_config_dialog ()
1540 wxPreferencesEditor* e = new wxPreferencesEditor ();
1542 #ifdef DCPOMATIC_OSX
1543 /* Width that we force some of the config panels to be on OSX so that
1544 the containing window doesn't shrink too much when we select those panels.
1545 This is obviously an unpleasant hack.
1547 wxSize ps = wxSize (520, -1);
1548 int const border = 16;
1550 wxSize ps = wxSize (-1, -1);
1551 int const border = 8;
1554 e->AddPage (new GeneralPage (ps, border));
1555 e->AddPage (new DefaultsPage (ps, border));
1556 e->AddPage (new EncodingServersPage (ps, border));
1557 e->AddPage (new KeysPage (ps, border));
1558 e->AddPage (new TMSPage (ps, border));
1559 e->AddPage (new KDMEmailPage (ps, border));
1560 e->AddPage (new AdvancedPage (ps, border));