2 Copyright (C) 2012-2015 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 "isdcf_metadata_dialog.h"
30 #include "server_dialog.h"
31 #include "make_chain_dialog.h"
32 #include "lib/config.h"
33 #include "lib/ratio.h"
34 #include "lib/filter.h"
35 #include "lib/dcp_content_type.h"
38 #include "lib/raw_convert.h"
39 #include "lib/cross.h"
40 #include "lib/exceptions.h"
41 #include <dcp/exceptions.h>
42 #include <dcp/certificate_chain.h>
43 #include <wx/stdpaths.h>
44 #include <wx/preferences.h>
45 #include <wx/filepicker.h>
46 #include <wx/spinctrl.h>
47 #include <boost/lexical_cast.hpp>
48 #include <boost/filesystem.hpp>
49 #include <boost/foreach.hpp>
57 using boost::shared_ptr;
58 using boost::lexical_cast;
59 using boost::function;
60 using boost::optional;
65 Page (wxSize panel_size, int border)
68 , _panel_size (panel_size)
69 , _window_exists (false)
71 _config_connection = Config::instance()->Changed.connect (boost::bind (&Page::config_changed_wrapper, this));
77 wxWindow* create_window (wxWindow* parent)
79 _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size);
80 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
84 _window_exists = true;
87 _panel->Bind (wxEVT_DESTROY, boost::bind (&Page::window_destroyed, this));
96 virtual void config_changed () = 0;
97 virtual void setup () = 0;
99 void config_changed_wrapper ()
101 if (_window_exists) {
106 void window_destroyed ()
108 _window_exists = false;
112 boost::signals2::scoped_connection _config_connection;
116 class StockPage : public wxStockPreferencesPage, public Page
119 StockPage (Kind kind, wxSize panel_size, int border)
120 : wxStockPreferencesPage (kind)
121 , Page (panel_size, border)
124 wxWindow* CreateWindow (wxWindow* parent)
126 return create_window (parent);
130 class StandardPage : public wxPreferencesPage, public Page
133 StandardPage (wxSize panel_size, int border)
134 : Page (panel_size, border)
137 wxWindow* CreateWindow (wxWindow* parent)
139 return create_window (parent);
143 class GeneralPage : public StockPage
146 GeneralPage (wxSize panel_size, int border)
147 : StockPage (Kind_General, panel_size, border)
153 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
154 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
157 _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language"));
158 table->Add (_set_language, wxGBPosition (r, 0));
159 _language = new wxChoice (_panel, wxID_ANY);
160 _language->Append (wxT ("Deutsch"));
161 _language->Append (wxT ("English"));
162 _language->Append (wxT ("Español"));
163 _language->Append (wxT ("Français"));
164 _language->Append (wxT ("Italiano"));
165 _language->Append (wxT ("Nederlands"));
166 _language->Append (wxT ("Svenska"));
167 _language->Append (wxT ("Русский"));
168 _language->Append (wxT ("Polski"));
169 _language->Append (wxT ("Dansk"));
170 _language->Append (wxT ("Português europeu"));
171 _language->Append (wxT ("Slovenský jazyk"));
172 table->Add (_language, wxGBPosition (r, 1));
175 wxStaticText* restart = add_label_to_sizer (
176 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
178 wxFont font = restart->GetFont();
179 font.SetStyle (wxFONTSTYLE_ITALIC);
180 font.SetPointSize (font.GetPointSize() - 1);
181 restart->SetFont (font);
184 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
185 _num_local_encoding_threads = new wxSpinCtrl (_panel);
186 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
189 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
190 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
193 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
194 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
197 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
198 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
201 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
202 bottom_table->AddGrowableCol (1, 1);
204 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
205 _issuer = new wxTextCtrl (_panel, wxID_ANY);
206 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
208 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
209 _creator = new wxTextCtrl (_panel, wxID_ANY);
210 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
212 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
215 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
216 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
218 _num_local_encoding_threads->SetRange (1, 128);
219 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
221 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
222 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
223 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
225 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
226 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
229 void config_changed ()
231 Config* config = Config::instance ();
233 checked_set (_set_language, static_cast<bool>(config->language()));
235 if (config->language().get_value_or ("") == "fr") {
236 checked_set (_language, 3);
237 } else if (config->language().get_value_or ("") == "it") {
238 checked_set (_language, 4);
239 } else if (config->language().get_value_or ("") == "es") {
240 checked_set (_language, 2);
241 } else if (config->language().get_value_or ("") == "sv") {
242 checked_set (_language, 6);
243 } else if (config->language().get_value_or ("") == "de") {
244 checked_set (_language, 0);
245 } else if (config->language().get_value_or ("") == "nl") {
246 checked_set (_language, 5);
247 } else if (config->language().get_value_or ("") == "ru") {
248 checked_set (_language, 7);
249 } else if (config->language().get_value_or ("") == "pl") {
250 checked_set (_language, 8);
251 } else if (config->language().get_value_or ("") == "da") {
252 checked_set (_language, 9);
253 } else if (config->language().get_value_or ("") == "pt") {
254 checked_set (_language, 10);
255 } else if (config->language().get_value_or ("") == "sk") {
256 checked_set (_language, 11);
258 _language->SetSelection (1);
261 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
262 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
263 checked_set (_check_for_updates, config->check_for_updates ());
264 checked_set (_check_for_test_updates, config->check_for_test_updates ());
265 checked_set (_issuer, config->dcp_issuer ());
266 checked_set (_creator, config->dcp_creator ());
268 setup_sensitivity ();
271 void setup_sensitivity ()
273 _language->Enable (_set_language->GetValue ());
274 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
277 void set_language_changed ()
279 setup_sensitivity ();
280 if (_set_language->GetValue ()) {
283 Config::instance()->unset_language ();
287 void language_changed ()
289 switch (_language->GetSelection ()) {
291 Config::instance()->set_language ("de");
294 Config::instance()->set_language ("en");
297 Config::instance()->set_language ("es");
300 Config::instance()->set_language ("fr");
303 Config::instance()->set_language ("it");
306 Config::instance()->set_language ("nl");
309 Config::instance()->set_language ("sv");
312 Config::instance()->set_language ("ru");
315 Config::instance()->set_language ("pl");
318 Config::instance()->set_language ("da");
321 Config::instance()->set_language ("pt");
324 Config::instance()->set_language ("sk");
329 void automatic_audio_analysis_changed ()
331 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
334 void check_for_updates_changed ()
336 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
339 void check_for_test_updates_changed ()
341 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
344 void num_local_encoding_threads_changed ()
346 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
349 void issuer_changed ()
351 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
354 void creator_changed ()
356 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
359 wxCheckBox* _set_language;
361 wxSpinCtrl* _num_local_encoding_threads;
362 wxCheckBox* _automatic_audio_analysis;
363 wxCheckBox* _check_for_updates;
364 wxCheckBox* _check_for_test_updates;
366 wxTextCtrl* _creator;
369 class DefaultsPage : public StandardPage
372 DefaultsPage (wxSize panel_size, int border)
373 : StandardPage (panel_size, border)
376 wxString GetName () const
378 return _("Defaults");
382 wxBitmap GetLargeIcon () const
384 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
391 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
392 table->AddGrowableCol (1, 1);
393 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
396 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
397 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
398 _still_length = new wxSpinCtrl (_panel);
399 s->Add (_still_length);
400 add_label_to_sizer (s, _panel, _("s"), false);
404 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
405 #ifdef DCPOMATIC_USE_OWN_PICKER
406 _directory = new DirPickerCtrl (_panel);
408 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
410 table->Add (_directory, 1, wxEXPAND);
412 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
413 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
414 table->Add (_isdcf_metadata_button);
416 add_label_to_sizer (table, _panel, _("Default container"), true);
417 _container = new wxChoice (_panel, wxID_ANY);
418 table->Add (_container);
420 add_label_to_sizer (table, _panel, _("Default content type"), true);
421 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
422 table->Add (_dcp_content_type);
425 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
426 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
427 _j2k_bandwidth = new wxSpinCtrl (_panel);
428 s->Add (_j2k_bandwidth);
429 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
434 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
435 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
436 _audio_delay = new wxSpinCtrl (_panel);
437 s->Add (_audio_delay);
438 add_label_to_sizer (s, _panel, _("ms"), false);
442 add_label_to_sizer (table, _panel, _("Default standard"), true);
443 _standard = new wxChoice (_panel, wxID_ANY);
444 table->Add (_standard);
446 _still_length->SetRange (1, 3600);
447 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
449 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
451 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
453 vector<Ratio const *> ratios = Ratio::all ();
454 for (size_t i = 0; i < ratios.size(); ++i) {
455 _container->Append (std_to_wx (ratios[i]->nickname ()));
458 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
460 vector<DCPContentType const *> const ct = DCPContentType::all ();
461 for (size_t i = 0; i < ct.size(); ++i) {
462 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
465 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
467 _j2k_bandwidth->SetRange (50, 250);
468 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
470 _audio_delay->SetRange (-1000, 1000);
471 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
473 _standard->Append (_("SMPTE"));
474 _standard->Append (_("Interop"));
475 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
478 void config_changed ()
480 Config* config = Config::instance ();
482 vector<Ratio const *> ratios = Ratio::all ();
483 for (size_t i = 0; i < ratios.size(); ++i) {
484 if (ratios[i] == config->default_container ()) {
485 _container->SetSelection (i);
489 vector<DCPContentType const *> const ct = DCPContentType::all ();
490 for (size_t i = 0; i < ct.size(); ++i) {
491 if (ct[i] == config->default_dcp_content_type ()) {
492 _dcp_content_type->SetSelection (i);
496 checked_set (_still_length, config->default_still_length ());
497 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
498 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
499 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
500 checked_set (_audio_delay, config->default_audio_delay ());
501 checked_set (_standard, config->default_interop() ? 1 : 0);
504 void j2k_bandwidth_changed ()
506 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
509 void audio_delay_changed ()
511 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
514 void directory_changed ()
516 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
519 void edit_isdcf_metadata_clicked ()
521 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
523 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
527 void still_length_changed ()
529 Config::instance()->set_default_still_length (_still_length->GetValue ());
532 void container_changed ()
534 vector<Ratio const *> ratio = Ratio::all ();
535 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
538 void dcp_content_type_changed ()
540 vector<DCPContentType const *> ct = DCPContentType::all ();
541 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
544 void standard_changed ()
546 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
549 wxSpinCtrl* _j2k_bandwidth;
550 wxSpinCtrl* _audio_delay;
551 wxButton* _isdcf_metadata_button;
552 wxSpinCtrl* _still_length;
553 #ifdef DCPOMATIC_USE_OWN_PICKER
554 DirPickerCtrl* _directory;
556 wxDirPickerCtrl* _directory;
558 wxChoice* _container;
559 wxChoice* _dcp_content_type;
563 class EncodingServersPage : public StandardPage
566 EncodingServersPage (wxSize panel_size, int border)
567 : StandardPage (panel_size, border)
570 wxString GetName () const
576 wxBitmap GetLargeIcon () const
578 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
585 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
586 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
588 vector<string> columns;
589 columns.push_back (wx_to_std (_("IP address / host name")));
590 _servers_list = new EditableList<string, ServerDialog> (
593 boost::bind (&Config::servers, Config::instance()),
594 boost::bind (&Config::set_servers, Config::instance(), _1),
595 boost::bind (&EncodingServersPage::server_column, this, _1)
598 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
600 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
603 void config_changed ()
605 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
606 _servers_list->refresh ();
609 void use_any_servers_changed ()
611 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
614 string server_column (string s)
619 wxCheckBox* _use_any_servers;
620 EditableList<string, ServerDialog>* _servers_list;
623 class CertificateChainEditor : public wxPanel
626 CertificateChainEditor (
630 function<void (shared_ptr<dcp::CertificateChain>)> set,
631 function<shared_ptr<const dcp::CertificateChain> (void)> get
637 wxFont subheading_font (*wxNORMAL_FONT);
638 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
640 _sizer = new wxBoxSizer (wxVERTICAL);
643 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
644 m->SetFont (subheading_font);
645 _sizer->Add (m, 0, wxALL, border);
648 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
649 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
651 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
656 ip.SetText (_("Type"));
658 _certificates->InsertColumn (0, ip);
664 ip.SetText (_("Thumbprint"));
667 wxFont font = ip.GetFont ();
668 font.SetFamily (wxFONTFAMILY_TELETYPE);
671 _certificates->InsertColumn (1, ip);
674 certificates_sizer->Add (_certificates, 1, wxEXPAND);
677 wxSizer* s = new wxBoxSizer (wxVERTICAL);
678 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
679 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
680 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
681 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
682 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
683 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
684 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
687 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
688 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
691 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
692 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
693 wxFont font = _private_key->GetFont ();
694 font.SetFamily (wxFONTFAMILY_TELETYPE);
695 _private_key->SetFont (font);
696 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
697 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
698 table->Add (_load_private_key, wxGBPosition (r, 2));
699 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
700 table->Add (_export_private_key, wxGBPosition (r, 3));
703 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
704 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
705 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
706 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
709 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
710 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
711 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
712 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
713 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
714 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
715 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
716 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
718 SetSizerAndFit (_sizer);
721 void config_changed ()
723 _chain.reset (new dcp::CertificateChain (*_get().get ()));
725 update_certificate_list ();
726 update_private_key ();
727 update_sensitivity ();
730 void add_button (wxWindow* button)
732 _button_sizer->Add (button);
737 void add_certificate ()
739 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
741 if (d->ShowModal() == wxID_OK) {
743 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
746 update_certificate_list ();
747 } catch (dcp::MiscError& e) {
748 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
754 update_sensitivity ();
757 void remove_certificate ()
759 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
764 _certificates->DeleteItem (i);
768 update_sensitivity ();
771 void export_certificate ()
773 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
778 wxFileDialog* d = new wxFileDialog (
779 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
780 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
783 dcp::CertificateChain::List all = _chain->root_to_leaf ();
784 dcp::CertificateChain::List::iterator j = all.begin ();
785 for (int k = 0; k < i; ++k) {
789 if (d->ShowModal () == wxID_OK) {
790 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
792 throw OpenFileError (wx_to_std (d->GetPath ()));
795 string const s = j->certificate (true);
796 fwrite (s.c_str(), 1, s.length(), f);
802 void update_certificate_list ()
804 _certificates->DeleteAllItems ();
806 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
807 BOOST_FOREACH (dcp::Certificate const & i, certs) {
810 _certificates->InsertItem (item);
811 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
814 _certificates->SetItem (n, 0, _("Root"));
815 } else if (n == (certs.size() - 1)) {
816 _certificates->SetItem (n, 0, _("Leaf"));
818 _certificates->SetItem (n, 0, _("Intermediate"));
825 void remake_certificates ()
827 shared_ptr<const dcp::CertificateChain> chain = _get ();
829 string subject_organization_name;
830 string subject_organizational_unit_name;
831 string root_common_name;
832 string intermediate_common_name;
833 string leaf_common_name;
835 dcp::CertificateChain::List all = chain->root_to_leaf ();
837 if (all.size() >= 1) {
839 subject_organization_name = chain->root().subject_organization_name ();
840 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
841 root_common_name = chain->root().subject_common_name ();
844 if (all.size() >= 2) {
846 leaf_common_name = chain->leaf().subject_common_name ();
849 if (all.size() >= 3) {
850 /* Have an intermediate */
851 dcp::CertificateChain::List::iterator i = all.begin ();
853 intermediate_common_name = i->subject_common_name ();
856 MakeChainDialog* d = new MakeChainDialog (
858 subject_organization_name,
859 subject_organizational_unit_name,
861 intermediate_common_name,
865 if (d->ShowModal () == wxID_OK) {
867 new dcp::CertificateChain (
870 d->organisational_unit (),
871 d->root_common_name (),
872 d->intermediate_common_name (),
873 d->leaf_common_name ()
878 update_certificate_list ();
879 update_private_key ();
885 void update_sensitivity ()
887 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
888 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
891 void update_private_key ()
893 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
897 void load_private_key ()
899 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
901 if (d->ShowModal() == wxID_OK) {
903 boost::filesystem::path p (wx_to_std (d->GetPath ()));
904 if (boost::filesystem::file_size (p) > 1024) {
905 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
909 _chain->set_key (dcp::file_to_string (p));
911 update_private_key ();
912 } catch (dcp::MiscError& e) {
913 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
919 update_sensitivity ();
922 void export_private_key ()
924 optional<string> key = _chain->key ();
929 wxFileDialog* d = new wxFileDialog (
930 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
931 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
934 if (d->ShowModal () == wxID_OK) {
935 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
937 throw OpenFileError (wx_to_std (d->GetPath ()));
940 string const s = _chain->key().get ();
941 fwrite (s.c_str(), 1, s.length(), f);
947 wxListCtrl* _certificates;
948 wxButton* _add_certificate;
949 wxButton* _export_certificate;
950 wxButton* _remove_certificate;
951 wxButton* _remake_certificates;
952 wxStaticText* _private_key;
953 wxButton* _load_private_key;
954 wxButton* _export_private_key;
956 wxBoxSizer* _button_sizer;
957 shared_ptr<dcp::CertificateChain> _chain;
958 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
959 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
962 class KeysPage : public StandardPage
965 KeysPage (wxSize panel_size, int border)
966 : StandardPage (panel_size, border)
969 wxString GetName () const
975 wxBitmap GetLargeIcon () const
977 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
985 _signer = new CertificateChainEditor (
986 _panel, _("Signing DCPs and KDMs"), _border,
987 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
988 boost::bind (&Config::signer_chain, Config::instance ())
991 _panel->GetSizer()->Add (_signer);
993 _decryption = new CertificateChainEditor (
994 _panel, _("Decrypting DCPs"), _border,
995 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
996 boost::bind (&Config::decryption_chain, Config::instance ())
999 _panel->GetSizer()->Add (_decryption);
1001 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1002 _decryption->add_button (_export_decryption_certificate);
1004 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1007 void export_decryption_certificate ()
1009 wxFileDialog* d = new wxFileDialog (
1010 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1011 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1014 if (d->ShowModal () == wxID_OK) {
1015 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1017 throw OpenFileError (wx_to_std (d->GetPath ()));
1020 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1021 fwrite (s.c_str(), 1, s.length(), f);
1027 void config_changed ()
1029 _signer->config_changed ();
1030 _decryption->config_changed ();
1033 CertificateChainEditor* _signer;
1034 CertificateChainEditor* _decryption;
1035 wxButton* _export_decryption_certificate;
1038 class TMSPage : public StandardPage
1041 TMSPage (wxSize panel_size, int border)
1042 : StandardPage (panel_size, border)
1045 wxString GetName () const
1050 #ifdef DCPOMATIC_OSX
1051 wxBitmap GetLargeIcon () const
1053 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1060 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1061 table->AddGrowableCol (1, 1);
1062 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1064 add_label_to_sizer (table, _panel, _("Protocol"), true);
1065 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1066 table->Add (_tms_protocol, 1, wxEXPAND);
1068 add_label_to_sizer (table, _panel, _("IP address"), true);
1069 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1070 table->Add (_tms_ip, 1, wxEXPAND);
1072 add_label_to_sizer (table, _panel, _("Target path"), true);
1073 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1074 table->Add (_tms_path, 1, wxEXPAND);
1076 add_label_to_sizer (table, _panel, _("User name"), true);
1077 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1078 table->Add (_tms_user, 1, wxEXPAND);
1080 add_label_to_sizer (table, _panel, _("Password"), true);
1081 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1082 table->Add (_tms_password, 1, wxEXPAND);
1084 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1085 _tms_protocol->Append (_("FTP (for Dolby)"));
1087 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1088 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1089 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1090 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1091 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1094 void config_changed ()
1096 Config* config = Config::instance ();
1098 checked_set (_tms_protocol, config->tms_protocol ());
1099 checked_set (_tms_ip, config->tms_ip ());
1100 checked_set (_tms_path, config->tms_path ());
1101 checked_set (_tms_user, config->tms_user ());
1102 checked_set (_tms_password, config->tms_password ());
1105 void tms_protocol_changed ()
1107 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1110 void tms_ip_changed ()
1112 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1115 void tms_path_changed ()
1117 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1120 void tms_user_changed ()
1122 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1125 void tms_password_changed ()
1127 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1130 wxChoice* _tms_protocol;
1131 wxTextCtrl* _tms_ip;
1132 wxTextCtrl* _tms_path;
1133 wxTextCtrl* _tms_user;
1134 wxTextCtrl* _tms_password;
1137 class KDMEmailPage : public StandardPage
1141 KDMEmailPage (wxSize panel_size, int border)
1142 #ifdef DCPOMATIC_OSX
1143 /* We have to force both width and height of this one */
1144 : StandardPage (wxSize (480, 128), border)
1146 : StandardPage (panel_size, border)
1150 wxString GetName () const
1152 return _("KDM Email");
1155 #ifdef DCPOMATIC_OSX
1156 wxBitmap GetLargeIcon () const
1158 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1165 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1166 table->AddGrowableCol (1, 1);
1167 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1169 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1171 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1172 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1173 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1174 add_label_to_sizer (s, _panel, _("port"), false);
1175 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1176 _mail_port->SetRange (0, 65535);
1177 s->Add (_mail_port);
1178 table->Add (s, 1, wxEXPAND | wxALL);
1181 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1182 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1183 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1185 add_label_to_sizer (table, _panel, _("Mail password"), true);
1186 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1187 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1189 add_label_to_sizer (table, _panel, _("Subject"), true);
1190 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1191 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1193 add_label_to_sizer (table, _panel, _("From address"), true);
1194 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1195 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1197 add_label_to_sizer (table, _panel, _("CC address"), true);
1198 _kdm_cc = new wxTextCtrl (_panel, wxID_ANY);
1199 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1201 add_label_to_sizer (table, _panel, _("BCC address"), true);
1202 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1203 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1205 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (480, 128), wxTE_MULTILINE);
1206 _panel->GetSizer()->Add (_kdm_email, 1, wxEXPAND | wxALL, _border);
1208 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1209 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1211 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1212 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1213 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1214 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1215 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1216 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1217 _kdm_cc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_cc_changed, this));
1218 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1219 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1220 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1223 void config_changed ()
1225 Config* config = Config::instance ();
1227 checked_set (_mail_server, config->mail_server ());
1228 checked_set (_mail_port, config->mail_port ());
1229 checked_set (_mail_user, config->mail_user ());
1230 checked_set (_mail_password, config->mail_password ());
1231 checked_set (_kdm_subject, config->kdm_subject ());
1232 checked_set (_kdm_from, config->kdm_from ());
1233 checked_set (_kdm_cc, config->kdm_cc ());
1234 checked_set (_kdm_bcc, config->kdm_bcc ());
1235 checked_set (_kdm_email, Config::instance()->kdm_email ());
1238 void mail_server_changed ()
1240 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1243 void mail_port_changed ()
1245 Config::instance()->set_mail_port (_mail_port->GetValue ());
1248 void mail_user_changed ()
1250 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1253 void mail_password_changed ()
1255 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1258 void kdm_subject_changed ()
1260 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1263 void kdm_from_changed ()
1265 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1268 void kdm_cc_changed ()
1270 Config::instance()->set_kdm_cc (wx_to_std (_kdm_cc->GetValue ()));
1273 void kdm_bcc_changed ()
1275 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1278 void kdm_email_changed ()
1280 if (_kdm_email->GetValue().IsEmpty ()) {
1281 /* Sometimes we get sent an erroneous notification that the email
1282 is empty; I don't know why.
1286 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1289 void reset_kdm_email ()
1291 Config::instance()->reset_kdm_email ();
1292 checked_set (_kdm_email, Config::instance()->kdm_email ());
1295 wxTextCtrl* _mail_server;
1296 wxSpinCtrl* _mail_port;
1297 wxTextCtrl* _mail_user;
1298 wxTextCtrl* _mail_password;
1299 wxTextCtrl* _kdm_subject;
1300 wxTextCtrl* _kdm_from;
1301 wxTextCtrl* _kdm_cc;
1302 wxTextCtrl* _kdm_bcc;
1303 wxTextCtrl* _kdm_email;
1304 wxButton* _reset_kdm_email;
1307 /** @class AdvancedPage
1308 * @brief Advanced page of the preferences dialog.
1310 class AdvancedPage : public StockPage
1313 AdvancedPage (wxSize panel_size, int border)
1314 : StockPage (Kind_Advanced, panel_size, border)
1315 , _maximum_j2k_bandwidth (0)
1316 , _allow_any_dcp_frame_rate (0)
1317 , _only_servers_encode (0)
1322 , _log_debug_decode (0)
1323 , _log_debug_encode (0)
1324 , _log_debug_email (0)
1330 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1331 table->AddGrowableCol (1, 1);
1332 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1335 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1336 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1337 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1338 s->Add (_maximum_j2k_bandwidth, 1);
1339 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1343 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1344 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1345 table->AddSpacer (0);
1347 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1348 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1349 table->AddSpacer (0);
1352 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1353 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1355 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1356 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1360 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1361 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1362 t->Add (_log_general, 1, wxEXPAND | wxALL);
1363 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1364 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1365 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1366 t->Add (_log_error, 1, wxEXPAND | wxALL);
1367 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1368 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1369 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1370 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1371 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1372 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1373 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1374 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1375 table->Add (t, 0, wxALL, 6);
1378 #ifdef DCPOMATIC_WINDOWS
1379 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1380 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1381 table->AddSpacer (0);
1384 _maximum_j2k_bandwidth->SetRange (1, 1000);
1385 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1386 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1387 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1388 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1389 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1390 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1391 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1392 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1393 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1394 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1395 #ifdef DCPOMATIC_WINDOWS
1396 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1400 void config_changed ()
1402 Config* config = Config::instance ();
1404 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1405 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1406 checked_set (_only_servers_encode, config->only_servers_encode ());
1407 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1408 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1409 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1410 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1411 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1412 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1413 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1414 #ifdef DCPOMATIC_WINDOWS
1415 checked_set (_win32_console, config->win32_console());
1419 void maximum_j2k_bandwidth_changed ()
1421 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1424 void allow_any_dcp_frame_rate_changed ()
1426 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1429 void only_servers_encode_changed ()
1431 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1437 if (_log_general->GetValue ()) {
1438 types |= LogEntry::TYPE_GENERAL;
1440 if (_log_warning->GetValue ()) {
1441 types |= LogEntry::TYPE_WARNING;
1443 if (_log_error->GetValue ()) {
1444 types |= LogEntry::TYPE_ERROR;
1446 if (_log_timing->GetValue ()) {
1447 types |= LogEntry::TYPE_TIMING;
1449 if (_log_debug_decode->GetValue ()) {
1450 types |= LogEntry::TYPE_DEBUG_DECODE;
1452 if (_log_debug_encode->GetValue ()) {
1453 types |= LogEntry::TYPE_DEBUG_ENCODE;
1455 if (_log_debug_email->GetValue ()) {
1456 types |= LogEntry::TYPE_DEBUG_EMAIL;
1458 Config::instance()->set_log_types (types);
1461 #ifdef DCPOMATIC_WINDOWS
1462 void win32_console_changed ()
1464 Config::instance()->set_win32_console (_win32_console->GetValue ());
1468 wxSpinCtrl* _maximum_j2k_bandwidth;
1469 wxCheckBox* _allow_any_dcp_frame_rate;
1470 wxCheckBox* _only_servers_encode;
1471 wxCheckBox* _log_general;
1472 wxCheckBox* _log_warning;
1473 wxCheckBox* _log_error;
1474 wxCheckBox* _log_timing;
1475 wxCheckBox* _log_debug_decode;
1476 wxCheckBox* _log_debug_encode;
1477 wxCheckBox* _log_debug_email;
1478 #ifdef DCPOMATIC_WINDOWS
1479 wxCheckBox* _win32_console;
1483 wxPreferencesEditor*
1484 create_config_dialog ()
1486 wxPreferencesEditor* e = new wxPreferencesEditor ();
1488 #ifdef DCPOMATIC_OSX
1489 /* Width that we force some of the config panels to be on OSX so that
1490 the containing window doesn't shrink too much when we select those panels.
1491 This is obviously an unpleasant hack.
1493 wxSize ps = wxSize (520, -1);
1494 int const border = 16;
1496 wxSize ps = wxSize (-1, -1);
1497 int const border = 8;
1500 e->AddPage (new GeneralPage (ps, border));
1501 e->AddPage (new DefaultsPage (ps, border));
1502 e->AddPage (new EncodingServersPage (ps, border));
1503 e->AddPage (new KeysPage (ps, border));
1504 e->AddPage (new TMSPage (ps, border));
1505 e->AddPage (new KDMEmailPage (ps, border));
1506 e->AddPage (new AdvancedPage (ps, border));