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 table->Add (_language, wxGBPosition (r, 1));
178 wxStaticText* restart = add_label_to_sizer (
179 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
181 wxFont font = restart->GetFont();
182 font.SetStyle (wxFONTSTYLE_ITALIC);
183 font.SetPointSize (font.GetPointSize() - 1);
184 restart->SetFont (font);
187 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
188 _num_local_encoding_threads = new wxSpinCtrl (_panel);
189 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
192 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
193 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml");
194 table->Add (_cinemas_file, wxGBPosition (r, 1));
197 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
198 _analyse_ebur128 = new wxCheckBox (_panel, wxID_ANY, _("Find integrated loudness, true peak and loudness range when analysing audio"));
199 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
203 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
204 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
207 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
208 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
211 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
212 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
215 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
216 bottom_table->AddGrowableCol (1, 1);
218 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
219 _issuer = new wxTextCtrl (_panel, wxID_ANY);
220 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
222 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
223 _creator = new wxTextCtrl (_panel, wxID_ANY);
224 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
226 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
229 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
230 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
231 _cinemas_file->Bind (wxEVT_COMMAND_FILEPICKER_CHANGED, boost::bind (&GeneralPage::cinemas_file_changed, this));
233 _num_local_encoding_threads->SetRange (1, 128);
234 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
236 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
237 _analyse_ebur128->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::analyse_ebur128_changed, this));
239 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
240 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
241 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
243 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
244 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
247 void config_changed ()
249 Config* config = Config::instance ();
251 checked_set (_set_language, static_cast<bool>(config->language()));
253 if (config->language().get_value_or ("") == "fr") {
254 checked_set (_language, 3);
255 } else if (config->language().get_value_or ("") == "it") {
256 checked_set (_language, 4);
257 } else if (config->language().get_value_or ("") == "es") {
258 checked_set (_language, 2);
259 } else if (config->language().get_value_or ("") == "sv") {
260 checked_set (_language, 6);
261 } else if (config->language().get_value_or ("") == "de") {
262 checked_set (_language, 0);
263 } else if (config->language().get_value_or ("") == "nl") {
264 checked_set (_language, 5);
265 } else if (config->language().get_value_or ("") == "ru") {
266 checked_set (_language, 7);
267 } else if (config->language().get_value_or ("") == "pl") {
268 checked_set (_language, 8);
269 } else if (config->language().get_value_or ("") == "da") {
270 checked_set (_language, 9);
271 } else if (config->language().get_value_or ("") == "pt") {
272 checked_set (_language, 10);
273 } else if (config->language().get_value_or ("") == "sk") {
274 checked_set (_language, 11);
275 } else if (config->language().get_value_or ("") == "cs") {
276 checked_set (_language, 12);
278 _language->SetSelection (1);
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 switch (_language->GetSelection ()) {
315 Config::instance()->set_language ("de");
318 Config::instance()->set_language ("en");
321 Config::instance()->set_language ("es");
324 Config::instance()->set_language ("fr");
327 Config::instance()->set_language ("it");
330 Config::instance()->set_language ("nl");
333 Config::instance()->set_language ("sv");
336 Config::instance()->set_language ("ru");
339 Config::instance()->set_language ("pl");
342 Config::instance()->set_language ("da");
345 Config::instance()->set_language ("pt");
348 Config::instance()->set_language ("sk");
351 Config::instance()->set_language ("cs");
356 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
357 void analyse_ebur128_changed ()
359 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
363 void automatic_audio_analysis_changed ()
365 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
368 void check_for_updates_changed ()
370 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
373 void check_for_test_updates_changed ()
375 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
378 void num_local_encoding_threads_changed ()
380 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
383 void issuer_changed ()
385 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
388 void creator_changed ()
390 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
393 void cinemas_file_changed ()
395 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
398 wxCheckBox* _set_language;
400 wxSpinCtrl* _num_local_encoding_threads;
401 FilePickerCtrl* _cinemas_file;
402 #ifdef DCPOMATIC_HAVE_PATCHED_FFMPEG
403 wxCheckBox* _analyse_ebur128;
405 wxCheckBox* _automatic_audio_analysis;
406 wxCheckBox* _check_for_updates;
407 wxCheckBox* _check_for_test_updates;
409 wxTextCtrl* _creator;
412 class DefaultsPage : public StandardPage
415 DefaultsPage (wxSize panel_size, int border)
416 : StandardPage (panel_size, border)
419 wxString GetName () const
421 return _("Defaults");
425 wxBitmap GetLargeIcon () const
427 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
434 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
435 table->AddGrowableCol (1, 1);
436 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
439 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
440 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
441 _still_length = new wxSpinCtrl (_panel);
442 s->Add (_still_length);
443 add_label_to_sizer (s, _panel, _("s"), false);
447 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
448 #ifdef DCPOMATIC_USE_OWN_PICKER
449 _directory = new DirPickerCtrl (_panel);
451 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
453 table->Add (_directory, 1, wxEXPAND);
455 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
456 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
457 table->Add (_isdcf_metadata_button);
459 add_label_to_sizer (table, _panel, _("Default container"), true);
460 _container = new wxChoice (_panel, wxID_ANY);
461 table->Add (_container);
463 add_label_to_sizer (table, _panel, _("Default content type"), true);
464 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
465 table->Add (_dcp_content_type);
468 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
469 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
470 _j2k_bandwidth = new wxSpinCtrl (_panel);
471 s->Add (_j2k_bandwidth);
472 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
477 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
478 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
479 _audio_delay = new wxSpinCtrl (_panel);
480 s->Add (_audio_delay);
481 add_label_to_sizer (s, _panel, _("ms"), false);
485 add_label_to_sizer (table, _panel, _("Default standard"), true);
486 _standard = new wxChoice (_panel, wxID_ANY);
487 table->Add (_standard);
489 _still_length->SetRange (1, 3600);
490 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
492 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
494 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
496 vector<Ratio const *> ratios = Ratio::all ();
497 for (size_t i = 0; i < ratios.size(); ++i) {
498 _container->Append (std_to_wx (ratios[i]->nickname ()));
501 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
503 vector<DCPContentType const *> const ct = DCPContentType::all ();
504 for (size_t i = 0; i < ct.size(); ++i) {
505 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
508 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
510 _j2k_bandwidth->SetRange (50, 250);
511 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
513 _audio_delay->SetRange (-1000, 1000);
514 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
516 _standard->Append (_("SMPTE"));
517 _standard->Append (_("Interop"));
518 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
521 void config_changed ()
523 Config* config = Config::instance ();
525 vector<Ratio const *> ratios = Ratio::all ();
526 for (size_t i = 0; i < ratios.size(); ++i) {
527 if (ratios[i] == config->default_container ()) {
528 _container->SetSelection (i);
532 vector<DCPContentType const *> const ct = DCPContentType::all ();
533 for (size_t i = 0; i < ct.size(); ++i) {
534 if (ct[i] == config->default_dcp_content_type ()) {
535 _dcp_content_type->SetSelection (i);
539 checked_set (_still_length, config->default_still_length ());
540 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
541 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
542 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
543 checked_set (_audio_delay, config->default_audio_delay ());
544 checked_set (_standard, config->default_interop() ? 1 : 0);
547 void j2k_bandwidth_changed ()
549 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
552 void audio_delay_changed ()
554 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
557 void directory_changed ()
559 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
562 void edit_isdcf_metadata_clicked ()
564 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
566 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
570 void still_length_changed ()
572 Config::instance()->set_default_still_length (_still_length->GetValue ());
575 void container_changed ()
577 vector<Ratio const *> ratio = Ratio::all ();
578 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
581 void dcp_content_type_changed ()
583 vector<DCPContentType const *> ct = DCPContentType::all ();
584 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
587 void standard_changed ()
589 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
592 wxSpinCtrl* _j2k_bandwidth;
593 wxSpinCtrl* _audio_delay;
594 wxButton* _isdcf_metadata_button;
595 wxSpinCtrl* _still_length;
596 #ifdef DCPOMATIC_USE_OWN_PICKER
597 DirPickerCtrl* _directory;
599 wxDirPickerCtrl* _directory;
601 wxChoice* _container;
602 wxChoice* _dcp_content_type;
606 class EncodingServersPage : public StandardPage
609 EncodingServersPage (wxSize panel_size, int border)
610 : StandardPage (panel_size, border)
613 wxString GetName () const
619 wxBitmap GetLargeIcon () const
621 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
628 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
629 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
631 vector<string> columns;
632 columns.push_back (wx_to_std (_("IP address / host name")));
633 _servers_list = new EditableList<string, ServerDialog> (
636 boost::bind (&Config::servers, Config::instance()),
637 boost::bind (&Config::set_servers, Config::instance(), _1),
638 boost::bind (&EncodingServersPage::server_column, this, _1)
641 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
643 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
646 void config_changed ()
648 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
649 _servers_list->refresh ();
652 void use_any_servers_changed ()
654 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
657 string server_column (string s)
662 wxCheckBox* _use_any_servers;
663 EditableList<string, ServerDialog>* _servers_list;
666 class CertificateChainEditor : public wxPanel
669 CertificateChainEditor (
673 function<void (shared_ptr<dcp::CertificateChain>)> set,
674 function<shared_ptr<const dcp::CertificateChain> (void)> get
680 wxFont subheading_font (*wxNORMAL_FONT);
681 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
683 _sizer = new wxBoxSizer (wxVERTICAL);
686 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
687 m->SetFont (subheading_font);
688 _sizer->Add (m, 0, wxALL, border);
691 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
692 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
694 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
699 ip.SetText (_("Type"));
701 _certificates->InsertColumn (0, ip);
707 ip.SetText (_("Thumbprint"));
710 wxFont font = ip.GetFont ();
711 font.SetFamily (wxFONTFAMILY_TELETYPE);
714 _certificates->InsertColumn (1, ip);
717 certificates_sizer->Add (_certificates, 1, wxEXPAND);
720 wxSizer* s = new wxBoxSizer (wxVERTICAL);
721 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
722 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
723 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
724 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
725 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
726 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
727 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
730 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
731 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
734 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
735 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
736 wxFont font = _private_key->GetFont ();
737 font.SetFamily (wxFONTFAMILY_TELETYPE);
738 _private_key->SetFont (font);
739 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
740 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
741 table->Add (_load_private_key, wxGBPosition (r, 2));
742 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
743 table->Add (_export_private_key, wxGBPosition (r, 3));
746 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
747 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
748 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
749 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
752 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
753 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
754 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
755 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
756 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
757 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
758 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
759 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
761 SetSizerAndFit (_sizer);
764 void config_changed ()
766 _chain.reset (new dcp::CertificateChain (*_get().get ()));
768 update_certificate_list ();
769 update_private_key ();
770 update_sensitivity ();
773 void add_button (wxWindow* button)
775 _button_sizer->Add (button);
780 void add_certificate ()
782 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
784 if (d->ShowModal() == wxID_OK) {
786 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
789 update_certificate_list ();
790 } catch (dcp::MiscError& e) {
791 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
797 update_sensitivity ();
800 void remove_certificate ()
802 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
807 _certificates->DeleteItem (i);
811 update_sensitivity ();
814 void export_certificate ()
816 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
821 wxFileDialog* d = new wxFileDialog (
822 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
823 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
826 dcp::CertificateChain::List all = _chain->root_to_leaf ();
827 dcp::CertificateChain::List::iterator j = all.begin ();
828 for (int k = 0; k < i; ++k) {
832 if (d->ShowModal () == wxID_OK) {
833 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
835 throw OpenFileError (wx_to_std (d->GetPath ()));
838 string const s = j->certificate (true);
839 fwrite (s.c_str(), 1, s.length(), f);
845 void update_certificate_list ()
847 _certificates->DeleteAllItems ();
849 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
850 BOOST_FOREACH (dcp::Certificate const & i, certs) {
853 _certificates->InsertItem (item);
854 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
857 _certificates->SetItem (n, 0, _("Root"));
858 } else if (n == (certs.size() - 1)) {
859 _certificates->SetItem (n, 0, _("Leaf"));
861 _certificates->SetItem (n, 0, _("Intermediate"));
868 void remake_certificates ()
870 shared_ptr<const dcp::CertificateChain> chain = _get ();
872 string subject_organization_name;
873 string subject_organizational_unit_name;
874 string root_common_name;
875 string intermediate_common_name;
876 string leaf_common_name;
878 dcp::CertificateChain::List all = chain->root_to_leaf ();
880 if (all.size() >= 1) {
882 subject_organization_name = chain->root().subject_organization_name ();
883 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
884 root_common_name = chain->root().subject_common_name ();
887 if (all.size() >= 2) {
889 leaf_common_name = chain->leaf().subject_common_name ();
892 if (all.size() >= 3) {
893 /* Have an intermediate */
894 dcp::CertificateChain::List::iterator i = all.begin ();
896 intermediate_common_name = i->subject_common_name ();
899 MakeChainDialog* d = new MakeChainDialog (
901 subject_organization_name,
902 subject_organizational_unit_name,
904 intermediate_common_name,
908 if (d->ShowModal () == wxID_OK) {
910 new dcp::CertificateChain (
913 d->organisational_unit (),
914 d->root_common_name (),
915 d->intermediate_common_name (),
916 d->leaf_common_name ()
921 update_certificate_list ();
922 update_private_key ();
928 void update_sensitivity ()
930 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
931 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
934 void update_private_key ()
936 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
940 void load_private_key ()
942 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
944 if (d->ShowModal() == wxID_OK) {
946 boost::filesystem::path p (wx_to_std (d->GetPath ()));
947 if (boost::filesystem::file_size (p) > 1024) {
948 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
952 _chain->set_key (dcp::file_to_string (p));
954 update_private_key ();
955 } catch (dcp::MiscError& e) {
956 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
962 update_sensitivity ();
965 void export_private_key ()
967 optional<string> key = _chain->key ();
972 wxFileDialog* d = new wxFileDialog (
973 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
974 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
977 if (d->ShowModal () == wxID_OK) {
978 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
980 throw OpenFileError (wx_to_std (d->GetPath ()));
983 string const s = _chain->key().get ();
984 fwrite (s.c_str(), 1, s.length(), f);
990 wxListCtrl* _certificates;
991 wxButton* _add_certificate;
992 wxButton* _export_certificate;
993 wxButton* _remove_certificate;
994 wxButton* _remake_certificates;
995 wxStaticText* _private_key;
996 wxButton* _load_private_key;
997 wxButton* _export_private_key;
999 wxBoxSizer* _button_sizer;
1000 shared_ptr<dcp::CertificateChain> _chain;
1001 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
1002 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
1005 class KeysPage : public StandardPage
1008 KeysPage (wxSize panel_size, int border)
1009 : StandardPage (panel_size, border)
1012 wxString GetName () const
1017 #ifdef DCPOMATIC_OSX
1018 wxBitmap GetLargeIcon () const
1020 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
1028 _signer = new CertificateChainEditor (
1029 _panel, _("Signing DCPs and KDMs"), _border,
1030 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
1031 boost::bind (&Config::signer_chain, Config::instance ())
1034 _panel->GetSizer()->Add (_signer);
1036 _decryption = new CertificateChainEditor (
1037 _panel, _("Decrypting DCPs"), _border,
1038 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1039 boost::bind (&Config::decryption_chain, Config::instance ())
1042 _panel->GetSizer()->Add (_decryption);
1044 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1045 _decryption->add_button (_export_decryption_certificate);
1047 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1050 void export_decryption_certificate ()
1052 wxFileDialog* d = new wxFileDialog (
1053 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1054 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1057 if (d->ShowModal () == wxID_OK) {
1058 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1060 throw OpenFileError (wx_to_std (d->GetPath ()));
1063 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1064 fwrite (s.c_str(), 1, s.length(), f);
1070 void config_changed ()
1072 _signer->config_changed ();
1073 _decryption->config_changed ();
1076 CertificateChainEditor* _signer;
1077 CertificateChainEditor* _decryption;
1078 wxButton* _export_decryption_certificate;
1081 class TMSPage : public StandardPage
1084 TMSPage (wxSize panel_size, int border)
1085 : StandardPage (panel_size, border)
1088 wxString GetName () const
1093 #ifdef DCPOMATIC_OSX
1094 wxBitmap GetLargeIcon () const
1096 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1103 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1104 table->AddGrowableCol (1, 1);
1105 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1107 add_label_to_sizer (table, _panel, _("Protocol"), true);
1108 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1109 table->Add (_tms_protocol, 1, wxEXPAND);
1111 add_label_to_sizer (table, _panel, _("IP address"), true);
1112 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1113 table->Add (_tms_ip, 1, wxEXPAND);
1115 add_label_to_sizer (table, _panel, _("Target path"), true);
1116 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1117 table->Add (_tms_path, 1, wxEXPAND);
1119 add_label_to_sizer (table, _panel, _("User name"), true);
1120 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1121 table->Add (_tms_user, 1, wxEXPAND);
1123 add_label_to_sizer (table, _panel, _("Password"), true);
1124 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1125 table->Add (_tms_password, 1, wxEXPAND);
1127 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1128 _tms_protocol->Append (_("FTP (for Dolby)"));
1130 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1131 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1132 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1133 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1134 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1137 void config_changed ()
1139 Config* config = Config::instance ();
1141 checked_set (_tms_protocol, config->tms_protocol ());
1142 checked_set (_tms_ip, config->tms_ip ());
1143 checked_set (_tms_path, config->tms_path ());
1144 checked_set (_tms_user, config->tms_user ());
1145 checked_set (_tms_password, config->tms_password ());
1148 void tms_protocol_changed ()
1150 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1153 void tms_ip_changed ()
1155 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1158 void tms_path_changed ()
1160 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1163 void tms_user_changed ()
1165 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1168 void tms_password_changed ()
1170 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1173 wxChoice* _tms_protocol;
1174 wxTextCtrl* _tms_ip;
1175 wxTextCtrl* _tms_path;
1176 wxTextCtrl* _tms_user;
1177 wxTextCtrl* _tms_password;
1186 class KDMEmailPage : public StandardPage
1190 KDMEmailPage (wxSize panel_size, int border)
1191 #ifdef DCPOMATIC_OSX
1192 /* We have to force both width and height of this one */
1193 : StandardPage (wxSize (480, 128), border)
1195 : StandardPage (panel_size, border)
1199 wxString GetName () const
1201 return _("KDM Email");
1204 #ifdef DCPOMATIC_OSX
1205 wxBitmap GetLargeIcon () const
1207 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1214 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1215 table->AddGrowableCol (1, 1);
1216 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1218 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1220 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1221 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1222 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1223 add_label_to_sizer (s, _panel, _("port"), false);
1224 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1225 _mail_port->SetRange (0, 65535);
1226 s->Add (_mail_port);
1227 table->Add (s, 1, wxEXPAND | wxALL);
1230 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1231 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1232 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1234 add_label_to_sizer (table, _panel, _("Mail password"), true);
1235 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1236 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1238 add_label_to_sizer (table, _panel, _("Subject"), true);
1239 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1240 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1242 add_label_to_sizer (table, _panel, _("From address"), true);
1243 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1244 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1246 vector<string> columns;
1247 columns.push_back (wx_to_std (_("Address")));
1248 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1249 _kdm_cc = new EditableList<string, EmailDialog> (
1250 _panel, columns, bind (&Config::kdm_cc, Config::instance()), bind (&Config::set_kdm_cc, Config::instance(), _1), bind (&column, _1)
1252 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1254 add_label_to_sizer (table, _panel, _("BCC address"), true);
1255 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1256 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1258 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1259 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1261 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1262 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1266 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1267 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1268 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1269 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1270 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1271 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1272 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1273 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1274 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1277 void config_changed ()
1279 Config* config = Config::instance ();
1281 checked_set (_mail_server, config->mail_server ());
1282 checked_set (_mail_port, config->mail_port ());
1283 checked_set (_mail_user, config->mail_user ());
1284 checked_set (_mail_password, config->mail_password ());
1285 checked_set (_kdm_subject, config->kdm_subject ());
1286 checked_set (_kdm_from, config->kdm_from ());
1287 checked_set (_kdm_bcc, config->kdm_bcc ());
1288 checked_set (_kdm_email, Config::instance()->kdm_email ());
1291 void mail_server_changed ()
1293 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1296 void mail_port_changed ()
1298 Config::instance()->set_mail_port (_mail_port->GetValue ());
1301 void mail_user_changed ()
1303 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1306 void mail_password_changed ()
1308 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1311 void kdm_subject_changed ()
1313 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1316 void kdm_from_changed ()
1318 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1321 void kdm_bcc_changed ()
1323 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1326 void kdm_email_changed ()
1328 if (_kdm_email->GetValue().IsEmpty ()) {
1329 /* Sometimes we get sent an erroneous notification that the email
1330 is empty; I don't know why.
1334 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1337 void reset_kdm_email ()
1339 Config::instance()->reset_kdm_email ();
1340 checked_set (_kdm_email, Config::instance()->kdm_email ());
1343 wxTextCtrl* _mail_server;
1344 wxSpinCtrl* _mail_port;
1345 wxTextCtrl* _mail_user;
1346 wxTextCtrl* _mail_password;
1347 wxTextCtrl* _kdm_subject;
1348 wxTextCtrl* _kdm_from;
1349 EditableList<string, EmailDialog>* _kdm_cc;
1350 wxTextCtrl* _kdm_bcc;
1351 wxTextCtrl* _kdm_email;
1352 wxButton* _reset_kdm_email;
1355 /** @class AdvancedPage
1356 * @brief Advanced page of the preferences dialog.
1358 class AdvancedPage : public StockPage
1361 AdvancedPage (wxSize panel_size, int border)
1362 : StockPage (Kind_Advanced, panel_size, border)
1363 , _maximum_j2k_bandwidth (0)
1364 , _allow_any_dcp_frame_rate (0)
1365 , _only_servers_encode (0)
1370 , _log_debug_decode (0)
1371 , _log_debug_encode (0)
1372 , _log_debug_email (0)
1378 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1379 table->AddGrowableCol (1, 1);
1380 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1383 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1384 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1385 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1386 s->Add (_maximum_j2k_bandwidth, 1);
1387 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1391 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1392 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1393 table->AddSpacer (0);
1395 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1396 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1397 table->AddSpacer (0);
1400 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1401 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1403 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1404 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1408 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1409 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1410 t->Add (_log_general, 1, wxEXPAND | wxALL);
1411 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1412 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1413 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1414 t->Add (_log_error, 1, wxEXPAND | wxALL);
1415 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1416 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1417 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1418 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1419 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1420 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1421 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1422 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1423 table->Add (t, 0, wxALL, 6);
1426 #ifdef DCPOMATIC_WINDOWS
1427 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1428 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1429 table->AddSpacer (0);
1432 _maximum_j2k_bandwidth->SetRange (1, 1000);
1433 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1434 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1435 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1436 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1437 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1438 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1439 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1440 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1441 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1442 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1443 #ifdef DCPOMATIC_WINDOWS
1444 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1448 void config_changed ()
1450 Config* config = Config::instance ();
1452 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1453 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1454 checked_set (_only_servers_encode, config->only_servers_encode ());
1455 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1456 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1457 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1458 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1459 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1460 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1461 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1462 #ifdef DCPOMATIC_WINDOWS
1463 checked_set (_win32_console, config->win32_console());
1467 void maximum_j2k_bandwidth_changed ()
1469 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1472 void allow_any_dcp_frame_rate_changed ()
1474 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1477 void only_servers_encode_changed ()
1479 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1485 if (_log_general->GetValue ()) {
1486 types |= LogEntry::TYPE_GENERAL;
1488 if (_log_warning->GetValue ()) {
1489 types |= LogEntry::TYPE_WARNING;
1491 if (_log_error->GetValue ()) {
1492 types |= LogEntry::TYPE_ERROR;
1494 if (_log_timing->GetValue ()) {
1495 types |= LogEntry::TYPE_TIMING;
1497 if (_log_debug_decode->GetValue ()) {
1498 types |= LogEntry::TYPE_DEBUG_DECODE;
1500 if (_log_debug_encode->GetValue ()) {
1501 types |= LogEntry::TYPE_DEBUG_ENCODE;
1503 if (_log_debug_email->GetValue ()) {
1504 types |= LogEntry::TYPE_DEBUG_EMAIL;
1506 Config::instance()->set_log_types (types);
1509 #ifdef DCPOMATIC_WINDOWS
1510 void win32_console_changed ()
1512 Config::instance()->set_win32_console (_win32_console->GetValue ());
1516 wxSpinCtrl* _maximum_j2k_bandwidth;
1517 wxCheckBox* _allow_any_dcp_frame_rate;
1518 wxCheckBox* _only_servers_encode;
1519 wxCheckBox* _log_general;
1520 wxCheckBox* _log_warning;
1521 wxCheckBox* _log_error;
1522 wxCheckBox* _log_timing;
1523 wxCheckBox* _log_debug_decode;
1524 wxCheckBox* _log_debug_encode;
1525 wxCheckBox* _log_debug_email;
1526 #ifdef DCPOMATIC_WINDOWS
1527 wxCheckBox* _win32_console;
1531 wxPreferencesEditor*
1532 create_config_dialog ()
1534 wxPreferencesEditor* e = new wxPreferencesEditor ();
1536 #ifdef DCPOMATIC_OSX
1537 /* Width that we force some of the config panels to be on OSX so that
1538 the containing window doesn't shrink too much when we select those panels.
1539 This is obviously an unpleasant hack.
1541 wxSize ps = wxSize (520, -1);
1542 int const border = 16;
1544 wxSize ps = wxSize (-1, -1);
1545 int const border = 8;
1548 e->AddPage (new GeneralPage (ps, border));
1549 e->AddPage (new DefaultsPage (ps, border));
1550 e->AddPage (new EncodingServersPage (ps, border));
1551 e->AddPage (new KeysPage (ps, border));
1552 e->AddPage (new TMSPage (ps, border));
1553 e->AddPage (new KDMEmailPage (ps, border));
1554 e->AddPage (new AdvancedPage (ps, border));