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 table->Add (_language, wxGBPosition (r, 1));
174 wxStaticText* restart = add_label_to_sizer (
175 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
177 wxFont font = restart->GetFont();
178 font.SetStyle (wxFONTSTYLE_ITALIC);
179 font.SetPointSize (font.GetPointSize() - 1);
180 restart->SetFont (font);
183 add_label_to_sizer (table, _panel, _("Threads to use for encoding on this host"), true, wxGBPosition (r, 0));
184 _num_local_encoding_threads = new wxSpinCtrl (_panel);
185 table->Add (_num_local_encoding_threads, wxGBPosition (r, 1));
188 _automatic_audio_analysis = new wxCheckBox (_panel, wxID_ANY, _("Automatically analyse content audio"));
189 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
192 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
193 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
196 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
197 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
200 wxFlexGridSizer* bottom_table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
201 bottom_table->AddGrowableCol (1, 1);
203 add_label_to_sizer (bottom_table, _panel, _("Issuer"), true);
204 _issuer = new wxTextCtrl (_panel, wxID_ANY);
205 bottom_table->Add (_issuer, 1, wxALL | wxEXPAND);
207 add_label_to_sizer (bottom_table, _panel, _("Creator"), true);
208 _creator = new wxTextCtrl (_panel, wxID_ANY);
209 bottom_table->Add (_creator, 1, wxALL | wxEXPAND);
211 table->Add (bottom_table, wxGBPosition (r, 0), wxGBSpan (2, 2), wxEXPAND);
214 _set_language->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::set_language_changed, this));
215 _language->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&GeneralPage::language_changed, this));
217 _num_local_encoding_threads->SetRange (1, 128);
218 _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this));
220 _automatic_audio_analysis->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::automatic_audio_analysis_changed, this));
221 _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this));
222 _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
224 _issuer->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::issuer_changed, this));
225 _creator->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::creator_changed, this));
228 void config_changed ()
230 Config* config = Config::instance ();
232 checked_set (_set_language, static_cast<bool>(config->language()));
234 if (config->language().get_value_or ("") == "fr") {
235 checked_set (_language, 3);
236 } else if (config->language().get_value_or ("") == "it") {
237 checked_set (_language, 4);
238 } else if (config->language().get_value_or ("") == "es") {
239 checked_set (_language, 2);
240 } else if (config->language().get_value_or ("") == "sv") {
241 checked_set (_language, 6);
242 } else if (config->language().get_value_or ("") == "de") {
243 checked_set (_language, 0);
244 } else if (config->language().get_value_or ("") == "nl") {
245 checked_set (_language, 5);
246 } else if (config->language().get_value_or ("") == "ru") {
247 checked_set (_language, 7);
248 } else if (config->language().get_value_or ("") == "pl") {
249 checked_set (_language, 8);
250 } else if (config->language().get_value_or ("") == "da") {
251 checked_set (_language, 9);
252 } else if (config->language().get_value_or ("") == "pt") {
253 checked_set (_language, 10);
255 _language->SetSelection (1);
258 checked_set (_num_local_encoding_threads, config->num_local_encoding_threads ());
259 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
260 checked_set (_check_for_updates, config->check_for_updates ());
261 checked_set (_check_for_test_updates, config->check_for_test_updates ());
262 checked_set (_issuer, config->dcp_issuer ());
263 checked_set (_creator, config->dcp_creator ());
265 setup_sensitivity ();
268 void setup_sensitivity ()
270 _language->Enable (_set_language->GetValue ());
271 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
274 void set_language_changed ()
276 setup_sensitivity ();
277 if (_set_language->GetValue ()) {
280 Config::instance()->unset_language ();
284 void language_changed ()
286 switch (_language->GetSelection ()) {
288 Config::instance()->set_language ("de");
291 Config::instance()->set_language ("en");
294 Config::instance()->set_language ("es");
297 Config::instance()->set_language ("fr");
300 Config::instance()->set_language ("it");
303 Config::instance()->set_language ("nl");
306 Config::instance()->set_language ("sv");
309 Config::instance()->set_language ("ru");
312 Config::instance()->set_language ("pl");
315 Config::instance()->set_language ("da");
318 Config::instance()->set_language ("pt");
323 void automatic_audio_analysis_changed ()
325 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
328 void check_for_updates_changed ()
330 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
333 void check_for_test_updates_changed ()
335 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
338 void num_local_encoding_threads_changed ()
340 Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ());
343 void issuer_changed ()
345 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
348 void creator_changed ()
350 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
353 wxCheckBox* _set_language;
355 wxSpinCtrl* _num_local_encoding_threads;
356 wxCheckBox* _automatic_audio_analysis;
357 wxCheckBox* _check_for_updates;
358 wxCheckBox* _check_for_test_updates;
360 wxTextCtrl* _creator;
363 class DefaultsPage : public StandardPage
366 DefaultsPage (wxSize panel_size, int border)
367 : StandardPage (panel_size, border)
370 wxString GetName () const
372 return _("Defaults");
376 wxBitmap GetLargeIcon () const
378 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
385 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
386 table->AddGrowableCol (1, 1);
387 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
390 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
391 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
392 _still_length = new wxSpinCtrl (_panel);
393 s->Add (_still_length);
394 add_label_to_sizer (s, _panel, _("s"), false);
398 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
399 #ifdef DCPOMATIC_USE_OWN_PICKER
400 _directory = new DirPickerCtrl (_panel);
402 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
404 table->Add (_directory, 1, wxEXPAND);
406 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
407 _isdcf_metadata_button = new wxButton (_panel, wxID_ANY, _("Edit..."));
408 table->Add (_isdcf_metadata_button);
410 add_label_to_sizer (table, _panel, _("Default container"), true);
411 _container = new wxChoice (_panel, wxID_ANY);
412 table->Add (_container);
414 add_label_to_sizer (table, _panel, _("Default content type"), true);
415 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
416 table->Add (_dcp_content_type);
419 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
420 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
421 _j2k_bandwidth = new wxSpinCtrl (_panel);
422 s->Add (_j2k_bandwidth);
423 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
428 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
429 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
430 _audio_delay = new wxSpinCtrl (_panel);
431 s->Add (_audio_delay);
432 add_label_to_sizer (s, _panel, _("ms"), false);
436 add_label_to_sizer (table, _panel, _("Default standard"), true);
437 _standard = new wxChoice (_panel, wxID_ANY);
438 table->Add (_standard);
440 _still_length->SetRange (1, 3600);
441 _still_length->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::still_length_changed, this));
443 _directory->Bind (wxEVT_COMMAND_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
445 _isdcf_metadata_button->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
447 vector<Ratio const *> ratios = Ratio::all ();
448 for (size_t i = 0; i < ratios.size(); ++i) {
449 _container->Append (std_to_wx (ratios[i]->nickname ()));
452 _container->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::container_changed, this));
454 vector<DCPContentType const *> const ct = DCPContentType::all ();
455 for (size_t i = 0; i < ct.size(); ++i) {
456 _dcp_content_type->Append (std_to_wx (ct[i]->pretty_name ()));
459 _dcp_content_type->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
461 _j2k_bandwidth->SetRange (50, 250);
462 _j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
464 _audio_delay->SetRange (-1000, 1000);
465 _audio_delay->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&DefaultsPage::audio_delay_changed, this));
467 _standard->Append (_("SMPTE"));
468 _standard->Append (_("Interop"));
469 _standard->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&DefaultsPage::standard_changed, this));
472 void config_changed ()
474 Config* config = Config::instance ();
476 vector<Ratio const *> ratios = Ratio::all ();
477 for (size_t i = 0; i < ratios.size(); ++i) {
478 if (ratios[i] == config->default_container ()) {
479 _container->SetSelection (i);
483 vector<DCPContentType const *> const ct = DCPContentType::all ();
484 for (size_t i = 0; i < ct.size(); ++i) {
485 if (ct[i] == config->default_dcp_content_type ()) {
486 _dcp_content_type->SetSelection (i);
490 checked_set (_still_length, config->default_still_length ());
491 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
492 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
493 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
494 checked_set (_audio_delay, config->default_audio_delay ());
495 checked_set (_standard, config->default_interop() ? 1 : 0);
498 void j2k_bandwidth_changed ()
500 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
503 void audio_delay_changed ()
505 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
508 void directory_changed ()
510 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
513 void edit_isdcf_metadata_clicked ()
515 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
517 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
521 void still_length_changed ()
523 Config::instance()->set_default_still_length (_still_length->GetValue ());
526 void container_changed ()
528 vector<Ratio const *> ratio = Ratio::all ();
529 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
532 void dcp_content_type_changed ()
534 vector<DCPContentType const *> ct = DCPContentType::all ();
535 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
538 void standard_changed ()
540 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
543 wxSpinCtrl* _j2k_bandwidth;
544 wxSpinCtrl* _audio_delay;
545 wxButton* _isdcf_metadata_button;
546 wxSpinCtrl* _still_length;
547 #ifdef DCPOMATIC_USE_OWN_PICKER
548 DirPickerCtrl* _directory;
550 wxDirPickerCtrl* _directory;
552 wxChoice* _container;
553 wxChoice* _dcp_content_type;
557 class EncodingServersPage : public StandardPage
560 EncodingServersPage (wxSize panel_size, int border)
561 : StandardPage (panel_size, border)
564 wxString GetName () const
570 wxBitmap GetLargeIcon () const
572 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
579 _use_any_servers = new wxCheckBox (_panel, wxID_ANY, _("Search network for servers"));
580 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
582 vector<string> columns;
583 columns.push_back (wx_to_std (_("IP address / host name")));
584 _servers_list = new EditableList<string, ServerDialog> (
587 boost::bind (&Config::servers, Config::instance()),
588 boost::bind (&Config::set_servers, Config::instance(), _1),
589 boost::bind (&EncodingServersPage::server_column, this, _1)
592 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
594 _use_any_servers->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
597 void config_changed ()
599 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
600 _servers_list->refresh ();
603 void use_any_servers_changed ()
605 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
608 string server_column (string s)
613 wxCheckBox* _use_any_servers;
614 EditableList<string, ServerDialog>* _servers_list;
617 class CertificateChainEditor : public wxPanel
620 CertificateChainEditor (
624 function<void (shared_ptr<dcp::CertificateChain>)> set,
625 function<shared_ptr<const dcp::CertificateChain> (void)> get
631 wxFont subheading_font (*wxNORMAL_FONT);
632 subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
634 _sizer = new wxBoxSizer (wxVERTICAL);
637 wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
638 m->SetFont (subheading_font);
639 _sizer->Add (m, 0, wxALL, border);
642 wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
643 _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
645 _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL);
650 ip.SetText (_("Type"));
652 _certificates->InsertColumn (0, ip);
658 ip.SetText (_("Thumbprint"));
661 wxFont font = ip.GetFont ();
662 font.SetFamily (wxFONTFAMILY_TELETYPE);
665 _certificates->InsertColumn (1, ip);
668 certificates_sizer->Add (_certificates, 1, wxEXPAND);
671 wxSizer* s = new wxBoxSizer (wxVERTICAL);
672 _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
673 s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
674 _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
675 s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
676 _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
677 s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
678 certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
681 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
682 _sizer->Add (table, 1, wxALL | wxEXPAND, border);
685 add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
686 _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
687 wxFont font = _private_key->GetFont ();
688 font.SetFamily (wxFONTFAMILY_TELETYPE);
689 _private_key->SetFont (font);
690 table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
691 _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
692 table->Add (_load_private_key, wxGBPosition (r, 2));
693 _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
694 table->Add (_export_private_key, wxGBPosition (r, 3));
697 _button_sizer = new wxBoxSizer (wxHORIZONTAL);
698 _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
699 _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
700 table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4));
703 _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::add_certificate, this));
704 _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remove_certificate, this));
705 _export_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_certificate, this));
706 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
707 _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
708 _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::remake_certificates, this));
709 _load_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::load_private_key, this));
710 _export_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&CertificateChainEditor::export_private_key, this));
712 SetSizerAndFit (_sizer);
715 void config_changed ()
717 _chain.reset (new dcp::CertificateChain (*_get().get ()));
719 update_certificate_list ();
720 update_private_key ();
721 update_sensitivity ();
724 void add_button (wxWindow* button)
726 _button_sizer->Add (button);
731 void add_certificate ()
733 wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
735 if (d->ShowModal() == wxID_OK) {
737 dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
740 update_certificate_list ();
741 } catch (dcp::MiscError& e) {
742 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
748 update_sensitivity ();
751 void remove_certificate ()
753 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
758 _certificates->DeleteItem (i);
762 update_sensitivity ();
765 void export_certificate ()
767 int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
772 wxFileDialog* d = new wxFileDialog (
773 this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
774 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
777 dcp::CertificateChain::List all = _chain->root_to_leaf ();
778 dcp::CertificateChain::List::iterator j = all.begin ();
779 for (int k = 0; k < i; ++k) {
783 if (d->ShowModal () == wxID_OK) {
784 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
786 throw OpenFileError (wx_to_std (d->GetPath ()));
789 string const s = j->certificate (true);
790 fwrite (s.c_str(), 1, s.length(), f);
796 void update_certificate_list ()
798 _certificates->DeleteAllItems ();
800 dcp::CertificateChain::List certs = _chain->root_to_leaf ();
801 BOOST_FOREACH (dcp::Certificate const & i, certs) {
804 _certificates->InsertItem (item);
805 _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
808 _certificates->SetItem (n, 0, _("Root"));
809 } else if (n == (certs.size() - 1)) {
810 _certificates->SetItem (n, 0, _("Leaf"));
812 _certificates->SetItem (n, 0, _("Intermediate"));
819 void remake_certificates ()
821 shared_ptr<const dcp::CertificateChain> chain = _get ();
823 string subject_organization_name;
824 string subject_organizational_unit_name;
825 string root_common_name;
826 string intermediate_common_name;
827 string leaf_common_name;
829 dcp::CertificateChain::List all = chain->root_to_leaf ();
831 if (all.size() >= 1) {
833 subject_organization_name = chain->root().subject_organization_name ();
834 subject_organizational_unit_name = chain->root().subject_organizational_unit_name ();
835 root_common_name = chain->root().subject_common_name ();
838 if (all.size() >= 2) {
840 leaf_common_name = chain->leaf().subject_common_name ();
843 if (all.size() >= 3) {
844 /* Have an intermediate */
845 dcp::CertificateChain::List::iterator i = all.begin ();
847 intermediate_common_name = i->subject_common_name ();
850 MakeChainDialog* d = new MakeChainDialog (
852 subject_organization_name,
853 subject_organizational_unit_name,
855 intermediate_common_name,
859 if (d->ShowModal () == wxID_OK) {
861 new dcp::CertificateChain (
864 d->organisational_unit (),
865 d->root_common_name (),
866 d->intermediate_common_name (),
867 d->leaf_common_name ()
872 update_certificate_list ();
873 update_private_key ();
879 void update_sensitivity ()
881 _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
882 _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
885 void update_private_key ()
887 checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
891 void load_private_key ()
893 wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
895 if (d->ShowModal() == wxID_OK) {
897 boost::filesystem::path p (wx_to_std (d->GetPath ()));
898 if (boost::filesystem::file_size (p) > 1024) {
899 error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
903 _chain->set_key (dcp::file_to_string (p));
905 update_private_key ();
906 } catch (dcp::MiscError& e) {
907 error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
913 update_sensitivity ();
916 void export_private_key ()
918 optional<string> key = _chain->key ();
923 wxFileDialog* d = new wxFileDialog (
924 this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
925 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
928 if (d->ShowModal () == wxID_OK) {
929 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
931 throw OpenFileError (wx_to_std (d->GetPath ()));
934 string const s = _chain->key().get ();
935 fwrite (s.c_str(), 1, s.length(), f);
941 wxListCtrl* _certificates;
942 wxButton* _add_certificate;
943 wxButton* _export_certificate;
944 wxButton* _remove_certificate;
945 wxButton* _remake_certificates;
946 wxStaticText* _private_key;
947 wxButton* _load_private_key;
948 wxButton* _export_private_key;
950 wxBoxSizer* _button_sizer;
951 shared_ptr<dcp::CertificateChain> _chain;
952 boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
953 boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
956 class KeysPage : public StandardPage
959 KeysPage (wxSize panel_size, int border)
960 : StandardPage (panel_size, border)
963 wxString GetName () const
969 wxBitmap GetLargeIcon () const
971 return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
979 _signer = new CertificateChainEditor (
980 _panel, _("Signing DCPs and KDMs"), _border,
981 boost::bind (&Config::set_signer_chain, Config::instance (), _1),
982 boost::bind (&Config::signer_chain, Config::instance ())
985 _panel->GetSizer()->Add (_signer);
987 _decryption = new CertificateChainEditor (
988 _panel, _("Decrypting DCPs"), _border,
989 boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
990 boost::bind (&Config::decryption_chain, Config::instance ())
993 _panel->GetSizer()->Add (_decryption);
995 _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
996 _decryption->add_button (_export_decryption_certificate);
998 _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
1001 void export_decryption_certificate ()
1003 wxFileDialog* d = new wxFileDialog (
1004 _panel, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"),
1005 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
1008 if (d->ShowModal () == wxID_OK) {
1009 FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "w");
1011 throw OpenFileError (wx_to_std (d->GetPath ()));
1014 string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
1015 fwrite (s.c_str(), 1, s.length(), f);
1021 void config_changed ()
1023 _signer->config_changed ();
1024 _decryption->config_changed ();
1027 CertificateChainEditor* _signer;
1028 CertificateChainEditor* _decryption;
1029 wxButton* _export_decryption_certificate;
1032 class TMSPage : public StandardPage
1035 TMSPage (wxSize panel_size, int border)
1036 : StandardPage (panel_size, border)
1039 wxString GetName () const
1044 #ifdef DCPOMATIC_OSX
1045 wxBitmap GetLargeIcon () const
1047 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
1054 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1055 table->AddGrowableCol (1, 1);
1056 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1058 add_label_to_sizer (table, _panel, _("Protocol"), true);
1059 _tms_protocol = new wxChoice (_panel, wxID_ANY);
1060 table->Add (_tms_protocol, 1, wxEXPAND);
1062 add_label_to_sizer (table, _panel, _("IP address"), true);
1063 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
1064 table->Add (_tms_ip, 1, wxEXPAND);
1066 add_label_to_sizer (table, _panel, _("Target path"), true);
1067 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
1068 table->Add (_tms_path, 1, wxEXPAND);
1070 add_label_to_sizer (table, _panel, _("User name"), true);
1071 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
1072 table->Add (_tms_user, 1, wxEXPAND);
1074 add_label_to_sizer (table, _panel, _("Password"), true);
1075 _tms_password = new wxTextCtrl (_panel, wxID_ANY);
1076 table->Add (_tms_password, 1, wxEXPAND);
1078 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
1079 _tms_protocol->Append (_("FTP (for Dolby)"));
1081 _tms_protocol->Bind (wxEVT_COMMAND_CHOICE_SELECTED, boost::bind (&TMSPage::tms_protocol_changed, this));
1082 _tms_ip->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_ip_changed, this));
1083 _tms_path->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_path_changed, this));
1084 _tms_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_user_changed, this));
1085 _tms_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&TMSPage::tms_password_changed, this));
1088 void config_changed ()
1090 Config* config = Config::instance ();
1092 checked_set (_tms_protocol, config->tms_protocol ());
1093 checked_set (_tms_ip, config->tms_ip ());
1094 checked_set (_tms_path, config->tms_path ());
1095 checked_set (_tms_user, config->tms_user ());
1096 checked_set (_tms_password, config->tms_password ());
1099 void tms_protocol_changed ()
1101 Config::instance()->set_tms_protocol (static_cast<Protocol> (_tms_protocol->GetSelection ()));
1104 void tms_ip_changed ()
1106 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
1109 void tms_path_changed ()
1111 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
1114 void tms_user_changed ()
1116 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
1119 void tms_password_changed ()
1121 Config::instance()->set_tms_password (wx_to_std (_tms_password->GetValue ()));
1124 wxChoice* _tms_protocol;
1125 wxTextCtrl* _tms_ip;
1126 wxTextCtrl* _tms_path;
1127 wxTextCtrl* _tms_user;
1128 wxTextCtrl* _tms_password;
1131 class KDMEmailPage : public StandardPage
1135 KDMEmailPage (wxSize panel_size, int border)
1136 #ifdef DCPOMATIC_OSX
1137 /* We have to force both width and height of this one */
1138 : StandardPage (wxSize (480, 128), border)
1140 : StandardPage (panel_size, border)
1144 wxString GetName () const
1146 return _("KDM Email");
1149 #ifdef DCPOMATIC_OSX
1150 wxBitmap GetLargeIcon () const
1152 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
1159 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1160 table->AddGrowableCol (1, 1);
1161 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
1163 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
1165 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1166 _mail_server = new wxTextCtrl (_panel, wxID_ANY);
1167 s->Add (_mail_server, 1, wxEXPAND | wxALL);
1168 add_label_to_sizer (s, _panel, _("port"), false);
1169 _mail_port = new wxSpinCtrl (_panel, wxID_ANY);
1170 _mail_port->SetRange (0, 65535);
1171 s->Add (_mail_port);
1172 table->Add (s, 1, wxEXPAND | wxALL);
1175 add_label_to_sizer (table, _panel, _("Mail user name"), true);
1176 _mail_user = new wxTextCtrl (_panel, wxID_ANY);
1177 table->Add (_mail_user, 1, wxEXPAND | wxALL);
1179 add_label_to_sizer (table, _panel, _("Mail password"), true);
1180 _mail_password = new wxTextCtrl (_panel, wxID_ANY);
1181 table->Add (_mail_password, 1, wxEXPAND | wxALL);
1183 add_label_to_sizer (table, _panel, _("Subject"), true);
1184 _kdm_subject = new wxTextCtrl (_panel, wxID_ANY);
1185 table->Add (_kdm_subject, 1, wxEXPAND | wxALL);
1187 add_label_to_sizer (table, _panel, _("From address"), true);
1188 _kdm_from = new wxTextCtrl (_panel, wxID_ANY);
1189 table->Add (_kdm_from, 1, wxEXPAND | wxALL);
1191 add_label_to_sizer (table, _panel, _("CC address"), true);
1192 _kdm_cc = new wxTextCtrl (_panel, wxID_ANY);
1193 table->Add (_kdm_cc, 1, wxEXPAND | wxALL);
1195 add_label_to_sizer (table, _panel, _("BCC address"), true);
1196 _kdm_bcc = new wxTextCtrl (_panel, wxID_ANY);
1197 table->Add (_kdm_bcc, 1, wxEXPAND | wxALL);
1199 _kdm_email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (480, 128), wxTE_MULTILINE);
1200 _panel->GetSizer()->Add (_kdm_email, 1, wxEXPAND | wxALL, _border);
1202 _reset_kdm_email = new wxButton (_panel, wxID_ANY, _("Reset to default subject and text"));
1203 _panel->GetSizer()->Add (_reset_kdm_email, 0, wxEXPAND | wxALL, _border);
1205 _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_server_changed, this));
1206 _mail_port->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&KDMEmailPage::mail_port_changed, this));
1207 _mail_user->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_user_changed, this));
1208 _mail_password->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::mail_password_changed, this));
1209 _kdm_subject->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
1210 _kdm_from->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_from_changed, this));
1211 _kdm_cc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_cc_changed, this));
1212 _kdm_bcc->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
1213 _kdm_email->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&KDMEmailPage::kdm_email_changed, this));
1214 _reset_kdm_email->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KDMEmailPage::reset_kdm_email, this));
1217 void config_changed ()
1219 Config* config = Config::instance ();
1221 checked_set (_mail_server, config->mail_server ());
1222 checked_set (_mail_port, config->mail_port ());
1223 checked_set (_mail_user, config->mail_user ());
1224 checked_set (_mail_password, config->mail_password ());
1225 checked_set (_kdm_subject, config->kdm_subject ());
1226 checked_set (_kdm_from, config->kdm_from ());
1227 checked_set (_kdm_cc, config->kdm_cc ());
1228 checked_set (_kdm_bcc, config->kdm_bcc ());
1229 checked_set (_kdm_email, Config::instance()->kdm_email ());
1232 void mail_server_changed ()
1234 Config::instance()->set_mail_server (wx_to_std (_mail_server->GetValue ()));
1237 void mail_port_changed ()
1239 Config::instance()->set_mail_port (_mail_port->GetValue ());
1242 void mail_user_changed ()
1244 Config::instance()->set_mail_user (wx_to_std (_mail_user->GetValue ()));
1247 void mail_password_changed ()
1249 Config::instance()->set_mail_password (wx_to_std (_mail_password->GetValue ()));
1252 void kdm_subject_changed ()
1254 Config::instance()->set_kdm_subject (wx_to_std (_kdm_subject->GetValue ()));
1257 void kdm_from_changed ()
1259 Config::instance()->set_kdm_from (wx_to_std (_kdm_from->GetValue ()));
1262 void kdm_cc_changed ()
1264 Config::instance()->set_kdm_cc (wx_to_std (_kdm_cc->GetValue ()));
1267 void kdm_bcc_changed ()
1269 Config::instance()->set_kdm_bcc (wx_to_std (_kdm_bcc->GetValue ()));
1272 void kdm_email_changed ()
1274 if (_kdm_email->GetValue().IsEmpty ()) {
1275 /* Sometimes we get sent an erroneous notification that the email
1276 is empty; I don't know why.
1280 Config::instance()->set_kdm_email (wx_to_std (_kdm_email->GetValue ()));
1283 void reset_kdm_email ()
1285 Config::instance()->reset_kdm_email ();
1286 checked_set (_kdm_email, Config::instance()->kdm_email ());
1289 wxTextCtrl* _mail_server;
1290 wxSpinCtrl* _mail_port;
1291 wxTextCtrl* _mail_user;
1292 wxTextCtrl* _mail_password;
1293 wxTextCtrl* _kdm_subject;
1294 wxTextCtrl* _kdm_from;
1295 wxTextCtrl* _kdm_cc;
1296 wxTextCtrl* _kdm_bcc;
1297 wxTextCtrl* _kdm_email;
1298 wxButton* _reset_kdm_email;
1301 /** @class AdvancedPage
1302 * @brief Advanced page of the preferences dialog.
1304 class AdvancedPage : public StockPage
1307 AdvancedPage (wxSize panel_size, int border)
1308 : StockPage (Kind_Advanced, panel_size, border)
1309 , _maximum_j2k_bandwidth (0)
1310 , _allow_any_dcp_frame_rate (0)
1311 , _only_servers_encode (0)
1316 , _log_debug_decode (0)
1317 , _log_debug_encode (0)
1318 , _log_debug_email (0)
1324 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1325 table->AddGrowableCol (1, 1);
1326 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1329 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1330 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1331 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1332 s->Add (_maximum_j2k_bandwidth, 1);
1333 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1337 _allow_any_dcp_frame_rate = new wxCheckBox (_panel, wxID_ANY, _("Allow any DCP frame rate"));
1338 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1339 table->AddSpacer (0);
1341 _only_servers_encode = new wxCheckBox (_panel, wxID_ANY, _("Only servers encode"));
1342 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1343 table->AddSpacer (0);
1346 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log:"));
1347 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL | wxALIGN_RIGHT, 6);
1349 wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Log"));
1350 table->Add (m, 0, wxALIGN_TOP | wxLEFT | wxRIGHT | wxEXPAND | wxALL, 6);
1354 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1355 _log_general = new wxCheckBox (_panel, wxID_ANY, _("General"));
1356 t->Add (_log_general, 1, wxEXPAND | wxALL);
1357 _log_warning = new wxCheckBox (_panel, wxID_ANY, _("Warnings"));
1358 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1359 _log_error = new wxCheckBox (_panel, wxID_ANY, _("Errors"));
1360 t->Add (_log_error, 1, wxEXPAND | wxALL);
1361 _log_timing = new wxCheckBox (_panel, wxID_ANY, S_("Config|Timing"));
1362 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1363 _log_debug_decode = new wxCheckBox (_panel, wxID_ANY, _("Debug: decode"));
1364 t->Add (_log_debug_decode, 1, wxEXPAND | wxALL);
1365 _log_debug_encode = new wxCheckBox (_panel, wxID_ANY, _("Debug: encode"));
1366 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1367 _log_debug_email = new wxCheckBox (_panel, wxID_ANY, _("Debug: email sending"));
1368 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1369 table->Add (t, 0, wxALL, 6);
1372 #ifdef DCPOMATIC_WINDOWS
1373 _win32_console = new wxCheckBox (_panel, wxID_ANY, _("Open console window"));
1374 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1375 table->AddSpacer (0);
1378 _maximum_j2k_bandwidth->SetRange (1, 1000);
1379 _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1380 _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1381 _only_servers_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1382 _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1383 _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1384 _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1385 _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1386 _log_debug_decode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1387 _log_debug_encode->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1388 _log_debug_email->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this));
1389 #ifdef DCPOMATIC_WINDOWS
1390 _win32_console->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::win32_console_changed, this));
1394 void config_changed ()
1396 Config* config = Config::instance ();
1398 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1399 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1400 checked_set (_only_servers_encode, config->only_servers_encode ());
1401 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1402 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1403 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1404 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1405 checked_set (_log_debug_decode, config->log_types() & LogEntry::TYPE_DEBUG_DECODE);
1406 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1407 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1408 #ifdef DCPOMATIC_WINDOWS
1409 checked_set (_win32_console, config->win32_console());
1413 void maximum_j2k_bandwidth_changed ()
1415 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1418 void allow_any_dcp_frame_rate_changed ()
1420 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1423 void only_servers_encode_changed ()
1425 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1431 if (_log_general->GetValue ()) {
1432 types |= LogEntry::TYPE_GENERAL;
1434 if (_log_warning->GetValue ()) {
1435 types |= LogEntry::TYPE_WARNING;
1437 if (_log_error->GetValue ()) {
1438 types |= LogEntry::TYPE_ERROR;
1440 if (_log_timing->GetValue ()) {
1441 types |= LogEntry::TYPE_TIMING;
1443 if (_log_debug_decode->GetValue ()) {
1444 types |= LogEntry::TYPE_DEBUG_DECODE;
1446 if (_log_debug_encode->GetValue ()) {
1447 types |= LogEntry::TYPE_DEBUG_ENCODE;
1449 if (_log_debug_email->GetValue ()) {
1450 types |= LogEntry::TYPE_DEBUG_EMAIL;
1452 Config::instance()->set_log_types (types);
1455 #ifdef DCPOMATIC_WINDOWS
1456 void win32_console_changed ()
1458 Config::instance()->set_win32_console (_win32_console->GetValue ());
1462 wxSpinCtrl* _maximum_j2k_bandwidth;
1463 wxCheckBox* _allow_any_dcp_frame_rate;
1464 wxCheckBox* _only_servers_encode;
1465 wxCheckBox* _log_general;
1466 wxCheckBox* _log_warning;
1467 wxCheckBox* _log_error;
1468 wxCheckBox* _log_timing;
1469 wxCheckBox* _log_debug_decode;
1470 wxCheckBox* _log_debug_encode;
1471 wxCheckBox* _log_debug_email;
1472 #ifdef DCPOMATIC_WINDOWS
1473 wxCheckBox* _win32_console;
1477 wxPreferencesEditor*
1478 create_config_dialog ()
1480 wxPreferencesEditor* e = new wxPreferencesEditor ();
1482 #ifdef DCPOMATIC_OSX
1483 /* Width that we force some of the config panels to be on OSX so that
1484 the containing window doesn't shrink too much when we select those panels.
1485 This is obviously an unpleasant hack.
1487 wxSize ps = wxSize (520, -1);
1488 int const border = 16;
1490 wxSize ps = wxSize (-1, -1);
1491 int const border = 8;
1494 e->AddPage (new GeneralPage (ps, border));
1495 e->AddPage (new DefaultsPage (ps, border));
1496 e->AddPage (new EncodingServersPage (ps, border));
1497 e->AddPage (new KeysPage (ps, border));
1498 e->AddPage (new TMSPage (ps, border));
1499 e->AddPage (new KDMEmailPage (ps, border));
1500 e->AddPage (new AdvancedPage (ps, border));