Restore paint-panel timing.
[dcpomatic.git] / src / wx / config_dialog.cc
index 4195aa128880de01777cb28301ec612256b6d6d3..a6b299bcb6dd6c976baf59bdfda754fdef475d1f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 */
 
 #include "config_dialog.h"
+#include "static_text.h"
+#include "check_box.h"
 #include "nag_dialog.h"
+#include "dcpomatic_button.h"
+#include <iostream>
 
 using std::string;
 using std::vector;
@@ -112,7 +116,7 @@ GeneralPage::GeneralPage (wxSize panel_size, int border)
 void
 GeneralPage::add_language_controls (wxGridBagSizer* table, int& r)
 {
-       _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language"));
+       _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<pair<string, string> > languages;
@@ -131,6 +135,7 @@ GeneralPage::add_language_controls (wxGridBagSizer* table, int& r)
        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));
@@ -152,12 +157,21 @@ GeneralPage::add_language_controls (wxGridBagSizer* table, int& r)
 void
 GeneralPage::add_play_sound_controls (wxGridBagSizer* table, int& r)
 {
-       _sound = new wxCheckBox (_panel, wxID_ANY, _("Play sound via"));
+       _sound = new CheckBox (_panel, _("Play sound via"));
        table->Add (_sound, wxGBPosition (r, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
+       wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
        _sound_output = new wxChoice (_panel, wxID_ANY);
-       table->Add (_sound_output, wxGBPosition (r, 1));
+       s->Add (_sound_output, 0);
+       _sound_output_details = new wxStaticText (_panel, wxID_ANY, wxT(""));
+       s->Add (_sound_output_details, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, DCPOMATIC_SIZER_X_GAP);
+       table->Add (s, wxGBPosition(r, 1));
        ++r;
 
+       wxFont font = _sound_output_details->GetFont();
+       font.SetStyle (wxFONTSTYLE_ITALIC);
+       font.SetPointSize (font.GetPointSize() - 1);
+       _sound_output_details->SetFont (font);
+
        RtAudio audio (DCPOMATIC_RTAUDIO_API);
        for (unsigned int i = 0; i < audio.getDeviceCount(); ++i) {
                RtAudio::DeviceInfo dev = audio.getDeviceInfo (i);
@@ -173,11 +187,11 @@ GeneralPage::add_play_sound_controls (wxGridBagSizer* table, int& r)
 void
 GeneralPage::add_update_controls (wxGridBagSizer* table, int& r)
 {
-       _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
+       _check_for_updates = new CheckBox (_panel, _("Check for updates on startup"));
        table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
        ++r;
 
-       _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
+       _check_for_test_updates = new CheckBox (_panel, _("Check for testing updates on startup"));
        table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
        ++r;
 
@@ -248,6 +262,33 @@ GeneralPage::config_changed ()
                }
        }
 
+       RtAudio audio (DCPOMATIC_RTAUDIO_API);
+
+       map<int, wxString> apis;
+       apis[RtAudio::MACOSX_CORE]    = _("CoreAudio");
+       apis[RtAudio::WINDOWS_ASIO]   = _("ASIO");
+       apis[RtAudio::WINDOWS_DS]     = _("Direct Sound");
+       apis[RtAudio::WINDOWS_WASAPI] = _("WASAPI");
+       apis[RtAudio::UNIX_JACK]      = _("JACK");
+       apis[RtAudio::LINUX_ALSA]     = _("ALSA");
+       apis[RtAudio::LINUX_PULSE]    = _("PulseAudio");
+       apis[RtAudio::LINUX_OSS]      = _("OSS");
+       apis[RtAudio::RTAUDIO_DUMMY]  = _("Dummy");
+
+       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;
+                       }
+               }
+       }
+
+       _sound_output_details->SetLabel (
+               wxString::Format(_("%d channels on %s"), channels, apis[audio.getCurrentApi()])
+               );
+
        setup_sensitivity ();
 }
 
@@ -329,12 +370,12 @@ CertificateChainEditor::CertificateChainEditor (
        int border,
        function<void (shared_ptr<dcp::CertificateChain>)> set,
        function<shared_ptr<const dcp::CertificateChain> (void)> get,
-       function<bool (void)> nag_remake
+       function<bool (void)> nag_alter
        )
        : wxDialog (parent, wxID_ANY, title)
        , _set (set)
        , _get (get)
-       , _nag_remake (nag_remake)
+       , _nag_alter (nag_alter)
 {
        wxFont subheading_font (*wxNORMAL_FONT);
        subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
@@ -342,7 +383,7 @@ CertificateChainEditor::CertificateChainEditor (
        _sizer = new wxBoxSizer (wxVERTICAL);
 
        {
-               wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
+               wxStaticText* m = new StaticText (this, title);
                m->SetFont (subheading_font);
                _sizer->Add (m, 0, wxALL, border);
        }
@@ -377,11 +418,11 @@ CertificateChainEditor::CertificateChainEditor (
 
        {
                wxSizer* s = new wxBoxSizer (wxVERTICAL);
-               _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
+               _add_certificate = new Button (this, _("Add..."));
                s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
-               _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
+               _remove_certificate = new Button (this, _("Remove"));
                s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
-               _export_certificate = new wxButton (this, wxID_ANY, _("Export"));
+               _export_certificate = new Button (this, _("Export"));
                s->Add (_export_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
                certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
        }
@@ -391,24 +432,26 @@ CertificateChainEditor::CertificateChainEditor (
        int r = 0;
 
        add_label_to_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
-       _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
+       _private_key = new StaticText (this, wxT(""));
        wxFont font = _private_key->GetFont ();
        font.SetFamily (wxFONTFAMILY_TELETYPE);
        _private_key->SetFont (font);
        table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
-       _import_private_key = new wxButton (this, wxID_ANY, _("Import..."));
+       _import_private_key = new Button (this, _("Import..."));
        table->Add (_import_private_key, wxGBPosition (r, 2));
-       _export_private_key = new wxButton (this, wxID_ANY, _("Export..."));
+       _export_private_key = new Button (this, _("Export..."));
        table->Add (_export_private_key, wxGBPosition (r, 3));
        ++r;
 
        _button_sizer = new wxBoxSizer (wxHORIZONTAL);
-       _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
+       _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;
 
-       _private_key_bad = new wxStaticText (this, wxID_ANY, _("Leaf private key does not match leaf certificate!"));
+       _private_key_bad = new StaticText (this, _("Leaf private key does not match leaf certificate!"));
        font = *wxSMALL_FONT;
        font.SetWeight (wxFONTWEIGHT_BOLD);
        _private_key_bad->SetFont (font);
@@ -421,6 +464,7 @@ CertificateChainEditor::CertificateChainEditor (
        _certificates->Bind        (wxEVT_LIST_ITEM_SELECTED,   bind (&CertificateChainEditor::update_sensitivity, this));
        _certificates->Bind        (wxEVT_LIST_ITEM_DESELECTED, bind (&CertificateChainEditor::update_sensitivity, this));
        _remake_certificates->Bind (wxEVT_BUTTON,       bind (&CertificateChainEditor::remake_certificates, this));
+       _export_chain->Bind        (wxEVT_BUTTON,       bind (&CertificateChainEditor::export_chain, this));
        _import_private_key->Bind  (wxEVT_BUTTON,       bind (&CertificateChainEditor::import_private_key, this));
        _export_private_key->Bind  (wxEVT_BUTTON,       bind (&CertificateChainEditor::export_private_key, this));
 
@@ -493,6 +537,11 @@ CertificateChainEditor::add_certificate ()
 void
 CertificateChainEditor::remove_certificate ()
 {
+       if (_nag_alter()) {
+               /* Cancel was clicked */
+               return;
+       }
+
        int i = _certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
        if (i == -1) {
                return;
@@ -504,6 +553,7 @@ CertificateChainEditor::remove_certificate ()
        _set (chain);
 
        update_sensitivity ();
+       update_certificate_list ();
 }
 
 void
@@ -526,15 +576,39 @@ CertificateChainEditor::export_certificate ()
        }
 
        if (d->ShowModal () == wxID_OK) {
-               FILE* f = fopen_boost (path_from_file_dialog (d, "pem"), "w");
+               boost::filesystem::path path (wx_to_std(d->GetPath()));
+               FILE* f = fopen_boost (path, "w");
                if (!f) {
-                       throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
+                       throw OpenFileError (path, errno, false);
                }
 
                string const s = j->certificate (true);
-               fwrite (s.c_str(), 1, s.length(), f);
+               checked_fwrite (s.c_str(), s.length(), f, path);
+               fclose (f);
+       }
+       d->Destroy ();
+}
+
+void
+CertificateChainEditor::export_chain ()
+{
+       wxFileDialog* d = new wxFileDialog (
+               this, _("Select Chain File"), wxEmptyString, wxEmptyString, 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 (!f) {
+                       throw OpenFileError (path, errno, false);
+               }
+
+               string const s = _get()->chain();
+               checked_fwrite (s.c_str(), s.length(), f, path);
                fclose (f);
        }
+
        d->Destroy ();
 }
 
@@ -604,7 +678,7 @@ CertificateChainEditor::remake_certificates ()
                intermediate_common_name = i->subject_common_name ();
        }
 
-       if (_nag_remake()) {
+       if (_nag_alter()) {
                /* Cancel was clicked */
                return;
        }
@@ -698,13 +772,14 @@ CertificateChainEditor::export_private_key ()
                );
 
        if (d->ShowModal () == wxID_OK) {
-               FILE* f = fopen_boost (path_from_file_dialog (d, "pem"), "w");
+               boost::filesystem::path path (wx_to_std(d->GetPath()));
+               FILE* f = fopen_boost (path, "w");
                if (!f) {
-                       throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
+                       throw OpenFileError (path, errno, false);
                }
 
                string const s = _get()->key().get ();
-               fwrite (s.c_str(), 1, s.length(), f);
+               checked_fwrite (s.c_str(), s.length(), f, path);
                fclose (f);
        }
        d->Destroy ();
@@ -725,35 +800,32 @@ KeysPage::setup ()
        wxSizer* sizer = _panel->GetSizer();
 
        {
-               wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Decrypting KDMs"));
+               wxStaticText* m = new StaticText (_panel, _("Decrypting KDMs"));
                m->SetFont (subheading_font);
                sizer->Add (m, 0, wxALL, _border);
        }
 
-       wxButton* export_decryption_certificate = new wxButton (_panel, wxID_ANY, _("Export KDM decryption certificate..."));
+       wxButton* export_decryption_certificate = new Button (_panel, _("Export KDM decryption certificate..."));
        sizer->Add (export_decryption_certificate, 0, wxLEFT, _border);
-       wxButton* export_decryption_chain = new wxButton (_panel, wxID_ANY, _("Export KDM decryption chain..."));
-       sizer->Add (export_decryption_chain, 0, wxLEFT, _border);
-       wxButton* export_settings = new wxButton (_panel, wxID_ANY, _("Export all KDM decryption settings..."));
+       wxButton* export_settings = new Button (_panel, _("Export all KDM decryption settings..."));
        sizer->Add (export_settings, 0, wxLEFT, _border);
-       wxButton* import_settings = new wxButton (_panel, wxID_ANY, _("Import all KDM decryption settings..."));
+       wxButton* import_settings = new Button (_panel, _("Import all KDM decryption settings..."));
        sizer->Add (import_settings, 0, wxLEFT, _border);
-       wxButton* decryption_advanced = new wxButton (_panel, wxID_ANY, _("Advanced..."));
+       wxButton* decryption_advanced = new Button (_panel, _("Advanced..."));
        sizer->Add (decryption_advanced, 0, wxALL, _border);
 
        export_decryption_certificate->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_certificate, this));
-       export_decryption_chain->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_chain, this));
        export_settings->Bind (wxEVT_BUTTON, bind (&KeysPage::export_decryption_chain_and_key, this));
        import_settings->Bind (wxEVT_BUTTON, bind (&KeysPage::import_decryption_chain_and_key, this));
        decryption_advanced->Bind (wxEVT_BUTTON, bind (&KeysPage::decryption_advanced, this));
 
        {
-               wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Signing DCPs and KDMs"));
+               wxStaticText* m = new StaticText (_panel, _("Signing DCPs and KDMs"));
                m->SetFont (subheading_font);
                sizer->Add (m, 0, wxALL, _border);
        }
 
-       wxButton* signing_advanced = new wxButton (_panel, wxID_ANY, _("Advanced..."));
+       wxButton* signing_advanced = new Button (_panel, _("Advanced..."));
        sizer->Add (signing_advanced, 0, wxLEFT, _border);
        signing_advanced->Bind (wxEVT_BUTTON, bind (&KeysPage::signing_advanced, this));
 }
@@ -765,7 +837,7 @@ KeysPage::decryption_advanced ()
                _panel, _("Decrypting KDMs"), _border,
                bind (&Config::set_decryption_chain, Config::instance (), _1),
                bind (&Config::decryption_chain, Config::instance ()),
-               bind (&KeysPage::nag_remake_decryption_chain, this)
+               bind (&KeysPage::nag_alter_decryption_chain, this)
                );
 
        c->ShowModal();
@@ -793,16 +865,17 @@ KeysPage::export_decryption_chain_and_key ()
                );
 
        if (d->ShowModal () == wxID_OK) {
-               FILE* f = fopen_boost (path_from_file_dialog (d, "dom"), "w");
+               boost::filesystem::path path (wx_to_std(d->GetPath()));
+               FILE* f = fopen_boost (path, "w");
                if (!f) {
-                       throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
+                       throw OpenFileError (path, errno, false);
                }
 
                string const chain = Config::instance()->decryption_chain()->chain();
-               fwrite (chain.c_str(), 1, chain.length(), f);
+               checked_fwrite (chain.c_str(), chain.length(), f, path);
                optional<string> const key = Config::instance()->decryption_chain()->key();
                DCPOMATIC_ASSERT (key);
-               fwrite (key->c_str(), 1, key->length(), f);
+               checked_fwrite (key->c_str(), key->length(), f, path);
                fclose (f);
        }
        d->Destroy ();
@@ -812,6 +885,15 @@ KeysPage::export_decryption_chain_and_key ()
 void
 KeysPage::import_decryption_chain_and_key ()
 {
+       if (NagDialog::maybe_nag (
+                   _panel,
+                   Config::NAG_IMPORT_DECRYPTION_CHAIN,
+                   _("If you continue with this operation you will no longer be able to use any DKDMs that you have created with the current certificates and key.  Also, any KDMs that have been sent to you for those certificates will become useless.  Proceed with caution!"),
+                   true
+                   )) {
+               return;
+       }
+
        wxFileDialog* d = new wxFileDialog (
                _panel, _("Select File To Import"), wxEmptyString, wxEmptyString, wxT ("DOM files (*.dom)|*.dom")
                );
@@ -851,37 +933,16 @@ KeysPage::import_decryption_chain_and_key ()
 }
 
 bool
-KeysPage::nag_remake_decryption_chain ()
+KeysPage::nag_alter_decryption_chain ()
 {
        return NagDialog::maybe_nag (
                _panel,
-               Config::NAG_REMAKE_DECRYPTION_CHAIN,
+               Config::NAG_ALTER_DECRYPTION_CHAIN,
                _("If you continue with this operation you will no longer be able to use any DKDMs that you have created.  Also, any KDMs that have been sent to you will become useless.  Proceed with caution!"),
                true
                );
 }
 
-void
-KeysPage::export_decryption_chain ()
-{
-       wxFileDialog* d = new wxFileDialog (
-               _panel, _("Select Chain File"), wxEmptyString, _("dcpomatic_kdm_decryption_chain.pem"), wxT ("PEM files (*.pem)|*.pem"),
-               wxFD_SAVE | wxFD_OVERWRITE_PROMPT
-               );
-
-       if (d->ShowModal () == wxID_OK) {
-               FILE* f = fopen_boost (path_from_file_dialog (d, "pem"), "w");
-               if (!f) {
-                       throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
-               }
-
-               string const s = Config::instance()->decryption_chain()->chain();
-               fwrite (s.c_str(), 1, s.length(), f);
-               fclose (f);
-       }
-       d->Destroy ();
-}
-
 void
 KeysPage::export_decryption_certificate ()
 {
@@ -891,14 +952,16 @@ KeysPage::export_decryption_certificate ()
                );
 
        if (d->ShowModal () == wxID_OK) {
-               FILE* f = fopen_boost (path_from_file_dialog (d, "pem"), "w");
+               boost::filesystem::path path (wx_to_std(d->GetPath()));
+               FILE* f = fopen_boost (path, "w");
                if (!f) {
-                       throw OpenFileError (wx_to_std (d->GetPath ()), errno, false);
+                       throw OpenFileError (path, errno, false);
                }
 
                string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
-               fwrite (s.c_str(), 1, s.length(), f);
+               checked_fwrite (s.c_str(), s.length(), f, path);
                fclose (f);
        }
+
        d->Destroy ();
 }