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 ("Čeština", "cs_CZ"));
165 languages.push_back (make_pair ("汉语/漢語", "zh_CN"));
166 languages.push_back (make_pair ("Dansk", "da_DK"));
167 languages.push_back (make_pair ("Deutsch", "de_DE"));
168 languages.push_back (make_pair ("English", "en_GB"));
169 languages.push_back (make_pair ("Español", "es_ES"));
170 languages.push_back (make_pair ("Français", "fr_FR"));
171 languages.push_back (make_pair ("Italiano", "it_IT"));
172 languages.push_back (make_pair ("Nederlands", "nl_NL"));
173 languages.push_back (make_pair ("Русский", "ru_RU"));
174 languages.push_back (make_pair ("Polski", "pl_PL"));
175 languages.push_back (make_pair ("Português europeu", "pt_PT"));
176 languages.push_back (make_pair ("Português do Brasil", "pt_BR"));
177 languages.push_back (make_pair ("Svenska", "sv_SE"));
178 languages.push_back (make_pair ("Slovenský jazyk", "sk_SK"));
179 languages.push_back (make_pair ("українська мова", "uk_UA"));
180 checked_set (_language, languages);
181 table->Add (_language, wxGBPosition (r, 1));
184 wxStaticText* restart = add_label_to_sizer (
185 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
187 wxFont font = restart->GetFont();
188 font.SetStyle (wxFONTSTYLE_ITALIC);
189 font.SetPointSize (font.GetPointSize() - 1);
190 restart->SetFont (font);
193 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
194 _num_local_encoding_threads = new wxSpinCtrl (_panel);
195 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
198 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
199 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml");
200 table->Add (_cinemas_file, wxGBPosition (r, 1));
203 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
204 _analyse_ebur128 = new wxCheckBox (_panel, wxID_ANY, _("Find integrated loudness, true peak and loudness range when analysing audio"));
205 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
209 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
210 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
213 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
214 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
217 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
218 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
221 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
222 bottom_table->AddGrowableCol (1, 1);
224 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
225 _issuer = new wxTextCtrl (_panel, wxID_ANY);
226 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
228 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
229 _creator = new wxTextCtrl (_panel, wxID_ANY);
230 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
232 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
235 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
236 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
237 _cinemas_file->Bind (wxEVT_COMMAND_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
239 _num_local_encoding_threads->SetRange (1, 128);
240 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
242 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
243 _analyse_ebur128->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::analyse_ebur128_changed, this));
245 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
246 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
247 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
249 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
250 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
253 void config_changed ()
255 Config* config = Config::instance ();
257 checked_set (_set_language, static_cast<bool>(config->language()));
259 /* Backwards compatibility of config file */
261 map<string, string> compat_map;
262 compat_map["fr"] = "fr_FR";
263 compat_map["it"] = "it_IT";
264 compat_map["es"] = "es_ES";
265 compat_map["sv"] = "sv_SE";
266 compat_map["de"] = "de_DE";
267 compat_map["nl"] = "nl_NL";
268 compat_map["ru"] = "ru_RU";
269 compat_map["pl"] = "pl_PL";
270 compat_map["da"] = "da_DK";
271 compat_map["pt"] = "pt_PT";
272 compat_map["sk"] = "sk_SK";
273 compat_map["cs"] = "cs_CZ";
274 compat_map["uk"] = "uk_UA";
276 string lang = config->language().get_value_or ("en_GB");
277 if (compat_map.find (lang) != compat_map.end ()) {
278 lang = compat_map[lang];
281 checked_set (_language, lang);
283 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
284 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
285 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
287 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
288 checked_set (_check_for_updates, config->check_for_updates ());
289 checked_set (_check_for_test_updates, config->check_for_test_updates ());
290 checked_set (_issuer, config->dcp_issuer ());
291 checked_set (_creator, config->dcp_creator ());
292 checked_set (_cinemas_file, config->cinemas_file());
294 setup_sensitivity ();
297 void setup_sensitivity ()
299 _language->Enable (_set_language->GetValue ());
300 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
303 void set_language_changed ()
305 setup_sensitivity ();
306 if (_set_language->GetValue ()) {
309 Config::instance()->unset_language ();
313 void language_changed ()
315 int const sel = _language->GetSelection ();
317 Config::instance()->set_language (string_client_data (_language->GetClientObject (sel)));
319 Config::instance()->unset_language ();
323 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
324 void analyse_ebur128_changed ()
326 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
330 void automatic_audio_analysis_changed ()
332 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
335 void check_for_updates_changed ()
337 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
340 void check_for_test_updates_changed ()
342 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
345 void num_local_encoding_threads_changed ()
347 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
350 void issuer_changed ()
352 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
355 void creator_changed ()
357 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
360 void cinemas_file_changed ()
362 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
365 wxCheckBox* _set_language;
367 wxSpinCtrl* _num_local_encoding_threads;
368 FilePickerCtrl* _cinemas_file;
369 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
370 wxCheckBox* _analyse_ebur128;
372 wxCheckBox* _automatic_audio_analysis;
373 wxCheckBox* _check_for_updates;
374 wxCheckBox* _check_for_test_updates;
376 wxTextCtrl* _creator;
379 class DefaultsPage : public StandardPage
382 DefaultsPage (wxSize panel_size, int border)
383 : StandardPage (panel_size, border)
386 wxString GetName () const
388 return _("Defaults");
392 wxBitmap GetLargeIcon () const
394 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
401 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
402 table->AddGrowableCol (1, 1);
403 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
406 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
407 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
408 _still_length = new wxSpinCtrl (_panel);
409 s->Add (_still_length);
410 add_label_to_sizer (s, _panel, _("s"), false);
414 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
415 #ifdef DCPOMATIC_USE_OWN_PICKER
416 _directory = new DirPickerCtrl (_panel);
418 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
420 table->Add (_directory, 1, wxEXPAND);
422 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
423 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
424 table->Add (_isdcf_metadata_button);
426 add_label_to_sizer (table, _panel, _("Default container"), true);
427 _container = new wxChoice (_panel, wxID_ANY);
428 table->Add (_container);
430 add_label_to_sizer (table, _panel, _("Default content type"), true);
431 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
432 table->Add (_dcp_content_type);
435 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
436 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
437 _j2k_bandwidth = new wxSpinCtrl (_panel);
438 s->Add (_j2k_bandwidth);
439 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
444 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
445 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
446 _audio_delay = new wxSpinCtrl (_panel);
447 s->Add (_audio_delay);
448 add_label_to_sizer (s, _panel, _("ms"), false);
452 add_label_to_sizer (table, _panel, _("Default standard"), true);
453 _standard = new wxChoice (_panel, wxID_ANY);
454 table->Add (_standard);
456 _still_length->SetRange (1, 3600);
457 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
459 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
461 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
463 vector<Ratio const *> ratios = Ratio::all ();
464 for (size_t i = 0; i < ratios.size(); ++i) {
465 _container->Append (std_to_wx (ratios[i]->nickname ()));
468 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
470 vector<DCPContentType const *> const ct = DCPContentType::all ();
471 for (size_t i = 0; i < ct.size(); ++i) {
472 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
475 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
477 _j2k_bandwidth->SetRange (50, 250);
478 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
480 _audio_delay->SetRange (-1000, 1000);
481 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
483 _standard->Append (_("SMPTE"));
484 _standard->Append (_("Interop"));
485 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
488 void config_changed ()
490 Config* config = Config::instance ();
492 vector<Ratio const *> ratios = Ratio::all ();
493 for (size_t i = 0; i < ratios.size(); ++i) {
494 if (ratios[i] == config->default_container ()) {
495 _container->SetSelection (i);
499 vector<DCPContentType const *> const ct = DCPContentType::all ();
500 for (size_t i = 0; i < ct.size(); ++i) {
501 if (ct[i] == config->default_dcp_content_type ()) {
502 _dcp_content_type->SetSelection (i);
506 checked_set (_still_length, config->default_still_length ());
507 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
508 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
509 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
510 checked_set (_audio_delay, config->default_audio_delay ());
511 checked_set (_standard, config->default_interop() ? 1 : 0);
514 void j2k_bandwidth_changed ()
516 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
519 void audio_delay_changed ()
521 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
524 void directory_changed ()
526 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
529 void edit_isdcf_metadata_clicked ()
531 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
533 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
537 void still_length_changed ()
539 Config::instance()->set_default_still_length (_still_length->GetValue ());
542 void container_changed ()
544 vector<Ratio const *> ratio = Ratio::all ();
545 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
548 void dcp_content_type_changed ()
550 vector<DCPContentType const *> ct = DCPContentType::all ();
551 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
554 void standard_changed ()
556 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
559 wxSpinCtrl* _j2k_bandwidth;
560 wxSpinCtrl* _audio_delay;
561 wxButton* _isdcf_metadata_button;
562 wxSpinCtrl* _still_length;
563 #ifdef DCPOMATIC_USE_OWN_PICKER
564 DirPickerCtrl* _directory;
566 wxDirPickerCtrl* _directory;
568 wxChoice* _container;
569 wxChoice* _dcp_content_type;
573 class EncodingServersPage : public StandardPage
576 EncodingServersPage (wxSize panel_size, int border)
577 : StandardPage (panel_size, border)
580 wxString GetName () const
586 wxBitmap GetLargeIcon () const
588 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
595 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
596 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
598 vector<string> columns;
599 columns.push_back (wx_to_std (_("IP address / host name")));
600 _servers_list = new EditableList<string, ServerDialog> (
603 boost::bind (&Config::servers, Config::instance()),
604 boost::bind (&Config::set_servers, Config::instance(), _1),
605 boost::bind (&always_valid),
606 boost::bind (&EncodingServersPage::server_column, this, _1)
609 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
611 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
614 void config_changed ()
616 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
617 _servers_list->refresh ();
620 void use_any_servers_changed ()
622 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
625 string server_column (string s)
630 wxCheckBox* _use_any_servers;
631 EditableList<string, ServerDialog>* _servers_list;
634 class CertificateChainEditor : public wxPanel
637 CertificateChainEditor (
641 function<void (shared_ptr<dcp::CertificateChain>)> set,
642 function<shared_ptr<const dcp::CertificateChain> (void)> get
648 wxFont subheading_font (*wxNORMAL_FONT);
649 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
651 _sizer = new wxBoxSizer (wxVERTICAL);
654 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
655 m->SetFont (subheading_font);
656 _sizer->Add (m, 0, wxALL, border);
659 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
660 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
662 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
667 ip.SetText (_("Type"));
669 _certificates->InsertColumn (0, ip);
675 ip.SetText (_("Thumbprint"));
678 wxFont font = ip.GetFont ();
679 font.SetFamily (wxFONTFAMILY_TELETYPE);
682 _certificates->InsertColumn (1, ip);
685 certificates_sizer->Add (_certificates, 1, wxEXPAND);
688 wxSizer* s = new wxBoxSizer (wxVERTICAL);
689 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
690 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
691 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
692 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
693 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
694 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
695 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
698 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
699 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
702 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
703 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
704 wxFont font = _private_key->GetFont ();
705 font.SetFamily (wxFONTFAMILY_TELETYPE);
706 _private_key->SetFont (font);
707 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
708 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
709 table->Add (_load_private_key, wxGBPosition (r, 2));
710 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
711 table->Add (_export_private_key, wxGBPosition (r, 3));
714 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
715 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
716 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
717 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
720 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
721 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
722 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
723 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
724 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
725 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
726 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
727 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
729 SetSizerAndFit (_sizer);
732 void config_changed ()
734 _chain.reset (new dcp::CertificateChain (*_get().get ()));
736 update_certificate_list ();
737 update_private_key ();
738 update_sensitivity ();
741 void add_button (wxWindow* button)
743 _button_sizer->Add (button);
748 void add_certificate ()
750 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
752 if (d->ShowModal() == wxID_OK) {
754 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
757 update_certificate_list ();
758 } catch (dcp::MiscError& e) {
759 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
765 update_sensitivity ();
768 void remove_certificate ()
770 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
775 _certificates->DeleteItem (i);
779 update_sensitivity ();
782 void export_certificate ()
784 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
789 wxFileDialog* d = new wxFileDialog (
790 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
791 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
794 dcp::CertificateChain::List all = _chain->root_to_leaf ();
795 dcp::CertificateChain::List::iterator j = all.begin ();
796 for (int k = 0; k < i; ++k) {
800 if (d->ShowModal () == wxID_OK) {
801 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
803 throw OpenFileError (wx_to_std (d->GetPath ()));
806 string const s = j->certificate (true);
807 fwrite (s.c_str(), 1, s.length(), f);
813 void update_certificate_list ()
815 _certificates->DeleteAllItems ();
817 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
818 BOOST_FOREACH (dcp::Certificate const & i, certs) {
821 _certificates->InsertItem (item);
822 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
825 _certificates->SetItem (n, 0, _("Root"));
826 } else if (n == (certs.size() - 1)) {
827 _certificates->SetItem (n, 0, _("Leaf"));
829 _certificates->SetItem (n, 0, _("Intermediate"));
836 void remake_certificates ()
838 shared_ptr<const dcp::CertificateChain> chain = _get ();
840 string subject_organization_name;
841 string subject_organizational_unit_name;
842 string root_common_name;
843 string intermediate_common_name;
844 string leaf_common_name;
846 dcp::CertificateChain::List all = chain->root_to_leaf ();
848 if (all.size() >= 1) {
850 subject_organization_name = chain->root().subject_organization_name ();
851 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
852 root_common_name = chain->root().subject_common_name ();
855 if (all.size() >= 2) {
857 leaf_common_name = chain->leaf().subject_common_name ();
860 if (all.size() >= 3) {
861 /* Have an intermediate */
862 dcp::CertificateChain::List::iterator i = all.begin ();
864 intermediate_common_name = i->subject_common_name ();
867 MakeChainDialog* d = new MakeChainDialog (
869 subject_organization_name,
870 subject_organizational_unit_name,
872 intermediate_common_name,
876 if (d->ShowModal () == wxID_OK) {
878 new dcp::CertificateChain (
881 d->organisational_unit (),
882 d->root_common_name (),
883 d->intermediate_common_name (),
884 d->leaf_common_name ()
889 update_certificate_list ();
890 update_private_key ();
896 void update_sensitivity ()
898 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
899 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
902 void update_private_key ()
904 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
908 void load_private_key ()
910 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
912 if (d->ShowModal() == wxID_OK) {
914 boost::filesystem::path p (wx_to_std (d->GetPath ()));
915 if (boost::filesystem::file_size (p) > 1024) {
916 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
920 _chain->set_key (dcp::file_to_string (p));
922 update_private_key ();
923 } catch (dcp::MiscError& e) {
924 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
930 update_sensitivity ();
933 void export_private_key ()
935 optional<string> key = _chain->key ();
940 wxFileDialog* d = new wxFileDialog (
941 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
942 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
945 if (d->ShowModal () == wxID_OK) {
946 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
948 throw OpenFileError (wx_to_std (d->GetPath ()));
951 string const s = _chain->key().get ();
952 fwrite (s.c_str(), 1, s.length(), f);
958 wxListCtrl* _certificates;
959 wxButton* _add_certificate;
960 wxButton* _export_certificate;
961 wxButton* _remove_certificate;
962 wxButton* _remake_certificates;
963 wxStaticText* _private_key;
964 wxButton* _load_private_key;
965 wxButton* _export_private_key;
967 wxBoxSizer* _button_sizer;
968 shared_ptr<dcp::CertificateChain> _chain;
969 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
970 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
973 class KeysPage : public StandardPage
976 KeysPage (wxSize panel_size, int border)
977 : StandardPage (panel_size, border)
980 wxString GetName () const
986 wxBitmap GetLargeIcon () const
988 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
996 _signer = new CertificateChainEditor (
997 _panel, _("Signing DCPs and KDMs"), _border,
998 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
999 boost::bind (&Config::signer_chain, Config::instance ())
1002 _panel->GetSizer()->Add (_signer);
1004 _decryption = new CertificateChainEditor (
1005 _panel, _("Decrypting DCPs"), _border,
1006 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1007 boost::bind (&Config::decryption_chain, Config::instance ())
1010 _panel->GetSizer()->Add (_decryption);
1012 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1013 _decryption->add_button (_export_decryption_certificate);
1015 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1018 void export_decryption_certificate ()
1020 wxFileDialog* d = new wxFileDialog (
1021 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1022 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1025 if (d->ShowModal () == wxID_OK) {
1026 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1028 throw OpenFileError (wx_to_std (d->GetPath ()));
1031 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1032 fwrite (s.c_str(), 1, s.length(), f);
1038 void config_changed ()
1040 _signer->config_changed ();
1041 _decryption->config_changed ();
1044 CertificateChainEditor* _signer;
1045 CertificateChainEditor* _decryption;
1046 wxButton* _export_decryption_certificate;
1049 class TMSPage : public StandardPage
1052 TMSPage (wxSize panel_size, int border)
1053 : StandardPage (panel_size, border)
1056 wxString GetName () const
1061 #ifdef DCPOMATIC_OSX
1062 wxBitmap GetLargeIcon () const
1064 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1071 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1072 table->AddGrowableCol (1, 1);
1073 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1075 add_label_to_sizer (table, _panel, _("Protocol"), true);
1076 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1077 table->Add (_tms_protocol, 1, wxEXPAND);
1079 add_label_to_sizer (table, _panel, _("IP address"), true);
1080 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1081 table->Add (_tms_ip, 1, wxEXPAND);
1083 add_label_to_sizer (table, _panel, _("Target path"), true);
1084 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1085 table->Add (_tms_path, 1, wxEXPAND);
1087 add_label_to_sizer (table, _panel, _("User name"), true);
1088 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1089 table->Add (_tms_user, 1, wxEXPAND);
1091 add_label_to_sizer (table, _panel, _("Password"), true);
1092 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1093 table->Add (_tms_password, 1, wxEXPAND);
1095 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1096 _tms_protocol->Append (_("FTP (for Dolby)"));
1098 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1099 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1100 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1101 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1102 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1105 void config_changed ()
1107 Config* config = Config::instance ();
1109 checked_set (_tms_protocol, config->tms_protocol ());
1110 checked_set (_tms_ip, config->tms_ip ());
1111 checked_set (_tms_path, config->tms_path ());
1112 checked_set (_tms_user, config->tms_user ());
1113 checked_set (_tms_password, config->tms_password ());
1116 void tms_protocol_changed ()
1118 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1121 void tms_ip_changed ()
1123 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1126 void tms_path_changed ()
1128 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1131 void tms_user_changed ()
1133 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1136 void tms_password_changed ()
1138 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1141 wxChoice* _tms_protocol;
1142 wxTextCtrl* _tms_ip;
1143 wxTextCtrl* _tms_path;
1144 wxTextCtrl* _tms_user;
1145 wxTextCtrl* _tms_password;
1154 class KDMEmailPage : public StandardPage
1158 KDMEmailPage (wxSize panel_size, int border)
1159 #ifdef DCPOMATIC_OSX
1160 /* We have to force both width and height of this one */
1161 : StandardPage (wxSize (480, 128), border)
1163 : StandardPage (panel_size, border)
1167 wxString GetName () const
1169 return _("KDM Email");
1172 #ifdef DCPOMATIC_OSX
1173 wxBitmap GetLargeIcon () const
1175 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1182 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1183 table->AddGrowableCol (1, 1);
1184 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1186 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1188 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1189 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1190 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1191 add_label_to_sizer (s, _panel, _("port"), false);
1192 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1193 _mail_port->SetRange (0, 65535);
1194 s->Add (_mail_port);
1195 table->Add (s, 1, wxEXPAND | wxALL);
1198 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1199 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1200 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1202 add_label_to_sizer (table, _panel, _("Mail password"), true);
1203 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1204 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1206 add_label_to_sizer (table, _panel, _("Subject"), true);
1207 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1208 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1210 add_label_to_sizer (table, _panel, _("From address"), true);
1211 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1212 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1214 vector<string> columns;
1215 columns.push_back (wx_to_std (_("Address")));
1216 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1217 _kdm_cc = new EditableList<string, EmailDialog> (
1220 bind (&Config::kdm_cc, Config::instance()),
1221 bind (&Config::set_kdm_cc, Config::instance(), _1),
1222 bind (&string_not_empty, _1),
1225 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1227 add_label_to_sizer (table, _panel, _("BCC address"), true);
1228 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1229 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1231 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1232 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1234 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1235 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1239 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1240 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1241 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1242 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1243 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1244 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1245 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1246 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1247 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1250 void config_changed ()
1252 Config* config = Config::instance ();
1254 checked_set (_mail_server, config->mail_server ());
1255 checked_set (_mail_port, config->mail_port ());
1256 checked_set (_mail_user, config->mail_user ());
1257 checked_set (_mail_password, config->mail_password ());
1258 checked_set (_kdm_subject, config->kdm_subject ());
1259 checked_set (_kdm_from, config->kdm_from ());
1260 checked_set (_kdm_bcc, config->kdm_bcc ());
1261 checked_set (_kdm_email, Config::instance()->kdm_email ());
1264 void mail_server_changed ()
1266 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1269 void mail_port_changed ()
1271 Config::instance()->set_mail_port (_mail_port->GetValue ());
1274 void mail_user_changed ()
1276 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1279 void mail_password_changed ()
1281 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1284 void kdm_subject_changed ()
1286 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1289 void kdm_from_changed ()
1291 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1294 void kdm_bcc_changed ()
1296 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1299 void kdm_email_changed ()
1301 if (_kdm_email->GetValue().IsEmpty ()) {
1302 /* Sometimes we get sent an erroneous notification that the email
1303 is empty; I don't know why.
1307 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1310 void reset_kdm_email ()
1312 Config::instance()->reset_kdm_email ();
1313 checked_set (_kdm_email, Config::instance()->kdm_email ());
1316 wxTextCtrl* _mail_server;
1317 wxSpinCtrl* _mail_port;
1318 wxTextCtrl* _mail_user;
1319 wxTextCtrl* _mail_password;
1320 wxTextCtrl* _kdm_subject;
1321 wxTextCtrl* _kdm_from;
1322 EditableList<string, EmailDialog>* _kdm_cc;
1323 wxTextCtrl* _kdm_bcc;
1324 wxTextCtrl* _kdm_email;
1325 wxButton* _reset_kdm_email;
1328 /** @class AdvancedPage
1329 * @brief Advanced page of the preferences dialog.
1331 class AdvancedPage : public StockPage
1334 AdvancedPage (wxSize panel_size, int border)
1335 : StockPage (Kind_Advanced, panel_size, border)
1336 , _maximum_j2k_bandwidth (0)
1337 , _allow_any_dcp_frame_rate (0)
1338 , _only_servers_encode (0)
1343 , _log_debug_decode (0)
1344 , _log_debug_encode (0)
1345 , _log_debug_email (0)
1351 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1352 table->AddGrowableCol (1, 1);
1353 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1356 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1357 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1358 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1359 s->Add (_maximum_j2k_bandwidth, 1);
1360 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1364 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1365 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1366 table->AddSpacer (0);
1368 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1369 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1370 table->AddSpacer (0);
1373 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1374 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1376 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1377 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1381 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1382 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1383 t->Add (_log_general, 1, wxEXPAND | wxALL);
1384 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1385 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1386 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1387 t->Add (_log_error, 1, wxEXPAND | wxALL);
1388 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1389 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1390 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1391 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1392 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1393 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1394 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1395 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1396 table->Add (t, 0, wxALL, 6);
1399 #ifdef DCPOMATIC_WINDOWS
1400 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1401 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1402 table->AddSpacer (0);
1405 _maximum_j2k_bandwidth->SetRange (1, 1000);
1406 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1407 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1408 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1409 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1410 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1411 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1412 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1413 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1414 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1415 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1416 #ifdef DCPOMATIC_WINDOWS
1417 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1421 void config_changed ()
1423 Config* config = Config::instance ();
1425 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1426 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1427 checked_set (_only_servers_encode, config->only_servers_encode ());
1428 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1429 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1430 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1431 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1432 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1433 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1434 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1435 #ifdef DCPOMATIC_WINDOWS
1436 checked_set (_win32_console, config->win32_console());
1440 void maximum_j2k_bandwidth_changed ()
1442 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1445 void allow_any_dcp_frame_rate_changed ()
1447 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1450 void only_servers_encode_changed ()
1452 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1458 if (_log_general->GetValue ()) {
1459 types |= LogEntry::TYPE_GENERAL;
1461 if (_log_warning->GetValue ()) {
1462 types |= LogEntry::TYPE_WARNING;
1464 if (_log_error->GetValue ()) {
1465 types |= LogEntry::TYPE_ERROR;
1467 if (_log_timing->GetValue ()) {
1468 types |= LogEntry::TYPE_TIMING;
1470 if (_log_debug_decode->GetValue ()) {
1471 types |= LogEntry::TYPE_DEBUG_DECODE;
1473 if (_log_debug_encode->GetValue ()) {
1474 types |= LogEntry::TYPE_DEBUG_ENCODE;
1476 if (_log_debug_email->GetValue ()) {
1477 types |= LogEntry::TYPE_DEBUG_EMAIL;
1479 Config::instance()->set_log_types (types);
1482 #ifdef DCPOMATIC_WINDOWS
1483 void win32_console_changed ()
1485 Config::instance()->set_win32_console (_win32_console->GetValue ());
1489 wxSpinCtrl* _maximum_j2k_bandwidth;
1490 wxCheckBox* _allow_any_dcp_frame_rate;
1491 wxCheckBox* _only_servers_encode;
1492 wxCheckBox* _log_general;
1493 wxCheckBox* _log_warning;
1494 wxCheckBox* _log_error;
1495 wxCheckBox* _log_timing;
1496 wxCheckBox* _log_debug_decode;
1497 wxCheckBox* _log_debug_encode;
1498 wxCheckBox* _log_debug_email;
1499 #ifdef DCPOMATIC_WINDOWS
1500 wxCheckBox* _win32_console;
1504 wxPreferencesEditor*
1505 create_config_dialog ()
1507 wxPreferencesEditor* e = new wxPreferencesEditor ();
1509 #ifdef DCPOMATIC_OSX
1510 /* Width that we force some of the config panels to be on OSX so that
1511 the containing window doesn't shrink too much when we select those panels.
1512 This is obviously an unpleasant hack.
1514 wxSize ps = wxSize (520, -1);
1515 int const border = 16;
1517 wxSize ps = wxSize (-1, -1);
1518 int const border = 8;
1521 e->AddPage (new GeneralPage (ps, border));
1522 e->AddPage (new DefaultsPage (ps, border));
1523 e->AddPage (new EncodingServersPage (ps, border));
1524 e->AddPage (new KeysPage (ps, border));
1525 e->AddPage (new TMSPage (ps, border));
1526 e->AddPage (new KDMEmailPage (ps, border));
1527 e->AddPage (new AdvancedPage (ps, border));