2 Copyright (C) 2012-2019 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/full_config_dialog.cc
22 * @brief A dialogue to edit all DCP-o-matic configuration.
25 #include "full_config_dialog.h"
27 #include "editable_list.h"
28 #include "filter_dialog.h"
29 #include "dir_picker_ctrl.h"
30 #include "file_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 "config_move_dialog.h"
38 #include "config_dialog.h"
39 #include "static_text.h"
40 #include "check_box.h"
41 #include "dcpomatic_button.h"
42 #include "password_entry.h"
43 #include "lib/config.h"
44 #include "lib/ratio.h"
45 #include "lib/filter.h"
46 #include "lib/dcp_content_type.h"
49 #include "lib/cross.h"
50 #include "lib/exceptions.h"
51 #include <dcp/locale_convert.h>
52 #include <dcp/exceptions.h>
53 #include <dcp/certificate_chain.h>
54 #include <wx/stdpaths.h>
55 #include <wx/preferences.h>
56 #include <wx/spinctrl.h>
57 #include <wx/filepicker.h>
59 #include <boost/filesystem.hpp>
60 #include <boost/foreach.hpp>
71 using boost::shared_ptr;
72 using boost::function;
73 using boost::optional;
74 #if BOOST_VERSION >= 106100
75 using namespace boost::placeholders;
77 using dcp::locale_convert;
79 class FullGeneralPage : public GeneralPage
82 FullGeneralPage (wxSize panel_size, int border)
83 : GeneralPage (panel_size, border)
89 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
90 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
93 add_language_controls (table, r);
95 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
96 _master_encoding_threads = new wxSpinCtrl (_panel);
97 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
100 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
101 _server_encoding_threads = new wxSpinCtrl (_panel);
102 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
105 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
106 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, true);
107 table->Add (_config_file, wxGBPosition (r, 1));
110 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
111 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, true);
112 table->Add (_cinemas_file, wxGBPosition (r, 1));
113 Button* export_cinemas = new Button (_panel, _("Export..."));
114 table->Add (export_cinemas, wxGBPosition (r, 2));
117 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
118 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
119 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
123 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
124 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
127 add_update_controls (table, r);
129 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::config_file_changed, this));
130 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::cinemas_file_changed, this));
132 _master_encoding_threads->SetRange (1, 128);
133 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
134 _server_encoding_threads->SetRange (1, 128);
135 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
136 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
138 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
139 _analyse_ebur128->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::analyse_ebur128_changed, this));
141 _automatic_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::automatic_audio_analysis_changed, this));
144 void config_changed ()
146 Config* config = Config::instance ();
148 checked_set (_master_encoding_threads, config->master_encoding_threads ());
149 checked_set (_server_encoding_threads, config->server_encoding_threads ());
150 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
151 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
153 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
154 checked_set (_config_file, config->config_file());
155 checked_set (_cinemas_file, config->cinemas_file());
157 GeneralPage::config_changed ();
160 void export_cinemas_file ()
162 wxFileDialog* d = new wxFileDialog (
163 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT ("XML files (*.xml)|*.xml"),
164 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
167 if (d->ShowModal () == wxID_OK) {
168 boost::filesystem::copy_file (Config::instance()->cinemas_file(), wx_to_std(d->GetPath()));
173 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
174 void analyse_ebur128_changed ()
176 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
180 void automatic_audio_analysis_changed ()
182 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
185 void master_encoding_threads_changed ()
187 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue ());
190 void server_encoding_threads_changed ()
192 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue ());
195 void config_file_changed ()
197 Config* config = Config::instance();
198 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
199 if (new_file == config->config_file()) {
202 bool copy_and_link = true;
203 if (boost::filesystem::exists(new_file)) {
204 ConfigMoveDialog* d = new ConfigMoveDialog (_panel, new_file);
205 if (d->ShowModal() == wxID_OK) {
206 copy_and_link = false;
213 if (new_file != config->config_file()) {
214 config->copy_and_link (new_file);
217 config->link (new_file);
221 void cinemas_file_changed ()
223 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
226 wxSpinCtrl* _master_encoding_threads;
227 wxSpinCtrl* _server_encoding_threads;
228 FilePickerCtrl* _config_file;
229 FilePickerCtrl* _cinemas_file;
230 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
231 wxCheckBox* _analyse_ebur128;
233 wxCheckBox* _automatic_audio_analysis;
236 class DefaultsPage : public Page
239 DefaultsPage (wxSize panel_size, int border)
240 : Page (panel_size, border)
243 wxString GetName () const
245 return _("Defaults");
249 wxBitmap GetLargeIcon () const
251 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
258 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
259 table->AddGrowableCol (1, 1);
260 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
263 add_label_to_sizer (table, _panel, _("Default duration of still images"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
264 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
265 _still_length = new wxSpinCtrl (_panel);
266 s->Add (_still_length);
267 add_label_to_sizer (s, _panel, _("s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
271 add_label_to_sizer (table, _panel, _("Default directory for new films"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
272 #ifdef DCPOMATIC_USE_OWN_PICKER
273 _directory = new DirPickerCtrl (_panel);
275 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
277 table->Add (_directory, 1, wxEXPAND);
279 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
280 _isdcf_metadata_button = new Button (_panel, _("Edit..."));
281 table->Add (_isdcf_metadata_button);
283 add_label_to_sizer (table, _panel, _("Default container"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
284 _container = new wxChoice (_panel, wxID_ANY);
285 table->Add (_container);
287 add_label_to_sizer (table, _panel, _("Default content type"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
288 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
289 table->Add (_dcp_content_type);
291 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
292 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
293 table->Add (_dcp_audio_channels);
296 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
297 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
298 _j2k_bandwidth = new wxSpinCtrl (_panel);
299 s->Add (_j2k_bandwidth);
300 add_label_to_sizer (s, _panel, _("Mbit/s"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
305 add_label_to_sizer (table, _panel, _("Default audio delay"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
306 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
307 _audio_delay = new wxSpinCtrl (_panel);
308 s->Add (_audio_delay);
309 add_label_to_sizer (s, _panel, _("ms"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
313 add_label_to_sizer (table, _panel, _("Default standard"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
314 _standard = new wxChoice (_panel, wxID_ANY);
315 table->Add (_standard);
317 add_label_to_sizer (table, _panel, _("Default KDM directory"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
318 #ifdef DCPOMATIC_USE_OWN_PICKER
319 _kdm_directory = new DirPickerCtrl (_panel);
321 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
324 table->Add (_kdm_directory, 1, wxEXPAND);
326 _still_length->SetRange (1, 3600);
327 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
329 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
330 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
332 _isdcf_metadata_button->Bind (wxEVT_BUTTON, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
334 BOOST_FOREACH (Ratio const * i, Ratio::containers()) {
335 _container->Append (std_to_wx(i->container_nickname()));
338 _container->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::container_changed, this));
340 BOOST_FOREACH (DCPContentType const * i, DCPContentType::all()) {
341 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
344 setup_audio_channels_choice (_dcp_audio_channels, 2);
346 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
347 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
349 _j2k_bandwidth->SetRange (50, 250);
350 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
352 _audio_delay->SetRange (-1000, 1000);
353 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
355 _standard->Append (_("SMPTE"));
356 _standard->Append (_("Interop"));
357 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
360 void config_changed ()
362 Config* config = Config::instance ();
364 vector<Ratio const *> containers = Ratio::containers ();
365 for (size_t i = 0; i < containers.size(); ++i) {
366 if (containers[i] == config->default_container ()) {
367 _container->SetSelection (i);
371 vector<DCPContentType const *> const ct = DCPContentType::all ();
372 for (size_t i = 0; i < ct.size(); ++i) {
373 if (ct[i] == config->default_dcp_content_type ()) {
374 _dcp_content_type->SetSelection (i);
378 checked_set (_still_length, config->default_still_length ());
379 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
380 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
381 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
382 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
383 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
384 checked_set (_audio_delay, config->default_audio_delay ());
385 checked_set (_standard, config->default_interop() ? 1 : 0);
388 void j2k_bandwidth_changed ()
390 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
393 void audio_delay_changed ()
395 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
398 void dcp_audio_channels_changed ()
400 int const s = _dcp_audio_channels->GetSelection ();
401 if (s != wxNOT_FOUND) {
402 Config::instance()->set_default_dcp_audio_channels (
403 locale_convert<int> (string_client_data (_dcp_audio_channels->GetClientObject (s)))
408 void directory_changed ()
410 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
413 void kdm_directory_changed ()
415 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
418 void edit_isdcf_metadata_clicked ()
420 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
422 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
426 void still_length_changed ()
428 Config::instance()->set_default_still_length (_still_length->GetValue ());
431 void container_changed ()
433 vector<Ratio const *> ratio = Ratio::containers ();
434 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
437 void dcp_content_type_changed ()
439 vector<DCPContentType const *> ct = DCPContentType::all ();
440 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
443 void standard_changed ()
445 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
448 wxSpinCtrl* _j2k_bandwidth;
449 wxSpinCtrl* _audio_delay;
450 wxButton* _isdcf_metadata_button;
451 wxSpinCtrl* _still_length;
452 #ifdef DCPOMATIC_USE_OWN_PICKER
453 DirPickerCtrl* _directory;
454 DirPickerCtrl* _kdm_directory;
456 wxDirPickerCtrl* _directory;
457 wxDirPickerCtrl* _kdm_directory;
459 wxChoice* _container;
460 wxChoice* _dcp_content_type;
461 wxChoice* _dcp_audio_channels;
465 class EncodingServersPage : public Page
468 EncodingServersPage (wxSize panel_size, int border)
469 : Page (panel_size, border)
472 wxString GetName () const
478 wxBitmap GetLargeIcon () const
480 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
487 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
488 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
490 vector<EditableListColumn> columns;
491 columns.push_back (EditableListColumn(_("IP address / host name")));
492 _servers_list = new EditableList<string, ServerDialog> (
495 boost::bind (&Config::servers, Config::instance()),
496 boost::bind (&Config::set_servers, Config::instance(), _1),
497 boost::bind (&EncodingServersPage::server_column, this, _1)
500 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
502 _use_any_servers->Bind (wxEVT_CHECKBOX, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
505 void config_changed ()
507 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
508 _servers_list->refresh ();
511 void use_any_servers_changed ()
513 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
516 string server_column (string s)
521 wxCheckBox* _use_any_servers;
522 EditableList<string, ServerDialog>* _servers_list;
525 class TMSPage : public Page
528 TMSPage (wxSize panel_size, int border)
529 : Page (panel_size, border)
532 wxString GetName () const
538 wxBitmap GetLargeIcon () const
540 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
547 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
548 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
550 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
551 table->AddGrowableCol (1, 1);
552 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
554 add_label_to_sizer (table, _panel, _("Protocol"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
555 _tms_protocol = new wxChoice (_panel, wxID_ANY);
556 table->Add (_tms_protocol, 1, wxEXPAND);
558 add_label_to_sizer (table, _panel, _("IP address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
559 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
560 table->Add (_tms_ip, 1, wxEXPAND);
562 add_label_to_sizer (table, _panel, _("Target path"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
563 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
564 table->Add (_tms_path, 1, wxEXPAND);
566 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
567 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
568 table->Add (_tms_user, 1, wxEXPAND);
570 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
571 _tms_password = new PasswordEntry (_panel);
572 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
574 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
575 _tms_protocol->Append (_("FTP (for Dolby)"));
577 _upload->Bind (wxEVT_CHECKBOX, boost::bind(&TMSPage::upload_changed, this));
578 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
579 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
580 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
581 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
582 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
585 void config_changed ()
587 Config* config = Config::instance ();
589 checked_set (_upload, config->upload_after_make_dcp());
590 checked_set (_tms_protocol, config->tms_protocol ());
591 checked_set (_tms_ip, config->tms_ip ());
592 checked_set (_tms_path, config->tms_path ());
593 checked_set (_tms_user, config->tms_user ());
594 checked_set (_tms_password, config->tms_password ());
597 void upload_changed ()
599 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
602 void tms_protocol_changed ()
604 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
607 void tms_ip_changed ()
609 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
612 void tms_path_changed ()
614 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
617 void tms_user_changed ()
619 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
622 void tms_password_changed ()
624 Config::instance()->set_tms_password (_tms_password->get());
628 wxChoice* _tms_protocol;
630 wxTextCtrl* _tms_path;
631 wxTextCtrl* _tms_user;
632 PasswordEntry* _tms_password;
641 class EmailPage : public Page
644 EmailPage (wxSize panel_size, int border)
645 : Page (panel_size, border)
648 wxString GetName () const
654 wxBitmap GetLargeIcon () const
656 return wxBitmap ("email", wxBITMAP_TYPE_PNG_RESOURCE);
663 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
664 table->AddGrowableCol (1, 1);
665 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
667 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
669 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
670 _server = new wxTextCtrl (_panel, wxID_ANY);
671 s->Add (_server, 1, wxEXPAND | wxALL);
672 add_label_to_sizer (s, _panel, _("port"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
673 _port = new wxSpinCtrl (_panel, wxID_ANY);
674 _port->SetRange (0, 65535);
676 add_label_to_sizer (s, _panel, _("protocol"), false, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
677 _protocol = new wxChoice (_panel, wxID_ANY);
678 /* Make sure this matches the switches in config_changed and port_changed below */
679 _protocol->Append (_("Auto"));
680 _protocol->Append (_("Plain"));
681 _protocol->Append (_("STARTTLS"));
682 _protocol->Append (_("SSL"));
684 table->Add (s, 1, wxEXPAND | wxALL);
687 add_label_to_sizer (table, _panel, _("User name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
688 _user = new wxTextCtrl (_panel, wxID_ANY);
689 table->Add (_user, 1, wxEXPAND | wxALL);
691 add_label_to_sizer (table, _panel, _("Password"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
692 _password = new PasswordEntry (_panel);
693 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
695 _server->Bind (wxEVT_TEXT, boost::bind (&EmailPage::server_changed, this));
696 _port->Bind (wxEVT_SPINCTRL, boost::bind (&EmailPage::port_changed, this));
697 _protocol->Bind (wxEVT_CHOICE, boost::bind (&EmailPage::protocol_changed, this));
698 _user->Bind (wxEVT_TEXT, boost::bind (&EmailPage::user_changed, this));
699 _password->Changed.connect (boost::bind (&EmailPage::password_changed, this));
702 void config_changed ()
704 Config* config = Config::instance ();
706 checked_set (_server, config->mail_server ());
707 checked_set (_port, config->mail_port ());
708 switch (config->mail_protocol()) {
709 case EMAIL_PROTOCOL_AUTO:
710 checked_set (_protocol, 0);
712 case EMAIL_PROTOCOL_PLAIN:
713 checked_set (_protocol, 1);
715 case EMAIL_PROTOCOL_STARTTLS:
716 checked_set (_protocol, 2);
718 case EMAIL_PROTOCOL_SSL:
719 checked_set (_protocol, 3);
722 checked_set (_user, config->mail_user ());
723 checked_set (_password, config->mail_password());
726 void server_changed ()
728 Config::instance()->set_mail_server (wx_to_std (_server->GetValue ()));
733 Config::instance()->set_mail_port (_port->GetValue ());
736 void protocol_changed ()
738 switch (_protocol->GetSelection()) {
740 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_AUTO);
743 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_PLAIN);
746 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_STARTTLS);
749 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_SSL);
756 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
759 void password_changed ()
761 Config::instance()->set_mail_password(_password->get());
768 PasswordEntry* _password;
771 class KDMEmailPage : public Page
775 KDMEmailPage (wxSize panel_size, int border)
777 /* We have to force both width and height of this one */
778 : Page (wxSize (panel_size.GetWidth(), 128), border)
780 : Page (panel_size, border)
784 wxString GetName () const
786 return _("KDM Email");
790 wxBitmap GetLargeIcon () const
792 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
799 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
800 table->AddGrowableCol (1, 1);
801 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
803 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
804 _subject = new wxTextCtrl (_panel, wxID_ANY);
805 table->Add (_subject, 1, wxEXPAND | wxALL);
807 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
808 _from = new wxTextCtrl (_panel, wxID_ANY);
809 table->Add (_from, 1, wxEXPAND | wxALL);
811 vector<EditableListColumn> columns;
812 columns.push_back (EditableListColumn(_("Address")));
813 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
814 _cc = new EditableList<string, EmailDialog> (
817 bind (&Config::kdm_cc, Config::instance()),
818 bind (&Config::set_kdm_cc, Config::instance(), _1),
821 table->Add (_cc, 1, wxEXPAND | wxALL);
823 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
824 _bcc = new wxTextCtrl (_panel, wxID_ANY);
825 table->Add (_bcc, 1, wxEXPAND | wxALL);
827 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
828 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
830 _reset_email = new Button (_panel, _("Reset to default subject and text"));
831 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
835 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
836 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
837 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
838 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
839 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
842 void config_changed ()
844 Config* config = Config::instance ();
846 checked_set (_subject, config->kdm_subject ());
847 checked_set (_from, config->kdm_from ());
848 checked_set (_bcc, config->kdm_bcc ());
849 checked_set (_email, Config::instance()->kdm_email ());
852 void kdm_subject_changed ()
854 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
857 void kdm_from_changed ()
859 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
862 void kdm_bcc_changed ()
864 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
867 void kdm_email_changed ()
869 if (_email->GetValue().IsEmpty ()) {
870 /* Sometimes we get sent an erroneous notification that the email
871 is empty; I don't know why.
875 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
880 Config::instance()->reset_kdm_email ();
881 checked_set (_email, Config::instance()->kdm_email ());
884 wxTextCtrl* _subject;
886 EditableList<string, EmailDialog>* _cc;
889 wxButton* _reset_email;
892 class NotificationsPage : public Page
895 NotificationsPage (wxSize panel_size, int border)
897 /* We have to force both width and height of this one */
898 : Page (wxSize (panel_size.GetWidth(), 128), border)
900 : Page (panel_size, border)
904 wxString GetName () const
906 return _("Notifications");
910 wxBitmap GetLargeIcon () const
912 return wxBitmap ("notifications", wxBITMAP_TYPE_PNG_RESOURCE);
919 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
920 table->AddGrowableCol (1, 1);
921 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
923 _enable_message_box = new CheckBox (_panel, _("Message box"));
924 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
925 table->AddSpacer (0);
927 _enable_email = new CheckBox (_panel, _("Email"));
928 table->Add (_enable_email, 1, wxEXPAND | wxALL);
929 table->AddSpacer (0);
931 add_label_to_sizer (table, _panel, _("Subject"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
932 _subject = new wxTextCtrl (_panel, wxID_ANY);
933 table->Add (_subject, 1, wxEXPAND | wxALL);
935 add_label_to_sizer (table, _panel, _("From address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
936 _from = new wxTextCtrl (_panel, wxID_ANY);
937 table->Add (_from, 1, wxEXPAND | wxALL);
939 add_label_to_sizer (table, _panel, _("To address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
940 _to = new wxTextCtrl (_panel, wxID_ANY);
941 table->Add (_to, 1, wxEXPAND | wxALL);
943 vector<EditableListColumn> columns;
944 columns.push_back (EditableListColumn(_("Address")));
945 add_label_to_sizer (table, _panel, _("CC addresses"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
946 _cc = new EditableList<string, EmailDialog> (
949 bind (&Config::notification_cc, Config::instance()),
950 bind (&Config::set_notification_cc, Config::instance(), _1),
953 table->Add (_cc, 1, wxEXPAND | wxALL);
955 add_label_to_sizer (table, _panel, _("BCC address"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
956 _bcc = new wxTextCtrl (_panel, wxID_ANY);
957 table->Add (_bcc, 1, wxEXPAND | wxALL);
959 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
960 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
962 _reset_email = new Button (_panel, _("Reset to default subject and text"));
963 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
967 _enable_message_box->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX));
968 _enable_email->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL));
970 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
971 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
972 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
973 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
974 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
975 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
977 update_sensitivity ();
980 void update_sensitivity ()
982 bool const s = _enable_email->GetValue();
989 _reset_email->Enable(s);
992 void config_changed ()
994 Config* config = Config::instance ();
996 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
997 checked_set (_enable_email, config->notification(Config::EMAIL));
998 checked_set (_subject, config->notification_subject ());
999 checked_set (_from, config->notification_from ());
1000 checked_set (_to, config->notification_to ());
1001 checked_set (_bcc, config->notification_bcc ());
1002 checked_set (_email, Config::instance()->notification_email ());
1004 update_sensitivity ();
1007 void notification_subject_changed ()
1009 Config::instance()->set_notification_subject (wx_to_std (_subject->GetValue ()));
1012 void notification_from_changed ()
1014 Config::instance()->set_notification_from (wx_to_std (_from->GetValue ()));
1017 void notification_to_changed ()
1019 Config::instance()->set_notification_to (wx_to_std (_to->GetValue ()));
1022 void notification_bcc_changed ()
1024 Config::instance()->set_notification_bcc (wx_to_std (_bcc->GetValue ()));
1027 void notification_email_changed ()
1029 if (_email->GetValue().IsEmpty ()) {
1030 /* Sometimes we get sent an erroneous notification that the email
1031 is empty; I don't know why.
1035 Config::instance()->set_notification_email (wx_to_std (_email->GetValue ()));
1040 Config::instance()->reset_notification_email ();
1041 checked_set (_email, Config::instance()->notification_email ());
1044 void type_changed (wxCheckBox* b, Config::Notification n)
1046 Config::instance()->set_notification(n, b->GetValue());
1047 update_sensitivity ();
1050 wxCheckBox* _enable_message_box;
1051 wxCheckBox* _enable_email;
1053 wxTextCtrl* _subject;
1056 EditableList<string, EmailDialog>* _cc;
1059 wxButton* _reset_email;
1062 class CoverSheetPage : public Page
1066 CoverSheetPage (wxSize panel_size, int border)
1067 #ifdef DCPOMATIC_OSX
1068 /* We have to force both width and height of this one */
1069 : Page (wxSize (panel_size.GetWidth(), 128), border)
1071 : Page (panel_size, border)
1075 wxString GetName () const
1077 return _("Cover Sheet");
1080 #ifdef DCPOMATIC_OSX
1081 wxBitmap GetLargeIcon () const
1083 return wxBitmap ("cover_sheet", wxBITMAP_TYPE_PNG_RESOURCE);
1090 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1091 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1093 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1094 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1096 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1097 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1100 void config_changed ()
1102 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
1105 void cover_sheet_changed ()
1107 if (_cover_sheet->GetValue().IsEmpty ()) {
1108 /* Sometimes we get sent an erroneous notification that the cover sheet
1109 is empty; I don't know why.
1113 Config::instance()->set_cover_sheet (wx_to_std (_cover_sheet->GetValue ()));
1116 void reset_cover_sheet ()
1118 Config::instance()->reset_cover_sheet ();
1119 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
1122 wxTextCtrl* _cover_sheet;
1123 wxButton* _reset_cover_sheet;
1127 class IdentifiersPage : public Page
1130 IdentifiersPage (wxSize panel_size, int border)
1131 : Page (panel_size, border)
1134 wxString GetName () const
1136 return _("Identifiers");
1139 #ifdef DCPOMATIC_OSX
1140 wxBitmap GetLargeIcon () const
1142 return wxBitmap ("identifiers", wxBITMAP_TYPE_PNG_RESOURCE);
1149 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1150 table->AddGrowableCol (1, 1);
1152 add_label_to_sizer (table, _panel, _("Issuer"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1153 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1154 _issuer->SetToolTip (_("This will be written to the DCP's XML files as the <Issuer>. If it is blank, a default value mentioning DCP-o-matic will be used."));
1155 table->Add (_issuer, 1, wxALL | wxEXPAND);
1157 add_label_to_sizer (table, _panel, _("Creator"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1158 _creator = new wxTextCtrl (_panel, wxID_ANY);
1159 _creator->SetToolTip (_("This will be written to the DCP's XML files as the <Creator>. If it is blank, a default value mentioning DCP-o-matic will be used."));
1160 table->Add (_creator, 1, wxALL | wxEXPAND);
1162 add_label_to_sizer (table, _panel, _("Company name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1163 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1164 _company_name->SetToolTip (_("This will be written to the DCP's MXF files as the 'company name'. If it is blank, a default value mentioning libdcp (an internal DCP-o-matic library) will be used."));
1165 table->Add (_company_name, 1, wxALL | wxEXPAND);
1167 add_label_to_sizer (table, _panel, _("Product name"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1168 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1169 _product_name->SetToolTip (_("This will be written to the DCP's MXF files as the 'product name'. If it is blank, a default value mentioning libdcp (an internal DCP-o-matic library) will be used."));
1170 table->Add (_product_name, 1, wxALL | wxEXPAND);
1172 add_label_to_sizer (table, _panel, _("Product version"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1173 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1174 _product_version->SetToolTip (_("This will be written to the DCP's MXF files as the 'product version'. If it is blank, a default value mentioning libdcp (an internal DCP-o-matic library) will be used."));
1175 table->Add (_product_version, 1, wxALL | wxEXPAND);
1177 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1178 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1179 _j2k_comment->SetToolTip (_("This will be written to the DCP's JPEG2000 data as a comment. If it is blank, a default value mentioning libdcp (an internal DCP-o-matic library) will be used."));
1180 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1182 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1184 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1185 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1186 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1187 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1188 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1189 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1192 void config_changed ()
1194 Config* config = Config::instance ();
1195 checked_set (_issuer, config->dcp_issuer ());
1196 checked_set (_creator, config->dcp_creator ());
1197 checked_set (_company_name, config->dcp_company_name ());
1198 checked_set (_product_name, config->dcp_product_name ());
1199 checked_set (_product_version, config->dcp_product_version ());
1200 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1203 void issuer_changed ()
1205 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
1208 void creator_changed ()
1210 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
1213 void company_name_changed ()
1215 Config::instance()->set_dcp_company_name (wx_to_std(_company_name->GetValue()));
1218 void product_name_changed ()
1220 Config::instance()->set_dcp_product_name (wx_to_std(_product_name->GetValue()));
1223 void product_version_changed ()
1225 Config::instance()->set_dcp_product_version (wx_to_std(_product_version->GetValue()));
1228 void j2k_comment_changed ()
1230 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1233 wxTextCtrl* _issuer;
1234 wxTextCtrl* _creator;
1235 wxTextCtrl* _company_name;
1236 wxTextCtrl* _product_name;
1237 wxTextCtrl* _product_version;
1238 wxTextCtrl* _j2k_comment;
1242 /** @class AdvancedPage
1243 * @brief Advanced page of the preferences dialog.
1245 class AdvancedPage : public Page
1248 AdvancedPage (wxSize panel_size, int border)
1249 : Page (panel_size, border)
1250 , _maximum_j2k_bandwidth (0)
1251 , _allow_any_dcp_frame_rate (0)
1252 , _allow_any_container (0)
1253 , _show_experimental_audio_processors (0)
1254 , _only_servers_encode (0)
1259 , _log_debug_threed (0)
1260 , _log_debug_encode (0)
1261 , _log_debug_email (0)
1262 , _log_debug_video_view (0)
1263 , _log_debug_player (0)
1264 , _log_debug_audio_analysis (0)
1267 wxString GetName () const
1269 return _("Advanced");
1272 #ifdef DCPOMATIC_OSX
1273 wxBitmap GetLargeIcon () const
1275 return wxBitmap ("advanced", wxBITMAP_TYPE_PNG_RESOURCE);
1280 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1282 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1284 flags |= wxALIGN_RIGHT;
1287 wxStaticText* m = new StaticText (parent, text);
1288 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1293 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1294 table->AddGrowableCol (1, 1);
1295 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1298 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1299 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1300 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1301 s->Add (_maximum_j2k_bandwidth, 1);
1302 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1306 add_label_to_sizer (table, _panel, _("Video display mode"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1307 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1308 table->Add (_video_display_mode);
1310 wxStaticText* restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1311 wxFont font = restart->GetFont();
1312 font.SetStyle (wxFONTSTYLE_ITALIC);
1313 font.SetPointSize (font.GetPointSize() - 1);
1314 restart->SetFont (font);
1315 table->AddSpacer (0);
1317 _allow_any_dcp_frame_rate = new CheckBox (_panel, _("Allow any DCP frame rate"));
1318 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1319 table->AddSpacer (0);
1321 _allow_any_container = new CheckBox (_panel, _("Allow full-frame and non-standard container ratios"));
1322 table->Add (_allow_any_container, 1, wxEXPAND | wxALL);
1323 table->AddSpacer (0);
1325 restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to see all ratios)"), false);
1326 restart->SetFont (font);
1327 table->AddSpacer (0);
1329 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1330 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxALL);
1331 table->AddSpacer (0);
1333 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1334 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1335 table->AddSpacer (0);
1338 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true, 0, wxLEFT | wxRIGHT | wxALIGN_CENTRE_VERTICAL);
1339 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1340 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1341 s->Add (_frames_in_memory_multiplier, 1);
1346 add_top_aligned_label_to_sizer (table, _panel, _("DCP metadata filename format"));
1347 dcp::NameFormat::Map titles;
1348 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1349 dcp::NameFormat::Map examples;
1350 examples['t'] = "cpl";
1351 _dcp_metadata_filename_format = new NameFormatEditor (
1352 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1354 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1358 add_top_aligned_label_to_sizer (table, _panel, _("DCP asset filename format"));
1359 dcp::NameFormat::Map titles;
1360 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1361 titles['r'] = wx_to_std (_("reel number"));
1362 titles['n'] = wx_to_std (_("number of reels"));
1363 titles['c'] = wx_to_std (_("content filename"));
1364 dcp::NameFormat::Map examples;
1365 examples['t'] = "j2c";
1366 examples['r'] = "1";
1367 examples['n'] = "4";
1368 examples['c'] = "myfile.mp4";
1369 _dcp_asset_filename_format = new NameFormatEditor (
1370 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1372 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1376 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1377 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1378 _log_general = new CheckBox (_panel, _("General"));
1379 t->Add (_log_general, 1, wxEXPAND | wxALL);
1380 _log_warning = new CheckBox (_panel, _("Warnings"));
1381 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1382 _log_error = new CheckBox (_panel, _("Errors"));
1383 t->Add (_log_error, 1, wxEXPAND | wxALL);
1384 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1385 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1386 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1387 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1388 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1389 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1390 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1391 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1392 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1393 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1394 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1395 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1396 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1397 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1398 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1399 table->Add (t, 0, wxALL, 6);
1402 #ifdef DCPOMATIC_WINDOWS
1403 _win32_console = new CheckBox (_panel, _("Open console window"));
1404 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1405 table->AddSpacer (0);
1408 _maximum_j2k_bandwidth->SetRange (1, 1000);
1409 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1410 _video_display_mode->Append (_("Simple (safer)"));
1411 _video_display_mode->Append (_("OpenGL (faster)"));
1412 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1413 _allow_any_dcp_frame_rate->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1414 _allow_any_container->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_container_changed, this));
1415 _show_experimental_audio_processors->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::show_experimental_audio_processors_changed, this));
1416 _only_servers_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1417 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1418 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1419 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1420 _log_general->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1421 _log_warning->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1422 _log_error->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1423 _log_timing->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1424 _log_debug_threed->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1425 _log_debug_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1426 _log_debug_email->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1427 _log_debug_video_view->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1428 _log_debug_player->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1429 _log_debug_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1430 #ifdef DCPOMATIC_WINDOWS
1431 _win32_console->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::win32_console_changed, this));
1435 void config_changed ()
1437 Config* config = Config::instance ();
1439 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1440 switch (config->video_view_type()) {
1441 case Config::VIDEO_VIEW_SIMPLE:
1442 checked_set (_video_display_mode, 0);
1444 case Config::VIDEO_VIEW_OPENGL:
1445 checked_set (_video_display_mode, 1);
1448 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1449 checked_set (_allow_any_container, config->allow_any_container ());
1450 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1451 checked_set (_only_servers_encode, config->only_servers_encode ());
1452 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1453 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1454 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1455 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1456 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREED);
1457 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1458 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1459 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1460 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1461 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1462 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1463 #ifdef DCPOMATIC_WINDOWS
1464 checked_set (_win32_console, config->win32_console());
1468 void maximum_j2k_bandwidth_changed ()
1470 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1473 void video_display_mode_changed ()
1475 if (_video_display_mode->GetSelection() == 0) {
1476 Config::instance()->set_video_view_type (Config::VIDEO_VIEW_SIMPLE);
1478 Config::instance()->set_video_view_type (Config::VIDEO_VIEW_OPENGL);
1482 void frames_in_memory_multiplier_changed ()
1484 Config::instance()->set_frames_in_memory_multiplier (_frames_in_memory_multiplier->GetValue());
1487 void allow_any_dcp_frame_rate_changed ()
1489 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1492 void allow_any_container_changed ()
1494 Config::instance()->set_allow_any_container (_allow_any_container->GetValue ());
1497 void show_experimental_audio_processors_changed ()
1499 Config::instance()->set_show_experimental_audio_processors (_show_experimental_audio_processors->GetValue ());
1502 void only_servers_encode_changed ()
1504 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1507 void dcp_metadata_filename_format_changed ()
1509 Config::instance()->set_dcp_metadata_filename_format (_dcp_metadata_filename_format->get ());
1512 void dcp_asset_filename_format_changed ()
1514 Config::instance()->set_dcp_asset_filename_format (_dcp_asset_filename_format->get ());
1520 if (_log_general->GetValue ()) {
1521 types |= LogEntry::TYPE_GENERAL;
1523 if (_log_warning->GetValue ()) {
1524 types |= LogEntry::TYPE_WARNING;
1526 if (_log_error->GetValue ()) {
1527 types |= LogEntry::TYPE_ERROR;
1529 if (_log_timing->GetValue ()) {
1530 types |= LogEntry::TYPE_TIMING;
1532 if (_log_debug_threed->GetValue ()) {
1533 types |= LogEntry::TYPE_DEBUG_THREED;
1535 if (_log_debug_encode->GetValue ()) {
1536 types |= LogEntry::TYPE_DEBUG_ENCODE;
1538 if (_log_debug_email->GetValue ()) {
1539 types |= LogEntry::TYPE_DEBUG_EMAIL;
1541 if (_log_debug_video_view->GetValue()) {
1542 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1544 if (_log_debug_player->GetValue()) {
1545 types |= LogEntry::TYPE_DEBUG_PLAYER;
1547 if (_log_debug_audio_analysis->GetValue()) {
1548 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1550 Config::instance()->set_log_types (types);
1553 #ifdef DCPOMATIC_WINDOWS
1554 void win32_console_changed ()
1556 Config::instance()->set_win32_console (_win32_console->GetValue ());
1560 wxSpinCtrl* _maximum_j2k_bandwidth;
1561 wxChoice* _video_display_mode;
1562 wxSpinCtrl* _frames_in_memory_multiplier;
1563 wxCheckBox* _allow_any_dcp_frame_rate;
1564 wxCheckBox* _allow_any_container;
1565 wxCheckBox* _show_experimental_audio_processors;
1566 wxCheckBox* _only_servers_encode;
1567 NameFormatEditor* _dcp_metadata_filename_format;
1568 NameFormatEditor* _dcp_asset_filename_format;
1569 wxCheckBox* _log_general;
1570 wxCheckBox* _log_warning;
1571 wxCheckBox* _log_error;
1572 wxCheckBox* _log_timing;
1573 wxCheckBox* _log_debug_threed;
1574 wxCheckBox* _log_debug_encode;
1575 wxCheckBox* _log_debug_email;
1576 wxCheckBox* _log_debug_video_view;
1577 wxCheckBox* _log_debug_player;
1578 wxCheckBox* _log_debug_audio_analysis;
1579 #ifdef DCPOMATIC_WINDOWS
1580 wxCheckBox* _win32_console;
1584 wxPreferencesEditor*
1585 create_full_config_dialog ()
1587 wxPreferencesEditor* e = new wxPreferencesEditor ();
1589 #ifdef DCPOMATIC_OSX
1590 /* Width that we force some of the config panels to be on OSX so that
1591 the containing window doesn't shrink too much when we select those panels.
1592 This is obviously an unpleasant hack.
1594 wxSize ps = wxSize (700, -1);
1595 int const border = 16;
1597 wxSize ps = wxSize (-1, -1);
1598 int const border = 8;
1601 e->AddPage (new FullGeneralPage (ps, border));
1602 e->AddPage (new SoundPage (ps, border));
1603 e->AddPage (new DefaultsPage (ps, border));
1604 e->AddPage (new EncodingServersPage (ps, border));
1605 e->AddPage (new KeysPage (ps, border));
1606 e->AddPage (new TMSPage (ps, border));
1607 e->AddPage (new EmailPage (ps, border));
1608 e->AddPage (new KDMEmailPage (ps, border));
1609 e->AddPage (new NotificationsPage (ps, border));
1610 e->AddPage (new CoverSheetPage (ps, border));
1611 e->AddPage (new IdentifiersPage (ps, border));
1612 e->AddPage (new AdvancedPage (ps, border));