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, _("DCP directory"), true, wxGBPosition (r, 0));
233 _dcp_directory = new wxDirPickerCtrl (_panel, wxID_ANY, wxEmptyString, wxDirSelectorPromptStr, wxDefaultPosition, wxSize (300, -1));
234 table->Add (_dcp_directory, wxGBPosition (r, 1));
237 add_label_to_sizer (table, _panel, _("KDM directory"), true, wxGBPosition (r, 0));
238 _kdm_directory = new wxDirPickerCtrl (_panel, wxID_ANY, wxEmptyString, wxDirSelectorPromptStr, wxDefaultPosition, wxSize (300, -1));
239 table->Add (_kdm_directory, wxGBPosition (r, 1));
242 #ifdef DCPOMATIC_VARIANT_SWAROOP
243 add_label_to_sizer (table, _panel, _("Background image"), true, wxGBPosition (r, 0));
244 _background_image = new FilePickerCtrl (_panel, _("Select image file"), "*.png;*.jpg;*.jpeg;*.tif;*.tiff", true);
245 table->Add (_background_image, wxGBPosition (r, 1));
249 _dcp_directory->Bind (wxEVT_DIRPICKER_CHANGED, bind(&LocationsPage::dcp_directory_changed, this));
250 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, bind(&LocationsPage::kdm_directory_changed, this));
251 #ifdef DCPOMATIC_VARIANT_SWAROOP
252 _background_image->Bind (wxEVT_FILEPICKER_CHANGED, bind(&LocationsPage::background_image_changed, this));
256 void config_changed ()
258 Config* config = Config::instance ();
260 if (config->player_dcp_directory()) {
261 checked_set (_dcp_directory, *config->player_dcp_directory());
263 if (config->player_kdm_directory()) {
264 checked_set (_kdm_directory, *config->player_kdm_directory());
266 #ifdef DCPOMATIC_VARIANT_SWAROOP
267 if (config->player_background_image()) {
268 checked_set (_background_image, *config->player_background_image());
273 void dcp_directory_changed ()
275 Config::instance()->set_player_dcp_directory(wx_to_std(_dcp_directory->GetPath()));
278 void kdm_directory_changed ()
280 Config::instance()->set_player_kdm_directory(wx_to_std(_kdm_directory->GetPath()));
283 #ifdef DCPOMATIC_VARIANT_SWAROOP
284 void background_image_changed ()
286 Config::instance()->set_player_background_image(wx_to_std(_background_image->GetPath()));
290 wxDirPickerCtrl* _dcp_directory;
291 wxDirPickerCtrl* _kdm_directory;
292 #ifdef DCPOMATIC_VARIANT_SWAROOP
293 FilePickerCtrl* _background_image;
297 #ifdef DCPOMATIC_VARIANT_SWAROOP
298 class WatermarkPage : public StandardPage
301 WatermarkPage (wxSize panel_size, int border)
302 : StandardPage (panel_size, border)
305 wxString GetName () const
307 return _("Watermark");
313 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
314 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
318 add_label_to_sizer (table, _panel, _("Theatre name"), true, wxGBPosition(r, 0));
319 _theatre = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(300, -1));
320 table->Add (_theatre, wxGBPosition(r, 1), wxGBSpan(1, 2));
323 add_label_to_sizer (table, _panel, _("Period"), true, wxGBPosition(r, 0));
324 _period = new wxSpinCtrl (_panel, wxID_ANY);
325 _period->SetRange (1, 60);
326 table->Add (_period, wxGBPosition(r, 1));
327 add_label_to_sizer (table, _panel, _("minutes"), false, wxGBPosition(r, 2));
330 add_label_to_sizer (table, _panel, _("Duration"), true, wxGBPosition(r, 0));
331 _duration = new wxSpinCtrl (_panel, wxID_ANY);
332 _duration->SetRange (100, 5000);
333 table->Add (_duration, wxGBPosition(r, 1));
334 add_label_to_sizer (table, _panel, _("milliseconds"), false, wxGBPosition(r, 2));
337 _theatre->Bind (wxEVT_TEXT, bind(&WatermarkPage::theatre_changed, this));
338 _duration->Bind (wxEVT_SPINCTRL, bind(&WatermarkPage::duration_changed, this));
339 _period->Bind (wxEVT_SPINCTRL, bind(&WatermarkPage::period_changed, this));
342 void config_changed ()
344 Config* config = Config::instance ();
345 checked_set (_theatre, config->player_watermark_theatre());
346 checked_set (_duration, config->player_watermark_duration());
347 checked_set (_period, config->player_watermark_period());
350 void theatre_changed ()
352 Config::instance()->set_player_watermark_theatre(wx_to_std(_theatre->GetValue()));
355 void period_changed ()
357 Config::instance()->set_player_watermark_period(_period->GetValue());
360 void duration_changed ()
362 Config::instance()->set_player_watermark_duration(_duration->GetValue());
365 wxTextCtrl* _theatre;
367 wxSpinCtrl* _duration;
370 class DevicesPage : public StandardPage
373 DevicesPage (wxSize panel_size, int border)
374 : StandardPage (panel_size, border)
377 wxString GetName () const
385 vector<string> columns;
386 columns.push_back(wx_to_std(_("Manufacturer ID")));
387 columns.push_back(wx_to_std(_("Product code")));
388 columns.push_back(wx_to_std(_("Serial")));
389 columns.push_back(wx_to_std(_("Manufacture week")));
390 columns.push_back(wx_to_std(_("Manufacture year")));
391 _monitor_list = new EditableList<Monitor, MonitorDialog> (
394 boost::bind (&Config::required_monitors, Config::instance()),
395 boost::bind (&Config::set_required_monitors, Config::instance(), _1),
396 boost::bind (&DevicesPage::monitor_column, this, _1, _2),
401 _panel->GetSizer()->Add(_monitor_list, 1, wxEXPAND | wxALL, _border);
403 wxButton* get = new wxButton(_panel, wxID_ANY, _("Read current devices"));
404 _panel->GetSizer()->Add(get, 0, wxEXPAND | wxALL, DCPOMATIC_SIZER_GAP);
405 get->Bind(wxEVT_BUTTON, bind(&DevicesPage::get_clicked, this));
410 Config::instance()->set_required_monitors(get_monitors());
411 _monitor_list->refresh ();
414 string monitor_column (Monitor m, int c)
418 return m.manufacturer_id;
420 return locale_convert<string>(m.manufacturer_product_code);
422 return locale_convert<string>(m.serial_number);
424 return locale_convert<string>(m.week_of_manufacture);
426 return locale_convert<string>(m.year_of_manufacture);
428 DCPOMATIC_ASSERT(false);
434 void config_changed ()
436 _monitor_list->refresh ();
440 EditableList<Monitor, MonitorDialog>* _monitor_list;
446 create_player_config_dialog ()
448 wxPreferencesEditor* e = new wxPreferencesEditor ();
451 /* Width that we force some of the config panels to be on OSX so that
452 the containing window doesn't shrink too much when we select those panels.
453 This is obviously an unpleasant hack.
455 wxSize ps = wxSize (520, -1);
456 int const border = 16;
458 wxSize ps = wxSize (-1, -1);
459 int const border = 8;
462 e->AddPage (new PlayerGeneralPage(wxSize(-1, 500), border));
463 e->AddPage (new LocationsPage(ps, border));
464 e->AddPage (new KeysPage(ps, border));
465 #ifdef DCPOMATIC_VARIANT_SWAROOP
466 e->AddPage (new WatermarkPage(ps, border));
467 e->AddPage (new DevicesPage(ps, border));