X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Fwx%2Fconfig_dialog.cc;h=e0effec53eafb90a25d2ff2e966f9d92f90406d7;hp=14948afe8d13e65fd5ee739a484fb991e68d5efb;hb=01e979c79f7d0aa20fac1bb24c699e0636168294;hpb=30c9ecad729397574754163d13253c54a2285a6a diff --git a/src/wx/config_dialog.cc b/src/wx/config_dialog.cc index 14948afe8..e0effec53 100644 --- a/src/wx/config_dialog.cc +++ b/src/wx/config_dialog.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2019 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -23,6 +23,8 @@ #include "check_box.h" #include "nag_dialog.h" #include "dcpomatic_button.h" +#include "audio_mapping_view.h" +#include #include using std::string; @@ -30,10 +32,14 @@ using std::vector; using std::pair; using std::make_pair; using std::map; +using std::make_shared; using boost::bind; using boost::optional; -using boost::shared_ptr; -using boost::function; +using std::shared_ptr; +using std::function; +#if BOOST_VERSION >= 106100 +using namespace boost::placeholders; +#endif static bool @@ -51,11 +57,19 @@ Page::Page (wxSize panel_size, int border) _config_connection = Config::instance()->Changed.connect (bind (&Page::config_changed_wrapper, this)); } + +wxWindow* +Page::CreateWindow (wxWindow* parent) +{ + return create_window (parent); +} + + wxWindow* Page::create_window (wxWindow* parent) { _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size); - wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); + auto s = new wxBoxSizer (wxVERTICAL); _panel->SetSizer (s); setup (); @@ -82,66 +96,49 @@ Page::window_destroyed () } -StockPage::StockPage (Kind kind, wxSize panel_size, int border) - : wxStockPreferencesPage (kind) - , Page (panel_size, border) -{ - -} - -wxWindow* -StockPage::CreateWindow (wxWindow* parent) -{ - return create_window (parent); -} - -StandardPage::StandardPage (wxSize panel_size, int border) +GeneralPage::GeneralPage (wxSize panel_size, int border) : Page (panel_size, border) { } -wxWindow* -StandardPage::CreateWindow (wxWindow* parent) -{ - return create_window (parent); -} -GeneralPage::GeneralPage (wxSize panel_size, int border) - : StockPage (Kind_General, panel_size, border) +wxString +GeneralPage::GetName () const { - + return _("General"); } + void GeneralPage::add_language_controls (wxGridBagSizer* table, int& r) { _set_language = new CheckBox (_panel, _("Set language")); table->Add (_set_language, wxGBPosition (r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL); _language = new wxChoice (_panel, wxID_ANY); - vector > languages; - languages.push_back (make_pair ("Čeština", "cs_CZ")); - languages.push_back (make_pair ("汉语/漢語", "zh_CN")); - languages.push_back (make_pair ("Dansk", "da_DK")); - languages.push_back (make_pair ("Deutsch", "de_DE")); - languages.push_back (make_pair ("English", "en_GB")); - languages.push_back (make_pair ("Español", "es_ES")); - languages.push_back (make_pair ("Français", "fr_FR")); - languages.push_back (make_pair ("Italiano", "it_IT")); - languages.push_back (make_pair ("Nederlands", "nl_NL")); - languages.push_back (make_pair ("Русский", "ru_RU")); - languages.push_back (make_pair ("Polski", "pl_PL")); - languages.push_back (make_pair ("Português europeu", "pt_PT")); - languages.push_back (make_pair ("Português do Brasil", "pt_BR")); - languages.push_back (make_pair ("Svenska", "sv_SE")); - languages.push_back (make_pair ("Slovenský jazyk", "sk_SK")); - languages.push_back (make_pair ("Türkçe", "tr_TR")); - languages.push_back (make_pair ("українська мова", "uk_UA")); + vector> languages; + languages.push_back (make_pair("Čeština", "cs_CZ")); + languages.push_back (make_pair("汉语/漢語", "zh_CN")); + languages.push_back (make_pair("Dansk", "da_DK")); + languages.push_back (make_pair("Deutsch", "de_DE")); + languages.push_back (make_pair("English", "en_GB")); + languages.push_back (make_pair("Español", "es_ES")); + languages.push_back (make_pair("Français", "fr_FR")); + languages.push_back (make_pair("Italiano", "it_IT")); + languages.push_back (make_pair("Nederlands", "nl_NL")); + languages.push_back (make_pair("Русский", "ru_RU")); + languages.push_back (make_pair("Polski", "pl_PL")); + languages.push_back (make_pair("Português europeu", "pt_PT")); + languages.push_back (make_pair("Português do Brasil", "pt_BR")); + languages.push_back (make_pair("Svenska", "sv_SE")); + languages.push_back (make_pair("Slovenský jazyk", "sk_SK")); + languages.push_back (make_pair("Türkçe", "tr_TR")); + languages.push_back (make_pair("українська мова", "uk_UA")); checked_set (_language, languages); table->Add (_language, wxGBPosition (r, 1)); ++r; - wxStaticText* restart = add_label_to_sizer ( + auto restart = add_label_to_sizer ( table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2) ); wxFont font = restart->GetFont(); @@ -172,7 +169,7 @@ GeneralPage::add_update_controls (wxGridBagSizer* table, int& r) void GeneralPage::config_changed () { - Config* config = Config::instance (); + auto config = Config::instance (); checked_set (_set_language, static_cast(config->language())); @@ -193,8 +190,8 @@ GeneralPage::config_changed () compat_map["cs"] = "cs_CZ"; compat_map["uk"] = "uk_UA"; - string lang = config->language().get_value_or ("en_GB"); - if (compat_map.find (lang) != compat_map.end ()) { + auto lang = config->language().get_value_or("en_GB"); + if (compat_map.find(lang) != compat_map.end ()) { lang = compat_map[lang]; } @@ -260,19 +257,10 @@ CertificateChainEditor::CertificateChainEditor ( , _get (get) , _nag_alter (nag_alter) { - wxFont subheading_font (*wxNORMAL_FONT); - subheading_font.SetWeight (wxFONTWEIGHT_BOLD); - _sizer = new wxBoxSizer (wxVERTICAL); - { - wxStaticText* m = new StaticText (this, title); - m->SetFont (subheading_font); - _sizer->Add (m, 0, wxALL, border); - } - - wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL); - _sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border); + auto certificates_sizer = new wxBoxSizer (wxHORIZONTAL); + _sizer->Add (certificates_sizer, 0, wxALL, border); _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (440, 150), wxLC_REPORT | wxLC_SINGLE_SEL); @@ -300,17 +288,19 @@ CertificateChainEditor::CertificateChainEditor ( certificates_sizer->Add (_certificates, 1, wxEXPAND); { - wxSizer* s = new wxBoxSizer (wxVERTICAL); + auto s = new wxBoxSizer (wxVERTICAL); _add_certificate = new Button (this, _("Add...")); - s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); + s->Add (_add_certificate, 1, wxTOP | wxBOTTOM | wxEXPAND, DCPOMATIC_BUTTON_STACK_GAP); _remove_certificate = new Button (this, _("Remove")); - s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); - _export_certificate = new Button (this, _("Export")); - s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); + s->Add (_remove_certificate, 1, wxTOP | wxBOTTOM | wxEXPAND, DCPOMATIC_BUTTON_STACK_GAP); + _export_certificate = new Button (this, _("Export certificate...")); + s->Add (_export_certificate, 1, wxTOP | wxBOTTOM | wxEXPAND, DCPOMATIC_BUTTON_STACK_GAP); + _export_chain = new Button (this, _("Export chain...")); + s->Add (_export_chain, 1, wxTOP | wxBOTTOM | wxEXPAND, DCPOMATIC_BUTTON_STACK_GAP); certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP); } - wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); + auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); _sizer->Add (table, 1, wxALL | wxEXPAND, border); int r = 0; @@ -329,8 +319,6 @@ CertificateChainEditor::CertificateChainEditor ( _button_sizer = new wxBoxSizer (wxHORIZONTAL); _remake_certificates = new Button (this, _("Re-make certificates and key...")); _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border); - _export_chain = new Button (this, _("Export chain...")); - _button_sizer->Add (_export_chain, 1, wxRIGHT, border); table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 4)); ++r; @@ -351,7 +339,7 @@ CertificateChainEditor::CertificateChainEditor ( _import_private_key->Bind (wxEVT_BUTTON, bind (&CertificateChainEditor::import_private_key, this)); _export_private_key->Bind (wxEVT_BUTTON, bind (&CertificateChainEditor::export_private_key, this)); - wxSizer* buttons = CreateSeparatedButtonSizer (wxCLOSE); + auto buttons = CreateSeparatedButtonSizer (wxCLOSE); if (buttons) { _sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder()); } @@ -373,7 +361,7 @@ CertificateChainEditor::add_button (wxWindow* button) void CertificateChainEditor::add_certificate () { - wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File")); + auto d = new wxFileDialog (this, _("Select Certificate File")); if (d->ShowModal() == wxID_OK) { try { @@ -394,7 +382,7 @@ CertificateChainEditor::add_certificate () "Only the first certificate will be used.") ); } - shared_ptr chain(new dcp::CertificateChain(*_get().get())); + auto chain = make_shared(*_get().get()); chain->add (c); if (!chain->chain_valid ()) { error_dialog ( @@ -431,7 +419,7 @@ CertificateChainEditor::remove_certificate () } _certificates->DeleteItem (i); - shared_ptr chain(new dcp::CertificateChain(*_get().get())); + auto chain = make_shared(*_get().get()); chain->remove (i); _set (chain); @@ -447,20 +435,33 @@ CertificateChainEditor::export_certificate () return; } - wxFileDialog* d = new wxFileDialog ( - this, _("Select Certificate File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"), + auto all = _get()->root_to_leaf(); + + wxString default_name; + if (i == 0) { + default_name = "root.pem"; + } else if (i == static_cast(all.size() - 1)) { + default_name = "leaf.pem"; + } else { + default_name = "intermediate.pem"; + } + + auto d = new wxFileDialog( + this, _("Select Certificate File"), wxEmptyString, default_name, wxT ("PEM files (*.pem)|*.pem"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); - dcp::CertificateChain::List all = _get()->root_to_leaf (); - dcp::CertificateChain::List::iterator j = all.begin (); + auto j = all.begin (); for (int k = 0; k < i; ++k) { ++j; } if (d->ShowModal () == wxID_OK) { boost::filesystem::path path (wx_to_std(d->GetPath())); - FILE* f = fopen_boost (path, "w"); + if (path.extension() != ".pem") { + path += ".pem"; + } + auto f = fopen_boost (path, "w"); if (!f) { throw OpenFileError (path, errno, OpenFileError::WRITE); } @@ -475,19 +476,22 @@ CertificateChainEditor::export_certificate () void CertificateChainEditor::export_chain () { - wxFileDialog* d = new wxFileDialog ( - this, _("Select Chain File"), wxEmptyString, wxEmptyString, wxT("PEM files (*.pem)|*.pem"), + auto d = new wxFileDialog ( + this, _("Select Chain File"), wxEmptyString, wxT("certificate_chain.pem"), wxT("PEM files (*.pem)|*.pem"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if (d->ShowModal () == wxID_OK) { boost::filesystem::path path (wx_to_std(d->GetPath())); - FILE* f = fopen_boost (path, "w"); + if (path.extension() != ".pem") { + path += ".pem"; + } + auto f = fopen_boost (path, "w"); if (!f) { throw OpenFileError (path, errno, OpenFileError::WRITE); } - string const s = _get()->chain(); + auto const s = _get()->chain(); checked_fwrite (s.c_str(), s.length(), f, path); fclose (f); } @@ -500,8 +504,8 @@ CertificateChainEditor::update_certificate_list () { _certificates->DeleteAllItems (); size_t n = 0; - dcp::CertificateChain::List certs = _get()->root_to_leaf (); - BOOST_FOREACH (dcp::Certificate const & i, certs) { + auto certs = _get()->root_to_leaf(); + for (auto const& i: certs) { wxListItem item; item.SetId (n); _certificates->InsertItem (item); @@ -532,7 +536,7 @@ CertificateChainEditor::update_certificate_list () void CertificateChainEditor::remake_certificates () { - shared_ptr chain = _get(); + auto chain = _get(); string subject_organization_name; string subject_organizational_unit_name; @@ -540,7 +544,7 @@ CertificateChainEditor::remake_certificates () string intermediate_common_name; string leaf_common_name; - dcp::CertificateChain::List all = chain->root_to_leaf (); + auto all = chain->root_to_leaf (); if (all.size() >= 1) { /* Have a root */ @@ -566,7 +570,7 @@ CertificateChainEditor::remake_certificates () return; } - MakeChainDialog* d = new MakeChainDialog ( + auto d = new MakeChainDialog ( this, subject_organization_name, subject_organizational_unit_name, @@ -577,15 +581,13 @@ CertificateChainEditor::remake_certificates () if (d->ShowModal () == wxID_OK) { _set ( - shared_ptr ( - new dcp::CertificateChain ( - openssl_path (), - d->organisation (), - d->organisational_unit (), - d->root_common_name (), - d->intermediate_common_name (), - d->leaf_common_name () - ) + make_shared ( + openssl_path (), + d->organisation (), + d->organisational_unit (), + d->root_common_name (), + d->intermediate_common_name (), + d->leaf_common_name () ) ); @@ -600,8 +602,8 @@ void CertificateChainEditor::update_sensitivity () { /* We can only remove the leaf certificate */ - _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) == (_certificates->GetItemCount() - 1)); - _export_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1); + _remove_certificate->Enable (_certificates->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) == (_certificates->GetItemCount() - 1)); + _export_certificate->Enable (_certificates->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1); } void @@ -614,7 +616,7 @@ CertificateChainEditor::update_private_key () void CertificateChainEditor::import_private_key () { - wxFileDialog* d = new wxFileDialog (this, _("Select Key File")); + auto d = new wxFileDialog (this, _("Select Key File")); if (d->ShowModal() == wxID_OK) { try { @@ -627,11 +629,11 @@ CertificateChainEditor::import_private_key () return; } - shared_ptr chain(new dcp::CertificateChain(*_get().get())); + auto chain = make_shared(*_get().get()); chain->set_key (dcp::file_to_string (p)); _set (chain); update_private_key (); - } catch (dcp::MiscError& e) { + } catch (std::exception& e) { error_dialog (this, _("Could not read certificate file."), std_to_wx(e.what())); } } @@ -644,24 +646,27 @@ CertificateChainEditor::import_private_key () void CertificateChainEditor::export_private_key () { - optional key = _get()->key(); + auto key = _get()->key(); if (!key) { return; } - wxFileDialog* d = new wxFileDialog ( - this, _("Select Key File"), wxEmptyString, wxEmptyString, wxT ("PEM files (*.pem)|*.pem"), + auto d = new wxFileDialog ( + this, _("Select Key File"), wxEmptyString, wxT("private_key.pem"), wxT("PEM files (*.pem)|*.pem"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if (d->ShowModal () == wxID_OK) { boost::filesystem::path path (wx_to_std(d->GetPath())); - FILE* f = fopen_boost (path, "w"); + if (path.extension() != ".pem") { + path += ".pem"; + } + auto f = fopen_boost (path, "w"); if (!f) { throw OpenFileError (path, errno, OpenFileError::WRITE); } - string const s = _get()->key().get (); + auto const s = _get()->key().get (); checked_fwrite (s.c_str(), s.length(), f, path); fclose (f); } @@ -680,22 +685,26 @@ KeysPage::setup () wxFont subheading_font (*wxNORMAL_FONT); subheading_font.SetWeight (wxFONTWEIGHT_BOLD); - wxSizer* sizer = _panel->GetSizer(); + auto sizer = _panel->GetSizer(); { - wxStaticText* m = new StaticText (_panel, _("Decrypting KDMs")); + auto m = new StaticText (_panel, _("Decrypting KDMs")); m->SetFont (subheading_font); - sizer->Add (m, 0, wxALL, _border); + sizer->Add (m, 0, wxALL | wxEXPAND, _border); } - wxButton* export_decryption_certificate = new Button (_panel, _("Export KDM decryption certificate...")); - sizer->Add (export_decryption_certificate, 0, wxLEFT, _border); - wxButton* export_settings = new Button (_panel, _("Export all KDM decryption settings...")); - sizer->Add (export_settings, 0, wxLEFT, _border); - wxButton* import_settings = new Button (_panel, _("Import all KDM decryption settings...")); - sizer->Add (import_settings, 0, wxLEFT, _border); - wxButton* decryption_advanced = new Button (_panel, _("Advanced...")); - sizer->Add (decryption_advanced, 0, wxALL, _border); + auto buttons = new wxBoxSizer (wxVERTICAL); + + auto export_decryption_certificate = new Button (_panel, _("Export KDM decryption leaf certificate...")); + buttons->Add (export_decryption_certificate, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); + auto export_settings = new Button (_panel, _("Export all KDM decryption settings...")); + buttons->Add (export_settings, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); + auto import_settings = new Button (_panel, _("Import all KDM decryption settings...")); + buttons->Add (import_settings, 0, wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); + auto decryption_advanced = new Button (_panel, _("Advanced...")); + buttons->Add (decryption_advanced, 0); + + sizer->Add (buttons, 0, wxLEFT, _border); export_decryption_certificate->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_certificate, this)); export_settings->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_chain_and_key, this)); @@ -703,24 +712,24 @@ KeysPage::setup () decryption_advanced->Bind (wxEVT_BUTTON, bind (&KeysPage::decryption_advanced, this)); { - wxStaticText* m = new StaticText (_panel, _("Signing DCPs and KDMs")); + auto m = new StaticText (_panel, _("Signing DCPs and KDMs")); m->SetFont (subheading_font); - sizer->Add (m, 0, wxALL, _border); + sizer->Add (m, 0, wxALL | wxEXPAND, _border); } - wxButton* signing_advanced = new Button (_panel, _("Advanced...")); - sizer->Add (signing_advanced, 0, wxLEFT, _border); + auto signing_advanced = new Button (_panel, _("Advanced...")); + sizer->Add (signing_advanced, 0, wxLEFT | wxBOTTOM, _border); signing_advanced->Bind (wxEVT_BUTTON, bind (&KeysPage::signing_advanced, this)); } void KeysPage::decryption_advanced () { - CertificateChainEditor* c = new CertificateChainEditor ( + auto c = new CertificateChainEditor ( _panel, _("Decrypting KDMs"), _border, - bind (&Config::set_decryption_chain, Config::instance (), _1), - bind (&Config::decryption_chain, Config::instance ()), - bind (&KeysPage::nag_alter_decryption_chain, this) + bind(&Config::set_decryption_chain, Config::instance(), _1), + bind(&Config::decryption_chain, Config::instance()), + bind(&KeysPage::nag_alter_decryption_chain, this) ); c->ShowModal(); @@ -729,11 +738,11 @@ KeysPage::decryption_advanced () void KeysPage::signing_advanced () { - CertificateChainEditor* c = new CertificateChainEditor ( + auto c = new CertificateChainEditor ( _panel, _("Signing DCPs and KDMs"), _border, - bind (&Config::set_signer_chain, Config::instance (), _1), - bind (&Config::signer_chain, Config::instance ()), - bind (&do_nothing) + bind(&Config::set_signer_chain, Config::instance(), _1), + bind(&Config::signer_chain, Config::instance()), + bind(&do_nothing) ); c->ShowModal(); @@ -742,19 +751,19 @@ KeysPage::signing_advanced () void KeysPage::export_decryption_chain_and_key () { - wxFileDialog* d = new wxFileDialog ( + auto d = new wxFileDialog ( _panel, _("Select Export File"), wxEmptyString, wxEmptyString, wxT ("DOM files (*.dom)|*.dom"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if (d->ShowModal () == wxID_OK) { boost::filesystem::path path (wx_to_std(d->GetPath())); - FILE* f = fopen_boost (path, "w"); + auto f = fopen_boost (path, "w"); if (!f) { throw OpenFileError (path, errno, OpenFileError::WRITE); } - string const chain = Config::instance()->decryption_chain()->chain(); + auto const chain = Config::instance()->decryption_chain()->chain(); checked_fwrite (chain.c_str(), chain.length(), f, path); optional const key = Config::instance()->decryption_chain()->key(); DCPOMATIC_ASSERT (key); @@ -777,12 +786,12 @@ KeysPage::import_decryption_chain_and_key () return; } - wxFileDialog* d = new wxFileDialog ( + auto d = new wxFileDialog ( _panel, _("Select File To Import"), wxEmptyString, wxEmptyString, wxT ("DOM files (*.dom)|*.dom") ); if (d->ShowModal () == wxID_OK) { - shared_ptr new_chain(new dcp::CertificateChain()); + auto new_chain = make_shared(); FILE* f = fopen_boost (wx_to_std (d->GetPath ()), "r"); if (!f) { @@ -829,19 +838,32 @@ KeysPage::nag_alter_decryption_chain () void KeysPage::export_decryption_certificate () { - wxFileDialog* d = new wxFileDialog ( - _panel, _("Select Certificate File"), wxEmptyString, _("dcpomatic_kdm_decryption_cert.pem"), wxT ("PEM files (*.pem)|*.pem"), + auto config = Config::instance(); + wxString default_name = "dcpomatic"; + if (!config->dcp_creator().empty()) { + default_name += "_" + std_to_wx(careful_string_filter(config->dcp_creator())); + } + if (!config->dcp_issuer().empty()) { + default_name += "_" + std_to_wx(careful_string_filter(config->dcp_issuer())); + } + default_name += wxT("_kdm_decryption_cert.pem"); + + auto d = new wxFileDialog ( + _panel, _("Select Certificate File"), wxEmptyString, default_name, wxT("PEM files (*.pem)|*.pem"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if (d->ShowModal () == wxID_OK) { boost::filesystem::path path (wx_to_std(d->GetPath())); - FILE* f = fopen_boost (path, "w"); + if (path.extension() != ".pem") { + path += ".pem"; + } + auto f = fopen_boost (path, "w"); if (!f) { throw OpenFileError (path, errno, OpenFileError::WRITE); } - string const s = Config::instance()->decryption_chain()->leaf().certificate (true); + auto const s = Config::instance()->decryption_chain()->leaf().certificate (true); checked_fwrite (s.c_str(), s.length(), f, path); fclose (f); } @@ -858,7 +880,7 @@ SoundPage::GetName () const void SoundPage::setup () { - wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); + auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border); int r = 0; @@ -873,6 +895,16 @@ SoundPage::setup () table->Add (s, wxGBPosition(r, 1)); ++r; + add_label_to_sizer (table, _panel, _("Mapping"), true, wxGBPosition(r, 0)); + _map = new AudioMappingView (_panel, _("DCP"), _("DCP"), _("Output"), _("output")); + _map->SetSize (-1, 600); + table->Add (_map, wxGBPosition(r, 1), wxDefaultSpan, wxEXPAND); + ++r; + + _reset_to_default = new Button (_panel, _("Reset to default")); + table->Add (_reset_to_default, wxGBPosition(r, 1)); + ++r; + wxFont font = _sound_output_details->GetFont(); font.SetStyle (wxFONTSTYLE_ITALIC); font.SetPointSize (font.GetPointSize() - 1); @@ -880,14 +912,32 @@ SoundPage::setup () RtAudio audio (DCPOMATIC_RTAUDIO_API); for (unsigned int i = 0; i < audio.getDeviceCount(); ++i) { - RtAudio::DeviceInfo dev = audio.getDeviceInfo (i); - if (dev.probed && dev.outputChannels > 0) { - _sound_output->Append (std_to_wx (dev.name)); + try { + auto dev = audio.getDeviceInfo (i); + if (dev.probed && dev.outputChannels > 0) { + _sound_output->Append (std_to_wx (dev.name)); + } + } catch (RtAudioError&) { + /* Something went wrong so let's just ignore that device */ } } - _sound->Bind (wxEVT_CHECKBOX, bind (&SoundPage::sound_changed, this)); - _sound_output->Bind (wxEVT_CHOICE, bind (&SoundPage::sound_output_changed, this)); + _sound->Bind (wxEVT_CHECKBOX, bind(&SoundPage::sound_changed, this)); + _sound_output->Bind (wxEVT_CHOICE, bind(&SoundPage::sound_output_changed, this)); + _map->Changed.connect (bind(&SoundPage::map_changed, this, _1)); + _reset_to_default->Bind (wxEVT_BUTTON, bind(&SoundPage::reset_to_default, this)); +} + +void +SoundPage::reset_to_default () +{ + Config::instance()->set_audio_mapping_to_default (); +} + +void +SoundPage::map_changed (AudioMapping m) +{ + Config::instance()->set_audio_mapping (m); } void @@ -900,8 +950,14 @@ void SoundPage::sound_output_changed () { RtAudio audio (DCPOMATIC_RTAUDIO_API); - optional const so = get_sound_output(); - if (!so || *so == audio.getDeviceInfo(audio.getDefaultOutputDevice()).name) { + auto const so = get_sound_output(); + string default_device; + try { + default_device = audio.getDeviceInfo(audio.getDefaultOutputDevice()).name; + } catch (RtAudioError&) { + /* Never mind */ + } + if (!so || *so == default_device) { Config::instance()->unset_sound_output (); } else { Config::instance()->set_sound_output (*so); @@ -911,11 +967,11 @@ SoundPage::sound_output_changed () void SoundPage::config_changed () { - Config* config = Config::instance (); + auto config = Config::instance (); checked_set (_sound, config->sound ()); - optional const current_so = get_sound_output (); + auto const current_so = get_sound_output (); optional configured_so; if (config->sound_output()) { @@ -925,7 +981,7 @@ SoundPage::config_changed () RtAudio audio (DCPOMATIC_RTAUDIO_API); try { configured_so = audio.getDeviceInfo(audio.getDefaultOutputDevice()).name; - } catch (RtAudioError& e) { + } catch (RtAudioError&) { /* Probably no audio devices at all */ } } @@ -958,9 +1014,13 @@ SoundPage::config_changed () int channels = 0; if (configured_so) { for (unsigned int i = 0; i < audio.getDeviceCount(); ++i) { - RtAudio::DeviceInfo info = audio.getDeviceInfo(i); - if (info.name == *configured_so && info.outputChannels > 0) { - channels = info.outputChannels; + try { + auto info = audio.getDeviceInfo(i); + if (info.name == *configured_so && info.outputChannels > 0) { + channels = info.outputChannels; + } + } catch (RtAudioError&) { + /* Never mind */ } } } @@ -969,6 +1029,20 @@ SoundPage::config_changed () wxString::Format(_("%d channels on %s"), channels, apis[audio.getCurrentApi()]) ); + _map->set (Config::instance()->audio_mapping(channels)); + + vector input; + for (int i = 0; i < MAX_DCP_AUDIO_CHANNELS; ++i) { + input.push_back (NamedChannel(short_audio_channel_name(i), i)); + } + _map->set_input_channels (input); + + vector output; + for (int i = 0; i < channels; ++i) { + output.push_back (NamedChannel(dcp::raw_convert(i), i)); + } + _map->set_output_channels (output); + setup_sensitivity (); } @@ -989,3 +1063,86 @@ SoundPage::get_sound_output () return wx_to_std (_sound_output->GetString (sel)); } + + +LocationsPage::LocationsPage (wxSize panel_size, int border) + : Page (panel_size, border) +{ + +} + +wxString +LocationsPage::GetName () const +{ + return _("Locations"); +} + +#ifdef DCPOMATIC_OSX +wxBitmap +LocationsPage::GetLargeIcon () const +{ + return wxBitmap(bitmap_path("locations"), wxBITMAP_TYPE_PNG); +} +#endif + +void +LocationsPage::setup () +{ + int r = 0; + + auto table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); + _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border); + + add_label_to_sizer (table, _panel, _("Content directory"), true, wxGBPosition (r, 0)); + _content_directory = new wxDirPickerCtrl (_panel, wxID_ANY, wxEmptyString, wxDirSelectorPromptStr, wxDefaultPosition, wxSize (300, -1)); + table->Add (_content_directory, wxGBPosition (r, 1)); + ++r; + + add_label_to_sizer (table, _panel, _("Playlist directory"), true, wxGBPosition (r, 0)); + _playlist_directory = new wxDirPickerCtrl (_panel, wxID_ANY, wxEmptyString, wxDirSelectorPromptStr, wxDefaultPosition, wxSize (300, -1)); + table->Add (_playlist_directory, wxGBPosition (r, 1)); + ++r; + + add_label_to_sizer (table, _panel, _("KDM directory"), true, wxGBPosition (r, 0)); + _kdm_directory = new wxDirPickerCtrl (_panel, wxID_ANY, wxEmptyString, wxDirSelectorPromptStr, wxDefaultPosition, wxSize (300, -1)); + table->Add (_kdm_directory, wxGBPosition (r, 1)); + ++r; + + _content_directory->Bind (wxEVT_DIRPICKER_CHANGED, bind(&LocationsPage::content_directory_changed, this)); + _playlist_directory->Bind (wxEVT_DIRPICKER_CHANGED, bind(&LocationsPage::playlist_directory_changed, this)); + _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, bind(&LocationsPage::kdm_directory_changed, this)); +} + +void +LocationsPage::config_changed () +{ + auto config = Config::instance (); + + if (config->player_content_directory()) { + checked_set (_content_directory, *config->player_content_directory()); + } + if (config->player_playlist_directory()) { + checked_set (_playlist_directory, *config->player_playlist_directory()); + } + if (config->player_kdm_directory()) { + checked_set (_kdm_directory, *config->player_kdm_directory()); + } +} + +void +LocationsPage::content_directory_changed () +{ + Config::instance()->set_player_content_directory(wx_to_std(_content_directory->GetPath())); +} + +void +LocationsPage::playlist_directory_changed () +{ + Config::instance()->set_player_playlist_directory(wx_to_std(_playlist_directory->GetPath())); +} + +void +LocationsPage::kdm_directory_changed () +{ + Config::instance()->set_player_kdm_directory(wx_to_std(_kdm_directory->GetPath())); +}