2 Copyright (C) 2012-2018 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 /** @file src/player_config_dialog.cc
22 * @brief A dialogue to edit DCP-o-matic Player configuration.
25 #include "config_dialog.h"
27 #include "editable_list.h"
28 #include "filter_dialog.h"
29 #include "file_picker_ctrl.h"
30 #include "dir_picker_ctrl.h"
31 #include "isdcf_metadata_dialog.h"
32 #include "server_dialog.h"
33 #include "make_chain_dialog.h"
34 #include "email_dialog.h"
35 #include "name_format_editor.h"
36 #include "nag_dialog.h"
37 #include "monitor_dialog.h"
38 #include "lib/config.h"
39 #include "lib/ratio.h"
40 #include "lib/filter.h"
41 #include "lib/dcp_content_type.h"
44 #include "lib/cross.h"
45 #include "lib/exceptions.h"
46 #include <dcp/locale_convert.h>
47 #include <dcp/exceptions.h>
48 #include <dcp/certificate_chain.h>
49 #include <wx/stdpaths.h>
50 #include <wx/preferences.h>
51 #include <wx/spinctrl.h>
52 #include <wx/filepicker.h>
54 #include <boost/filesystem.hpp>
55 #include <boost/foreach.hpp>
66 using boost::shared_ptr;
67 using boost::function;
68 using boost::optional;
69 using dcp::locale_convert;
71 class PlayerGeneralPage : public GeneralPage
74 PlayerGeneralPage (wxSize panel_size, int border)
75 : GeneralPage (panel_size, border)
81 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
82 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
85 add_language_controls (table, r);
86 add_play_sound_controls (table, r);
87 add_update_controls (table, r);
89 add_label_to_sizer (table, _panel, _("Start player as"), true, wxGBPosition(r, 0));
90 _player_mode = new wxChoice (_panel, wxID_ANY);
91 _player_mode->Append (_("window"));
92 _player_mode->Append (_("full screen"));
93 _player_mode->Append (_("full screen with controls on other monitor"));
94 table->Add (_player_mode, wxGBPosition(r, 1));
97 add_label_to_sizer (table, _panel, _("Dual-screen displays"), true, wxGBPosition(r, 0));
98 _image_display = new wxChoice (_panel, wxID_ANY);
99 _image_display->Append (_("Image on primary, controls on secondary"));
100 _image_display->Append (_("Image on secondary, controls on primary"));
101 table->Add (_image_display, wxGBPosition(r, 1));
104 _respect_kdm = new wxCheckBox (_panel, wxID_ANY, _("Respect KDM validity periods"));
105 table->Add (_respect_kdm, wxGBPosition(r, 0), wxGBSpan(1, 2));
108 add_label_to_sizer (table, _panel, _("Log file"), true, wxGBPosition (r, 0));
109 _log_file = new FilePickerCtrl (_panel, _("Select log file"), "*", true);
110 table->Add (_log_file, wxGBPosition (r, 1));
113 #ifdef DCPOMATIC_VARIANT_SWAROOP
114 add_label_to_sizer (table, _panel, _("KDM server URL"), true, wxGBPosition(r, 0));
115 _kdm_server_url = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(400, -1));
116 table->Add (_kdm_server_url, wxGBPosition (r, 1));
120 _player_mode->Bind (wxEVT_CHOICE, bind(&PlayerGeneralPage::player_mode_changed, this));
121 _image_display->Bind (wxEVT_CHOICE, bind(&PlayerGeneralPage::image_display_changed, this));
122 _respect_kdm->Bind (wxEVT_CHECKBOX, bind(&PlayerGeneralPage::respect_kdm_changed, this));
123 _log_file->Bind (wxEVT_FILEPICKER_CHANGED, bind(&PlayerGeneralPage::log_file_changed, this));
124 #ifdef DCPOMATIC_VARIANT_SWAROOP
125 _kdm_server_url->Bind (wxEVT_TEXT, bind(&PlayerGeneralPage::kdm_server_url_changed, this));
129 void config_changed ()
131 GeneralPage::config_changed ();
133 Config* config = Config::instance ();
135 switch (config->player_mode()) {
136 case Config::PLAYER_MODE_WINDOW:
137 checked_set (_player_mode, 0);
139 case Config::PLAYER_MODE_FULL:
140 checked_set (_player_mode, 1);
142 case Config::PLAYER_MODE_DUAL:
143 checked_set (_player_mode, 2);
147 checked_set (_image_display, config->image_display());
148 checked_set (_respect_kdm, config->respect_kdm_validity_periods());
149 if (config->player_log_file()) {
150 checked_set (_log_file, *config->player_log_file());
152 #ifdef DCPOMATIC_VARIANT_SWAROOP
153 checked_set (_kdm_server_url, config->kdm_server_url());
158 void player_mode_changed ()
160 switch (_player_mode->GetSelection()) {
162 Config::instance()->set_player_mode(Config::PLAYER_MODE_WINDOW);
165 Config::instance()->set_player_mode(Config::PLAYER_MODE_FULL);
168 Config::instance()->set_player_mode(Config::PLAYER_MODE_DUAL);
173 void image_display_changed ()
175 Config::instance()->set_image_display(_image_display->GetSelection());
178 void respect_kdm_changed ()
180 Config::instance()->set_respect_kdm_validity_periods(_respect_kdm->GetValue());
183 void log_file_changed ()
185 Config::instance()->set_player_log_file(wx_to_std(_log_file->GetPath()));
188 #ifdef DCPOMATIC_VARIANT_SWAROOP
189 void kdm_server_url_changed ()
191 Config::instance()->set_kdm_server_url(wx_to_std(_kdm_server_url->GetValue()));
195 wxChoice* _player_mode;
196 wxChoice* _image_display;
197 wxCheckBox* _respect_kdm;
198 FilePickerCtrl* _log_file;
199 #ifdef DCPOMATIC_VARIANT_SWAROOP
200 wxTextCtrl* _kdm_server_url;
204 class LocationsPage : public StandardPage
207 LocationsPage (wxSize panel_size, int border)
208 : StandardPage (panel_size, border)
211 wxString GetName () const
213 return _("Locations");
217 wxBitmap GetLargeIcon () const
219 return wxBitmap ("locations", wxBITMAP_TYPE_PNG_RESOURCE);
229 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
230 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
232 add_label_to_sizer (table, _panel, _("Content directory"), true, wxGBPosition (r, 0));
233 _content_directory = new wxDirPickerCtrl (_panel, wxID_ANY, wxEmptyString, wxDirSelectorPromptStr, wxDefaultPosition, wxSize (300, -1));
234 table->Add (_content_directory, wxGBPosition (r, 1));
237 add_label_to_sizer (table, _panel, _("Playlist directory"), true, wxGBPosition (r, 0));
238 _playlist_directory = new wxDirPickerCtrl (_panel, wxID_ANY, wxEmptyString, wxDirSelectorPromptStr, wxDefaultPosition, wxSize (300, -1));
239 table->Add (_playlist_directory, wxGBPosition (r, 1));
242 add_label_to_sizer (table, _panel, _("KDM directory"), true, wxGBPosition (r, 0));
243 _kdm_directory = new wxDirPickerCtrl (_panel, wxID_ANY, wxEmptyString, wxDirSelectorPromptStr, wxDefaultPosition, wxSize (300, -1));
244 table->Add (_kdm_directory, wxGBPosition (r, 1));
247 #ifdef DCPOMATIC_VARIANT_SWAROOP
248 add_label_to_sizer (table, _panel, _("Background image"), true, wxGBPosition (r, 0));
249 _background_image = new FilePickerCtrl (_panel, _("Select image file"), "*.png;*.jpg;*.jpeg;*.tif;*.tiff", true);
250 table->Add (_background_image, wxGBPosition (r, 1));
254 _content_directory->Bind (wxEVT_DIRPICKER_CHANGED, bind(&LocationsPage::content_directory_changed, this));
255 _playlist_directory->Bind (wxEVT_DIRPICKER_CHANGED, bind(&LocationsPage::playlist_directory_changed, this));
256 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, bind(&LocationsPage::kdm_directory_changed, this));
257 #ifdef DCPOMATIC_VARIANT_SWAROOP
258 _background_image->Bind (wxEVT_FILEPICKER_CHANGED, bind(&LocationsPage::background_image_changed, this));
262 void config_changed ()
264 Config* config = Config::instance ();
266 if (config->player_content_directory()) {
267 checked_set (_content_directory, *config->player_content_directory());
269 if (config->player_playlist_directory()) {
270 checked_set (_playlist_directory, *config->player_playlist_directory());
272 if (config->player_kdm_directory()) {
273 checked_set (_kdm_directory, *config->player_kdm_directory());
275 #ifdef DCPOMATIC_VARIANT_SWAROOP
276 if (config->player_background_image()) {
277 checked_set (_background_image, *config->player_background_image());
282 void content_directory_changed ()
284 Config::instance()->set_player_content_directory(wx_to_std(_content_directory->GetPath()));
287 void playlist_directory_changed ()
289 Config::instance()->set_player_playlist_directory(wx_to_std(_playlist_directory->GetPath()));
292 void kdm_directory_changed ()
294 Config::instance()->set_player_kdm_directory(wx_to_std(_kdm_directory->GetPath()));
297 #ifdef DCPOMATIC_VARIANT_SWAROOP
298 void background_image_changed ()
300 Config::instance()->set_player_background_image(wx_to_std(_background_image->GetPath()));
304 wxDirPickerCtrl* _content_directory;
305 wxDirPickerCtrl* _playlist_directory;
306 wxDirPickerCtrl* _kdm_directory;
307 #ifdef DCPOMATIC_VARIANT_SWAROOP
308 FilePickerCtrl* _background_image;
312 #ifdef DCPOMATIC_VARIANT_SWAROOP
313 class WatermarkPage : public StandardPage
316 WatermarkPage (wxSize panel_size, int border)
317 : StandardPage (panel_size, border)
320 wxString GetName () const
322 return _("Watermark");
328 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
329 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
333 add_label_to_sizer (table, _panel, _("Theatre name"), true, wxGBPosition(r, 0));
334 _theatre = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(300, -1));
335 table->Add (_theatre, wxGBPosition(r, 1), wxGBSpan(1, 2));
338 add_label_to_sizer (table, _panel, _("Period"), true, wxGBPosition(r, 0));
339 _period = new wxSpinCtrl (_panel, wxID_ANY);
340 _period->SetRange (1, 60);
341 table->Add (_period, wxGBPosition(r, 1));
342 add_label_to_sizer (table, _panel, _("minutes"), false, wxGBPosition(r, 2));
345 add_label_to_sizer (table, _panel, _("Duration"), true, wxGBPosition(r, 0));
346 _duration = new wxSpinCtrl (_panel, wxID_ANY);
347 _duration->SetRange (100, 5000);
348 table->Add (_duration, wxGBPosition(r, 1));
349 add_label_to_sizer (table, _panel, _("milliseconds"), false, wxGBPosition(r, 2));
352 _theatre->Bind (wxEVT_TEXT, bind(&WatermarkPage::theatre_changed, this));
353 _duration->Bind (wxEVT_SPINCTRL, bind(&WatermarkPage::duration_changed, this));
354 _period->Bind (wxEVT_SPINCTRL, bind(&WatermarkPage::period_changed, this));
357 void config_changed ()
359 Config* config = Config::instance ();
360 checked_set (_theatre, config->player_watermark_theatre());
361 checked_set (_duration, config->player_watermark_duration());
362 checked_set (_period, config->player_watermark_period());
365 void theatre_changed ()
367 Config::instance()->set_player_watermark_theatre(wx_to_std(_theatre->GetValue()));
370 void period_changed ()
372 Config::instance()->set_player_watermark_period(_period->GetValue());
375 void duration_changed ()
377 Config::instance()->set_player_watermark_duration(_duration->GetValue());
380 wxTextCtrl* _theatre;
382 wxSpinCtrl* _duration;
385 class DevicesPage : public StandardPage
388 DevicesPage (wxSize panel_size, int border)
389 : StandardPage (panel_size, border)
392 wxString GetName () const
400 vector<string> columns;
401 columns.push_back(wx_to_std(_("Manufacturer ID")));
402 columns.push_back(wx_to_std(_("Product code")));
403 columns.push_back(wx_to_std(_("Serial")));
404 columns.push_back(wx_to_std(_("Manufacture week")));
405 columns.push_back(wx_to_std(_("Manufacture year")));
406 _monitor_list = new EditableList<Monitor, MonitorDialog> (
409 boost::bind (&Config::required_monitors, Config::instance()),
410 boost::bind (&Config::set_required_monitors, Config::instance(), _1),
411 boost::bind (&DevicesPage::monitor_column, this, _1, _2),
416 _panel->GetSizer()->Add(_monitor_list, 1, wxEXPAND | wxALL, _border);
418 wxButton* get = new wxButton(_panel, wxID_ANY, _("Read current devices"));
419 _panel->GetSizer()->Add(get, 0, wxEXPAND | wxALL, DCPOMATIC_SIZER_GAP);
420 get->Bind(wxEVT_BUTTON, bind(&DevicesPage::get_clicked, this));
425 Config::instance()->set_required_monitors(get_monitors());
426 _monitor_list->refresh ();
429 string monitor_column (Monitor m, int c)
433 return m.manufacturer_id;
435 return locale_convert<string>(m.manufacturer_product_code);
437 return locale_convert<string>(m.serial_number);
439 return locale_convert<string>(m.week_of_manufacture);
441 return locale_convert<string>(m.year_of_manufacture);
443 DCPOMATIC_ASSERT(false);
449 void config_changed ()
451 _monitor_list->refresh ();
455 EditableList<Monitor, MonitorDialog>* _monitor_list;
461 create_player_config_dialog ()
463 wxPreferencesEditor* e = new wxPreferencesEditor ();
466 /* Width that we force some of the config panels to be on OSX so that
467 the containing window doesn't shrink too much when we select those panels.
468 This is obviously an unpleasant hack.
470 wxSize ps = wxSize (520, -1);
471 int const border = 16;
473 wxSize ps = wxSize (-1, -1);
474 int const border = 8;
477 e->AddPage (new PlayerGeneralPage(wxSize(-1, 500), border));
478 e->AddPage (new LocationsPage(ps, border));
479 e->AddPage (new KeysPage(ps, border));
480 #ifdef DCPOMATIC_VARIANT_SWAROOP
481 e->AddPage (new WatermarkPage(ps, border));
482 e->AddPage (new DevicesPage(ps, border));