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>
61 using boost::shared_ptr;
62 using boost::function;
63 using boost::optional;
68 Page (wxSize panel_size, int border)
71 , _panel_size (panel_size)
72 , _window_exists (false)
74 _config_connection = Config::instance()->Changed.connect (boost::bind (&Page::config_changed_wrapper, this));
80 wxWindow* create_window (wxWindow* parent)
82 _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size);
83 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
87 _window_exists = true;
90 _panel->Bind (wxEVT_DESTROY, boost::bind (&Page::window_destroyed, this));
99 virtual void config_changed () = 0;
100 virtual void setup () = 0;
102 void config_changed_wrapper ()
104 if (_window_exists) {
109 void window_destroyed ()
111 _window_exists = false;
115 boost::signals2::scoped_connection _config_connection;
119 class StockPage : public wxStockPreferencesPage, public Page
122 StockPage (Kind kind, wxSize panel_size, int border)
123 : wxStockPreferencesPage (kind)
124 , Page (panel_size, border)
127 wxWindow* CreateWindow (wxWindow* parent)
129 return create_window (parent);
133 class StandardPage : public wxPreferencesPage, public Page
136 StandardPage (wxSize panel_size, int border)
137 : Page (panel_size, border)
140 wxWindow* CreateWindow (wxWindow* parent)
142 return create_window (parent);
146 class GeneralPage : public StockPage
149 GeneralPage (wxSize panel_size, int border)
150 : StockPage (Kind_General, panel_size, border)
156 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
157 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
160 _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language"));
161 table->Add (_set_language, wxGBPosition (r, 0));
162 _language = new wxChoice (_panel, wxID_ANY);
163 vector<pair<string, string> > languages;
164 languages.push_back (make_pair ("Deutsch", "de_DE"));
165 languages.push_back (make_pair ("English", "en_GB"));
166 languages.push_back (make_pair ("Español", "es_ES"));
167 languages.push_back (make_pair ("Français", "fr_FR"));
168 languages.push_back (make_pair ("Italiano", "it_IT"));
169 languages.push_back (make_pair ("Nederlands", "nl_NL"));
170 languages.push_back (make_pair ("Svenska", "sv_SE"));
171 languages.push_back (make_pair ("Русский", "ru_RU"));
172 languages.push_back (make_pair ("Polski", "pl_PL"));
173 languages.push_back (make_pair ("Dansk", "da_DK"));
174 languages.push_back (make_pair ("Português europeu", "pt_PT"));
175 languages.push_back (make_pair ("Slovenský jazyk", "sk_SK"));
176 languages.push_back (make_pair ("Čeština", "cs_CZ"));
177 languages.push_back (make_pair ("українська мова", "uk_UA"));
178 checked_set (_language, languages);
179 table->Add (_language, wxGBPosition (r, 1));
182 wxStaticText* restart = add_label_to_sizer (
183 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
185 wxFont font = restart->GetFont();
186 font.SetStyle (wxFONTSTYLE_ITALIC);
187 font.SetPointSize (font.GetPointSize() - 1);
188 restart->SetFont (font);
191 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
192 _num_local_encoding_threads = new wxSpinCtrl (_panel);
193 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
196 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
197 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml");
198 table->Add (_cinemas_file, wxGBPosition (r, 1));
201 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
202 _analyse_ebur128 = new wxCheckBox (_panel, wxID_ANY, _("Find integrated loudness, true peak and loudness range when analysing audio"));
203 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
207 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
208 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
211 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
212 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
215 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
216 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
219 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
220 bottom_table->AddGrowableCol (1, 1);
222 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
223 _issuer = new wxTextCtrl (_panel, wxID_ANY);
224 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
226 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
227 _creator = new wxTextCtrl (_panel, wxID_ANY);
228 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
230 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
233 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
234 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
235 _cinemas_file->Bind (wxEVT_COMMAND_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
237 _num_local_encoding_threads->SetRange (1, 128);
238 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
240 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
241 _analyse_ebur128->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::analyse_ebur128_changed, this));
243 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
244 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
245 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
247 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
248 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
251 void config_changed ()
253 Config* config = Config::instance ();
255 checked_set (_set_language, static_cast<bool>(config->language()));
257 /* Backwards compatibility of config file */
259 map<string, string> compat_map;
260 compat_map["fr"] = "fr_FR";
261 compat_map["it"] = "it_IT";
262 compat_map["es"] = "es_ES";
263 compat_map["sv"] = "sv_SE";
264 compat_map["de"] = "de_DE";
265 compat_map["nl"] = "nl_NL";
266 compat_map["ru"] = "ru_RU";
267 compat_map["pl"] = "pl_PL";
268 compat_map["da"] = "da_DK";
269 compat_map["pt"] = "pt_PT";
270 compat_map["sk"] = "sk_SK";
271 compat_map["cs"] = "cs_CZ";
272 compat_map["uk"] = "uk_UA";
274 string lang = config->language().get_value_or ("en_GB");
275 if (compat_map.find (lang) != compat_map.end ()) {
276 lang = compat_map[lang];
279 checked_set (_language, lang);
281 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
282 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
283 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
285 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
286 checked_set (_check_for_updates, config->check_for_updates ());
287 checked_set (_check_for_test_updates, config->check_for_test_updates ());
288 checked_set (_issuer, config->dcp_issuer ());
289 checked_set (_creator, config->dcp_creator ());
290 checked_set (_cinemas_file, config->cinemas_file());
292 setup_sensitivity ();
295 void setup_sensitivity ()
297 _language->Enable (_set_language->GetValue ());
298 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
301 void set_language_changed ()
303 setup_sensitivity ();
304 if (_set_language->GetValue ()) {
307 Config::instance()->unset_language ();
311 void language_changed ()
313 int const sel = _language->GetSelection ();
315 Config::instance()->set_language (string_client_data (_language->GetClientObject (sel)));
317 Config::instance()->unset_language ();
321 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
322 void analyse_ebur128_changed ()
324 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
328 void automatic_audio_analysis_changed ()
330 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
333 void check_for_updates_changed ()
335 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
338 void check_for_test_updates_changed ()
340 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
343 void num_local_encoding_threads_changed ()
345 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
348 void issuer_changed ()
350 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
353 void creator_changed ()
355 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
358 void cinemas_file_changed ()
360 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
363 wxCheckBox* _set_language;
365 wxSpinCtrl* _num_local_encoding_threads;
366 FilePickerCtrl* _cinemas_file;
367 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
368 wxCheckBox* _analyse_ebur128;
370 wxCheckBox* _automatic_audio_analysis;
371 wxCheckBox* _check_for_updates;
372 wxCheckBox* _check_for_test_updates;
374 wxTextCtrl* _creator;
377 class DefaultsPage : public StandardPage
380 DefaultsPage (wxSize panel_size, int border)
381 : StandardPage (panel_size, border)
384 wxString GetName () const
386 return _("Defaults");
390 wxBitmap GetLargeIcon () const
392 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
399 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
400 table->AddGrowableCol (1, 1);
401 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
404 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
405 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
406 _still_length = new wxSpinCtrl (_panel);
407 s->Add (_still_length);
408 add_label_to_sizer (s, _panel, _("s"), false);
412 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
413 #ifdef DCPOMATIC_USE_OWN_PICKER
414 _directory = new DirPickerCtrl (_panel);
416 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
418 table->Add (_directory, 1, wxEXPAND);
420 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
421 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
422 table->Add (_isdcf_metadata_button);
424 add_label_to_sizer (table, _panel, _("Default container"), true);
425 _container = new wxChoice (_panel, wxID_ANY);
426 table->Add (_container);
428 add_label_to_sizer (table, _panel, _("Default content type"), true);
429 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
430 table->Add (_dcp_content_type);
433 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
434 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
435 _j2k_bandwidth = new wxSpinCtrl (_panel);
436 s->Add (_j2k_bandwidth);
437 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
442 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
443 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
444 _audio_delay = new wxSpinCtrl (_panel);
445 s->Add (_audio_delay);
446 add_label_to_sizer (s, _panel, _("ms"), false);
450 add_label_to_sizer (table, _panel, _("Default standard"), true);
451 _standard = new wxChoice (_panel, wxID_ANY);
452 table->Add (_standard);
454 _still_length->SetRange (1, 3600);
455 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
457 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
459 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
461 vector<Ratio const *> ratios = Ratio::all ();
462 for (size_t i = 0; i < ratios.size(); ++i) {
463 _container->Append (std_to_wx (ratios[i]->nickname ()));
466 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
468 vector<DCPContentType const *> const ct = DCPContentType::all ();
469 for (size_t i = 0; i < ct.size(); ++i) {
470 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
473 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
475 _j2k_bandwidth->SetRange (50, 250);
476 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
478 _audio_delay->SetRange (-1000, 1000);
479 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
481 _standard->Append (_("SMPTE"));
482 _standard->Append (_("Interop"));
483 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
486 void config_changed ()
488 Config* config = Config::instance ();
490 vector<Ratio const *> ratios = Ratio::all ();
491 for (size_t i = 0; i < ratios.size(); ++i) {
492 if (ratios[i] == config->default_container ()) {
493 _container->SetSelection (i);
497 vector<DCPContentType const *> const ct = DCPContentType::all ();
498 for (size_t i = 0; i < ct.size(); ++i) {
499 if (ct[i] == config->default_dcp_content_type ()) {
500 _dcp_content_type->SetSelection (i);
504 checked_set (_still_length, config->default_still_length ());
505 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
506 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
507 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
508 checked_set (_audio_delay, config->default_audio_delay ());
509 checked_set (_standard, config->default_interop() ? 1 : 0);
512 void j2k_bandwidth_changed ()
514 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
517 void audio_delay_changed ()
519 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
522 void directory_changed ()
524 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
527 void edit_isdcf_metadata_clicked ()
529 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
531 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
535 void still_length_changed ()
537 Config::instance()->set_default_still_length (_still_length->GetValue ());
540 void container_changed ()
542 vector<Ratio const *> ratio = Ratio::all ();
543 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
546 void dcp_content_type_changed ()
548 vector<DCPContentType const *> ct = DCPContentType::all ();
549 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
552 void standard_changed ()
554 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
557 wxSpinCtrl* _j2k_bandwidth;
558 wxSpinCtrl* _audio_delay;
559 wxButton* _isdcf_metadata_button;
560 wxSpinCtrl* _still_length;
561 #ifdef DCPOMATIC_USE_OWN_PICKER
562 DirPickerCtrl* _directory;
564 wxDirPickerCtrl* _directory;
566 wxChoice* _container;
567 wxChoice* _dcp_content_type;
571 class EncodingServersPage : public StandardPage
574 EncodingServersPage (wxSize panel_size, int border)
575 : StandardPage (panel_size, border)
578 wxString GetName () const
584 wxBitmap GetLargeIcon () const
586 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
593 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
594 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
596 vector<string> columns;
597 columns.push_back (wx_to_std (_("IP address / host name")));
598 _servers_list = new EditableList<string, ServerDialog> (
601 boost::bind (&Config::servers, Config::instance()),
602 boost::bind (&Config::set_servers, Config::instance(), _1),
603 boost::bind (&always_valid),
604 boost::bind (&EncodingServersPage::server_column, this, _1)
607 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
609 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
612 void config_changed ()
614 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
615 _servers_list->refresh ();
618 void use_any_servers_changed ()
620 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
623 string server_column (string s)
628 wxCheckBox* _use_any_servers;
629 EditableList<string, ServerDialog>* _servers_list;
632 class CertificateChainEditor : public wxPanel
635 CertificateChainEditor (
639 function<void (shared_ptr<dcp::CertificateChain>)> set,
640 function<shared_ptr<const dcp::CertificateChain> (void)> get
646 wxFont subheading_font (*wxNORMAL_FONT);
647 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
649 _sizer = new wxBoxSizer (wxVERTICAL);
652 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
653 m->SetFont (subheading_font);
654 _sizer->Add (m, 0, wxALL, border);
657 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
658 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
660 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
665 ip.SetText (_("Type"));
667 _certificates->InsertColumn (0, ip);
673 ip.SetText (_("Thumbprint"));
676 wxFont font = ip.GetFont ();
677 font.SetFamily (wxFONTFAMILY_TELETYPE);
680 _certificates->InsertColumn (1, ip);
683 certificates_sizer->Add (_certificates, 1, wxEXPAND);
686 wxSizer* s = new wxBoxSizer (wxVERTICAL);
687 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
688 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
689 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
690 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
691 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
692 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
693 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
696 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
697 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
700 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
701 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
702 wxFont font = _private_key->GetFont ();
703 font.SetFamily (wxFONTFAMILY_TELETYPE);
704 _private_key->SetFont (font);
705 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
706 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
707 table->Add (_load_private_key, wxGBPosition (r, 2));
708 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
709 table->Add (_export_private_key, wxGBPosition (r, 3));
712 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
713 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
714 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
715 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
718 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
719 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
720 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
721 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
722 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
723 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
724 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
725 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
727 SetSizerAndFit (_sizer);
730 void config_changed ()
732 _chain.reset (new dcp::CertificateChain (*_get().get ()));
734 update_certificate_list ();
735 update_private_key ();
736 update_sensitivity ();
739 void add_button (wxWindow* button)
741 _button_sizer->Add (button);
746 void add_certificate ()
748 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
750 if (d->ShowModal() == wxID_OK) {
752 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
755 update_certificate_list ();
756 } catch (dcp::MiscError& e) {
757 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
763 update_sensitivity ();
766 void remove_certificate ()
768 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
773 _certificates->DeleteItem (i);
777 update_sensitivity ();
780 void export_certificate ()
782 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
787 wxFileDialog* d = new wxFileDialog (
788 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
789 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
792 dcp::CertificateChain::List all = _chain->root_to_leaf ();
793 dcp::CertificateChain::List::iterator j = all.begin ();
794 for (int k = 0; k < i; ++k) {
798 if (d->ShowModal () == wxID_OK) {
799 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
801 throw OpenFileError (wx_to_std (d->GetPath ()));
804 string const s = j->certificate (true);
805 fwrite (s.c_str(), 1, s.length(), f);
811 void update_certificate_list ()
813 _certificates->DeleteAllItems ();
815 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
816 BOOST_FOREACH (dcp::Certificate const & i, certs) {
819 _certificates->InsertItem (item);
820 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
823 _certificates->SetItem (n, 0, _("Root"));
824 } else if (n == (certs.size() - 1)) {
825 _certificates->SetItem (n, 0, _("Leaf"));
827 _certificates->SetItem (n, 0, _("Intermediate"));
834 void remake_certificates ()
836 shared_ptr<const dcp::CertificateChain> chain = _get ();
838 string subject_organization_name;
839 string subject_organizational_unit_name;
840 string root_common_name;
841 string intermediate_common_name;
842 string leaf_common_name;
844 dcp::CertificateChain::List all = chain->root_to_leaf ();
846 if (all.size() >= 1) {
848 subject_organization_name = chain->root().subject_organization_name ();
849 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
850 root_common_name = chain->root().subject_common_name ();
853 if (all.size() >= 2) {
855 leaf_common_name = chain->leaf().subject_common_name ();
858 if (all.size() >= 3) {
859 /* Have an intermediate */
860 dcp::CertificateChain::List::iterator i = all.begin ();
862 intermediate_common_name = i->subject_common_name ();
865 MakeChainDialog* d = new MakeChainDialog (
867 subject_organization_name,
868 subject_organizational_unit_name,
870 intermediate_common_name,
874 if (d->ShowModal () == wxID_OK) {
876 new dcp::CertificateChain (
879 d->organisational_unit (),
880 d->root_common_name (),
881 d->intermediate_common_name (),
882 d->leaf_common_name ()
887 update_certificate_list ();
888 update_private_key ();
894 void update_sensitivity ()
896 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
897 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
900 void update_private_key ()
902 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
906 void load_private_key ()
908 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
910 if (d->ShowModal() == wxID_OK) {
912 boost::filesystem::path p (wx_to_std (d->GetPath ()));
913 if (boost::filesystem::file_size (p) > 1024) {
914 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
918 _chain->set_key (dcp::file_to_string (p));
920 update_private_key ();
921 } catch (dcp::MiscError& e) {
922 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
928 update_sensitivity ();
931 void export_private_key ()
933 optional<string> key = _chain->key ();
938 wxFileDialog* d = new wxFileDialog (
939 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
940 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
943 if (d->ShowModal () == wxID_OK) {
944 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
946 throw OpenFileError (wx_to_std (d->GetPath ()));
949 string const s = _chain->key().get ();
950 fwrite (s.c_str(), 1, s.length(), f);
956 wxListCtrl* _certificates;
957 wxButton* _add_certificate;
958 wxButton* _export_certificate;
959 wxButton* _remove_certificate;
960 wxButton* _remake_certificates;
961 wxStaticText* _private_key;
962 wxButton* _load_private_key;
963 wxButton* _export_private_key;
965 wxBoxSizer* _button_sizer;
966 shared_ptr<dcp::CertificateChain> _chain;
967 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
968 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
971 class KeysPage : public StandardPage
974 KeysPage (wxSize panel_size, int border)
975 : StandardPage (panel_size, border)
978 wxString GetName () const
984 wxBitmap GetLargeIcon () const
986 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
994 _signer = new CertificateChainEditor (
995 _panel, _("Signing DCPs and KDMs"), _border,
996 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
997 boost::bind (&Config::signer_chain, Config::instance ())
1000 _panel->GetSizer()->Add (_signer);
1002 _decryption = new CertificateChainEditor (
1003 _panel, _("Decrypting DCPs"), _border,
1004 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1005 boost::bind (&Config::decryption_chain, Config::instance ())
1008 _panel->GetSizer()->Add (_decryption);
1010 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1011 _decryption->add_button (_export_decryption_certificate);
1013 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1016 void export_decryption_certificate ()
1018 wxFileDialog* d = new wxFileDialog (
1019 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1020 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1023 if (d->ShowModal () == wxID_OK) {
1024 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1026 throw OpenFileError (wx_to_std (d->GetPath ()));
1029 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1030 fwrite (s.c_str(), 1, s.length(), f);
1036 void config_changed ()
1038 _signer->config_changed ();
1039 _decryption->config_changed ();
1042 CertificateChainEditor* _signer;
1043 CertificateChainEditor* _decryption;
1044 wxButton* _export_decryption_certificate;
1047 class TMSPage : public StandardPage
1050 TMSPage (wxSize panel_size, int border)
1051 : StandardPage (panel_size, border)
1054 wxString GetName () const
1059 #ifdef DCPOMATIC_OSX
1060 wxBitmap GetLargeIcon () const
1062 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1069 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1070 table->AddGrowableCol (1, 1);
1071 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1073 add_label_to_sizer (table, _panel, _("Protocol"), true);
1074 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1075 table->Add (_tms_protocol, 1, wxEXPAND);
1077 add_label_to_sizer (table, _panel, _("IP address"), true);
1078 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1079 table->Add (_tms_ip, 1, wxEXPAND);
1081 add_label_to_sizer (table, _panel, _("Target path"), true);
1082 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1083 table->Add (_tms_path, 1, wxEXPAND);
1085 add_label_to_sizer (table, _panel, _("User name"), true);
1086 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1087 table->Add (_tms_user, 1, wxEXPAND);
1089 add_label_to_sizer (table, _panel, _("Password"), true);
1090 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1091 table->Add (_tms_password, 1, wxEXPAND);
1093 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1094 _tms_protocol->Append (_("FTP (for Dolby)"));
1096 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1097 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1098 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1099 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1100 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1103 void config_changed ()
1105 Config* config = Config::instance ();
1107 checked_set (_tms_protocol, config->tms_protocol ());
1108 checked_set (_tms_ip, config->tms_ip ());
1109 checked_set (_tms_path, config->tms_path ());
1110 checked_set (_tms_user, config->tms_user ());
1111 checked_set (_tms_password, config->tms_password ());
1114 void tms_protocol_changed ()
1116 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1119 void tms_ip_changed ()
1121 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1124 void tms_path_changed ()
1126 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1129 void tms_user_changed ()
1131 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1134 void tms_password_changed ()
1136 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1139 wxChoice* _tms_protocol;
1140 wxTextCtrl* _tms_ip;
1141 wxTextCtrl* _tms_path;
1142 wxTextCtrl* _tms_user;
1143 wxTextCtrl* _tms_password;
1152 class KDMEmailPage : public StandardPage
1156 KDMEmailPage (wxSize panel_size, int border)
1157 #ifdef DCPOMATIC_OSX
1158 /* We have to force both width and height of this one */
1159 : StandardPage (wxSize (480, 128), border)
1161 : StandardPage (panel_size, border)
1165 wxString GetName () const
1167 return _("KDM Email");
1170 #ifdef DCPOMATIC_OSX
1171 wxBitmap GetLargeIcon () const
1173 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1180 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1181 table->AddGrowableCol (1, 1);
1182 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1184 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1186 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1187 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1188 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1189 add_label_to_sizer (s, _panel, _("port"), false);
1190 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1191 _mail_port->SetRange (0, 65535);
1192 s->Add (_mail_port);
1193 table->Add (s, 1, wxEXPAND | wxALL);
1196 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1197 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1198 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1200 add_label_to_sizer (table, _panel, _("Mail password"), true);
1201 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1202 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1204 add_label_to_sizer (table, _panel, _("Subject"), true);
1205 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1206 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1208 add_label_to_sizer (table, _panel, _("From address"), true);
1209 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1210 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1212 vector<string> columns;
1213 columns.push_back (wx_to_std (_("Address")));
1214 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1215 _kdm_cc = new EditableList<string, EmailDialog> (
1218 bind (&Config::kdm_cc, Config::instance()),
1219 bind (&Config::set_kdm_cc, Config::instance(), _1),
1220 bind (&string_not_empty, _1),
1223 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1225 add_label_to_sizer (table, _panel, _("BCC address"), true);
1226 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1227 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1229 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1230 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1232 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1233 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1237 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1238 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1239 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1240 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1241 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1242 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1243 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1244 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1245 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1248 void config_changed ()
1250 Config* config = Config::instance ();
1252 checked_set (_mail_server, config->mail_server ());
1253 checked_set (_mail_port, config->mail_port ());
1254 checked_set (_mail_user, config->mail_user ());
1255 checked_set (_mail_password, config->mail_password ());
1256 checked_set (_kdm_subject, config->kdm_subject ());
1257 checked_set (_kdm_from, config->kdm_from ());
1258 checked_set (_kdm_bcc, config->kdm_bcc ());
1259 checked_set (_kdm_email, Config::instance()->kdm_email ());
1262 void mail_server_changed ()
1264 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1267 void mail_port_changed ()
1269 Config::instance()->set_mail_port (_mail_port->GetValue ());
1272 void mail_user_changed ()
1274 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1277 void mail_password_changed ()
1279 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1282 void kdm_subject_changed ()
1284 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1287 void kdm_from_changed ()
1289 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1292 void kdm_bcc_changed ()
1294 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1297 void kdm_email_changed ()
1299 if (_kdm_email->GetValue().IsEmpty ()) {
1300 /* Sometimes we get sent an erroneous notification that the email
1301 is empty; I don't know why.
1305 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1308 void reset_kdm_email ()
1310 Config::instance()->reset_kdm_email ();
1311 checked_set (_kdm_email, Config::instance()->kdm_email ());
1314 wxTextCtrl* _mail_server;
1315 wxSpinCtrl* _mail_port;
1316 wxTextCtrl* _mail_user;
1317 wxTextCtrl* _mail_password;
1318 wxTextCtrl* _kdm_subject;
1319 wxTextCtrl* _kdm_from;
1320 EditableList<string, EmailDialog>* _kdm_cc;
1321 wxTextCtrl* _kdm_bcc;
1322 wxTextCtrl* _kdm_email;
1323 wxButton* _reset_kdm_email;
1326 /** @class AdvancedPage
1327 * @brief Advanced page of the preferences dialog.
1329 class AdvancedPage : public StockPage
1332 AdvancedPage (wxSize panel_size, int border)
1333 : StockPage (Kind_Advanced, panel_size, border)
1334 , _maximum_j2k_bandwidth (0)
1335 , _allow_any_dcp_frame_rate (0)
1336 , _only_servers_encode (0)
1341 , _log_debug_decode (0)
1342 , _log_debug_encode (0)
1343 , _log_debug_email (0)
1349 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1350 table->AddGrowableCol (1, 1);
1351 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1354 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1355 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1356 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1357 s->Add (_maximum_j2k_bandwidth, 1);
1358 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1362 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1363 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1364 table->AddSpacer (0);
1366 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1367 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1368 table->AddSpacer (0);
1371 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1372 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1374 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1375 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1379 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1380 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1381 t->Add (_log_general, 1, wxEXPAND | wxALL);
1382 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1383 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1384 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1385 t->Add (_log_error, 1, wxEXPAND | wxALL);
1386 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1387 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1388 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1389 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1390 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1391 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1392 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1393 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1394 table->Add (t, 0, wxALL, 6);
1397 #ifdef DCPOMATIC_WINDOWS
1398 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1399 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1400 table->AddSpacer (0);
1403 _maximum_j2k_bandwidth->SetRange (1, 1000);
1404 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1405 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1406 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1407 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1408 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1409 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1410 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1411 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1412 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1413 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1414 #ifdef DCPOMATIC_WINDOWS
1415 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1419 void config_changed ()
1421 Config* config = Config::instance ();
1423 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1424 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1425 checked_set (_only_servers_encode, config->only_servers_encode ());
1426 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1427 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1428 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1429 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1430 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1431 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1432 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1433 #ifdef DCPOMATIC_WINDOWS
1434 checked_set (_win32_console, config->win32_console());
1438 void maximum_j2k_bandwidth_changed ()
1440 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1443 void allow_any_dcp_frame_rate_changed ()
1445 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1448 void only_servers_encode_changed ()
1450 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1456 if (_log_general->GetValue ()) {
1457 types |= LogEntry::TYPE_GENERAL;
1459 if (_log_warning->GetValue ()) {
1460 types |= LogEntry::TYPE_WARNING;
1462 if (_log_error->GetValue ()) {
1463 types |= LogEntry::TYPE_ERROR;
1465 if (_log_timing->GetValue ()) {
1466 types |= LogEntry::TYPE_TIMING;
1468 if (_log_debug_decode->GetValue ()) {
1469 types |= LogEntry::TYPE_DEBUG_DECODE;
1471 if (_log_debug_encode->GetValue ()) {
1472 types |= LogEntry::TYPE_DEBUG_ENCODE;
1474 if (_log_debug_email->GetValue ()) {
1475 types |= LogEntry::TYPE_DEBUG_EMAIL;
1477 Config::instance()->set_log_types (types);
1480 #ifdef DCPOMATIC_WINDOWS
1481 void win32_console_changed ()
1483 Config::instance()->set_win32_console (_win32_console->GetValue ());
1487 wxSpinCtrl* _maximum_j2k_bandwidth;
1488 wxCheckBox* _allow_any_dcp_frame_rate;
1489 wxCheckBox* _only_servers_encode;
1490 wxCheckBox* _log_general;
1491 wxCheckBox* _log_warning;
1492 wxCheckBox* _log_error;
1493 wxCheckBox* _log_timing;
1494 wxCheckBox* _log_debug_decode;
1495 wxCheckBox* _log_debug_encode;
1496 wxCheckBox* _log_debug_email;
1497 #ifdef DCPOMATIC_WINDOWS
1498 wxCheckBox* _win32_console;
1502 wxPreferencesEditor*
1503 create_config_dialog ()
1505 wxPreferencesEditor* e = new wxPreferencesEditor ();
1507 #ifdef DCPOMATIC_OSX
1508 /* Width that we force some of the config panels to be on OSX so that
1509 the containing window doesn't shrink too much when we select those panels.
1510 This is obviously an unpleasant hack.
1512 wxSize ps = wxSize (520, -1);
1513 int const border = 16;
1515 wxSize ps = wxSize (-1, -1);
1516 int const border = 8;
1519 e->AddPage (new GeneralPage (ps, border));
1520 e->AddPage (new DefaultsPage (ps, border));
1521 e->AddPage (new EncodingServersPage (ps, border));
1522 e->AddPage (new KeysPage (ps, border));
1523 e->AddPage (new TMSPage (ps, border));
1524 e->AddPage (new KDMEmailPage (ps, border));
1525 e->AddPage (new AdvancedPage (ps, border));