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 "isdcf_metadata_dialog.h"
30 #include "server_dialog.h"
31 #include "make_chain_dialog.h"
32 #include "email_dialog.h"
33 #include "lib/config.h"
34 #include "lib/ratio.h"
35 #include "lib/filter.h"
36 #include "lib/dcp_content_type.h"
39 #include "lib/raw_convert.h"
40 #include "lib/cross.h"
41 #include "lib/exceptions.h"
42 #include <dcp/exceptions.h>
43 #include <dcp/certificate_chain.h>
44 #include <wx/stdpaths.h>
45 #include <wx/preferences.h>
46 #include <wx/filepicker.h>
47 #include <wx/spinctrl.h>
48 #include <boost/lexical_cast.hpp>
49 #include <boost/filesystem.hpp>
50 #include <boost/foreach.hpp>
58 using boost::shared_ptr;
59 using boost::lexical_cast;
60 using boost::function;
61 using boost::optional;
66 Page (wxSize panel_size, int border)
69 , _panel_size (panel_size)
70 , _window_exists (false)
72 _config_connection = Config::instance()->Changed.connect (boost::bind (&Page::config_changed_wrapper, this));
78 wxWindow* create_window (wxWindow* parent)
80 _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size);
81 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
85 _window_exists = true;
88 _panel->Bind (wxEVT_DESTROY, boost::bind (&Page::window_destroyed, this));
97 virtual void config_changed () = 0;
98 virtual void setup () = 0;
100 void config_changed_wrapper ()
102 if (_window_exists) {
107 void window_destroyed ()
109 _window_exists = false;
113 boost::signals2::scoped_connection _config_connection;
117 class StockPage : public wxStockPreferencesPage, public Page
120 StockPage (Kind kind, wxSize panel_size, int border)
121 : wxStockPreferencesPage (kind)
122 , Page (panel_size, border)
125 wxWindow* CreateWindow (wxWindow* parent)
127 return create_window (parent);
131 class StandardPage : public wxPreferencesPage, public Page
134 StandardPage (wxSize panel_size, int border)
135 : Page (panel_size, border)
138 wxWindow* CreateWindow (wxWindow* parent)
140 return create_window (parent);
144 class GeneralPage : public StockPage
147 GeneralPage (wxSize panel_size, int border)
148 : StockPage (Kind_General, panel_size, border)
154 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
155 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
158 _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language"));
159 table->Add (_set_language, wxGBPosition (r, 0));
160 _language = new wxChoice (_panel, wxID_ANY);
161 _language->Append (wxT ("Deutsch"));
162 _language->Append (wxT ("English"));
163 _language->Append (wxT ("Español"));
164 _language->Append (wxT ("Français"));
165 _language->Append (wxT ("Italiano"));
166 _language->Append (wxT ("Nederlands"));
167 _language->Append (wxT ("Svenska"));
168 _language->Append (wxT ("Русский"));
169 _language->Append (wxT ("Polski"));
170 _language->Append (wxT ("Dansk"));
171 _language->Append (wxT ("Português europeu"));
172 _language->Append (wxT ("Slovenský jazyk"));
173 table->Add (_language, wxGBPosition (r, 1));
176 wxStaticText* restart = add_label_to_sizer (
177 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
179 wxFont font = restart->GetFont();
180 font.SetStyle (wxFONTSTYLE_ITALIC);
181 font.SetPointSize (font.GetPointSize() - 1);
182 restart->SetFont (font);
185 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
186 _num_local_encoding_threads = new wxSpinCtrl (_panel);
187 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
190 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
191 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
194 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
195 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
198 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
199 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
202 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
203 bottom_table->AddGrowableCol (1, 1);
205 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
206 _issuer = new wxTextCtrl (_panel, wxID_ANY);
207 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
209 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
210 _creator = new wxTextCtrl (_panel, wxID_ANY);
211 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
213 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
216 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
217 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
219 _num_local_encoding_threads->SetRange (1, 128);
220 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
222 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
223 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
224 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
226 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
227 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
230 void config_changed ()
232 Config* config = Config::instance ();
234 checked_set (_set_language, static_cast<bool>(config->language()));
236 if (config->language().get_value_or ("") == "fr") {
237 checked_set (_language, 3);
238 } else if (config->language().get_value_or ("") == "it") {
239 checked_set (_language, 4);
240 } else if (config->language().get_value_or ("") == "es") {
241 checked_set (_language, 2);
242 } else if (config->language().get_value_or ("") == "sv") {
243 checked_set (_language, 6);
244 } else if (config->language().get_value_or ("") == "de") {
245 checked_set (_language, 0);
246 } else if (config->language().get_value_or ("") == "nl") {
247 checked_set (_language, 5);
248 } else if (config->language().get_value_or ("") == "ru") {
249 checked_set (_language, 7);
250 } else if (config->language().get_value_or ("") == "pl") {
251 checked_set (_language, 8);
252 } else if (config->language().get_value_or ("") == "da") {
253 checked_set (_language, 9);
254 } else if (config->language().get_value_or ("") == "pt") {
255 checked_set (_language, 10);
256 } else if (config->language().get_value_or ("") == "sk") {
257 checked_set (_language, 11);
259 _language->SetSelection (1);
262 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
263 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
264 checked_set (_check_for_updates, config->check_for_updates ());
265 checked_set (_check_for_test_updates, config->check_for_test_updates ());
266 checked_set (_issuer, config->dcp_issuer ());
267 checked_set (_creator, config->dcp_creator ());
269 setup_sensitivity ();
272 void setup_sensitivity ()
274 _language->Enable (_set_language->GetValue ());
275 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
278 void set_language_changed ()
280 setup_sensitivity ();
281 if (_set_language->GetValue ()) {
284 Config::instance()->unset_language ();
288 void language_changed ()
290 switch (_language->GetSelection ()) {
292 Config::instance()->set_language ("de");
295 Config::instance()->set_language ("en");
298 Config::instance()->set_language ("es");
301 Config::instance()->set_language ("fr");
304 Config::instance()->set_language ("it");
307 Config::instance()->set_language ("nl");
310 Config::instance()->set_language ("sv");
313 Config::instance()->set_language ("ru");
316 Config::instance()->set_language ("pl");
319 Config::instance()->set_language ("da");
322 Config::instance()->set_language ("pt");
325 Config::instance()->set_language ("sk");
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 wxCheckBox* _set_language;
362 wxSpinCtrl* _num_local_encoding_threads;
363 wxCheckBox* _automatic_audio_analysis;
364 wxCheckBox* _check_for_updates;
365 wxCheckBox* _check_for_test_updates;
367 wxTextCtrl* _creator;
370 class DefaultsPage : public StandardPage
373 DefaultsPage (wxSize panel_size, int border)
374 : StandardPage (panel_size, border)
377 wxString GetName () const
379 return _("Defaults");
383 wxBitmap GetLargeIcon () const
385 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
392 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
393 table->AddGrowableCol (1, 1);
394 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
397 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
398 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
399 _still_length = new wxSpinCtrl (_panel);
400 s->Add (_still_length);
401 add_label_to_sizer (s, _panel, _("s"), false);
405 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
406 #ifdef DCPOMATIC_USE_OWN_PICKER
407 _directory = new DirPickerCtrl (_panel);
409 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
411 table->Add (_directory, 1, wxEXPAND);
413 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
414 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
415 table->Add (_isdcf_metadata_button);
417 add_label_to_sizer (table, _panel, _("Default container"), true);
418 _container = new wxChoice (_panel, wxID_ANY);
419 table->Add (_container);
421 add_label_to_sizer (table, _panel, _("Default content type"), true);
422 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
423 table->Add (_dcp_content_type);
426 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
427 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
428 _j2k_bandwidth = new wxSpinCtrl (_panel);
429 s->Add (_j2k_bandwidth);
430 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
435 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
436 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
437 _audio_delay = new wxSpinCtrl (_panel);
438 s->Add (_audio_delay);
439 add_label_to_sizer (s, _panel, _("ms"), false);
443 add_label_to_sizer (table, _panel, _("Default standard"), true);
444 _standard = new wxChoice (_panel, wxID_ANY);
445 table->Add (_standard);
447 _still_length->SetRange (1, 3600);
448 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
450 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
452 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
454 vector<Ratio const *> ratios = Ratio::all ();
455 for (size_t i = 0; i < ratios.size(); ++i) {
456 _container->Append (std_to_wx (ratios[i]->nickname ()));
459 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
461 vector<DCPContentType const *> const ct = DCPContentType::all ();
462 for (size_t i = 0; i < ct.size(); ++i) {
463 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
466 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
468 _j2k_bandwidth->SetRange (50, 250);
469 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
471 _audio_delay->SetRange (-1000, 1000);
472 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
474 _standard->Append (_("SMPTE"));
475 _standard->Append (_("Interop"));
476 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
479 void config_changed ()
481 Config* config = Config::instance ();
483 vector<Ratio const *> ratios = Ratio::all ();
484 for (size_t i = 0; i < ratios.size(); ++i) {
485 if (ratios[i] == config->default_container ()) {
486 _container->SetSelection (i);
490 vector<DCPContentType const *> const ct = DCPContentType::all ();
491 for (size_t i = 0; i < ct.size(); ++i) {
492 if (ct[i] == config->default_dcp_content_type ()) {
493 _dcp_content_type->SetSelection (i);
497 checked_set (_still_length, config->default_still_length ());
498 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
499 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
500 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
501 checked_set (_audio_delay, config->default_audio_delay ());
502 checked_set (_standard, config->default_interop() ? 1 : 0);
505 void j2k_bandwidth_changed ()
507 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
510 void audio_delay_changed ()
512 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
515 void directory_changed ()
517 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
520 void edit_isdcf_metadata_clicked ()
522 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
524 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
528 void still_length_changed ()
530 Config::instance()->set_default_still_length (_still_length->GetValue ());
533 void container_changed ()
535 vector<Ratio const *> ratio = Ratio::all ();
536 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
539 void dcp_content_type_changed ()
541 vector<DCPContentType const *> ct = DCPContentType::all ();
542 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
545 void standard_changed ()
547 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
550 wxSpinCtrl* _j2k_bandwidth;
551 wxSpinCtrl* _audio_delay;
552 wxButton* _isdcf_metadata_button;
553 wxSpinCtrl* _still_length;
554 #ifdef DCPOMATIC_USE_OWN_PICKER
555 DirPickerCtrl* _directory;
557 wxDirPickerCtrl* _directory;
559 wxChoice* _container;
560 wxChoice* _dcp_content_type;
564 class EncodingServersPage : public StandardPage
567 EncodingServersPage (wxSize panel_size, int border)
568 : StandardPage (panel_size, border)
571 wxString GetName () const
577 wxBitmap GetLargeIcon () const
579 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
586 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
587 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
589 vector<string> columns;
590 columns.push_back (wx_to_std (_("IP address / host name")));
591 _servers_list = new EditableList<string, ServerDialog> (
594 boost::bind (&Config::servers, Config::instance()),
595 boost::bind (&Config::set_servers, Config::instance(), _1),
596 boost::bind (&EncodingServersPage::server_column, this, _1)
599 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
601 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
604 void config_changed ()
606 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
607 _servers_list->refresh ();
610 void use_any_servers_changed ()
612 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
615 string server_column (string s)
620 wxCheckBox* _use_any_servers;
621 EditableList<string, ServerDialog>* _servers_list;
624 class CertificateChainEditor : public wxPanel
627 CertificateChainEditor (
631 function<void (shared_ptr<dcp::CertificateChain>)> set,
632 function<shared_ptr<const dcp::CertificateChain> (void)> get
638 wxFont subheading_font (*wxNORMAL_FONT);
639 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
641 _sizer = new wxBoxSizer (wxVERTICAL);
644 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
645 m->SetFont (subheading_font);
646 _sizer->Add (m, 0, wxALL, border);
649 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
650 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
652 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
657 ip.SetText (_("Type"));
659 _certificates->InsertColumn (0, ip);
665 ip.SetText (_("Thumbprint"));
668 wxFont font = ip.GetFont ();
669 font.SetFamily (wxFONTFAMILY_TELETYPE);
672 _certificates->InsertColumn (1, ip);
675 certificates_sizer->Add (_certificates, 1, wxEXPAND);
678 wxSizer* s = new wxBoxSizer (wxVERTICAL);
679 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
680 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
681 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
682 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
683 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
684 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
685 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
688 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
689 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
692 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
693 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
694 wxFont font = _private_key->GetFont ();
695 font.SetFamily (wxFONTFAMILY_TELETYPE);
696 _private_key->SetFont (font);
697 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
698 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
699 table->Add (_load_private_key, wxGBPosition (r, 2));
700 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
701 table->Add (_export_private_key, wxGBPosition (r, 3));
704 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
705 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
706 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
707 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
710 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
711 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
712 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
713 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
714 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
715 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
716 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
717 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
719 SetSizerAndFit (_sizer);
722 void config_changed ()
724 _chain.reset (new dcp::CertificateChain (*_get().get ()));
726 update_certificate_list ();
727 update_private_key ();
728 update_sensitivity ();
731 void add_button (wxWindow* button)
733 _button_sizer->Add (button);
738 void add_certificate ()
740 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
742 if (d->ShowModal() == wxID_OK) {
744 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
747 update_certificate_list ();
748 } catch (dcp::MiscError& e) {
749 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
755 update_sensitivity ();
758 void remove_certificate ()
760 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
765 _certificates->DeleteItem (i);
769 update_sensitivity ();
772 void export_certificate ()
774 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
779 wxFileDialog* d = new wxFileDialog (
780 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
781 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
784 dcp::CertificateChain::List all = _chain->root_to_leaf ();
785 dcp::CertificateChain::List::iterator j = all.begin ();
786 for (int k = 0; k < i; ++k) {
790 if (d->ShowModal () == wxID_OK) {
791 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
793 throw OpenFileError (wx_to_std (d->GetPath ()));
796 string const s = j->certificate (true);
797 fwrite (s.c_str(), 1, s.length(), f);
803 void update_certificate_list ()
805 _certificates->DeleteAllItems ();
807 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
808 BOOST_FOREACH (dcp::Certificate const & i, certs) {
811 _certificates->InsertItem (item);
812 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
815 _certificates->SetItem (n, 0, _("Root"));
816 } else if (n == (certs.size() - 1)) {
817 _certificates->SetItem (n, 0, _("Leaf"));
819 _certificates->SetItem (n, 0, _("Intermediate"));
826 void remake_certificates ()
828 shared_ptr<const dcp::CertificateChain> chain = _get ();
830 string subject_organization_name;
831 string subject_organizational_unit_name;
832 string root_common_name;
833 string intermediate_common_name;
834 string leaf_common_name;
836 dcp::CertificateChain::List all = chain->root_to_leaf ();
838 if (all.size() >= 1) {
840 subject_organization_name = chain->root().subject_organization_name ();
841 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
842 root_common_name = chain->root().subject_common_name ();
845 if (all.size() >= 2) {
847 leaf_common_name = chain->leaf().subject_common_name ();
850 if (all.size() >= 3) {
851 /* Have an intermediate */
852 dcp::CertificateChain::List::iterator i = all.begin ();
854 intermediate_common_name = i->subject_common_name ();
857 MakeChainDialog* d = new MakeChainDialog (
859 subject_organization_name,
860 subject_organizational_unit_name,
862 intermediate_common_name,
866 if (d->ShowModal () == wxID_OK) {
868 new dcp::CertificateChain (
871 d->organisational_unit (),
872 d->root_common_name (),
873 d->intermediate_common_name (),
874 d->leaf_common_name ()
879 update_certificate_list ();
880 update_private_key ();
886 void update_sensitivity ()
888 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
889 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
892 void update_private_key ()
894 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
898 void load_private_key ()
900 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
902 if (d->ShowModal() == wxID_OK) {
904 boost::filesystem::path p (wx_to_std (d->GetPath ()));
905 if (boost::filesystem::file_size (p) > 1024) {
906 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
910 _chain->set_key (dcp::file_to_string (p));
912 update_private_key ();
913 } catch (dcp::MiscError& e) {
914 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
920 update_sensitivity ();
923 void export_private_key ()
925 optional<string> key = _chain->key ();
930 wxFileDialog* d = new wxFileDialog (
931 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
932 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
935 if (d->ShowModal () == wxID_OK) {
936 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
938 throw OpenFileError (wx_to_std (d->GetPath ()));
941 string const s = _chain->key().get ();
942 fwrite (s.c_str(), 1, s.length(), f);
948 wxListCtrl* _certificates;
949 wxButton* _add_certificate;
950 wxButton* _export_certificate;
951 wxButton* _remove_certificate;
952 wxButton* _remake_certificates;
953 wxStaticText* _private_key;
954 wxButton* _load_private_key;
955 wxButton* _export_private_key;
957 wxBoxSizer* _button_sizer;
958 shared_ptr<dcp::CertificateChain> _chain;
959 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
960 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
963 class KeysPage : public StandardPage
966 KeysPage (wxSize panel_size, int border)
967 : StandardPage (panel_size, border)
970 wxString GetName () const
976 wxBitmap GetLargeIcon () const
978 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
986 _signer = new CertificateChainEditor (
987 _panel, _("Signing DCPs and KDMs"), _border,
988 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
989 boost::bind (&Config::signer_chain, Config::instance ())
992 _panel->GetSizer()->Add (_signer);
994 _decryption = new CertificateChainEditor (
995 _panel, _("Decrypting DCPs"), _border,
996 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
997 boost::bind (&Config::decryption_chain, Config::instance ())
1000 _panel->GetSizer()->Add (_decryption);
1002 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1003 _decryption->add_button (_export_decryption_certificate);
1005 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1008 void export_decryption_certificate ()
1010 wxFileDialog* d = new wxFileDialog (
1011 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1012 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1015 if (d->ShowModal () == wxID_OK) {
1016 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1018 throw OpenFileError (wx_to_std (d->GetPath ()));
1021 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1022 fwrite (s.c_str(), 1, s.length(), f);
1028 void config_changed ()
1030 _signer->config_changed ();
1031 _decryption->config_changed ();
1034 CertificateChainEditor* _signer;
1035 CertificateChainEditor* _decryption;
1036 wxButton* _export_decryption_certificate;
1039 class TMSPage : public StandardPage
1042 TMSPage (wxSize panel_size, int border)
1043 : StandardPage (panel_size, border)
1046 wxString GetName () const
1051 #ifdef DCPOMATIC_OSX
1052 wxBitmap GetLargeIcon () const
1054 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1061 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1062 table->AddGrowableCol (1, 1);
1063 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1065 add_label_to_sizer (table, _panel, _("Protocol"), true);
1066 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1067 table->Add (_tms_protocol, 1, wxEXPAND);
1069 add_label_to_sizer (table, _panel, _("IP address"), true);
1070 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1071 table->Add (_tms_ip, 1, wxEXPAND);
1073 add_label_to_sizer (table, _panel, _("Target path"), true);
1074 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1075 table->Add (_tms_path, 1, wxEXPAND);
1077 add_label_to_sizer (table, _panel, _("User name"), true);
1078 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1079 table->Add (_tms_user, 1, wxEXPAND);
1081 add_label_to_sizer (table, _panel, _("Password"), true);
1082 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1083 table->Add (_tms_password, 1, wxEXPAND);
1085 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1086 _tms_protocol->Append (_("FTP (for Dolby)"));
1088 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1089 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1090 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1091 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1092 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1095 void config_changed ()
1097 Config* config = Config::instance ();
1099 checked_set (_tms_protocol, config->tms_protocol ());
1100 checked_set (_tms_ip, config->tms_ip ());
1101 checked_set (_tms_path, config->tms_path ());
1102 checked_set (_tms_user, config->tms_user ());
1103 checked_set (_tms_password, config->tms_password ());
1106 void tms_protocol_changed ()
1108 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1111 void tms_ip_changed ()
1113 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1116 void tms_path_changed ()
1118 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1121 void tms_user_changed ()
1123 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1126 void tms_password_changed ()
1128 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1131 wxChoice* _tms_protocol;
1132 wxTextCtrl* _tms_ip;
1133 wxTextCtrl* _tms_path;
1134 wxTextCtrl* _tms_user;
1135 wxTextCtrl* _tms_password;
1144 class KDMEmailPage : public StandardPage
1148 KDMEmailPage (wxSize panel_size, int border)
1149 #ifdef DCPOMATIC_OSX
1150 /* We have to force both width and height of this one */
1151 : StandardPage (wxSize (480, 128), border)
1153 : StandardPage (panel_size, border)
1157 wxString GetName () const
1159 return _("KDM Email");
1162 #ifdef DCPOMATIC_OSX
1163 wxBitmap GetLargeIcon () const
1165 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1172 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1173 table->AddGrowableCol (1, 1);
1174 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1176 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1178 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1179 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1180 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1181 add_label_to_sizer (s, _panel, _("port"), false);
1182 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1183 _mail_port->SetRange (0, 65535);
1184 s->Add (_mail_port);
1185 table->Add (s, 1, wxEXPAND | wxALL);
1188 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1189 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1190 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1192 add_label_to_sizer (table, _panel, _("Mail password"), true);
1193 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1194 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1196 add_label_to_sizer (table, _panel, _("Subject"), true);
1197 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1198 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1200 add_label_to_sizer (table, _panel, _("From address"), true);
1201 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1202 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1204 vector<string> columns;
1205 columns.push_back (wx_to_std (_("Address")));
1206 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1207 _kdm_cc = new EditableList<string, EmailDialog> (
1208 _panel, columns, bind (&Config::kdm_cc, Config::instance()), bind (&Config::set_kdm_cc, Config::instance(), _1), bind (&column, _1)
1210 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1212 add_label_to_sizer (table, _panel, _("BCC address"), true);
1213 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1214 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1216 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1217 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1219 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1220 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1222 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1223 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1224 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1225 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1226 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1227 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1228 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1229 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1230 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1233 void config_changed ()
1235 Config* config = Config::instance ();
1237 checked_set (_mail_server, config->mail_server ());
1238 checked_set (_mail_port, config->mail_port ());
1239 checked_set (_mail_user, config->mail_user ());
1240 checked_set (_mail_password, config->mail_password ());
1241 checked_set (_kdm_subject, config->kdm_subject ());
1242 checked_set (_kdm_from, config->kdm_from ());
1243 checked_set (_kdm_bcc, config->kdm_bcc ());
1244 checked_set (_kdm_email, Config::instance()->kdm_email ());
1247 void mail_server_changed ()
1249 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1252 void mail_port_changed ()
1254 Config::instance()->set_mail_port (_mail_port->GetValue ());
1257 void mail_user_changed ()
1259 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1262 void mail_password_changed ()
1264 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1267 void kdm_subject_changed ()
1269 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1272 void kdm_from_changed ()
1274 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1277 void kdm_bcc_changed ()
1279 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1282 void kdm_email_changed ()
1284 if (_kdm_email->GetValue().IsEmpty ()) {
1285 /* Sometimes we get sent an erroneous notification that the email
1286 is empty; I don't know why.
1290 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1293 void reset_kdm_email ()
1295 Config::instance()->reset_kdm_email ();
1296 checked_set (_kdm_email, Config::instance()->kdm_email ());
1299 wxTextCtrl* _mail_server;
1300 wxSpinCtrl* _mail_port;
1301 wxTextCtrl* _mail_user;
1302 wxTextCtrl* _mail_password;
1303 wxTextCtrl* _kdm_subject;
1304 wxTextCtrl* _kdm_from;
1305 EditableList<string, EmailDialog>* _kdm_cc;
1306 wxTextCtrl* _kdm_bcc;
1307 wxTextCtrl* _kdm_email;
1308 wxButton* _reset_kdm_email;
1311 /** @class AdvancedPage
1312 * @brief Advanced page of the preferences dialog.
1314 class AdvancedPage : public StockPage
1317 AdvancedPage (wxSize panel_size, int border)
1318 : StockPage (Kind_Advanced, panel_size, border)
1319 , _maximum_j2k_bandwidth (0)
1320 , _allow_any_dcp_frame_rate (0)
1321 , _only_servers_encode (0)
1326 , _log_debug_decode (0)
1327 , _log_debug_encode (0)
1328 , _log_debug_email (0)
1334 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1335 table->AddGrowableCol (1, 1);
1336 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1339 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1340 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1341 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1342 s->Add (_maximum_j2k_bandwidth, 1);
1343 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1347 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1348 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1349 table->AddSpacer (0);
1351 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1352 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1353 table->AddSpacer (0);
1356 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1357 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1359 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1360 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1364 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1365 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1366 t->Add (_log_general, 1, wxEXPAND | wxALL);
1367 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1368 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1369 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1370 t->Add (_log_error, 1, wxEXPAND | wxALL);
1371 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1372 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1373 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1374 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1375 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1376 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1377 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1378 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1379 table->Add (t, 0, wxALL, 6);
1382 #ifdef DCPOMATIC_WINDOWS
1383 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1384 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1385 table->AddSpacer (0);
1388 _maximum_j2k_bandwidth->SetRange (1, 1000);
1389 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1390 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1391 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1392 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1393 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1394 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1395 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1396 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1397 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1398 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1399 #ifdef DCPOMATIC_WINDOWS
1400 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1404 void config_changed ()
1406 Config* config = Config::instance ();
1408 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1409 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1410 checked_set (_only_servers_encode, config->only_servers_encode ());
1411 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1412 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1413 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1414 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1415 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1416 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1417 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1418 #ifdef DCPOMATIC_WINDOWS
1419 checked_set (_win32_console, config->win32_console());
1423 void maximum_j2k_bandwidth_changed ()
1425 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1428 void allow_any_dcp_frame_rate_changed ()
1430 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1433 void only_servers_encode_changed ()
1435 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1441 if (_log_general->GetValue ()) {
1442 types |= LogEntry::TYPE_GENERAL;
1444 if (_log_warning->GetValue ()) {
1445 types |= LogEntry::TYPE_WARNING;
1447 if (_log_error->GetValue ()) {
1448 types |= LogEntry::TYPE_ERROR;
1450 if (_log_timing->GetValue ()) {
1451 types |= LogEntry::TYPE_TIMING;
1453 if (_log_debug_decode->GetValue ()) {
1454 types |= LogEntry::TYPE_DEBUG_DECODE;
1456 if (_log_debug_encode->GetValue ()) {
1457 types |= LogEntry::TYPE_DEBUG_ENCODE;
1459 if (_log_debug_email->GetValue ()) {
1460 types |= LogEntry::TYPE_DEBUG_EMAIL;
1462 Config::instance()->set_log_types (types);
1465 #ifdef DCPOMATIC_WINDOWS
1466 void win32_console_changed ()
1468 Config::instance()->set_win32_console (_win32_console->GetValue ());
1472 wxSpinCtrl* _maximum_j2k_bandwidth;
1473 wxCheckBox* _allow_any_dcp_frame_rate;
1474 wxCheckBox* _only_servers_encode;
1475 wxCheckBox* _log_general;
1476 wxCheckBox* _log_warning;
1477 wxCheckBox* _log_error;
1478 wxCheckBox* _log_timing;
1479 wxCheckBox* _log_debug_decode;
1480 wxCheckBox* _log_debug_encode;
1481 wxCheckBox* _log_debug_email;
1482 #ifdef DCPOMATIC_WINDOWS
1483 wxCheckBox* _win32_console;
1487 wxPreferencesEditor*
1488 create_config_dialog ()
1490 wxPreferencesEditor* e = new wxPreferencesEditor ();
1492 #ifdef DCPOMATIC_OSX
1493 /* Width that we force some of the config panels to be on OSX so that
1494 the containing window doesn't shrink too much when we select those panels.
1495 This is obviously an unpleasant hack.
1497 wxSize ps = wxSize (520, -1);
1498 int const border = 16;
1500 wxSize ps = wxSize (-1, -1);
1501 int const border = 8;
1504 e->AddPage (new GeneralPage (ps, border));
1505 e->AddPage (new DefaultsPage (ps, border));
1506 e->AddPage (new EncodingServersPage (ps, border));
1507 e->AddPage (new KeysPage (ps, border));
1508 e->AddPage (new TMSPage (ps, border));
1509 e->AddPage (new KDMEmailPage (ps, border));
1510 e->AddPage (new AdvancedPage (ps, border));