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 _language->Append (wxT ("Čeština"));
174 table->Add (_language, wxGBPosition (r, 1));
177 wxStaticText* restart = add_label_to_sizer (
178 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
180 wxFont font = restart->GetFont();
181 font.SetStyle (wxFONTSTYLE_ITALIC);
182 font.SetPointSize (font.GetPointSize() - 1);
183 restart->SetFont (font);
186 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
187 _num_local_encoding_threads = new wxSpinCtrl (_panel);
188 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
191 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
192 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
195 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
196 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
199 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
200 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
203 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
204 bottom_table->AddGrowableCol (1, 1);
206 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
207 _issuer = new wxTextCtrl (_panel, wxID_ANY);
208 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
210 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
211 _creator = new wxTextCtrl (_panel, wxID_ANY);
212 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
214 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
217 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
218 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
220 _num_local_encoding_threads->SetRange (1, 128);
221 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
223 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
224 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
225 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
227 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
228 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
231 void config_changed ()
233 Config* config = Config::instance ();
235 checked_set (_set_language, static_cast<bool>(config->language()));
237 if (config->language().get_value_or ("") == "fr") {
238 checked_set (_language, 3);
239 } else if (config->language().get_value_or ("") == "it") {
240 checked_set (_language, 4);
241 } else if (config->language().get_value_or ("") == "es") {
242 checked_set (_language, 2);
243 } else if (config->language().get_value_or ("") == "sv") {
244 checked_set (_language, 6);
245 } else if (config->language().get_value_or ("") == "de") {
246 checked_set (_language, 0);
247 } else if (config->language().get_value_or ("") == "nl") {
248 checked_set (_language, 5);
249 } else if (config->language().get_value_or ("") == "ru") {
250 checked_set (_language, 7);
251 } else if (config->language().get_value_or ("") == "pl") {
252 checked_set (_language, 8);
253 } else if (config->language().get_value_or ("") == "da") {
254 checked_set (_language, 9);
255 } else if (config->language().get_value_or ("") == "pt") {
256 checked_set (_language, 10);
257 } else if (config->language().get_value_or ("") == "sk") {
258 checked_set (_language, 11);
259 } else if (config->language().get_value_or ("") == "cs") {
260 checked_set (_language, 12);
262 _language->SetSelection (1);
265 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
266 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
267 checked_set (_check_for_updates, config->check_for_updates ());
268 checked_set (_check_for_test_updates, config->check_for_test_updates ());
269 checked_set (_issuer, config->dcp_issuer ());
270 checked_set (_creator, config->dcp_creator ());
272 setup_sensitivity ();
275 void setup_sensitivity ()
277 _language->Enable (_set_language->GetValue ());
278 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
281 void set_language_changed ()
283 setup_sensitivity ();
284 if (_set_language->GetValue ()) {
287 Config::instance()->unset_language ();
291 void language_changed ()
293 switch (_language->GetSelection ()) {
295 Config::instance()->set_language ("de");
298 Config::instance()->set_language ("en");
301 Config::instance()->set_language ("es");
304 Config::instance()->set_language ("fr");
307 Config::instance()->set_language ("it");
310 Config::instance()->set_language ("nl");
313 Config::instance()->set_language ("sv");
316 Config::instance()->set_language ("ru");
319 Config::instance()->set_language ("pl");
322 Config::instance()->set_language ("da");
325 Config::instance()->set_language ("pt");
328 Config::instance()->set_language ("sk");
331 Config::instance()->set_language ("cs");
336 void automatic_audio_analysis_changed ()
338 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
341 void check_for_updates_changed ()
343 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
346 void check_for_test_updates_changed ()
348 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
351 void num_local_encoding_threads_changed ()
353 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
356 void issuer_changed ()
358 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
361 void creator_changed ()
363 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
366 wxCheckBox* _set_language;
368 wxSpinCtrl* _num_local_encoding_threads;
369 wxCheckBox* _automatic_audio_analysis;
370 wxCheckBox* _check_for_updates;
371 wxCheckBox* _check_for_test_updates;
373 wxTextCtrl* _creator;
376 class DefaultsPage : public StandardPage
379 DefaultsPage (wxSize panel_size, int border)
380 : StandardPage (panel_size, border)
383 wxString GetName () const
385 return _("Defaults");
389 wxBitmap GetLargeIcon () const
391 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
398 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
399 table->AddGrowableCol (1, 1);
400 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
403 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
404 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
405 _still_length = new wxSpinCtrl (_panel);
406 s->Add (_still_length);
407 add_label_to_sizer (s, _panel, _("s"), false);
411 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
412 #ifdef DCPOMATIC_USE_OWN_PICKER
413 _directory = new DirPickerCtrl (_panel);
415 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
417 table->Add (_directory, 1, wxEXPAND);
419 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
420 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
421 table->Add (_isdcf_metadata_button);
423 add_label_to_sizer (table, _panel, _("Default container"), true);
424 _container = new wxChoice (_panel, wxID_ANY);
425 table->Add (_container);
427 add_label_to_sizer (table, _panel, _("Default content type"), true);
428 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
429 table->Add (_dcp_content_type);
432 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
433 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
434 _j2k_bandwidth = new wxSpinCtrl (_panel);
435 s->Add (_j2k_bandwidth);
436 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
441 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
442 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
443 _audio_delay = new wxSpinCtrl (_panel);
444 s->Add (_audio_delay);
445 add_label_to_sizer (s, _panel, _("ms"), false);
449 add_label_to_sizer (table, _panel, _("Default standard"), true);
450 _standard = new wxChoice (_panel, wxID_ANY);
451 table->Add (_standard);
453 _still_length->SetRange (1, 3600);
454 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
456 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
458 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
460 vector<Ratio const *> ratios = Ratio::all ();
461 for (size_t i = 0; i < ratios.size(); ++i) {
462 _container->Append (std_to_wx (ratios[i]->nickname ()));
465 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
467 vector<DCPContentType const *> const ct = DCPContentType::all ();
468 for (size_t i = 0; i < ct.size(); ++i) {
469 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
472 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
474 _j2k_bandwidth->SetRange (50, 250);
475 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
477 _audio_delay->SetRange (-1000, 1000);
478 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
480 _standard->Append (_("SMPTE"));
481 _standard->Append (_("Interop"));
482 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
485 void config_changed ()
487 Config* config = Config::instance ();
489 vector<Ratio const *> ratios = Ratio::all ();
490 for (size_t i = 0; i < ratios.size(); ++i) {
491 if (ratios[i] == config->default_container ()) {
492 _container->SetSelection (i);
496 vector<DCPContentType const *> const ct = DCPContentType::all ();
497 for (size_t i = 0; i < ct.size(); ++i) {
498 if (ct[i] == config->default_dcp_content_type ()) {
499 _dcp_content_type->SetSelection (i);
503 checked_set (_still_length, config->default_still_length ());
504 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
505 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
506 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
507 checked_set (_audio_delay, config->default_audio_delay ());
508 checked_set (_standard, config->default_interop() ? 1 : 0);
511 void j2k_bandwidth_changed ()
513 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
516 void audio_delay_changed ()
518 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
521 void directory_changed ()
523 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
526 void edit_isdcf_metadata_clicked ()
528 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
530 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
534 void still_length_changed ()
536 Config::instance()->set_default_still_length (_still_length->GetValue ());
539 void container_changed ()
541 vector<Ratio const *> ratio = Ratio::all ();
542 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
545 void dcp_content_type_changed ()
547 vector<DCPContentType const *> ct = DCPContentType::all ();
548 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
551 void standard_changed ()
553 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
556 wxSpinCtrl* _j2k_bandwidth;
557 wxSpinCtrl* _audio_delay;
558 wxButton* _isdcf_metadata_button;
559 wxSpinCtrl* _still_length;
560 #ifdef DCPOMATIC_USE_OWN_PICKER
561 DirPickerCtrl* _directory;
563 wxDirPickerCtrl* _directory;
565 wxChoice* _container;
566 wxChoice* _dcp_content_type;
570 class EncodingServersPage : public StandardPage
573 EncodingServersPage (wxSize panel_size, int border)
574 : StandardPage (panel_size, border)
577 wxString GetName () const
583 wxBitmap GetLargeIcon () const
585 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
592 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
593 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
595 vector<string> columns;
596 columns.push_back (wx_to_std (_("IP address / host name")));
597 _servers_list = new EditableList<string, ServerDialog> (
600 boost::bind (&Config::servers, Config::instance()),
601 boost::bind (&Config::set_servers, Config::instance(), _1),
602 boost::bind (&EncodingServersPage::server_column, this, _1)
605 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
607 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
610 void config_changed ()
612 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
613 _servers_list->refresh ();
616 void use_any_servers_changed ()
618 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
621 string server_column (string s)
626 wxCheckBox* _use_any_servers;
627 EditableList<string, ServerDialog>* _servers_list;
630 class CertificateChainEditor : public wxPanel
633 CertificateChainEditor (
637 function<void (shared_ptr<dcp::CertificateChain>)> set,
638 function<shared_ptr<const dcp::CertificateChain> (void)> get
644 wxFont subheading_font (*wxNORMAL_FONT);
645 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
647 _sizer = new wxBoxSizer (wxVERTICAL);
650 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
651 m->SetFont (subheading_font);
652 _sizer->Add (m, 0, wxALL, border);
655 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
656 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
658 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
663 ip.SetText (_("Type"));
665 _certificates->InsertColumn (0, ip);
671 ip.SetText (_("Thumbprint"));
674 wxFont font = ip.GetFont ();
675 font.SetFamily (wxFONTFAMILY_TELETYPE);
678 _certificates->InsertColumn (1, ip);
681 certificates_sizer->Add (_certificates, 1, wxEXPAND);
684 wxSizer* s = new wxBoxSizer (wxVERTICAL);
685 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
686 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
687 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
688 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
689 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
690 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
691 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
694 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
695 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
698 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
699 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
700 wxFont font = _private_key->GetFont ();
701 font.SetFamily (wxFONTFAMILY_TELETYPE);
702 _private_key->SetFont (font);
703 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
704 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
705 table->Add (_load_private_key, wxGBPosition (r, 2));
706 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
707 table->Add (_export_private_key, wxGBPosition (r, 3));
710 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
711 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
712 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
713 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
716 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
717 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
718 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
719 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
720 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
721 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
722 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
723 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
725 SetSizerAndFit (_sizer);
728 void config_changed ()
730 _chain.reset (new dcp::CertificateChain (*_get().get ()));
732 update_certificate_list ();
733 update_private_key ();
734 update_sensitivity ();
737 void add_button (wxWindow* button)
739 _button_sizer->Add (button);
744 void add_certificate ()
746 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
748 if (d->ShowModal() == wxID_OK) {
750 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
753 update_certificate_list ();
754 } catch (dcp::MiscError& e) {
755 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
761 update_sensitivity ();
764 void remove_certificate ()
766 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
771 _certificates->DeleteItem (i);
775 update_sensitivity ();
778 void export_certificate ()
780 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
785 wxFileDialog* d = new wxFileDialog (
786 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
787 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
790 dcp::CertificateChain::List all = _chain->root_to_leaf ();
791 dcp::CertificateChain::List::iterator j = all.begin ();
792 for (int k = 0; k < i; ++k) {
796 if (d->ShowModal () == wxID_OK) {
797 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
799 throw OpenFileError (wx_to_std (d->GetPath ()));
802 string const s = j->certificate (true);
803 fwrite (s.c_str(), 1, s.length(), f);
809 void update_certificate_list ()
811 _certificates->DeleteAllItems ();
813 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
814 BOOST_FOREACH (dcp::Certificate const & i, certs) {
817 _certificates->InsertItem (item);
818 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
821 _certificates->SetItem (n, 0, _("Root"));
822 } else if (n == (certs.size() - 1)) {
823 _certificates->SetItem (n, 0, _("Leaf"));
825 _certificates->SetItem (n, 0, _("Intermediate"));
832 void remake_certificates ()
834 shared_ptr<const dcp::CertificateChain> chain = _get ();
836 string subject_organization_name;
837 string subject_organizational_unit_name;
838 string root_common_name;
839 string intermediate_common_name;
840 string leaf_common_name;
842 dcp::CertificateChain::List all = chain->root_to_leaf ();
844 if (all.size() >= 1) {
846 subject_organization_name = chain->root().subject_organization_name ();
847 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
848 root_common_name = chain->root().subject_common_name ();
851 if (all.size() >= 2) {
853 leaf_common_name = chain->leaf().subject_common_name ();
856 if (all.size() >= 3) {
857 /* Have an intermediate */
858 dcp::CertificateChain::List::iterator i = all.begin ();
860 intermediate_common_name = i->subject_common_name ();
863 MakeChainDialog* d = new MakeChainDialog (
865 subject_organization_name,
866 subject_organizational_unit_name,
868 intermediate_common_name,
872 if (d->ShowModal () == wxID_OK) {
874 new dcp::CertificateChain (
877 d->organisational_unit (),
878 d->root_common_name (),
879 d->intermediate_common_name (),
880 d->leaf_common_name ()
885 update_certificate_list ();
886 update_private_key ();
892 void update_sensitivity ()
894 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
895 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
898 void update_private_key ()
900 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
904 void load_private_key ()
906 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
908 if (d->ShowModal() == wxID_OK) {
910 boost::filesystem::path p (wx_to_std (d->GetPath ()));
911 if (boost::filesystem::file_size (p) > 1024) {
912 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
916 _chain->set_key (dcp::file_to_string (p));
918 update_private_key ();
919 } catch (dcp::MiscError& e) {
920 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
926 update_sensitivity ();
929 void export_private_key ()
931 optional<string> key = _chain->key ();
936 wxFileDialog* d = new wxFileDialog (
937 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
938 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
941 if (d->ShowModal () == wxID_OK) {
942 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
944 throw OpenFileError (wx_to_std (d->GetPath ()));
947 string const s = _chain->key().get ();
948 fwrite (s.c_str(), 1, s.length(), f);
954 wxListCtrl* _certificates;
955 wxButton* _add_certificate;
956 wxButton* _export_certificate;
957 wxButton* _remove_certificate;
958 wxButton* _remake_certificates;
959 wxStaticText* _private_key;
960 wxButton* _load_private_key;
961 wxButton* _export_private_key;
963 wxBoxSizer* _button_sizer;
964 shared_ptr<dcp::CertificateChain> _chain;
965 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
966 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
969 class KeysPage : public StandardPage
972 KeysPage (wxSize panel_size, int border)
973 : StandardPage (panel_size, border)
976 wxString GetName () const
982 wxBitmap GetLargeIcon () const
984 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
992 _signer = new CertificateChainEditor (
993 _panel, _("Signing DCPs and KDMs"), _border,
994 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
995 boost::bind (&Config::signer_chain, Config::instance ())
998 _panel->GetSizer()->Add (_signer);
1000 _decryption = new CertificateChainEditor (
1001 _panel, _("Decrypting DCPs"), _border,
1002 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
1003 boost::bind (&Config::decryption_chain, Config::instance ())
1006 _panel->GetSizer()->Add (_decryption);
1008 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
1009 _decryption->add_button (_export_decryption_certificate);
1011 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1014 void export_decryption_certificate ()
1016 wxFileDialog* d = new wxFileDialog (
1017 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1018 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1021 if (d->ShowModal () == wxID_OK) {
1022 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1024 throw OpenFileError (wx_to_std (d->GetPath ()));
1027 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1028 fwrite (s.c_str(), 1, s.length(), f);
1034 void config_changed ()
1036 _signer->config_changed ();
1037 _decryption->config_changed ();
1040 CertificateChainEditor* _signer;
1041 CertificateChainEditor* _decryption;
1042 wxButton* _export_decryption_certificate;
1045 class TMSPage : public StandardPage
1048 TMSPage (wxSize panel_size, int border)
1049 : StandardPage (panel_size, border)
1052 wxString GetName () const
1057 #ifdef DCPOMATIC_OSX
1058 wxBitmap GetLargeIcon () const
1060 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1067 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1068 table->AddGrowableCol (1, 1);
1069 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1071 add_label_to_sizer (table, _panel, _("Protocol"), true);
1072 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1073 table->Add (_tms_protocol, 1, wxEXPAND);
1075 add_label_to_sizer (table, _panel, _("IP address"), true);
1076 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1077 table->Add (_tms_ip, 1, wxEXPAND);
1079 add_label_to_sizer (table, _panel, _("Target path"), true);
1080 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1081 table->Add (_tms_path, 1, wxEXPAND);
1083 add_label_to_sizer (table, _panel, _("User name"), true);
1084 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1085 table->Add (_tms_user, 1, wxEXPAND);
1087 add_label_to_sizer (table, _panel, _("Password"), true);
1088 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1089 table->Add (_tms_password, 1, wxEXPAND);
1091 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1092 _tms_protocol->Append (_("FTP (for Dolby)"));
1094 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1095 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1096 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1097 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1098 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1101 void config_changed ()
1103 Config* config = Config::instance ();
1105 checked_set (_tms_protocol, config->tms_protocol ());
1106 checked_set (_tms_ip, config->tms_ip ());
1107 checked_set (_tms_path, config->tms_path ());
1108 checked_set (_tms_user, config->tms_user ());
1109 checked_set (_tms_password, config->tms_password ());
1112 void tms_protocol_changed ()
1114 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1117 void tms_ip_changed ()
1119 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1122 void tms_path_changed ()
1124 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1127 void tms_user_changed ()
1129 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1132 void tms_password_changed ()
1134 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1137 wxChoice* _tms_protocol;
1138 wxTextCtrl* _tms_ip;
1139 wxTextCtrl* _tms_path;
1140 wxTextCtrl* _tms_user;
1141 wxTextCtrl* _tms_password;
1150 class KDMEmailPage : public StandardPage
1154 KDMEmailPage (wxSize panel_size, int border)
1155 #ifdef DCPOMATIC_OSX
1156 /* We have to force both width and height of this one */
1157 : StandardPage (wxSize (480, 128), border)
1159 : StandardPage (panel_size, border)
1163 wxString GetName () const
1165 return _("KDM Email");
1168 #ifdef DCPOMATIC_OSX
1169 wxBitmap GetLargeIcon () const
1171 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1178 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1179 table->AddGrowableCol (1, 1);
1180 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1182 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1184 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1185 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1186 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1187 add_label_to_sizer (s, _panel, _("port"), false);
1188 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1189 _mail_port->SetRange (0, 65535);
1190 s->Add (_mail_port);
1191 table->Add (s, 1, wxEXPAND | wxALL);
1194 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1195 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1196 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1198 add_label_to_sizer (table, _panel, _("Mail password"), true);
1199 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1200 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1202 add_label_to_sizer (table, _panel, _("Subject"), true);
1203 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1204 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1206 add_label_to_sizer (table, _panel, _("From address"), true);
1207 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1208 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1210 vector<string> columns;
1211 columns.push_back (wx_to_std (_("Address")));
1212 add_label_to_sizer (table, _panel, _("CC addresses"), true);
1213 _kdm_cc = new EditableList<string, EmailDialog> (
1214 _panel, columns, bind (&Config::kdm_cc, Config::instance()), bind (&Config::set_kdm_cc, Config::instance(), _1), bind (&column, _1)
1216 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1218 add_label_to_sizer (table, _panel, _("BCC address"), true);
1219 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1220 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1222 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1223 _panel->GetSizer()->Add (_kdm_email, 0, wxEXPAND | wxALL, _border);
1225 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1226 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1228 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1229 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1230 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1231 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1232 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1233 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1234 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1235 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1236 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1239 void config_changed ()
1241 Config* config = Config::instance ();
1243 checked_set (_mail_server, config->mail_server ());
1244 checked_set (_mail_port, config->mail_port ());
1245 checked_set (_mail_user, config->mail_user ());
1246 checked_set (_mail_password, config->mail_password ());
1247 checked_set (_kdm_subject, config->kdm_subject ());
1248 checked_set (_kdm_from, config->kdm_from ());
1249 checked_set (_kdm_bcc, config->kdm_bcc ());
1250 checked_set (_kdm_email, Config::instance()->kdm_email ());
1253 void mail_server_changed ()
1255 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1258 void mail_port_changed ()
1260 Config::instance()->set_mail_port (_mail_port->GetValue ());
1263 void mail_user_changed ()
1265 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1268 void mail_password_changed ()
1270 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1273 void kdm_subject_changed ()
1275 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1278 void kdm_from_changed ()
1280 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1283 void kdm_bcc_changed ()
1285 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1288 void kdm_email_changed ()
1290 if (_kdm_email->GetValue().IsEmpty ()) {
1291 /* Sometimes we get sent an erroneous notification that the email
1292 is empty; I don't know why.
1296 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1299 void reset_kdm_email ()
1301 Config::instance()->reset_kdm_email ();
1302 checked_set (_kdm_email, Config::instance()->kdm_email ());
1305 wxTextCtrl* _mail_server;
1306 wxSpinCtrl* _mail_port;
1307 wxTextCtrl* _mail_user;
1308 wxTextCtrl* _mail_password;
1309 wxTextCtrl* _kdm_subject;
1310 wxTextCtrl* _kdm_from;
1311 EditableList<string, EmailDialog>* _kdm_cc;
1312 wxTextCtrl* _kdm_bcc;
1313 wxTextCtrl* _kdm_email;
1314 wxButton* _reset_kdm_email;
1317 /** @class AdvancedPage
1318 * @brief Advanced page of the preferences dialog.
1320 class AdvancedPage : public StockPage
1323 AdvancedPage (wxSize panel_size, int border)
1324 : StockPage (Kind_Advanced, panel_size, border)
1325 , _maximum_j2k_bandwidth (0)
1326 , _allow_any_dcp_frame_rate (0)
1327 , _only_servers_encode (0)
1332 , _log_debug_decode (0)
1333 , _log_debug_encode (0)
1334 , _log_debug_email (0)
1340 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1341 table->AddGrowableCol (1, 1);
1342 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1345 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1346 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1347 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1348 s->Add (_maximum_j2k_bandwidth, 1);
1349 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1353 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1354 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1355 table->AddSpacer (0);
1357 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1358 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1359 table->AddSpacer (0);
1362 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1363 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1365 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1366 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1370 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1371 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1372 t->Add (_log_general, 1, wxEXPAND | wxALL);
1373 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1374 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1375 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1376 t->Add (_log_error, 1, wxEXPAND | wxALL);
1377 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1378 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1379 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1380 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1381 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1382 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1383 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1384 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1385 table->Add (t, 0, wxALL, 6);
1388 #ifdef DCPOMATIC_WINDOWS
1389 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1390 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1391 table->AddSpacer (0);
1394 _maximum_j2k_bandwidth->SetRange (1, 1000);
1395 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1396 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1397 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1398 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1399 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1400 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1401 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1402 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1403 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1404 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1405 #ifdef DCPOMATIC_WINDOWS
1406 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1410 void config_changed ()
1412 Config* config = Config::instance ();
1414 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1415 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1416 checked_set (_only_servers_encode, config->only_servers_encode ());
1417 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1418 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1419 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1420 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1421 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1422 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1423 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1424 #ifdef DCPOMATIC_WINDOWS
1425 checked_set (_win32_console, config->win32_console());
1429 void maximum_j2k_bandwidth_changed ()
1431 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1434 void allow_any_dcp_frame_rate_changed ()
1436 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1439 void only_servers_encode_changed ()
1441 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1447 if (_log_general->GetValue ()) {
1448 types |= LogEntry::TYPE_GENERAL;
1450 if (_log_warning->GetValue ()) {
1451 types |= LogEntry::TYPE_WARNING;
1453 if (_log_error->GetValue ()) {
1454 types |= LogEntry::TYPE_ERROR;
1456 if (_log_timing->GetValue ()) {
1457 types |= LogEntry::TYPE_TIMING;
1459 if (_log_debug_decode->GetValue ()) {
1460 types |= LogEntry::TYPE_DEBUG_DECODE;
1462 if (_log_debug_encode->GetValue ()) {
1463 types |= LogEntry::TYPE_DEBUG_ENCODE;
1465 if (_log_debug_email->GetValue ()) {
1466 types |= LogEntry::TYPE_DEBUG_EMAIL;
1468 Config::instance()->set_log_types (types);
1471 #ifdef DCPOMATIC_WINDOWS
1472 void win32_console_changed ()
1474 Config::instance()->set_win32_console (_win32_console->GetValue ());
1478 wxSpinCtrl* _maximum_j2k_bandwidth;
1479 wxCheckBox* _allow_any_dcp_frame_rate;
1480 wxCheckBox* _only_servers_encode;
1481 wxCheckBox* _log_general;
1482 wxCheckBox* _log_warning;
1483 wxCheckBox* _log_error;
1484 wxCheckBox* _log_timing;
1485 wxCheckBox* _log_debug_decode;
1486 wxCheckBox* _log_debug_encode;
1487 wxCheckBox* _log_debug_email;
1488 #ifdef DCPOMATIC_WINDOWS
1489 wxCheckBox* _win32_console;
1493 wxPreferencesEditor*
1494 create_config_dialog ()
1496 wxPreferencesEditor* e = new wxPreferencesEditor ();
1498 #ifdef DCPOMATIC_OSX
1499 /* Width that we force some of the config panels to be on OSX so that
1500 the containing window doesn't shrink too much when we select those panels.
1501 This is obviously an unpleasant hack.
1503 wxSize ps = wxSize (520, -1);
1504 int const border = 16;
1506 wxSize ps = wxSize (-1, -1);
1507 int const border = 8;
1510 e->AddPage (new GeneralPage (ps, border));
1511 e->AddPage (new DefaultsPage (ps, border));
1512 e->AddPage (new EncodingServersPage (ps, border));
1513 e->AddPage (new KeysPage (ps, border));
1514 e->AddPage (new TMSPage (ps, border));
1515 e->AddPage (new KDMEmailPage (ps, border));
1516 e->AddPage (new AdvancedPage (ps, border));