Supporters update.
[dcpomatic.git] / src / wx / player_config_dialog.cc
1 /*
2     Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
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.
10
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.
15
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/>.
18
19 */
20
21
22 /** @file src/player_config_dialog.cc
23  *  @brief A dialogue to edit DCP-o-matic Player configuration.
24  */
25
26
27 #include "check_box.h"
28 #include "config_dialog.h"
29 #include "dir_picker_ctrl.h"
30 #include "editable_list.h"
31 #include "email_dialog.h"
32 #include "file_picker_ctrl.h"
33 #include "filter_dialog.h"
34 #include "make_chain_dialog.h"
35 #include "nag_dialog.h"
36 #include "name_format_editor.h"
37 #include "server_dialog.h"
38 #include "static_text.h"
39 #include "wx_util.h"
40 #include "lib/config.h"
41 #include "lib/cross.h"
42 #include "lib/dcp_content_type.h"
43 #include "lib/exceptions.h"
44 #include "lib/filter.h"
45 #include "lib/log.h"
46 #include "lib/ratio.h"
47 #include "lib/util.h"
48 #include <dcp/certificate_chain.h>
49 #include <dcp/exceptions.h>
50 #include <dcp/locale_convert.h>
51 #include <dcp/warnings.h>
52 LIBDCP_DISABLE_WARNINGS
53 #include <wx/filepicker.h>
54 #include <wx/preferences.h>
55 #include <wx/spinctrl.h>
56 #include <wx/stdpaths.h>
57 LIBDCP_ENABLE_WARNINGS
58 #include <RtAudio.h>
59 #include <boost/filesystem.hpp>
60
61
62 using std::function;
63 using std::list;
64 using std::make_pair;
65 using std::map;
66 using std::pair;
67 using std::shared_ptr;
68 using std::string;
69 using std::vector;
70 using boost::bind;
71 using boost::optional;
72 #if BOOST_VERSION >= 106100
73 using namespace boost::placeholders;
74 #endif
75 using dcp::locale_convert;
76
77
78 class PlayerGeneralPage : public GeneralPage
79 {
80 public:
81         PlayerGeneralPage (wxSize panel_size, int border)
82                 : GeneralPage (panel_size, border)
83         {}
84
85 private:
86         void setup () override
87         {
88                 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
89                 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
90
91                 int r = 0;
92                 add_language_controls (table, r);
93                 add_update_controls (table, r);
94
95                 add_label_to_sizer (table, _panel, _("Start player as"), true, wxGBPosition(r, 0));
96                 _player_mode = new wxChoice (_panel, wxID_ANY);
97                 _player_mode->Append (_("window"));
98                 _player_mode->Append (_("full screen"));
99                 _player_mode->Append (_("full screen with separate advanced controls"));
100                 table->Add (_player_mode, wxGBPosition(r, 1));
101                 ++r;
102
103                 add_label_to_sizer (table, _panel, _("Dual-screen displays"), true, wxGBPosition(r, 0));
104                 _image_display = new wxChoice (_panel, wxID_ANY);
105                 _image_display->Append (_("Image on primary, controls on secondary"));
106                 _image_display->Append (_("Image on secondary, controls on primary"));
107                 table->Add (_image_display, wxGBPosition(r, 1));
108                 ++r;
109
110                 add_label_to_sizer (table, _panel, _("Video display mode"), true, wxGBPosition(r, 0));
111                 _video_display_mode = new wxChoice (_panel, wxID_ANY);
112                 _video_display_mode->Append (_("Simple (safer)"));
113                 _video_display_mode->Append (_("OpenGL (faster)"));
114                 table->Add (_video_display_mode, wxGBPosition(r, 1));
115                 ++r;
116
117                 wxStaticText* restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false, wxGBPosition(r, 0));
118                 wxFont font = restart->GetFont();
119                 font.SetStyle (wxFONTSTYLE_ITALIC);
120                 font.SetPointSize (font.GetPointSize() - 1);
121                 restart->SetFont (font);
122                 ++r;
123
124                 _respect_kdm = new CheckBox (_panel, _("Respect KDM validity periods"));
125                 table->Add (_respect_kdm, wxGBPosition(r, 0), wxGBSpan(1, 2));
126                 ++r;
127
128                 add_label_to_sizer (table, _panel, _("Debug log file"), true, wxGBPosition (r, 0));
129                 _debug_log_file = new FilePickerCtrl(_panel, _("Select debug log file"), "*", false, true, "DebugLogPath");
130                 table->Add (_debug_log_file, wxGBPosition(r, 1));
131                 ++r;
132
133                 _player_mode->Bind (wxEVT_CHOICE, bind(&PlayerGeneralPage::player_mode_changed, this));
134                 _image_display->Bind (wxEVT_CHOICE, bind(&PlayerGeneralPage::image_display_changed, this));
135                 _video_display_mode->Bind (wxEVT_CHOICE, bind(&PlayerGeneralPage::video_display_mode_changed, this));
136                 _respect_kdm->bind(&PlayerGeneralPage::respect_kdm_changed, this);
137                 _debug_log_file->Bind (wxEVT_FILEPICKER_CHANGED, bind(&PlayerGeneralPage::debug_log_file_changed, this));
138         }
139
140         void config_changed () override
141         {
142                 GeneralPage::config_changed ();
143
144                 Config* config = Config::instance ();
145
146                 switch (config->player_mode()) {
147                 case Config::PLAYER_MODE_WINDOW:
148                         checked_set (_player_mode, 0);
149                         break;
150                 case Config::PLAYER_MODE_FULL:
151                         checked_set (_player_mode, 1);
152                         break;
153                 case Config::PLAYER_MODE_DUAL:
154                         checked_set (_player_mode, 2);
155                         break;
156                 }
157
158                 switch (config->video_view_type()) {
159                 case Config::VIDEO_VIEW_SIMPLE:
160                         checked_set (_video_display_mode, 0);
161                         break;
162                 case Config::VIDEO_VIEW_OPENGL:
163                         checked_set (_video_display_mode, 1);
164                         break;
165                 }
166
167                 checked_set (_image_display, config->image_display());
168                 checked_set (_respect_kdm, config->respect_kdm_validity_periods());
169                 if (config->player_debug_log_file()) {
170                         checked_set (_debug_log_file, *config->player_debug_log_file());
171                 }
172         }
173
174 private:
175         void player_mode_changed ()
176         {
177                 switch (_player_mode->GetSelection()) {
178                 case 0:
179                         Config::instance()->set_player_mode(Config::PLAYER_MODE_WINDOW);
180                         break;
181                 case 1:
182                         Config::instance()->set_player_mode(Config::PLAYER_MODE_FULL);
183                         break;
184                 case 2:
185                         Config::instance()->set_player_mode(Config::PLAYER_MODE_DUAL);
186                         break;
187                 }
188         }
189
190         void image_display_changed ()
191         {
192                 Config::instance()->set_image_display(_image_display->GetSelection());
193         }
194
195         void video_display_mode_changed ()
196         {
197                 if (_video_display_mode->GetSelection() == 0) {
198                         Config::instance()->set_video_view_type (Config::VIDEO_VIEW_SIMPLE);
199                 } else {
200                         Config::instance()->set_video_view_type (Config::VIDEO_VIEW_OPENGL);
201                 }
202         }
203
204         void respect_kdm_changed ()
205         {
206                 Config::instance()->set_respect_kdm_validity_periods(_respect_kdm->GetValue());
207         }
208
209         void debug_log_file_changed ()
210         {
211                 if (auto path = _debug_log_file->path()) {
212                         Config::instance()->set_player_debug_log_file(*path);
213                 }
214         }
215
216         wxChoice* _player_mode;
217         wxChoice* _image_display;
218         wxChoice* _video_display_mode;
219         CheckBox* _respect_kdm;
220         FilePickerCtrl* _debug_log_file;
221 };
222
223
224 /** @class PlayerAdvancedPage
225  *  @brief Advanced page of the preferences dialog for the player.
226  */
227 class PlayerAdvancedPage : public Page
228 {
229 public:
230         PlayerAdvancedPage (wxSize panel_size, int border)
231                 : Page (panel_size, border)
232                 , _log_general (0)
233                 , _log_warning (0)
234                 , _log_error (0)
235                 , _log_timing (0)
236         {}
237
238         wxString GetName () const override
239         {
240                 return _("Advanced");
241         }
242
243 #ifdef DCPOMATIC_OSX
244         wxBitmap GetLargeIcon () const override
245         {
246                 return wxBitmap(icon_path("advanced"), wxBITMAP_TYPE_PNG);
247         }
248 #endif
249
250 private:
251         void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
252         {
253                 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
254 #ifdef __WXOSX__
255                 flags |= wxALIGN_RIGHT;
256                 text += wxT (":");
257 #endif
258                 wxStaticText* m = new StaticText (parent, text);
259                 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
260         }
261
262         void setup () override
263         {
264                 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
265                 table->AddGrowableCol (1, 1);
266                 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
267
268                 {
269                         add_top_aligned_label_to_sizer (table, _panel, _("Log"));
270                         wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
271                         _log_general = new CheckBox (_panel, _("General"));
272                         t->Add (_log_general, 1, wxEXPAND | wxALL);
273                         _log_warning = new CheckBox (_panel, _("Warnings"));
274                         t->Add (_log_warning, 1, wxEXPAND | wxALL);
275                         _log_error = new CheckBox (_panel, _("Errors"));
276                         t->Add (_log_error, 1, wxEXPAND | wxALL);
277                         /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
278                         _log_timing = new CheckBox (_panel, S_("Config|Timing"));
279                         t->Add (_log_timing, 1, wxEXPAND | wxALL);
280                         _log_debug_video_view = new CheckBox(_panel, _("Debug: video view"));
281                         t->Add(_log_debug_video_view, 1, wxEXPAND | wxALL);
282                         table->Add (t, 0, wxALL, 6);
283                 }
284
285 #ifdef DCPOMATIC_WINDOWS
286                 _win32_console = new CheckBox (_panel, _("Open console window"));
287                 table->Add (_win32_console, 1, wxEXPAND | wxALL);
288                 table->AddSpacer (0);
289 #endif
290
291                 _log_general->bind(&PlayerAdvancedPage::log_changed, this);
292                 _log_warning->bind(&PlayerAdvancedPage::log_changed, this);
293                 _log_error->bind(&PlayerAdvancedPage::log_changed, this);
294                 _log_timing->bind(&PlayerAdvancedPage::log_changed, this);
295                 _log_debug_video_view->bind(&PlayerAdvancedPage::log_changed, this);
296 #ifdef DCPOMATIC_WINDOWS
297                 _win32_console->bind(&PlayerAdvancedPage::win32_console_changed, this);
298 #endif
299         }
300
301         void config_changed () override
302         {
303                 auto config = Config::instance ();
304
305                 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
306                 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
307                 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
308                 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
309 #ifdef DCPOMATIC_WINDOWS
310                 checked_set (_win32_console, config->win32_console());
311 #endif
312         }
313
314         void log_changed ()
315         {
316                 int types = 0;
317                 if (_log_general->GetValue ()) {
318                         types |= LogEntry::TYPE_GENERAL;
319                 }
320                 if (_log_warning->GetValue ()) {
321                         types |= LogEntry::TYPE_WARNING;
322                 }
323                 if (_log_error->GetValue ())  {
324                         types |= LogEntry::TYPE_ERROR;
325                 }
326                 if (_log_timing->GetValue ()) {
327                         types |= LogEntry::TYPE_TIMING;
328                 }
329                 if (_log_debug_video_view->GetValue()) {
330                         types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
331                 }
332                 Config::instance()->set_log_types (types);
333         }
334
335 #ifdef DCPOMATIC_WINDOWS
336         void win32_console_changed ()
337         {
338                 Config::instance()->set_win32_console (_win32_console->GetValue ());
339         }
340 #endif
341
342         CheckBox* _log_general;
343         CheckBox* _log_warning;
344         CheckBox* _log_error;
345         CheckBox* _log_timing;
346         CheckBox* _log_debug_video_view;
347 #ifdef DCPOMATIC_WINDOWS
348         CheckBox* _win32_console;
349 #endif
350 };
351
352
353 wxPreferencesEditor*
354 create_player_config_dialog ()
355 {
356         auto e = new wxPreferencesEditor (_("DCP-o-matic Player Preferences"));
357
358 #ifdef DCPOMATIC_OSX
359         /* Width that we force some of the config panels to be on OSX so that
360            the containing window doesn't shrink too much when we select those panels.
361            This is obviously an unpleasant hack.
362         */
363         auto ps = wxSize (520, -1);
364         int const border = 16;
365 #else
366         auto ps = wxSize (-1, -1);
367         int const border = 8;
368 #endif
369
370         e->AddPage (new PlayerGeneralPage(wxSize(-1, 500), border));
371         e->AddPage (new SoundPage(ps, border));
372         e->AddPage (new LocationsPage(ps, border));
373         e->AddPage (new KeysPage(ps, border));
374         e->AddPage (new PlayerAdvancedPage(ps, border));
375         return e;
376 }