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 using dcp::locale_convert;
76 class FullGeneralPage : public GeneralPage
79 FullGeneralPage (wxSize panel_size, int border)
80 : GeneralPage (panel_size, border)
86 wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
87 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
90 add_language_controls (table, r);
92 add_label_to_sizer (table, _panel, _("Interface complexity"), true, wxGBPosition(r, 0));
93 _interface_complexity = new wxChoice (_panel, wxID_ANY);
94 table->Add (_interface_complexity, wxGBPosition (r, 1));
97 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
98 _master_encoding_threads = new wxSpinCtrl (_panel);
99 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
102 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
103 _server_encoding_threads = new wxSpinCtrl (_panel);
104 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
107 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
108 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, true);
109 table->Add (_config_file, wxGBPosition (r, 1));
112 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
113 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, true);
114 table->Add (_cinemas_file, wxGBPosition (r, 1));
115 Button* export_cinemas = new Button (_panel, _("Export..."));
116 table->Add (export_cinemas, wxGBPosition (r, 2));
119 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
120 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
121 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
125 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
126 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
129 add_update_controls (table, r);
131 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::config_file_changed, this));
132 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::cinemas_file_changed, this));
134 _interface_complexity->Append (_("Simple"));
135 _interface_complexity->Append (_("Full"));
136 _interface_complexity->Bind (wxEVT_CHOICE, boost::bind(&FullGeneralPage::interface_complexity_changed, this));
138 _master_encoding_threads->SetRange (1, 128);
139 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
140 _server_encoding_threads->SetRange (1, 128);
141 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
142 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
144 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
145 _analyse_ebur128->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::analyse_ebur128_changed, this));
147 _automatic_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::automatic_audio_analysis_changed, this));
150 void config_changed ()
152 Config* config = Config::instance ();
154 switch (config->interface_complexity()) {
155 case Config::INTERFACE_SIMPLE:
156 checked_set (_interface_complexity, 0);
158 case Config::INTERFACE_FULL:
159 checked_set (_interface_complexity, 1);
162 checked_set (_master_encoding_threads, config->master_encoding_threads ());
163 checked_set (_server_encoding_threads, config->server_encoding_threads ());
164 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
165 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
167 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
168 checked_set (_config_file, config->config_file());
169 checked_set (_cinemas_file, config->cinemas_file());
171 GeneralPage::config_changed ();
174 void export_cinemas_file ()
176 wxFileDialog* d = new wxFileDialog (
177 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT ("XML files (*.xml)|*.xml"),
178 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
181 if (d->ShowModal () == wxID_OK) {
182 boost::filesystem::copy_file (Config::instance()->cinemas_file(), wx_to_std(d->GetPath()));
187 void interface_complexity_changed ()
189 if (_interface_complexity->GetSelection() == 0) {
190 Config::instance()->set_interface_complexity (Config::INTERFACE_SIMPLE);
192 Config::instance()->set_interface_complexity (Config::INTERFACE_FULL);
197 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
198 void analyse_ebur128_changed ()
200 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
204 void automatic_audio_analysis_changed ()
206 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
209 void master_encoding_threads_changed ()
211 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue ());
214 void server_encoding_threads_changed ()
216 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue ());
219 void config_file_changed ()
221 Config* config = Config::instance();
222 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
223 if (new_file == config->config_file()) {
226 bool copy_and_link = true;
227 if (boost::filesystem::exists(new_file)) {
228 ConfigMoveDialog* d = new ConfigMoveDialog (_panel, new_file);
229 if (d->ShowModal() == wxID_OK) {
230 copy_and_link = false;
237 if (new_file != config->config_file()) {
238 config->copy_and_link (new_file);
241 config->link (new_file);
245 void cinemas_file_changed ()
247 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
250 wxChoice* _interface_complexity;
251 wxSpinCtrl* _master_encoding_threads;
252 wxSpinCtrl* _server_encoding_threads;
253 FilePickerCtrl* _config_file;
254 FilePickerCtrl* _cinemas_file;
255 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
256 wxCheckBox* _analyse_ebur128;
258 wxCheckBox* _automatic_audio_analysis;
261 class DefaultsPage : public Page
264 DefaultsPage (wxSize panel_size, int border)
265 : Page (panel_size, border)
268 wxString GetName () const
270 return _("Defaults");
274 wxBitmap GetLargeIcon () const
276 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
283 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
284 table->AddGrowableCol (1, 1);
285 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
288 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
289 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
290 _still_length = new wxSpinCtrl (_panel);
291 s->Add (_still_length);
292 add_label_to_sizer (s, _panel, _("s"), false);
296 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
297 #ifdef DCPOMATIC_USE_OWN_PICKER
298 _directory = new DirPickerCtrl (_panel);
300 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
302 table->Add (_directory, 1, wxEXPAND);
304 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
305 _isdcf_metadata_button = new Button (_panel, _("Edit..."));
306 table->Add (_isdcf_metadata_button);
308 add_label_to_sizer (table, _panel, _("Default container"), true);
309 _container = new wxChoice (_panel, wxID_ANY);
310 table->Add (_container);
312 add_label_to_sizer (table, _panel, _("Default content type"), true);
313 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
314 table->Add (_dcp_content_type);
316 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true);
317 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
318 table->Add (_dcp_audio_channels);
321 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
322 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
323 _j2k_bandwidth = new wxSpinCtrl (_panel);
324 s->Add (_j2k_bandwidth);
325 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
330 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
331 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
332 _audio_delay = new wxSpinCtrl (_panel);
333 s->Add (_audio_delay);
334 add_label_to_sizer (s, _panel, _("ms"), false);
338 add_label_to_sizer (table, _panel, _("Default standard"), true);
339 _standard = new wxChoice (_panel, wxID_ANY);
340 table->Add (_standard);
342 add_label_to_sizer (table, _panel, _("Default KDM directory"), true);
343 #ifdef DCPOMATIC_USE_OWN_PICKER
344 _kdm_directory = new DirPickerCtrl (_panel);
346 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
349 table->Add (_kdm_directory, 1, wxEXPAND);
351 _still_length->SetRange (1, 3600);
352 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
354 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
355 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
357 _isdcf_metadata_button->Bind (wxEVT_BUTTON, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
359 BOOST_FOREACH (Ratio const * i, Ratio::containers()) {
360 _container->Append (std_to_wx(i->container_nickname()));
363 _container->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::container_changed, this));
365 BOOST_FOREACH (DCPContentType const * i, DCPContentType::all()) {
366 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
369 setup_audio_channels_choice (_dcp_audio_channels, 2);
371 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
372 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
374 _j2k_bandwidth->SetRange (50, 250);
375 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
377 _audio_delay->SetRange (-1000, 1000);
378 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
380 _standard->Append (_("SMPTE"));
381 _standard->Append (_("Interop"));
382 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
385 void config_changed ()
387 Config* config = Config::instance ();
389 vector<Ratio const *> containers = Ratio::containers ();
390 for (size_t i = 0; i < containers.size(); ++i) {
391 if (containers[i] == config->default_container ()) {
392 _container->SetSelection (i);
396 vector<DCPContentType const *> const ct = DCPContentType::all ();
397 for (size_t i = 0; i < ct.size(); ++i) {
398 if (ct[i] == config->default_dcp_content_type ()) {
399 _dcp_content_type->SetSelection (i);
403 checked_set (_still_length, config->default_still_length ());
404 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
405 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
406 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
407 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
408 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
409 checked_set (_audio_delay, config->default_audio_delay ());
410 checked_set (_standard, config->default_interop() ? 1 : 0);
413 void j2k_bandwidth_changed ()
415 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
418 void audio_delay_changed ()
420 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
423 void dcp_audio_channels_changed ()
425 int const s = _dcp_audio_channels->GetSelection ();
426 if (s != wxNOT_FOUND) {
427 Config::instance()->set_default_dcp_audio_channels (
428 locale_convert<int> (string_client_data (_dcp_audio_channels->GetClientObject (s)))
433 void directory_changed ()
435 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
438 void kdm_directory_changed ()
440 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
443 void edit_isdcf_metadata_clicked ()
445 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
447 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
451 void still_length_changed ()
453 Config::instance()->set_default_still_length (_still_length->GetValue ());
456 void container_changed ()
458 vector<Ratio const *> ratio = Ratio::containers ();
459 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
462 void dcp_content_type_changed ()
464 vector<DCPContentType const *> ct = DCPContentType::all ();
465 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
468 void standard_changed ()
470 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
473 wxSpinCtrl* _j2k_bandwidth;
474 wxSpinCtrl* _audio_delay;
475 wxButton* _isdcf_metadata_button;
476 wxSpinCtrl* _still_length;
477 #ifdef DCPOMATIC_USE_OWN_PICKER
478 DirPickerCtrl* _directory;
479 DirPickerCtrl* _kdm_directory;
481 wxDirPickerCtrl* _directory;
482 wxDirPickerCtrl* _kdm_directory;
484 wxChoice* _container;
485 wxChoice* _dcp_content_type;
486 wxChoice* _dcp_audio_channels;
490 class EncodingServersPage : public Page
493 EncodingServersPage (wxSize panel_size, int border)
494 : Page (panel_size, border)
497 wxString GetName () const
503 wxBitmap GetLargeIcon () const
505 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
512 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
513 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
515 vector<EditableListColumn> columns;
516 columns.push_back (EditableListColumn(wx_to_std(_("IP address / host name"))));
517 _servers_list = new EditableList<string, ServerDialog> (
520 boost::bind (&Config::servers, Config::instance()),
521 boost::bind (&Config::set_servers, Config::instance(), _1),
522 boost::bind (&EncodingServersPage::server_column, this, _1)
525 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
527 _use_any_servers->Bind (wxEVT_CHECKBOX, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
530 void config_changed ()
532 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
533 _servers_list->refresh ();
536 void use_any_servers_changed ()
538 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
541 string server_column (string s)
546 wxCheckBox* _use_any_servers;
547 EditableList<string, ServerDialog>* _servers_list;
550 class TMSPage : public Page
553 TMSPage (wxSize panel_size, int border)
554 : Page (panel_size, border)
557 wxString GetName () const
563 wxBitmap GetLargeIcon () const
565 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
572 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
573 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
575 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
576 table->AddGrowableCol (1, 1);
577 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
579 add_label_to_sizer (table, _panel, _("Protocol"), true);
580 _tms_protocol = new wxChoice (_panel, wxID_ANY);
581 table->Add (_tms_protocol, 1, wxEXPAND);
583 add_label_to_sizer (table, _panel, _("IP address"), true);
584 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
585 table->Add (_tms_ip, 1, wxEXPAND);
587 add_label_to_sizer (table, _panel, _("Target path"), true);
588 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
589 table->Add (_tms_path, 1, wxEXPAND);
591 add_label_to_sizer (table, _panel, _("User name"), true);
592 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
593 table->Add (_tms_user, 1, wxEXPAND);
595 add_label_to_sizer (table, _panel, _("Password"), true);
596 _tms_password = new PasswordEntry (_panel);
597 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
599 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
600 _tms_protocol->Append (_("FTP (for Dolby)"));
602 _upload->Bind (wxEVT_CHECKBOX, boost::bind(&TMSPage::upload_changed, this));
603 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
604 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
605 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
606 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
607 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
610 void config_changed ()
612 Config* config = Config::instance ();
614 checked_set (_upload, config->upload_after_make_dcp());
615 checked_set (_tms_protocol, config->tms_protocol ());
616 checked_set (_tms_ip, config->tms_ip ());
617 checked_set (_tms_path, config->tms_path ());
618 checked_set (_tms_user, config->tms_user ());
619 checked_set (_tms_password, config->tms_password ());
622 void upload_changed ()
624 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
627 void tms_protocol_changed ()
629 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
632 void tms_ip_changed ()
634 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
637 void tms_path_changed ()
639 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
642 void tms_user_changed ()
644 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
647 void tms_password_changed ()
649 Config::instance()->set_tms_password (_tms_password->get());
653 wxChoice* _tms_protocol;
655 wxTextCtrl* _tms_path;
656 wxTextCtrl* _tms_user;
657 PasswordEntry* _tms_password;
666 class EmailPage : public Page
669 EmailPage (wxSize panel_size, int border)
670 : Page (panel_size, border)
673 wxString GetName () const
679 wxBitmap GetLargeIcon () const
681 return wxBitmap ("email", wxBITMAP_TYPE_PNG_RESOURCE);
688 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
689 table->AddGrowableCol (1, 1);
690 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
692 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
694 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
695 _server = new wxTextCtrl (_panel, wxID_ANY);
696 s->Add (_server, 1, wxEXPAND | wxALL);
697 add_label_to_sizer (s, _panel, _("port"), false);
698 _port = new wxSpinCtrl (_panel, wxID_ANY);
699 _port->SetRange (0, 65535);
701 add_label_to_sizer (s, _panel, _("protocol"), false);
702 _protocol = new wxChoice (_panel, wxID_ANY);
703 /* Make sure this matches the switches in config_changed and port_changed below */
704 _protocol->Append (_("Auto"));
705 _protocol->Append (_("Plain"));
706 _protocol->Append (_("STARTTLS"));
707 _protocol->Append (_("SSL"));
709 table->Add (s, 1, wxEXPAND | wxALL);
712 add_label_to_sizer (table, _panel, _("User name"), true);
713 _user = new wxTextCtrl (_panel, wxID_ANY);
714 table->Add (_user, 1, wxEXPAND | wxALL);
716 add_label_to_sizer (table, _panel, _("Password"), true);
717 _password = new PasswordEntry (_panel);
718 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
720 _server->Bind (wxEVT_TEXT, boost::bind (&EmailPage::server_changed, this));
721 _port->Bind (wxEVT_SPINCTRL, boost::bind (&EmailPage::port_changed, this));
722 _protocol->Bind (wxEVT_CHOICE, boost::bind (&EmailPage::protocol_changed, this));
723 _user->Bind (wxEVT_TEXT, boost::bind (&EmailPage::user_changed, this));
724 _password->Changed.connect (boost::bind (&EmailPage::password_changed, this));
727 void config_changed ()
729 Config* config = Config::instance ();
731 checked_set (_server, config->mail_server ());
732 checked_set (_port, config->mail_port ());
733 switch (config->mail_protocol()) {
734 case EMAIL_PROTOCOL_AUTO:
735 checked_set (_protocol, 0);
737 case EMAIL_PROTOCOL_PLAIN:
738 checked_set (_protocol, 1);
740 case EMAIL_PROTOCOL_STARTTLS:
741 checked_set (_protocol, 2);
743 case EMAIL_PROTOCOL_SSL:
744 checked_set (_protocol, 3);
747 checked_set (_user, config->mail_user ());
748 checked_set (_password, config->mail_password());
751 void server_changed ()
753 Config::instance()->set_mail_server (wx_to_std (_server->GetValue ()));
758 Config::instance()->set_mail_port (_port->GetValue ());
761 void protocol_changed ()
763 switch (_protocol->GetSelection()) {
765 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_AUTO);
768 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_PLAIN);
771 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_STARTTLS);
774 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_SSL);
781 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
784 void password_changed ()
786 Config::instance()->set_mail_password(_password->get());
793 PasswordEntry* _password;
796 class KDMEmailPage : public Page
800 KDMEmailPage (wxSize panel_size, int border)
802 /* We have to force both width and height of this one */
803 : Page (wxSize (panel_size.GetWidth(), 128), border)
805 : Page (panel_size, border)
809 wxString GetName () const
811 return _("KDM Email");
815 wxBitmap GetLargeIcon () const
817 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
824 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
825 table->AddGrowableCol (1, 1);
826 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
828 add_label_to_sizer (table, _panel, _("Subject"), true);
829 _subject = new wxTextCtrl (_panel, wxID_ANY);
830 table->Add (_subject, 1, wxEXPAND | wxALL);
832 add_label_to_sizer (table, _panel, _("From address"), true);
833 _from = new wxTextCtrl (_panel, wxID_ANY);
834 table->Add (_from, 1, wxEXPAND | wxALL);
836 vector<EditableListColumn> columns;
837 columns.push_back (EditableListColumn(wx_to_std(_("Address"))));
838 add_label_to_sizer (table, _panel, _("CC addresses"), true);
839 _cc = new EditableList<string, EmailDialog> (
842 bind (&Config::kdm_cc, Config::instance()),
843 bind (&Config::set_kdm_cc, Config::instance(), _1),
846 table->Add (_cc, 1, wxEXPAND | wxALL);
848 add_label_to_sizer (table, _panel, _("BCC address"), true);
849 _bcc = new wxTextCtrl (_panel, wxID_ANY);
850 table->Add (_bcc, 1, wxEXPAND | wxALL);
852 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
853 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
855 _reset_email = new Button (_panel, _("Reset to default subject and text"));
856 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
860 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
861 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
862 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
863 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
864 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
867 void config_changed ()
869 Config* config = Config::instance ();
871 checked_set (_subject, config->kdm_subject ());
872 checked_set (_from, config->kdm_from ());
873 checked_set (_bcc, config->kdm_bcc ());
874 checked_set (_email, Config::instance()->kdm_email ());
877 void kdm_subject_changed ()
879 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
882 void kdm_from_changed ()
884 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
887 void kdm_bcc_changed ()
889 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
892 void kdm_email_changed ()
894 if (_email->GetValue().IsEmpty ()) {
895 /* Sometimes we get sent an erroneous notification that the email
896 is empty; I don't know why.
900 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
905 Config::instance()->reset_kdm_email ();
906 checked_set (_email, Config::instance()->kdm_email ());
909 wxTextCtrl* _subject;
911 EditableList<string, EmailDialog>* _cc;
914 wxButton* _reset_email;
917 class NotificationsPage : public Page
920 NotificationsPage (wxSize panel_size, int border)
922 /* We have to force both width and height of this one */
923 : Page (wxSize (panel_size.GetWidth(), 128), border)
925 : Page (panel_size, border)
929 wxString GetName () const
931 return _("Notifications");
935 wxBitmap GetLargeIcon () const
937 return wxBitmap ("notifications", wxBITMAP_TYPE_PNG_RESOURCE);
944 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
945 table->AddGrowableCol (1, 1);
946 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
948 _enable_message_box = new CheckBox (_panel, _("Message box"));
949 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
950 table->AddSpacer (0);
952 _enable_email = new CheckBox (_panel, _("Email"));
953 table->Add (_enable_email, 1, wxEXPAND | wxALL);
954 table->AddSpacer (0);
956 add_label_to_sizer (table, _panel, _("Subject"), true);
957 _subject = new wxTextCtrl (_panel, wxID_ANY);
958 table->Add (_subject, 1, wxEXPAND | wxALL);
960 add_label_to_sizer (table, _panel, _("From address"), true);
961 _from = new wxTextCtrl (_panel, wxID_ANY);
962 table->Add (_from, 1, wxEXPAND | wxALL);
964 add_label_to_sizer (table, _panel, _("To address"), true);
965 _to = new wxTextCtrl (_panel, wxID_ANY);
966 table->Add (_to, 1, wxEXPAND | wxALL);
968 vector<EditableListColumn> columns;
969 columns.push_back (EditableListColumn(wx_to_std(_("Address"))));
970 add_label_to_sizer (table, _panel, _("CC addresses"), true);
971 _cc = new EditableList<string, EmailDialog> (
974 bind (&Config::notification_cc, Config::instance()),
975 bind (&Config::set_notification_cc, Config::instance(), _1),
978 table->Add (_cc, 1, wxEXPAND | wxALL);
980 add_label_to_sizer (table, _panel, _("BCC address"), true);
981 _bcc = new wxTextCtrl (_panel, wxID_ANY);
982 table->Add (_bcc, 1, wxEXPAND | wxALL);
984 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
985 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
987 _reset_email = new Button (_panel, _("Reset to default subject and text"));
988 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
992 _enable_message_box->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX));
993 _enable_email->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL));
995 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
996 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
997 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
998 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
999 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
1000 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
1002 update_sensitivity ();
1005 void update_sensitivity ()
1007 bool const s = _enable_email->GetValue();
1008 _subject->Enable(s);
1014 _reset_email->Enable(s);
1017 void config_changed ()
1019 Config* config = Config::instance ();
1021 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
1022 checked_set (_enable_email, config->notification(Config::EMAIL));
1023 checked_set (_subject, config->notification_subject ());
1024 checked_set (_from, config->notification_from ());
1025 checked_set (_to, config->notification_to ());
1026 checked_set (_bcc, config->notification_bcc ());
1027 checked_set (_email, Config::instance()->notification_email ());
1029 update_sensitivity ();
1032 void notification_subject_changed ()
1034 Config::instance()->set_notification_subject (wx_to_std (_subject->GetValue ()));
1037 void notification_from_changed ()
1039 Config::instance()->set_notification_from (wx_to_std (_from->GetValue ()));
1042 void notification_to_changed ()
1044 Config::instance()->set_notification_to (wx_to_std (_to->GetValue ()));
1047 void notification_bcc_changed ()
1049 Config::instance()->set_notification_bcc (wx_to_std (_bcc->GetValue ()));
1052 void notification_email_changed ()
1054 if (_email->GetValue().IsEmpty ()) {
1055 /* Sometimes we get sent an erroneous notification that the email
1056 is empty; I don't know why.
1060 Config::instance()->set_notification_email (wx_to_std (_email->GetValue ()));
1065 Config::instance()->reset_notification_email ();
1066 checked_set (_email, Config::instance()->notification_email ());
1069 void type_changed (wxCheckBox* b, Config::Notification n)
1071 Config::instance()->set_notification(n, b->GetValue());
1072 update_sensitivity ();
1075 wxCheckBox* _enable_message_box;
1076 wxCheckBox* _enable_email;
1078 wxTextCtrl* _subject;
1081 EditableList<string, EmailDialog>* _cc;
1084 wxButton* _reset_email;
1087 class CoverSheetPage : public Page
1091 CoverSheetPage (wxSize panel_size, int border)
1092 #ifdef DCPOMATIC_OSX
1093 /* We have to force both width and height of this one */
1094 : Page (wxSize (panel_size.GetWidth(), 128), border)
1096 : Page (panel_size, border)
1100 wxString GetName () const
1102 return _("Cover Sheet");
1105 #ifdef DCPOMATIC_OSX
1106 wxBitmap GetLargeIcon () const
1108 return wxBitmap ("cover_sheet", wxBITMAP_TYPE_PNG_RESOURCE);
1115 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1116 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1118 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1119 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1121 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1122 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1125 void config_changed ()
1127 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
1130 void cover_sheet_changed ()
1132 if (_cover_sheet->GetValue().IsEmpty ()) {
1133 /* Sometimes we get sent an erroneous notification that the cover sheet
1134 is empty; I don't know why.
1138 Config::instance()->set_cover_sheet (wx_to_std (_cover_sheet->GetValue ()));
1141 void reset_cover_sheet ()
1143 Config::instance()->reset_cover_sheet ();
1144 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
1147 wxTextCtrl* _cover_sheet;
1148 wxButton* _reset_cover_sheet;
1152 class IdentifiersPage : public Page
1155 IdentifiersPage (wxSize panel_size, int border)
1156 : Page (panel_size, border)
1159 wxString GetName () const
1161 return _("Identifiers");
1164 #ifdef DCPOMATIC_OSX
1165 wxBitmap GetLargeIcon () const
1167 return wxBitmap ("identifiers", wxBITMAP_TYPE_PNG_RESOURCE);
1174 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1175 table->AddGrowableCol (1, 1);
1177 add_label_to_sizer (table, _panel, _("Issuer"), true);
1178 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1179 _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."));
1180 table->Add (_issuer, 1, wxALL | wxEXPAND);
1182 add_label_to_sizer (table, _panel, _("Creator"), true);
1183 _creator = new wxTextCtrl (_panel, wxID_ANY);
1184 _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."));
1185 table->Add (_creator, 1, wxALL | wxEXPAND);
1187 add_label_to_sizer (table, _panel, _("Company name"), true);
1188 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1189 _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."));
1190 table->Add (_company_name, 1, wxALL | wxEXPAND);
1192 add_label_to_sizer (table, _panel, _("Product name"), true);
1193 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1194 _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."));
1195 table->Add (_product_name, 1, wxALL | wxEXPAND);
1197 add_label_to_sizer (table, _panel, _("Product version"), true);
1198 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1199 _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."));
1200 table->Add (_product_version, 1, wxALL | wxEXPAND);
1202 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true);
1203 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1204 _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."));
1205 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1207 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1209 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1210 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1211 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1212 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1213 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1214 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1217 void config_changed ()
1219 Config* config = Config::instance ();
1220 checked_set (_issuer, config->dcp_issuer ());
1221 checked_set (_creator, config->dcp_creator ());
1222 checked_set (_company_name, config->dcp_company_name ());
1223 checked_set (_product_name, config->dcp_product_name ());
1224 checked_set (_product_version, config->dcp_product_version ());
1225 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1228 void issuer_changed ()
1230 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
1233 void creator_changed ()
1235 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
1238 void company_name_changed ()
1240 Config::instance()->set_dcp_company_name (wx_to_std(_company_name->GetValue()));
1243 void product_name_changed ()
1245 Config::instance()->set_dcp_product_name (wx_to_std(_product_name->GetValue()));
1248 void product_version_changed ()
1250 Config::instance()->set_dcp_product_version (wx_to_std(_product_version->GetValue()));
1253 void j2k_comment_changed ()
1255 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1258 wxTextCtrl* _issuer;
1259 wxTextCtrl* _creator;
1260 wxTextCtrl* _company_name;
1261 wxTextCtrl* _product_name;
1262 wxTextCtrl* _product_version;
1263 wxTextCtrl* _j2k_comment;
1267 /** @class AdvancedPage
1268 * @brief Advanced page of the preferences dialog.
1270 class AdvancedPage : public Page
1273 AdvancedPage (wxSize panel_size, int border)
1274 : Page (panel_size, border)
1275 , _maximum_j2k_bandwidth (0)
1276 , _allow_any_dcp_frame_rate (0)
1277 , _allow_any_container (0)
1278 , _show_experimental_audio_processors (0)
1279 , _only_servers_encode (0)
1284 , _log_debug_threed (0)
1285 , _log_debug_encode (0)
1286 , _log_debug_email (0)
1287 , _log_debug_video_view (0)
1288 , _log_debug_player (0)
1289 , _log_debug_audio_analysis (0)
1292 wxString GetName () const
1294 return _("Advanced");
1297 #ifdef DCPOMATIC_OSX
1298 wxBitmap GetLargeIcon () const
1300 return wxBitmap ("advanced", wxBITMAP_TYPE_PNG_RESOURCE);
1305 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1307 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1309 flags |= wxALIGN_RIGHT;
1312 wxStaticText* m = new StaticText (parent, text);
1313 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1318 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1319 table->AddGrowableCol (1, 1);
1320 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1323 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1324 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1325 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1326 s->Add (_maximum_j2k_bandwidth, 1);
1327 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1331 add_label_to_sizer (table, _panel, _("Video display mode"), true);
1332 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1333 table->Add (_video_display_mode);
1335 wxStaticText* restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1336 wxFont font = restart->GetFont();
1337 font.SetStyle (wxFONTSTYLE_ITALIC);
1338 font.SetPointSize (font.GetPointSize() - 1);
1339 restart->SetFont (font);
1340 table->AddSpacer (0);
1342 _allow_any_dcp_frame_rate = new CheckBox (_panel, _("Allow any DCP frame rate"));
1343 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1344 table->AddSpacer (0);
1346 _allow_any_container = new CheckBox (_panel, _("Allow full-frame and non-standard container ratios"));
1347 table->Add (_allow_any_container, 1, wxEXPAND | wxALL);
1348 table->AddSpacer (0);
1350 restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to see all ratios)"), false);
1351 restart->SetFont (font);
1352 table->AddSpacer (0);
1354 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1355 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxALL);
1356 table->AddSpacer (0);
1358 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1359 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1360 table->AddSpacer (0);
1363 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true);
1364 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1365 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1366 s->Add (_frames_in_memory_multiplier, 1);
1371 add_top_aligned_label_to_sizer (table, _panel, _("DCP metadata filename format"));
1372 dcp::NameFormat::Map titles;
1373 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1374 dcp::NameFormat::Map examples;
1375 examples['t'] = "cpl";
1376 _dcp_metadata_filename_format = new NameFormatEditor (
1377 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1379 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1383 add_top_aligned_label_to_sizer (table, _panel, _("DCP asset filename format"));
1384 dcp::NameFormat::Map titles;
1385 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1386 titles['r'] = wx_to_std (_("reel number"));
1387 titles['n'] = wx_to_std (_("number of reels"));
1388 titles['c'] = wx_to_std (_("content filename"));
1389 dcp::NameFormat::Map examples;
1390 examples['t'] = "j2c";
1391 examples['r'] = "1";
1392 examples['n'] = "4";
1393 examples['c'] = "myfile.mp4";
1394 _dcp_asset_filename_format = new NameFormatEditor (
1395 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1397 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1401 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1402 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1403 _log_general = new CheckBox (_panel, _("General"));
1404 t->Add (_log_general, 1, wxEXPAND | wxALL);
1405 _log_warning = new CheckBox (_panel, _("Warnings"));
1406 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1407 _log_error = new CheckBox (_panel, _("Errors"));
1408 t->Add (_log_error, 1, wxEXPAND | wxALL);
1409 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1410 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1411 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1412 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1413 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1414 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1415 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1416 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1417 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1418 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1419 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1420 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1421 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1422 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1423 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1424 table->Add (t, 0, wxALL, 6);
1427 #ifdef DCPOMATIC_WINDOWS
1428 _win32_console = new CheckBox (_panel, _("Open console window"));
1429 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1430 table->AddSpacer (0);
1433 _maximum_j2k_bandwidth->SetRange (1, 1000);
1434 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1435 _video_display_mode->Append (_("Simple (safer)"));
1436 _video_display_mode->Append (_("OpenGL (faster)"));
1437 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1438 _allow_any_dcp_frame_rate->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1439 _allow_any_container->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_container_changed, this));
1440 _show_experimental_audio_processors->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::show_experimental_audio_processors_changed, this));
1441 _only_servers_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1442 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1443 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1444 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1445 _log_general->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1446 _log_warning->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1447 _log_error->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1448 _log_timing->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1449 _log_debug_threed->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1450 _log_debug_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1451 _log_debug_email->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1452 _log_debug_video_view->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1453 _log_debug_player->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1454 _log_debug_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1455 #ifdef DCPOMATIC_WINDOWS
1456 _win32_console->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::win32_console_changed, this));
1460 void config_changed ()
1462 Config* config = Config::instance ();
1464 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1465 switch (config->video_view_type()) {
1466 case Config::VIDEO_VIEW_SIMPLE:
1467 checked_set (_video_display_mode, 0);
1469 case Config::VIDEO_VIEW_OPENGL:
1470 checked_set (_video_display_mode, 1);
1473 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1474 checked_set (_allow_any_container, config->allow_any_container ());
1475 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1476 checked_set (_only_servers_encode, config->only_servers_encode ());
1477 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1478 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1479 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1480 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1481 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREED);
1482 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1483 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1484 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1485 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1486 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1487 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1488 #ifdef DCPOMATIC_WINDOWS
1489 checked_set (_win32_console, config->win32_console());
1493 void maximum_j2k_bandwidth_changed ()
1495 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1498 void video_display_mode_changed ()
1500 if (_video_display_mode->GetSelection() == 0) {
1501 Config::instance()->set_video_view_type (Config::VIDEO_VIEW_SIMPLE);
1503 Config::instance()->set_video_view_type (Config::VIDEO_VIEW_OPENGL);
1507 void frames_in_memory_multiplier_changed ()
1509 Config::instance()->set_frames_in_memory_multiplier (_frames_in_memory_multiplier->GetValue());
1512 void allow_any_dcp_frame_rate_changed ()
1514 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1517 void allow_any_container_changed ()
1519 Config::instance()->set_allow_any_container (_allow_any_container->GetValue ());
1522 void show_experimental_audio_processors_changed ()
1524 Config::instance()->set_show_experimental_audio_processors (_show_experimental_audio_processors->GetValue ());
1527 void only_servers_encode_changed ()
1529 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1532 void dcp_metadata_filename_format_changed ()
1534 Config::instance()->set_dcp_metadata_filename_format (_dcp_metadata_filename_format->get ());
1537 void dcp_asset_filename_format_changed ()
1539 Config::instance()->set_dcp_asset_filename_format (_dcp_asset_filename_format->get ());
1545 if (_log_general->GetValue ()) {
1546 types |= LogEntry::TYPE_GENERAL;
1548 if (_log_warning->GetValue ()) {
1549 types |= LogEntry::TYPE_WARNING;
1551 if (_log_error->GetValue ()) {
1552 types |= LogEntry::TYPE_ERROR;
1554 if (_log_timing->GetValue ()) {
1555 types |= LogEntry::TYPE_TIMING;
1557 if (_log_debug_threed->GetValue ()) {
1558 types |= LogEntry::TYPE_DEBUG_THREED;
1560 if (_log_debug_encode->GetValue ()) {
1561 types |= LogEntry::TYPE_DEBUG_ENCODE;
1563 if (_log_debug_email->GetValue ()) {
1564 types |= LogEntry::TYPE_DEBUG_EMAIL;
1566 if (_log_debug_video_view->GetValue()) {
1567 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1569 if (_log_debug_player->GetValue()) {
1570 types |= LogEntry::TYPE_DEBUG_PLAYER;
1572 if (_log_debug_audio_analysis->GetValue()) {
1573 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1575 Config::instance()->set_log_types (types);
1578 #ifdef DCPOMATIC_WINDOWS
1579 void win32_console_changed ()
1581 Config::instance()->set_win32_console (_win32_console->GetValue ());
1585 wxSpinCtrl* _maximum_j2k_bandwidth;
1586 wxChoice* _video_display_mode;
1587 wxSpinCtrl* _frames_in_memory_multiplier;
1588 wxCheckBox* _allow_any_dcp_frame_rate;
1589 wxCheckBox* _allow_any_container;
1590 wxCheckBox* _show_experimental_audio_processors;
1591 wxCheckBox* _only_servers_encode;
1592 NameFormatEditor* _dcp_metadata_filename_format;
1593 NameFormatEditor* _dcp_asset_filename_format;
1594 wxCheckBox* _log_general;
1595 wxCheckBox* _log_warning;
1596 wxCheckBox* _log_error;
1597 wxCheckBox* _log_timing;
1598 wxCheckBox* _log_debug_threed;
1599 wxCheckBox* _log_debug_encode;
1600 wxCheckBox* _log_debug_email;
1601 wxCheckBox* _log_debug_video_view;
1602 wxCheckBox* _log_debug_player;
1603 wxCheckBox* _log_debug_audio_analysis;
1604 #ifdef DCPOMATIC_WINDOWS
1605 wxCheckBox* _win32_console;
1609 wxPreferencesEditor*
1610 create_full_config_dialog ()
1612 wxPreferencesEditor* e = new wxPreferencesEditor ();
1614 #ifdef DCPOMATIC_OSX
1615 /* Width that we force some of the config panels to be on OSX so that
1616 the containing window doesn't shrink too much when we select those panels.
1617 This is obviously an unpleasant hack.
1619 wxSize ps = wxSize (700, -1);
1620 int const border = 16;
1622 wxSize ps = wxSize (-1, -1);
1623 int const border = 8;
1626 e->AddPage (new FullGeneralPage (ps, border));
1627 e->AddPage (new SoundPage (ps, border));
1628 e->AddPage (new DefaultsPage (ps, border));
1629 e->AddPage (new EncodingServersPage (ps, border));
1630 e->AddPage (new KeysPage (ps, border));
1631 e->AddPage (new TMSPage (ps, border));
1632 e->AddPage (new EmailPage (ps, border));
1633 e->AddPage (new KDMEmailPage (ps, border));
1634 e->AddPage (new NotificationsPage (ps, border));
1635 e->AddPage (new CoverSheetPage (ps, border));
1636 e->AddPage (new IdentifiersPage (ps, border));
1637 e->AddPage (new AdvancedPage (ps, border));