5ac1fe28d2f75760a1c3bd6e72442458d9d97cd2
[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);
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                 Config::instance()->set_player_debug_log_file(wx_to_std(_debug_log_file->GetPath()));
212         }
213
214         wxChoice* _player_mode;
215         wxChoice* _image_display;
216         wxChoice* _video_display_mode;
217         CheckBox* _respect_kdm;
218         FilePickerCtrl* _debug_log_file;
219 };
220
221
222 /** @class PlayerAdvancedPage
223  *  @brief Advanced page of the preferences dialog for the player.
224  */
225 class PlayerAdvancedPage : public Page
226 {
227 public:
228         PlayerAdvancedPage (wxSize panel_size, int border)
229                 : Page (panel_size, border)
230                 , _log_general (0)
231                 , _log_warning (0)
232                 , _log_error (0)
233                 , _log_timing (0)
234         {}
235
236         wxString GetName () const override
237         {
238                 return _("Advanced");
239         }
240
241 #ifdef DCPOMATIC_OSX
242         wxBitmap GetLargeIcon () const override
243         {
244                 return wxBitmap(icon_path("advanced"), wxBITMAP_TYPE_PNG);
245         }
246 #endif
247
248 private:
249         void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
250         {
251                 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
252 #ifdef __WXOSX__
253                 flags |= wxALIGN_RIGHT;
254                 text += wxT (":");
255 #endif
256                 wxStaticText* m = new StaticText (parent, text);
257                 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
258         }
259
260         void setup () override
261         {
262                 auto table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
263                 table->AddGrowableCol (1, 1);
264                 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
265
266                 {
267                         add_top_aligned_label_to_sizer (table, _panel, _("Log"));
268                         wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
269                         _log_general = new CheckBox (_panel, _("General"));
270                         t->Add (_log_general, 1, wxEXPAND | wxALL);
271                         _log_warning = new CheckBox (_panel, _("Warnings"));
272                         t->Add (_log_warning, 1, wxEXPAND | wxALL);
273                         _log_error = new CheckBox (_panel, _("Errors"));
274                         t->Add (_log_error, 1, wxEXPAND | wxALL);
275                         /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
276                         _log_timing = new CheckBox (_panel, S_("Config|Timing"));
277                         t->Add (_log_timing, 1, wxEXPAND | wxALL);
278                         _log_debug_video_view = new CheckBox(_panel, _("Debug: video view"));
279                         t->Add(_log_debug_video_view, 1, wxEXPAND | wxALL);
280                         table->Add (t, 0, wxALL, 6);
281                 }
282
283 #ifdef DCPOMATIC_WINDOWS
284                 _win32_console = new CheckBox (_panel, _("Open console window"));
285                 table->Add (_win32_console, 1, wxEXPAND | wxALL);
286                 table->AddSpacer (0);
287 #endif
288
289                 _log_general->bind(&PlayerAdvancedPage::log_changed, this);
290                 _log_warning->bind(&PlayerAdvancedPage::log_changed, this);
291                 _log_error->bind(&PlayerAdvancedPage::log_changed, this);
292                 _log_timing->bind(&PlayerAdvancedPage::log_changed, this);
293                 _log_debug_video_view->bind(&PlayerAdvancedPage::log_changed, this);
294 #ifdef DCPOMATIC_WINDOWS
295                 _win32_console->bind(&PlayerAdvancedPage::win32_console_changed, this);
296 #endif
297         }
298
299         void config_changed () override
300         {
301                 auto config = Config::instance ();
302
303                 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
304                 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
305                 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
306                 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
307 #ifdef DCPOMATIC_WINDOWS
308                 checked_set (_win32_console, config->win32_console());
309 #endif
310         }
311
312         void log_changed ()
313         {
314                 int types = 0;
315                 if (_log_general->GetValue ()) {
316                         types |= LogEntry::TYPE_GENERAL;
317                 }
318                 if (_log_warning->GetValue ()) {
319                         types |= LogEntry::TYPE_WARNING;
320                 }
321                 if (_log_error->GetValue ())  {
322                         types |= LogEntry::TYPE_ERROR;
323                 }
324                 if (_log_timing->GetValue ()) {
325                         types |= LogEntry::TYPE_TIMING;
326                 }
327                 if (_log_debug_video_view->GetValue()) {
328                         types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
329                 }
330                 Config::instance()->set_log_types (types);
331         }
332
333 #ifdef DCPOMATIC_WINDOWS
334         void win32_console_changed ()
335         {
336                 Config::instance()->set_win32_console (_win32_console->GetValue ());
337         }
338 #endif
339
340         CheckBox* _log_general;
341         CheckBox* _log_warning;
342         CheckBox* _log_error;
343         CheckBox* _log_timing;
344         CheckBox* _log_debug_video_view;
345 #ifdef DCPOMATIC_WINDOWS
346         CheckBox* _win32_console;
347 #endif
348 };
349
350
351 wxPreferencesEditor*
352 create_player_config_dialog ()
353 {
354         auto e = new wxPreferencesEditor (_("DCP-o-matic Player Preferences"));
355
356 #ifdef DCPOMATIC_OSX
357         /* Width that we force some of the config panels to be on OSX so that
358            the containing window doesn't shrink too much when we select those panels.
359            This is obviously an unpleasant hack.
360         */
361         auto ps = wxSize (520, -1);
362         int const border = 16;
363 #else
364         auto ps = wxSize (-1, -1);
365         int const border = 8;
366 #endif
367
368         e->AddPage (new PlayerGeneralPage(wxSize(-1, 500), border));
369         e->AddPage (new SoundPage(ps, border));
370         e->AddPage (new LocationsPage(ps, border));
371         e->AddPage (new KeysPage(ps, border));
372         e->AddPage (new PlayerAdvancedPage(ps, border));
373         return e;
374 }