2 Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
4 This file is part of DCP-o-matic.
6 DCP-o-matic is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 DCP-o-matic is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
21 #ifndef DCPOMATIC_CONFIG_DIALOG_H
22 #define DCPOMATIC_CONFIG_DIALOG_H
25 #include "editable_list.h"
26 #include "lib/config.h"
27 #include "lib/ratio.h"
28 #include "lib/filter.h"
29 #include "lib/dcp_content_type.h"
32 #include "lib/cross.h"
33 #include "lib/exceptions.h"
34 #include <dcp/locale_convert.h>
35 #include <dcp/exceptions.h>
36 #include <dcp/certificate_chain.h>
37 #include <wx/stdpaths.h>
38 #include <wx/preferences.h>
39 #include <wx/spinctrl.h>
40 #include <wx/filepicker.h>
42 #include <boost/filesystem.hpp>
43 #include <boost/foreach.hpp>
49 Page (wxSize panel_size, int border)
52 , _panel_size (panel_size)
53 , _window_exists (false)
55 _config_connection = Config::instance()->Changed.connect (boost::bind (&Page::config_changed_wrapper, this));
61 wxWindow* create_window (wxWindow* parent)
63 _panel = new wxPanel (parent, wxID_ANY, wxDefaultPosition, _panel_size);
64 wxBoxSizer* s = new wxBoxSizer (wxVERTICAL);
68 _window_exists = true;
71 _panel->Bind (wxEVT_DESTROY, boost::bind (&Page::window_destroyed, this));
80 virtual void config_changed () = 0;
81 virtual void setup () = 0;
83 void config_changed_wrapper ()
90 void window_destroyed ()
92 _window_exists = false;
96 boost::signals2::scoped_connection _config_connection;
100 class StockPage : public wxStockPreferencesPage, public Page
103 StockPage (Kind kind, wxSize panel_size, int border)
104 : wxStockPreferencesPage (kind)
105 , Page (panel_size, border)
108 wxWindow* CreateWindow (wxWindow* parent)
110 return create_window (parent);
114 class StandardPage : public wxPreferencesPage, public Page
117 StandardPage (wxSize panel_size, int border)
118 : Page (panel_size, border)
121 wxWindow* CreateWindow (wxWindow* parent)
123 return create_window (parent);
127 class GeneralPage : public StockPage
130 GeneralPage (wxSize panel_size, int border)
131 : StockPage (Kind_General, panel_size, border)
135 void add_language_controls (wxGridBagSizer* table, int& r)
137 _set_language = new wxCheckBox (_panel, wxID_ANY, _("Set language"));
138 table->Add (_set_language, wxGBPosition (r, 0));
139 _language = new wxChoice (_panel, wxID_ANY);
140 std::vector<std::pair<std::string, std::string> > languages;
141 languages.push_back (std::make_pair ("Čeština", "cs_CZ"));
142 languages.push_back (std::make_pair ("汉语/漢語", "zh_CN"));
143 languages.push_back (std::make_pair ("Dansk", "da_DK"));
144 languages.push_back (std::make_pair ("Deutsch", "de_DE"));
145 languages.push_back (std::make_pair ("English", "en_GB"));
146 languages.push_back (std::make_pair ("Español", "es_ES"));
147 languages.push_back (std::make_pair ("Français", "fr_FR"));
148 languages.push_back (std::make_pair ("Italiano", "it_IT"));
149 languages.push_back (std::make_pair ("Nederlands", "nl_NL"));
150 languages.push_back (std::make_pair ("Русский", "ru_RU"));
151 languages.push_back (std::make_pair ("Polski", "pl_PL"));
152 languages.push_back (std::make_pair ("Português europeu", "pt_PT"));
153 languages.push_back (std::make_pair ("Português do Brasil", "pt_BR"));
154 languages.push_back (std::make_pair ("Svenska", "sv_SE"));
155 languages.push_back (std::make_pair ("Slovenský jazyk", "sk_SK"));
156 languages.push_back (std::make_pair ("українська мова", "uk_UA"));
157 checked_set (_language, languages);
158 table->Add (_language, wxGBPosition (r, 1));
161 wxStaticText* restart = add_label_to_sizer (
162 table, _panel, _("(restart DCP-o-matic to see language changes)"), false, wxGBPosition (r, 0), wxGBSpan (1, 2)
164 wxFont font = restart->GetFont();
165 font.SetStyle (wxFONTSTYLE_ITALIC);
166 font.SetPointSize (font.GetPointSize() - 1);
167 restart->SetFont (font);
170 _set_language->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::set_language_changed, this));
171 _language->Bind (wxEVT_CHOICE, boost::bind (&GeneralPage::language_changed, this));
174 void add_play_sound_controls (wxGridBagSizer* table, int& r)
176 _sound = new wxCheckBox (_panel, wxID_ANY, _("Play sound via"));
177 table->Add (_sound, wxGBPosition (r, 0));
178 _sound_output = new wxChoice (_panel, wxID_ANY);
179 table->Add (_sound_output, wxGBPosition (r, 1));
182 RtAudio audio (DCPOMATIC_RTAUDIO_API);
183 for (unsigned int i = 0; i < audio.getDeviceCount(); ++i) {
184 RtAudio::DeviceInfo dev = audio.getDeviceInfo (i);
185 if (dev.probed && dev.outputChannels > 0) {
186 _sound_output->Append (std_to_wx (dev.name));
190 _sound->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::sound_changed, this));
191 _sound_output->Bind (wxEVT_CHOICE, boost::bind (&GeneralPage::sound_output_changed, this));
194 void add_update_controls (wxGridBagSizer* table, int& r)
196 _check_for_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for updates on startup"));
197 table->Add (_check_for_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
200 _check_for_test_updates = new wxCheckBox (_panel, wxID_ANY, _("Check for testing updates on startup"));
201 table->Add (_check_for_test_updates, wxGBPosition (r, 0), wxGBSpan (1, 2));
204 _check_for_updates->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::check_for_updates_changed, this));
205 _check_for_test_updates->Bind (wxEVT_CHECKBOX, boost::bind (&GeneralPage::check_for_test_updates_changed, this));
208 virtual void config_changed ()
210 Config* config = Config::instance ();
212 checked_set (_set_language, static_cast<bool>(config->language()));
214 /* Backwards compatibility of config file */
216 std::map<std::string, std::string> compat_map;
217 compat_map["fr"] = "fr_FR";
218 compat_map["it"] = "it_IT";
219 compat_map["es"] = "es_ES";
220 compat_map["sv"] = "sv_SE";
221 compat_map["de"] = "de_DE";
222 compat_map["nl"] = "nl_NL";
223 compat_map["ru"] = "ru_RU";
224 compat_map["pl"] = "pl_PL";
225 compat_map["da"] = "da_DK";
226 compat_map["pt"] = "pt_PT";
227 compat_map["sk"] = "sk_SK";
228 compat_map["cs"] = "cs_CZ";
229 compat_map["uk"] = "uk_UA";
231 std::string lang = config->language().get_value_or ("en_GB");
232 if (compat_map.find (lang) != compat_map.end ()) {
233 lang = compat_map[lang];
236 checked_set (_language, lang);
238 checked_set (_check_for_updates, config->check_for_updates ());
239 checked_set (_check_for_test_updates, config->check_for_test_updates ());
241 checked_set (_sound, config->sound ());
243 boost::optional<std::string> const current_so = get_sound_output ();
244 boost::optional<std::string> configured_so;
246 if (config->sound_output()) {
247 configured_so = config->sound_output().get();
249 /* No configured output means we should use the default */
250 RtAudio audio (DCPOMATIC_RTAUDIO_API);
252 configured_so = audio.getDeviceInfo(audio.getDefaultOutputDevice()).name;
253 } catch (RtAudioError& e) {
254 /* Probably no audio devices at all */
258 if (configured_so && current_so != configured_so) {
259 /* Update _sound_output with the configured value */
261 while (i < _sound_output->GetCount()) {
262 if (_sound_output->GetString(i) == std_to_wx(*configured_so)) {
263 _sound_output->SetSelection (i);
270 setup_sensitivity ();
274 void setup_sensitivity ()
276 _language->Enable (_set_language->GetValue ());
277 _check_for_test_updates->Enable (_check_for_updates->GetValue ());
278 _sound_output->Enable (_sound->GetValue ());
281 /** @return Currently-selected preview sound output in the dialogue */
282 boost::optional<std::string> get_sound_output ()
284 int const sel = _sound_output->GetSelection ();
285 if (sel == wxNOT_FOUND) {
286 return boost::optional<std::string> ();
289 return wx_to_std (_sound_output->GetString (sel));
292 void set_language_changed ()
294 setup_sensitivity ();
295 if (_set_language->GetValue ()) {
298 Config::instance()->unset_language ();
302 void language_changed ()
304 int const sel = _language->GetSelection ();
306 Config::instance()->set_language (string_client_data (_language->GetClientObject (sel)));
308 Config::instance()->unset_language ();
312 void check_for_updates_changed ()
314 Config::instance()->set_check_for_updates (_check_for_updates->GetValue ());
317 void check_for_test_updates_changed ()
319 Config::instance()->set_check_for_test_updates (_check_for_test_updates->GetValue ());
322 void sound_changed ()
324 Config::instance()->set_sound (_sound->GetValue ());
327 void sound_output_changed ()
329 RtAudio audio (DCPOMATIC_RTAUDIO_API);
330 boost::optional<std::string> const so = get_sound_output();
331 if (!so || *so == audio.getDeviceInfo(audio.getDefaultOutputDevice()).name) {
332 Config::instance()->unset_sound_output ();
334 Config::instance()->set_sound_output (*so);
338 wxCheckBox* _set_language;
341 wxChoice* _sound_output;
342 wxCheckBox* _check_for_updates;
343 wxCheckBox* _check_for_test_updates;