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