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