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, _("Interface complexity"), true, wxGBPosition(r, 0));
96 _interface_complexity = new wxChoice (_panel, wxID_ANY);
97 table->Add (_interface_complexity, wxGBPosition (r, 1));
100 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic should use"), true, wxGBPosition (r, 0));
101 _master_encoding_threads = new wxSpinCtrl (_panel);
102 table->Add (_master_encoding_threads, wxGBPosition (r, 1));
105 add_label_to_sizer (table, _panel, _("Number of threads DCP-o-matic encode server should use"), true, wxGBPosition (r, 0));
106 _server_encoding_threads = new wxSpinCtrl (_panel);
107 table->Add (_server_encoding_threads, wxGBPosition (r, 1));
110 add_label_to_sizer (table, _panel, _("Configuration file"), true, wxGBPosition (r, 0));
111 _config_file = new FilePickerCtrl (_panel, _("Select configuration file"), "*.xml", true, true);
112 table->Add (_config_file, wxGBPosition (r, 1));
115 add_label_to_sizer (table, _panel, _("Cinema and screen database file"), true, wxGBPosition (r, 0));
116 _cinemas_file = new FilePickerCtrl (_panel, _("Select cinema and screen database file"), "*.xml", true, true);
117 table->Add (_cinemas_file, wxGBPosition (r, 1));
118 Button* export_cinemas = new Button (_panel, _("Export..."));
119 table->Add (export_cinemas, wxGBPosition (r, 2));
122 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
123 _analyse_ebur128 = new CheckBox (_panel, _("Find integrated loudness, true peak and loudness range when analysing audio"));
124 table->Add (_analyse_ebur128, wxGBPosition (r, 0), wxGBSpan (1, 2));
128 _automatic_audio_analysis = new CheckBox (_panel, _("Automatically analyse content audio"));
129 table->Add (_automatic_audio_analysis, wxGBPosition (r, 0), wxGBSpan (1, 2));
132 add_update_controls (table, r);
134 _config_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::config_file_changed, this));
135 _cinemas_file->Bind (wxEVT_FILEPICKER_CHANGED, boost::bind (&FullGeneralPage::cinemas_file_changed, this));
137 _interface_complexity->Append (_("Simple"));
138 _interface_complexity->Append (_("Full"));
139 _interface_complexity->Bind (wxEVT_CHOICE, boost::bind(&FullGeneralPage::interface_complexity_changed, this));
141 _master_encoding_threads->SetRange (1, 128);
142 _master_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::master_encoding_threads_changed, this));
143 _server_encoding_threads->SetRange (1, 128);
144 _server_encoding_threads->Bind (wxEVT_SPINCTRL, boost::bind (&FullGeneralPage::server_encoding_threads_changed, this));
145 export_cinemas->Bind (wxEVT_BUTTON, boost::bind (&FullGeneralPage::export_cinemas_file, this));
147 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
148 _analyse_ebur128->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::analyse_ebur128_changed, this));
150 _automatic_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&FullGeneralPage::automatic_audio_analysis_changed, this));
153 void config_changed ()
155 Config* config = Config::instance ();
157 switch (config->interface_complexity()) {
158 case Config::INTERFACE_SIMPLE:
159 checked_set (_interface_complexity, 0);
161 case Config::INTERFACE_FULL:
162 checked_set (_interface_complexity, 1);
165 checked_set (_master_encoding_threads, config->master_encoding_threads ());
166 checked_set (_server_encoding_threads, config->server_encoding_threads ());
167 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
168 checked_set (_analyse_ebur128, config->analyse_ebur128 ());
170 checked_set (_automatic_audio_analysis, config->automatic_audio_analysis ());
171 checked_set (_config_file, config->config_file());
172 checked_set (_cinemas_file, config->cinemas_file());
174 GeneralPage::config_changed ();
177 void export_cinemas_file ()
179 wxFileDialog* d = new wxFileDialog (
180 _panel, _("Select Cinemas File"), wxEmptyString, wxEmptyString, wxT ("XML files (*.xml)|*.xml"),
181 wxFD_SAVE | wxFD_OVERWRITE_PROMPT
184 if (d->ShowModal () == wxID_OK) {
185 boost::filesystem::copy_file (Config::instance()->cinemas_file(), wx_to_std(d->GetPath()));
190 void interface_complexity_changed ()
192 if (_interface_complexity->GetSelection() == 0) {
193 Config::instance()->set_interface_complexity (Config::INTERFACE_SIMPLE);
195 Config::instance()->set_interface_complexity (Config::INTERFACE_FULL);
200 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
201 void analyse_ebur128_changed ()
203 Config::instance()->set_analyse_ebur128 (_analyse_ebur128->GetValue ());
207 void automatic_audio_analysis_changed ()
209 Config::instance()->set_automatic_audio_analysis (_automatic_audio_analysis->GetValue ());
212 void master_encoding_threads_changed ()
214 Config::instance()->set_master_encoding_threads (_master_encoding_threads->GetValue ());
217 void server_encoding_threads_changed ()
219 Config::instance()->set_server_encoding_threads (_server_encoding_threads->GetValue ());
222 void config_file_changed ()
224 Config* config = Config::instance();
225 boost::filesystem::path new_file = wx_to_std(_config_file->GetPath());
226 if (new_file == config->config_file()) {
229 bool copy_and_link = true;
230 if (boost::filesystem::exists(new_file)) {
231 ConfigMoveDialog* d = new ConfigMoveDialog (_panel, new_file);
232 if (d->ShowModal() == wxID_OK) {
233 copy_and_link = false;
240 if (new_file != config->config_file()) {
241 config->copy_and_link (new_file);
244 config->link (new_file);
248 void cinemas_file_changed ()
250 Config::instance()->set_cinemas_file (wx_to_std (_cinemas_file->GetPath ()));
253 wxChoice* _interface_complexity;
254 wxSpinCtrl* _master_encoding_threads;
255 wxSpinCtrl* _server_encoding_threads;
256 FilePickerCtrl* _config_file;
257 FilePickerCtrl* _cinemas_file;
258 #ifdef DCPOMATIC_HAVE_EBUR128_PATCHED_FFMPEG
259 wxCheckBox* _analyse_ebur128;
261 wxCheckBox* _automatic_audio_analysis;
264 class DefaultsPage : public Page
267 DefaultsPage (wxSize panel_size, int border)
268 : Page (panel_size, border)
271 wxString GetName () const
273 return _("Defaults");
277 wxBitmap GetLargeIcon () const
279 return wxBitmap ("defaults", wxBITMAP_TYPE_PNG_RESOURCE);
286 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
287 table->AddGrowableCol (1, 1);
288 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
291 add_label_to_sizer (table, _panel, _("Default duration of still images"), true);
292 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
293 _still_length = new wxSpinCtrl (_panel);
294 s->Add (_still_length);
295 add_label_to_sizer (s, _panel, _("s"), false);
299 add_label_to_sizer (table, _panel, _("Default directory for new films"), true);
300 #ifdef DCPOMATIC_USE_OWN_PICKER
301 _directory = new DirPickerCtrl (_panel);
303 _directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
305 table->Add (_directory, 1, wxEXPAND);
307 add_label_to_sizer (table, _panel, _("Default ISDCF name details"), true);
308 _isdcf_metadata_button = new Button (_panel, _("Edit..."));
309 table->Add (_isdcf_metadata_button);
311 add_label_to_sizer (table, _panel, _("Default container"), true);
312 _container = new wxChoice (_panel, wxID_ANY);
313 table->Add (_container);
315 add_label_to_sizer (table, _panel, _("Default content type"), true);
316 _dcp_content_type = new wxChoice (_panel, wxID_ANY);
317 table->Add (_dcp_content_type);
319 add_label_to_sizer (table, _panel, _("Default DCP audio channels"), true);
320 _dcp_audio_channels = new wxChoice (_panel, wxID_ANY);
321 table->Add (_dcp_audio_channels);
324 add_label_to_sizer (table, _panel, _("Default JPEG2000 bandwidth"), true);
325 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
326 _j2k_bandwidth = new wxSpinCtrl (_panel);
327 s->Add (_j2k_bandwidth);
328 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
333 add_label_to_sizer (table, _panel, _("Default audio delay"), true);
334 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
335 _audio_delay = new wxSpinCtrl (_panel);
336 s->Add (_audio_delay);
337 add_label_to_sizer (s, _panel, _("ms"), false);
341 add_label_to_sizer (table, _panel, _("Default standard"), true);
342 _standard = new wxChoice (_panel, wxID_ANY);
343 table->Add (_standard);
345 add_label_to_sizer (table, _panel, _("Default KDM directory"), true);
346 #ifdef DCPOMATIC_USE_OWN_PICKER
347 _kdm_directory = new DirPickerCtrl (_panel);
349 _kdm_directory = new wxDirPickerCtrl (_panel, wxDD_DIR_MUST_EXIST);
352 table->Add (_kdm_directory, 1, wxEXPAND);
354 _still_length->SetRange (1, 3600);
355 _still_length->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::still_length_changed, this));
357 _directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::directory_changed, this));
358 _kdm_directory->Bind (wxEVT_DIRPICKER_CHANGED, boost::bind (&DefaultsPage::kdm_directory_changed, this));
360 _isdcf_metadata_button->Bind (wxEVT_BUTTON, boost::bind (&DefaultsPage::edit_isdcf_metadata_clicked, this));
362 BOOST_FOREACH (Ratio const * i, Ratio::containers()) {
363 _container->Append (std_to_wx(i->container_nickname()));
366 _container->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::container_changed, this));
368 BOOST_FOREACH (DCPContentType const * i, DCPContentType::all()) {
369 _dcp_content_type->Append (std_to_wx (i->pretty_name ()));
372 setup_audio_channels_choice (_dcp_audio_channels, 2);
374 _dcp_content_type->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_content_type_changed, this));
375 _dcp_audio_channels->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::dcp_audio_channels_changed, this));
377 _j2k_bandwidth->SetRange (50, 250);
378 _j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::j2k_bandwidth_changed, this));
380 _audio_delay->SetRange (-1000, 1000);
381 _audio_delay->Bind (wxEVT_SPINCTRL, boost::bind (&DefaultsPage::audio_delay_changed, this));
383 _standard->Append (_("SMPTE"));
384 _standard->Append (_("Interop"));
385 _standard->Bind (wxEVT_CHOICE, boost::bind (&DefaultsPage::standard_changed, this));
388 void config_changed ()
390 Config* config = Config::instance ();
392 vector<Ratio const *> containers = Ratio::containers ();
393 for (size_t i = 0; i < containers.size(); ++i) {
394 if (containers[i] == config->default_container ()) {
395 _container->SetSelection (i);
399 vector<DCPContentType const *> const ct = DCPContentType::all ();
400 for (size_t i = 0; i < ct.size(); ++i) {
401 if (ct[i] == config->default_dcp_content_type ()) {
402 _dcp_content_type->SetSelection (i);
406 checked_set (_still_length, config->default_still_length ());
407 _directory->SetPath (std_to_wx (config->default_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
408 _kdm_directory->SetPath (std_to_wx (config->default_kdm_directory_or (wx_to_std (wxStandardPaths::Get().GetDocumentsDir())).string ()));
409 checked_set (_j2k_bandwidth, config->default_j2k_bandwidth() / 1000000);
410 _j2k_bandwidth->SetRange (50, config->maximum_j2k_bandwidth() / 1000000);
411 checked_set (_dcp_audio_channels, locale_convert<string> (config->default_dcp_audio_channels()));
412 checked_set (_audio_delay, config->default_audio_delay ());
413 checked_set (_standard, config->default_interop() ? 1 : 0);
416 void j2k_bandwidth_changed ()
418 Config::instance()->set_default_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1000000);
421 void audio_delay_changed ()
423 Config::instance()->set_default_audio_delay (_audio_delay->GetValue());
426 void dcp_audio_channels_changed ()
428 int const s = _dcp_audio_channels->GetSelection ();
429 if (s != wxNOT_FOUND) {
430 Config::instance()->set_default_dcp_audio_channels (
431 locale_convert<int> (string_client_data (_dcp_audio_channels->GetClientObject (s)))
436 void directory_changed ()
438 Config::instance()->set_default_directory (wx_to_std (_directory->GetPath ()));
441 void kdm_directory_changed ()
443 Config::instance()->set_default_kdm_directory (wx_to_std (_kdm_directory->GetPath ()));
446 void edit_isdcf_metadata_clicked ()
448 ISDCFMetadataDialog* d = new ISDCFMetadataDialog (_panel, Config::instance()->default_isdcf_metadata (), false);
450 Config::instance()->set_default_isdcf_metadata (d->isdcf_metadata ());
454 void still_length_changed ()
456 Config::instance()->set_default_still_length (_still_length->GetValue ());
459 void container_changed ()
461 vector<Ratio const *> ratio = Ratio::containers ();
462 Config::instance()->set_default_container (ratio[_container->GetSelection()]);
465 void dcp_content_type_changed ()
467 vector<DCPContentType const *> ct = DCPContentType::all ();
468 Config::instance()->set_default_dcp_content_type (ct[_dcp_content_type->GetSelection()]);
471 void standard_changed ()
473 Config::instance()->set_default_interop (_standard->GetSelection() == 1);
476 wxSpinCtrl* _j2k_bandwidth;
477 wxSpinCtrl* _audio_delay;
478 wxButton* _isdcf_metadata_button;
479 wxSpinCtrl* _still_length;
480 #ifdef DCPOMATIC_USE_OWN_PICKER
481 DirPickerCtrl* _directory;
482 DirPickerCtrl* _kdm_directory;
484 wxDirPickerCtrl* _directory;
485 wxDirPickerCtrl* _kdm_directory;
487 wxChoice* _container;
488 wxChoice* _dcp_content_type;
489 wxChoice* _dcp_audio_channels;
493 class EncodingServersPage : public Page
496 EncodingServersPage (wxSize panel_size, int border)
497 : Page (panel_size, border)
500 wxString GetName () const
506 wxBitmap GetLargeIcon () const
508 return wxBitmap ("servers", wxBITMAP_TYPE_PNG_RESOURCE);
515 _use_any_servers = new CheckBox (_panel, _("Search network for servers"));
516 _panel->GetSizer()->Add (_use_any_servers, 0, wxALL, _border);
518 vector<EditableListColumn> columns;
519 columns.push_back (EditableListColumn(_("IP address / host name")));
520 _servers_list = new EditableList<string, ServerDialog> (
523 boost::bind (&Config::servers, Config::instance()),
524 boost::bind (&Config::set_servers, Config::instance(), _1),
525 boost::bind (&EncodingServersPage::server_column, this, _1)
528 _panel->GetSizer()->Add (_servers_list, 1, wxEXPAND | wxALL, _border);
530 _use_any_servers->Bind (wxEVT_CHECKBOX, boost::bind (&EncodingServersPage::use_any_servers_changed, this));
533 void config_changed ()
535 checked_set (_use_any_servers, Config::instance()->use_any_servers ());
536 _servers_list->refresh ();
539 void use_any_servers_changed ()
541 Config::instance()->set_use_any_servers (_use_any_servers->GetValue ());
544 string server_column (string s)
549 wxCheckBox* _use_any_servers;
550 EditableList<string, ServerDialog>* _servers_list;
553 class TMSPage : public Page
556 TMSPage (wxSize panel_size, int border)
557 : Page (panel_size, border)
560 wxString GetName () const
566 wxBitmap GetLargeIcon () const
568 return wxBitmap ("tms", wxBITMAP_TYPE_PNG_RESOURCE);
575 _upload = new CheckBox (_panel, _("Upload DCP to TMS after creation"));
576 _panel->GetSizer()->Add (_upload, 0, wxALL | wxEXPAND, _border);
578 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
579 table->AddGrowableCol (1, 1);
580 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
582 add_label_to_sizer (table, _panel, _("Protocol"), true);
583 _tms_protocol = new wxChoice (_panel, wxID_ANY);
584 table->Add (_tms_protocol, 1, wxEXPAND);
586 add_label_to_sizer (table, _panel, _("IP address"), true);
587 _tms_ip = new wxTextCtrl (_panel, wxID_ANY);
588 table->Add (_tms_ip, 1, wxEXPAND);
590 add_label_to_sizer (table, _panel, _("Target path"), true);
591 _tms_path = new wxTextCtrl (_panel, wxID_ANY);
592 table->Add (_tms_path, 1, wxEXPAND);
594 add_label_to_sizer (table, _panel, _("User name"), true);
595 _tms_user = new wxTextCtrl (_panel, wxID_ANY);
596 table->Add (_tms_user, 1, wxEXPAND);
598 add_label_to_sizer (table, _panel, _("Password"), true);
599 _tms_password = new PasswordEntry (_panel);
600 table->Add (_tms_password->get_panel(), 1, wxEXPAND);
602 _tms_protocol->Append (_("SCP (for AAM and Doremi)"));
603 _tms_protocol->Append (_("FTP (for Dolby)"));
605 _upload->Bind (wxEVT_CHECKBOX, boost::bind(&TMSPage::upload_changed, this));
606 _tms_protocol->Bind (wxEVT_CHOICE, boost::bind (&TMSPage::tms_protocol_changed, this));
607 _tms_ip->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_ip_changed, this));
608 _tms_path->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_path_changed, this));
609 _tms_user->Bind (wxEVT_TEXT, boost::bind (&TMSPage::tms_user_changed, this));
610 _tms_password->Changed.connect (boost::bind (&TMSPage::tms_password_changed, this));
613 void config_changed ()
615 Config* config = Config::instance ();
617 checked_set (_upload, config->upload_after_make_dcp());
618 checked_set (_tms_protocol, config->tms_protocol ());
619 checked_set (_tms_ip, config->tms_ip ());
620 checked_set (_tms_path, config->tms_path ());
621 checked_set (_tms_user, config->tms_user ());
622 checked_set (_tms_password, config->tms_password ());
625 void upload_changed ()
627 Config::instance()->set_upload_after_make_dcp (_upload->GetValue());
630 void tms_protocol_changed ()
632 Config::instance()->set_tms_protocol(static_cast<FileTransferProtocol>(_tms_protocol->GetSelection()));
635 void tms_ip_changed ()
637 Config::instance()->set_tms_ip (wx_to_std (_tms_ip->GetValue ()));
640 void tms_path_changed ()
642 Config::instance()->set_tms_path (wx_to_std (_tms_path->GetValue ()));
645 void tms_user_changed ()
647 Config::instance()->set_tms_user (wx_to_std (_tms_user->GetValue ()));
650 void tms_password_changed ()
652 Config::instance()->set_tms_password (_tms_password->get());
656 wxChoice* _tms_protocol;
658 wxTextCtrl* _tms_path;
659 wxTextCtrl* _tms_user;
660 PasswordEntry* _tms_password;
669 class EmailPage : public Page
672 EmailPage (wxSize panel_size, int border)
673 : Page (panel_size, border)
676 wxString GetName () const
682 wxBitmap GetLargeIcon () const
684 return wxBitmap ("email", wxBITMAP_TYPE_PNG_RESOURCE);
691 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
692 table->AddGrowableCol (1, 1);
693 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
695 add_label_to_sizer (table, _panel, _("Outgoing mail server"), true);
697 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
698 _server = new wxTextCtrl (_panel, wxID_ANY);
699 s->Add (_server, 1, wxEXPAND | wxALL);
700 add_label_to_sizer (s, _panel, _("port"), false);
701 _port = new wxSpinCtrl (_panel, wxID_ANY);
702 _port->SetRange (0, 65535);
704 add_label_to_sizer (s, _panel, _("protocol"), false);
705 _protocol = new wxChoice (_panel, wxID_ANY);
706 /* Make sure this matches the switches in config_changed and port_changed below */
707 _protocol->Append (_("Auto"));
708 _protocol->Append (_("Plain"));
709 _protocol->Append (_("STARTTLS"));
710 _protocol->Append (_("SSL"));
712 table->Add (s, 1, wxEXPAND | wxALL);
715 add_label_to_sizer (table, _panel, _("User name"), true);
716 _user = new wxTextCtrl (_panel, wxID_ANY);
717 table->Add (_user, 1, wxEXPAND | wxALL);
719 add_label_to_sizer (table, _panel, _("Password"), true);
720 _password = new PasswordEntry (_panel);
721 table->Add (_password->get_panel(), 1, wxEXPAND | wxALL);
723 _server->Bind (wxEVT_TEXT, boost::bind (&EmailPage::server_changed, this));
724 _port->Bind (wxEVT_SPINCTRL, boost::bind (&EmailPage::port_changed, this));
725 _protocol->Bind (wxEVT_CHOICE, boost::bind (&EmailPage::protocol_changed, this));
726 _user->Bind (wxEVT_TEXT, boost::bind (&EmailPage::user_changed, this));
727 _password->Changed.connect (boost::bind (&EmailPage::password_changed, this));
730 void config_changed ()
732 Config* config = Config::instance ();
734 checked_set (_server, config->mail_server ());
735 checked_set (_port, config->mail_port ());
736 switch (config->mail_protocol()) {
737 case EMAIL_PROTOCOL_AUTO:
738 checked_set (_protocol, 0);
740 case EMAIL_PROTOCOL_PLAIN:
741 checked_set (_protocol, 1);
743 case EMAIL_PROTOCOL_STARTTLS:
744 checked_set (_protocol, 2);
746 case EMAIL_PROTOCOL_SSL:
747 checked_set (_protocol, 3);
750 checked_set (_user, config->mail_user ());
751 checked_set (_password, config->mail_password());
754 void server_changed ()
756 Config::instance()->set_mail_server (wx_to_std (_server->GetValue ()));
761 Config::instance()->set_mail_port (_port->GetValue ());
764 void protocol_changed ()
766 switch (_protocol->GetSelection()) {
768 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_AUTO);
771 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_PLAIN);
774 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_STARTTLS);
777 Config::instance()->set_mail_protocol(EMAIL_PROTOCOL_SSL);
784 Config::instance()->set_mail_user (wx_to_std (_user->GetValue ()));
787 void password_changed ()
789 Config::instance()->set_mail_password(_password->get());
796 PasswordEntry* _password;
799 class KDMEmailPage : public Page
803 KDMEmailPage (wxSize panel_size, int border)
805 /* We have to force both width and height of this one */
806 : Page (wxSize (panel_size.GetWidth(), 128), border)
808 : Page (panel_size, border)
812 wxString GetName () const
814 return _("KDM Email");
818 wxBitmap GetLargeIcon () const
820 return wxBitmap ("kdm_email", wxBITMAP_TYPE_PNG_RESOURCE);
827 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
828 table->AddGrowableCol (1, 1);
829 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
831 add_label_to_sizer (table, _panel, _("Subject"), true);
832 _subject = new wxTextCtrl (_panel, wxID_ANY);
833 table->Add (_subject, 1, wxEXPAND | wxALL);
835 add_label_to_sizer (table, _panel, _("From address"), true);
836 _from = new wxTextCtrl (_panel, wxID_ANY);
837 table->Add (_from, 1, wxEXPAND | wxALL);
839 vector<EditableListColumn> columns;
840 columns.push_back (EditableListColumn(_("Address")));
841 add_label_to_sizer (table, _panel, _("CC addresses"), true);
842 _cc = new EditableList<string, EmailDialog> (
845 bind (&Config::kdm_cc, Config::instance()),
846 bind (&Config::set_kdm_cc, Config::instance(), _1),
849 table->Add (_cc, 1, wxEXPAND | wxALL);
851 add_label_to_sizer (table, _panel, _("BCC address"), true);
852 _bcc = new wxTextCtrl (_panel, wxID_ANY);
853 table->Add (_bcc, 1, wxEXPAND | wxALL);
855 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
856 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
858 _reset_email = new Button (_panel, _("Reset to default subject and text"));
859 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
863 _subject->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_subject_changed, this));
864 _from->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_from_changed, this));
865 _bcc->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_bcc_changed, this));
866 _email->Bind (wxEVT_TEXT, boost::bind (&KDMEmailPage::kdm_email_changed, this));
867 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&KDMEmailPage::reset_email, this));
870 void config_changed ()
872 Config* config = Config::instance ();
874 checked_set (_subject, config->kdm_subject ());
875 checked_set (_from, config->kdm_from ());
876 checked_set (_bcc, config->kdm_bcc ());
877 checked_set (_email, Config::instance()->kdm_email ());
880 void kdm_subject_changed ()
882 Config::instance()->set_kdm_subject (wx_to_std (_subject->GetValue ()));
885 void kdm_from_changed ()
887 Config::instance()->set_kdm_from (wx_to_std (_from->GetValue ()));
890 void kdm_bcc_changed ()
892 Config::instance()->set_kdm_bcc (wx_to_std (_bcc->GetValue ()));
895 void kdm_email_changed ()
897 if (_email->GetValue().IsEmpty ()) {
898 /* Sometimes we get sent an erroneous notification that the email
899 is empty; I don't know why.
903 Config::instance()->set_kdm_email (wx_to_std (_email->GetValue ()));
908 Config::instance()->reset_kdm_email ();
909 checked_set (_email, Config::instance()->kdm_email ());
912 wxTextCtrl* _subject;
914 EditableList<string, EmailDialog>* _cc;
917 wxButton* _reset_email;
920 class NotificationsPage : public Page
923 NotificationsPage (wxSize panel_size, int border)
925 /* We have to force both width and height of this one */
926 : Page (wxSize (panel_size.GetWidth(), 128), border)
928 : Page (panel_size, border)
932 wxString GetName () const
934 return _("Notifications");
938 wxBitmap GetLargeIcon () const
940 return wxBitmap ("notifications", wxBITMAP_TYPE_PNG_RESOURCE);
947 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
948 table->AddGrowableCol (1, 1);
949 _panel->GetSizer()->Add (table, 1, wxEXPAND | wxALL, _border);
951 _enable_message_box = new CheckBox (_panel, _("Message box"));
952 table->Add (_enable_message_box, 1, wxEXPAND | wxALL);
953 table->AddSpacer (0);
955 _enable_email = new CheckBox (_panel, _("Email"));
956 table->Add (_enable_email, 1, wxEXPAND | wxALL);
957 table->AddSpacer (0);
959 add_label_to_sizer (table, _panel, _("Subject"), true);
960 _subject = new wxTextCtrl (_panel, wxID_ANY);
961 table->Add (_subject, 1, wxEXPAND | wxALL);
963 add_label_to_sizer (table, _panel, _("From address"), true);
964 _from = new wxTextCtrl (_panel, wxID_ANY);
965 table->Add (_from, 1, wxEXPAND | wxALL);
967 add_label_to_sizer (table, _panel, _("To address"), true);
968 _to = new wxTextCtrl (_panel, wxID_ANY);
969 table->Add (_to, 1, wxEXPAND | wxALL);
971 vector<EditableListColumn> columns;
972 columns.push_back (EditableListColumn(_("Address")));
973 add_label_to_sizer (table, _panel, _("CC addresses"), true);
974 _cc = new EditableList<string, EmailDialog> (
977 bind (&Config::notification_cc, Config::instance()),
978 bind (&Config::set_notification_cc, Config::instance(), _1),
981 table->Add (_cc, 1, wxEXPAND | wxALL);
983 add_label_to_sizer (table, _panel, _("BCC address"), true);
984 _bcc = new wxTextCtrl (_panel, wxID_ANY);
985 table->Add (_bcc, 1, wxEXPAND | wxALL);
987 _email = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
988 _panel->GetSizer()->Add (_email, 0, wxEXPAND | wxALL, _border);
990 _reset_email = new Button (_panel, _("Reset to default subject and text"));
991 _panel->GetSizer()->Add (_reset_email, 0, wxEXPAND | wxALL, _border);
995 _enable_message_box->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_message_box, Config::MESSAGE_BOX));
996 _enable_email->Bind (wxEVT_CHECKBOX, boost::bind (&NotificationsPage::type_changed, this, _enable_email, Config::EMAIL));
998 _subject->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_subject_changed, this));
999 _from->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_from_changed, this));
1000 _to->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_to_changed, this));
1001 _bcc->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_bcc_changed, this));
1002 _email->Bind (wxEVT_TEXT, boost::bind (&NotificationsPage::notification_email_changed, this));
1003 _reset_email->Bind (wxEVT_BUTTON, boost::bind (&NotificationsPage::reset_email, this));
1005 update_sensitivity ();
1008 void update_sensitivity ()
1010 bool const s = _enable_email->GetValue();
1011 _subject->Enable(s);
1017 _reset_email->Enable(s);
1020 void config_changed ()
1022 Config* config = Config::instance ();
1024 checked_set (_enable_message_box, config->notification(Config::MESSAGE_BOX));
1025 checked_set (_enable_email, config->notification(Config::EMAIL));
1026 checked_set (_subject, config->notification_subject ());
1027 checked_set (_from, config->notification_from ());
1028 checked_set (_to, config->notification_to ());
1029 checked_set (_bcc, config->notification_bcc ());
1030 checked_set (_email, Config::instance()->notification_email ());
1032 update_sensitivity ();
1035 void notification_subject_changed ()
1037 Config::instance()->set_notification_subject (wx_to_std (_subject->GetValue ()));
1040 void notification_from_changed ()
1042 Config::instance()->set_notification_from (wx_to_std (_from->GetValue ()));
1045 void notification_to_changed ()
1047 Config::instance()->set_notification_to (wx_to_std (_to->GetValue ()));
1050 void notification_bcc_changed ()
1052 Config::instance()->set_notification_bcc (wx_to_std (_bcc->GetValue ()));
1055 void notification_email_changed ()
1057 if (_email->GetValue().IsEmpty ()) {
1058 /* Sometimes we get sent an erroneous notification that the email
1059 is empty; I don't know why.
1063 Config::instance()->set_notification_email (wx_to_std (_email->GetValue ()));
1068 Config::instance()->reset_notification_email ();
1069 checked_set (_email, Config::instance()->notification_email ());
1072 void type_changed (wxCheckBox* b, Config::Notification n)
1074 Config::instance()->set_notification(n, b->GetValue());
1075 update_sensitivity ();
1078 wxCheckBox* _enable_message_box;
1079 wxCheckBox* _enable_email;
1081 wxTextCtrl* _subject;
1084 EditableList<string, EmailDialog>* _cc;
1087 wxButton* _reset_email;
1090 class CoverSheetPage : public Page
1094 CoverSheetPage (wxSize panel_size, int border)
1095 #ifdef DCPOMATIC_OSX
1096 /* We have to force both width and height of this one */
1097 : Page (wxSize (panel_size.GetWidth(), 128), border)
1099 : Page (panel_size, border)
1103 wxString GetName () const
1105 return _("Cover Sheet");
1108 #ifdef DCPOMATIC_OSX
1109 wxBitmap GetLargeIcon () const
1111 return wxBitmap ("cover_sheet", wxBITMAP_TYPE_PNG_RESOURCE);
1118 _cover_sheet = new wxTextCtrl (_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (-1, 200), wxTE_MULTILINE);
1119 _panel->GetSizer()->Add (_cover_sheet, 0, wxEXPAND | wxALL, _border);
1121 _reset_cover_sheet = new Button (_panel, _("Reset to default text"));
1122 _panel->GetSizer()->Add (_reset_cover_sheet, 0, wxEXPAND | wxALL, _border);
1124 _cover_sheet->Bind (wxEVT_TEXT, boost::bind (&CoverSheetPage::cover_sheet_changed, this));
1125 _reset_cover_sheet->Bind (wxEVT_BUTTON, boost::bind (&CoverSheetPage::reset_cover_sheet, this));
1128 void config_changed ()
1130 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
1133 void cover_sheet_changed ()
1135 if (_cover_sheet->GetValue().IsEmpty ()) {
1136 /* Sometimes we get sent an erroneous notification that the cover sheet
1137 is empty; I don't know why.
1141 Config::instance()->set_cover_sheet (wx_to_std (_cover_sheet->GetValue ()));
1144 void reset_cover_sheet ()
1146 Config::instance()->reset_cover_sheet ();
1147 checked_set (_cover_sheet, Config::instance()->cover_sheet ());
1150 wxTextCtrl* _cover_sheet;
1151 wxButton* _reset_cover_sheet;
1155 class IdentifiersPage : public Page
1158 IdentifiersPage (wxSize panel_size, int border)
1159 : Page (panel_size, border)
1162 wxString GetName () const
1164 return _("Identifiers");
1167 #ifdef DCPOMATIC_OSX
1168 wxBitmap GetLargeIcon () const
1170 return wxBitmap ("identifiers", wxBITMAP_TYPE_PNG_RESOURCE);
1177 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1178 table->AddGrowableCol (1, 1);
1180 add_label_to_sizer (table, _panel, _("Issuer"), true);
1181 _issuer = new wxTextCtrl (_panel, wxID_ANY);
1182 _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."));
1183 table->Add (_issuer, 1, wxALL | wxEXPAND);
1185 add_label_to_sizer (table, _panel, _("Creator"), true);
1186 _creator = new wxTextCtrl (_panel, wxID_ANY);
1187 _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."));
1188 table->Add (_creator, 1, wxALL | wxEXPAND);
1190 add_label_to_sizer (table, _panel, _("Company name"), true);
1191 _company_name = new wxTextCtrl (_panel, wxID_ANY);
1192 _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."));
1193 table->Add (_company_name, 1, wxALL | wxEXPAND);
1195 add_label_to_sizer (table, _panel, _("Product name"), true);
1196 _product_name = new wxTextCtrl (_panel, wxID_ANY);
1197 _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."));
1198 table->Add (_product_name, 1, wxALL | wxEXPAND);
1200 add_label_to_sizer (table, _panel, _("Product version"), true);
1201 _product_version = new wxTextCtrl (_panel, wxID_ANY);
1202 _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."));
1203 table->Add (_product_version, 1, wxALL | wxEXPAND);
1205 add_label_to_sizer (table, _panel, _("JPEG2000 comment"), true);
1206 _j2k_comment = new wxTextCtrl (_panel, wxID_ANY);
1207 _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."));
1208 table->Add (_j2k_comment, 1, wxALL | wxEXPAND);
1210 _panel->GetSizer()->Add (table, 0, wxEXPAND | wxALL, _border);
1212 _issuer->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::issuer_changed, this));
1213 _creator->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::creator_changed, this));
1214 _company_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::company_name_changed, this));
1215 _product_name->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_name_changed, this));
1216 _product_version->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::product_version_changed, this));
1217 _j2k_comment->Bind (wxEVT_TEXT, boost::bind(&IdentifiersPage::j2k_comment_changed, this));
1220 void config_changed ()
1222 Config* config = Config::instance ();
1223 checked_set (_issuer, config->dcp_issuer ());
1224 checked_set (_creator, config->dcp_creator ());
1225 checked_set (_company_name, config->dcp_company_name ());
1226 checked_set (_product_name, config->dcp_product_name ());
1227 checked_set (_product_version, config->dcp_product_version ());
1228 checked_set (_j2k_comment, config->dcp_j2k_comment ());
1231 void issuer_changed ()
1233 Config::instance()->set_dcp_issuer (wx_to_std (_issuer->GetValue ()));
1236 void creator_changed ()
1238 Config::instance()->set_dcp_creator (wx_to_std (_creator->GetValue ()));
1241 void company_name_changed ()
1243 Config::instance()->set_dcp_company_name (wx_to_std(_company_name->GetValue()));
1246 void product_name_changed ()
1248 Config::instance()->set_dcp_product_name (wx_to_std(_product_name->GetValue()));
1251 void product_version_changed ()
1253 Config::instance()->set_dcp_product_version (wx_to_std(_product_version->GetValue()));
1256 void j2k_comment_changed ()
1258 Config::instance()->set_dcp_j2k_comment (wx_to_std(_j2k_comment->GetValue()));
1261 wxTextCtrl* _issuer;
1262 wxTextCtrl* _creator;
1263 wxTextCtrl* _company_name;
1264 wxTextCtrl* _product_name;
1265 wxTextCtrl* _product_version;
1266 wxTextCtrl* _j2k_comment;
1270 /** @class AdvancedPage
1271 * @brief Advanced page of the preferences dialog.
1273 class AdvancedPage : public Page
1276 AdvancedPage (wxSize panel_size, int border)
1277 : Page (panel_size, border)
1278 , _maximum_j2k_bandwidth (0)
1279 , _allow_any_dcp_frame_rate (0)
1280 , _allow_any_container (0)
1281 , _show_experimental_audio_processors (0)
1282 , _only_servers_encode (0)
1287 , _log_debug_threed (0)
1288 , _log_debug_encode (0)
1289 , _log_debug_email (0)
1290 , _log_debug_video_view (0)
1291 , _log_debug_player (0)
1292 , _log_debug_audio_analysis (0)
1295 wxString GetName () const
1297 return _("Advanced");
1300 #ifdef DCPOMATIC_OSX
1301 wxBitmap GetLargeIcon () const
1303 return wxBitmap ("advanced", wxBITMAP_TYPE_PNG_RESOURCE);
1308 void add_top_aligned_label_to_sizer (wxSizer* table, wxWindow* parent, wxString text)
1310 int flags = wxALIGN_TOP | wxTOP | wxLEFT;
1312 flags |= wxALIGN_RIGHT;
1315 wxStaticText* m = new StaticText (parent, text);
1316 table->Add (m, 0, flags, DCPOMATIC_SIZER_Y_GAP);
1321 wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
1322 table->AddGrowableCol (1, 1);
1323 _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
1326 add_label_to_sizer (table, _panel, _("Maximum JPEG2000 bandwidth"), true);
1327 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1328 _maximum_j2k_bandwidth = new wxSpinCtrl (_panel);
1329 s->Add (_maximum_j2k_bandwidth, 1);
1330 add_label_to_sizer (s, _panel, _("Mbit/s"), false);
1334 add_label_to_sizer (table, _panel, _("Video display mode"), true);
1335 _video_display_mode = new wxChoice (_panel, wxID_ANY);
1336 table->Add (_video_display_mode);
1338 wxStaticText* restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to change display mode)"), false);
1339 wxFont font = restart->GetFont();
1340 font.SetStyle (wxFONTSTYLE_ITALIC);
1341 font.SetPointSize (font.GetPointSize() - 1);
1342 restart->SetFont (font);
1343 table->AddSpacer (0);
1345 _allow_any_dcp_frame_rate = new CheckBox (_panel, _("Allow any DCP frame rate"));
1346 table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL);
1347 table->AddSpacer (0);
1349 _allow_any_container = new CheckBox (_panel, _("Allow full-frame and non-standard container ratios"));
1350 table->Add (_allow_any_container, 1, wxEXPAND | wxALL);
1351 table->AddSpacer (0);
1353 restart = add_label_to_sizer (table, _panel, _("(restart DCP-o-matic to see all ratios)"), false);
1354 restart->SetFont (font);
1355 table->AddSpacer (0);
1357 _show_experimental_audio_processors = new CheckBox (_panel, _("Show experimental audio processors"));
1358 table->Add (_show_experimental_audio_processors, 1, wxEXPAND | wxALL);
1359 table->AddSpacer (0);
1361 _only_servers_encode = new CheckBox (_panel, _("Only servers encode"));
1362 table->Add (_only_servers_encode, 1, wxEXPAND | wxALL);
1363 table->AddSpacer (0);
1366 add_label_to_sizer (table, _panel, _("Maximum number of frames to store per thread"), true);
1367 wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
1368 _frames_in_memory_multiplier = new wxSpinCtrl (_panel);
1369 s->Add (_frames_in_memory_multiplier, 1);
1374 add_top_aligned_label_to_sizer (table, _panel, _("DCP metadata filename format"));
1375 dcp::NameFormat::Map titles;
1376 titles['t'] = wx_to_std (_("type (cpl/pkl)"));
1377 dcp::NameFormat::Map examples;
1378 examples['t'] = "cpl";
1379 _dcp_metadata_filename_format = new NameFormatEditor (
1380 _panel, Config::instance()->dcp_metadata_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.xml"
1382 table->Add (_dcp_metadata_filename_format->panel(), 1, wxEXPAND | wxALL);
1386 add_top_aligned_label_to_sizer (table, _panel, _("DCP asset filename format"));
1387 dcp::NameFormat::Map titles;
1388 titles['t'] = wx_to_std (_("type (j2c/pcm/sub)"));
1389 titles['r'] = wx_to_std (_("reel number"));
1390 titles['n'] = wx_to_std (_("number of reels"));
1391 titles['c'] = wx_to_std (_("content filename"));
1392 dcp::NameFormat::Map examples;
1393 examples['t'] = "j2c";
1394 examples['r'] = "1";
1395 examples['n'] = "4";
1396 examples['c'] = "myfile.mp4";
1397 _dcp_asset_filename_format = new NameFormatEditor (
1398 _panel, Config::instance()->dcp_asset_filename_format(), titles, examples, "_eb1c112c-ca3c-4ae6-9263-c6714ff05d64.mxf"
1400 table->Add (_dcp_asset_filename_format->panel(), 1, wxEXPAND | wxALL);
1404 add_top_aligned_label_to_sizer (table, _panel, _("Log"));
1405 wxBoxSizer* t = new wxBoxSizer (wxVERTICAL);
1406 _log_general = new CheckBox (_panel, _("General"));
1407 t->Add (_log_general, 1, wxEXPAND | wxALL);
1408 _log_warning = new CheckBox (_panel, _("Warnings"));
1409 t->Add (_log_warning, 1, wxEXPAND | wxALL);
1410 _log_error = new CheckBox (_panel, _("Errors"));
1411 t->Add (_log_error, 1, wxEXPAND | wxALL);
1412 /// TRANSLATORS: translate the word "Timing" here; do not include the "Config|" prefix
1413 _log_timing = new CheckBox (_panel, S_("Config|Timing"));
1414 t->Add (_log_timing, 1, wxEXPAND | wxALL);
1415 _log_debug_threed = new CheckBox (_panel, _("Debug: 3D"));
1416 t->Add (_log_debug_threed, 1, wxEXPAND | wxALL);
1417 _log_debug_encode = new CheckBox (_panel, _("Debug: encode"));
1418 t->Add (_log_debug_encode, 1, wxEXPAND | wxALL);
1419 _log_debug_email = new CheckBox (_panel, _("Debug: email sending"));
1420 t->Add (_log_debug_email, 1, wxEXPAND | wxALL);
1421 _log_debug_video_view = new CheckBox (_panel, _("Debug: video view"));
1422 t->Add (_log_debug_video_view, 1, wxEXPAND | wxALL);
1423 _log_debug_player = new CheckBox (_panel, _("Debug: player"));
1424 t->Add (_log_debug_player, 1, wxEXPAND | wxALL);
1425 _log_debug_audio_analysis = new CheckBox (_panel, _("Debug: audio analysis"));
1426 t->Add (_log_debug_audio_analysis, 1, wxEXPAND | wxALL);
1427 table->Add (t, 0, wxALL, 6);
1430 #ifdef DCPOMATIC_WINDOWS
1431 _win32_console = new CheckBox (_panel, _("Open console window"));
1432 table->Add (_win32_console, 1, wxEXPAND | wxALL);
1433 table->AddSpacer (0);
1436 _maximum_j2k_bandwidth->SetRange (1, 1000);
1437 _maximum_j2k_bandwidth->Bind (wxEVT_SPINCTRL, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this));
1438 _video_display_mode->Append (_("Simple (safer)"));
1439 _video_display_mode->Append (_("OpenGL (faster)"));
1440 _video_display_mode->Bind (wxEVT_CHOICE, boost::bind(&AdvancedPage::video_display_mode_changed, this));
1441 _allow_any_dcp_frame_rate->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this));
1442 _allow_any_container->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::allow_any_container_changed, this));
1443 _show_experimental_audio_processors->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::show_experimental_audio_processors_changed, this));
1444 _only_servers_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::only_servers_encode_changed, this));
1445 _frames_in_memory_multiplier->Bind (wxEVT_SPINCTRL, boost::bind(&AdvancedPage::frames_in_memory_multiplier_changed, this));
1446 _dcp_metadata_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_metadata_filename_format_changed, this));
1447 _dcp_asset_filename_format->Changed.connect (boost::bind (&AdvancedPage::dcp_asset_filename_format_changed, this));
1448 _log_general->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1449 _log_warning->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1450 _log_error->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1451 _log_timing->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1452 _log_debug_threed->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1453 _log_debug_encode->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1454 _log_debug_email->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1455 _log_debug_video_view->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1456 _log_debug_player->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1457 _log_debug_audio_analysis->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::log_changed, this));
1458 #ifdef DCPOMATIC_WINDOWS
1459 _win32_console->Bind (wxEVT_CHECKBOX, boost::bind (&AdvancedPage::win32_console_changed, this));
1463 void config_changed ()
1465 Config* config = Config::instance ();
1467 checked_set (_maximum_j2k_bandwidth, config->maximum_j2k_bandwidth() / 1000000);
1468 switch (config->video_view_type()) {
1469 case Config::VIDEO_VIEW_SIMPLE:
1470 checked_set (_video_display_mode, 0);
1472 case Config::VIDEO_VIEW_OPENGL:
1473 checked_set (_video_display_mode, 1);
1476 checked_set (_allow_any_dcp_frame_rate, config->allow_any_dcp_frame_rate ());
1477 checked_set (_allow_any_container, config->allow_any_container ());
1478 checked_set (_show_experimental_audio_processors, config->show_experimental_audio_processors ());
1479 checked_set (_only_servers_encode, config->only_servers_encode ());
1480 checked_set (_log_general, config->log_types() & LogEntry::TYPE_GENERAL);
1481 checked_set (_log_warning, config->log_types() & LogEntry::TYPE_WARNING);
1482 checked_set (_log_error, config->log_types() & LogEntry::TYPE_ERROR);
1483 checked_set (_log_timing, config->log_types() & LogEntry::TYPE_TIMING);
1484 checked_set (_log_debug_threed, config->log_types() & LogEntry::TYPE_DEBUG_THREED);
1485 checked_set (_log_debug_encode, config->log_types() & LogEntry::TYPE_DEBUG_ENCODE);
1486 checked_set (_log_debug_email, config->log_types() & LogEntry::TYPE_DEBUG_EMAIL);
1487 checked_set (_log_debug_video_view, config->log_types() & LogEntry::TYPE_DEBUG_VIDEO_VIEW);
1488 checked_set (_log_debug_player, config->log_types() & LogEntry::TYPE_DEBUG_PLAYER);
1489 checked_set (_log_debug_audio_analysis, config->log_types() & LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS);
1490 checked_set (_frames_in_memory_multiplier, config->frames_in_memory_multiplier());
1491 #ifdef DCPOMATIC_WINDOWS
1492 checked_set (_win32_console, config->win32_console());
1496 void maximum_j2k_bandwidth_changed ()
1498 Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000);
1501 void video_display_mode_changed ()
1503 if (_video_display_mode->GetSelection() == 0) {
1504 Config::instance()->set_video_view_type (Config::VIDEO_VIEW_SIMPLE);
1506 Config::instance()->set_video_view_type (Config::VIDEO_VIEW_OPENGL);
1510 void frames_in_memory_multiplier_changed ()
1512 Config::instance()->set_frames_in_memory_multiplier (_frames_in_memory_multiplier->GetValue());
1515 void allow_any_dcp_frame_rate_changed ()
1517 Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ());
1520 void allow_any_container_changed ()
1522 Config::instance()->set_allow_any_container (_allow_any_container->GetValue ());
1525 void show_experimental_audio_processors_changed ()
1527 Config::instance()->set_show_experimental_audio_processors (_show_experimental_audio_processors->GetValue ());
1530 void only_servers_encode_changed ()
1532 Config::instance()->set_only_servers_encode (_only_servers_encode->GetValue ());
1535 void dcp_metadata_filename_format_changed ()
1537 Config::instance()->set_dcp_metadata_filename_format (_dcp_metadata_filename_format->get ());
1540 void dcp_asset_filename_format_changed ()
1542 Config::instance()->set_dcp_asset_filename_format (_dcp_asset_filename_format->get ());
1548 if (_log_general->GetValue ()) {
1549 types |= LogEntry::TYPE_GENERAL;
1551 if (_log_warning->GetValue ()) {
1552 types |= LogEntry::TYPE_WARNING;
1554 if (_log_error->GetValue ()) {
1555 types |= LogEntry::TYPE_ERROR;
1557 if (_log_timing->GetValue ()) {
1558 types |= LogEntry::TYPE_TIMING;
1560 if (_log_debug_threed->GetValue ()) {
1561 types |= LogEntry::TYPE_DEBUG_THREED;
1563 if (_log_debug_encode->GetValue ()) {
1564 types |= LogEntry::TYPE_DEBUG_ENCODE;
1566 if (_log_debug_email->GetValue ()) {
1567 types |= LogEntry::TYPE_DEBUG_EMAIL;
1569 if (_log_debug_video_view->GetValue()) {
1570 types |= LogEntry::TYPE_DEBUG_VIDEO_VIEW;
1572 if (_log_debug_player->GetValue()) {
1573 types |= LogEntry::TYPE_DEBUG_PLAYER;
1575 if (_log_debug_audio_analysis->GetValue()) {
1576 types |= LogEntry::TYPE_DEBUG_AUDIO_ANALYSIS;
1578 Config::instance()->set_log_types (types);
1581 #ifdef DCPOMATIC_WINDOWS
1582 void win32_console_changed ()
1584 Config::instance()->set_win32_console (_win32_console->GetValue ());
1588 wxSpinCtrl* _maximum_j2k_bandwidth;
1589 wxChoice* _video_display_mode;
1590 wxSpinCtrl* _frames_in_memory_multiplier;
1591 wxCheckBox* _allow_any_dcp_frame_rate;
1592 wxCheckBox* _allow_any_container;
1593 wxCheckBox* _show_experimental_audio_processors;
1594 wxCheckBox* _only_servers_encode;
1595 NameFormatEditor* _dcp_metadata_filename_format;
1596 NameFormatEditor* _dcp_asset_filename_format;
1597 wxCheckBox* _log_general;
1598 wxCheckBox* _log_warning;
1599 wxCheckBox* _log_error;
1600 wxCheckBox* _log_timing;
1601 wxCheckBox* _log_debug_threed;
1602 wxCheckBox* _log_debug_encode;
1603 wxCheckBox* _log_debug_email;
1604 wxCheckBox* _log_debug_video_view;
1605 wxCheckBox* _log_debug_player;
1606 wxCheckBox* _log_debug_audio_analysis;
1607 #ifdef DCPOMATIC_WINDOWS
1608 wxCheckBox* _win32_console;
1612 wxPreferencesEditor*
1613 create_full_config_dialog ()
1615 wxPreferencesEditor* e = new wxPreferencesEditor ();
1617 #ifdef DCPOMATIC_OSX
1618 /* Width that we force some of the config panels to be on OSX so that
1619 the containing window doesn't shrink too much when we select those panels.
1620 This is obviously an unpleasant hack.
1622 wxSize ps = wxSize (700, -1);
1623 int const border = 16;
1625 wxSize ps = wxSize (-1, -1);
1626 int const border = 8;
1629 e->AddPage (new FullGeneralPage (ps, border));
1630 e->AddPage (new SoundPage (ps, border));
1631 e->AddPage (new DefaultsPage (ps, border));
1632 e->AddPage (new EncodingServersPage (ps, border));
1633 e->AddPage (new KeysPage (ps, border));
1634 e->AddPage (new TMSPage (ps, border));
1635 e->AddPage (new EmailPage (ps, border));
1636 e->AddPage (new KDMEmailPage (ps, border));
1637 e->AddPage (new NotificationsPage (ps, border));
1638 e->AddPage (new CoverSheetPage (ps, border));
1639 e->AddPage (new IdentifiersPage (ps, border));
1640 e->AddPage (new AdvancedPage (ps, border));