Add PreviewSoundAPI to config.
[dcpomatic.git] / src / lib / config.cc
1 /*
2     Copyright (C) 2012-2022 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
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.
10
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.
15
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/>.
18
19 */
20
21
22 #include "cinema.h"
23 #include "colour_conversion.h"
24 #include "compose.hpp"
25 #include "config.h"
26 #include "cross.h"
27 #include "crypto.h"
28 #include "dcp_content_type.h"
29 #include "dkdm_recipient.h"
30 #include "dkdm_wrapper.h"
31 #include "film.h"
32 #include "filter.h"
33 #include "log.h"
34 #include "ratio.h"
35 #include "types.h"
36 #include "util.h"
37 #include "zipper.h"
38 #include <dcp/certificate_chain.h>
39 #include <dcp/name_format.h>
40 #include <dcp/raw_convert.h>
41 #include <libcxml/cxml.h>
42 #include <glib.h>
43 #include <libxml++/libxml++.h>
44 #include <boost/filesystem.hpp>
45 #include <boost/algorithm/string.hpp>
46 #include <boost/thread.hpp>
47 #include <cstdlib>
48 #include <fstream>
49 #include <iostream>
50
51 #include "i18n.h"
52
53
54 using std::cout;
55 using std::dynamic_pointer_cast;
56 using std::ifstream;
57 using std::list;
58 using std::make_shared;
59 using std::max;
60 using std::min;
61 using std::remove;
62 using std::shared_ptr;
63 using std::string;
64 using std::vector;
65 using boost::algorithm::trim;
66 using boost::optional;
67 using dcp::raw_convert;
68
69
70 Config* Config::_instance = 0;
71 int const Config::_current_version = 3;
72 boost::signals2::signal<void (Config::LoadFailure)> Config::FailedToLoad;
73 boost::signals2::signal<void (string)> Config::Warning;
74 boost::signals2::signal<bool (Config::BadReason)> Config::Bad;
75
76
77 /** Construct default configuration */
78 Config::Config ()
79         /* DKDMs are not considered a thing to reset on set_defaults() */
80         : _dkdms (new DKDMGroup ("root"))
81         , _default_kdm_duration (1, RoughDuration::Unit::WEEKS)
82         , _export(this)
83 {
84         set_defaults ();
85 }
86
87 void
88 Config::set_defaults ()
89 {
90         _master_encoding_threads = max (2U, boost::thread::hardware_concurrency ());
91         _server_encoding_threads = max (2U, boost::thread::hardware_concurrency ());
92         _server_port_base = 6192;
93         _use_any_servers = true;
94         _servers.clear ();
95         _only_servers_encode = false;
96         _tms_protocol = FileTransferProtocol::SCP;
97         _tms_passive = true;
98         _tms_ip = "";
99         _tms_path = ".";
100         _tms_user = "";
101         _tms_password = "";
102         _allow_any_dcp_frame_rate = false;
103         _allow_any_container = false;
104         _allow_96khz_audio = false;
105         _use_all_audio_channels = false;
106         _show_experimental_audio_processors = false;
107         _language = optional<string> ();
108         _default_still_length = 10;
109         _default_container = Ratio::from_id ("185");
110         _default_dcp_content_type = DCPContentType::from_isdcf_name ("FTR");
111         _default_dcp_audio_channels = 6;
112         _default_j2k_bandwidth = 150000000;
113         _default_audio_delay = 0;
114         _default_interop = false;
115         _default_metadata.clear ();
116         _upload_after_make_dcp = false;
117         _mail_server = "";
118         _mail_port = 25;
119         _mail_protocol = EmailProtocol::AUTO;
120         _mail_user = "";
121         _mail_password = "";
122         _kdm_from = "";
123         _kdm_cc.clear ();
124         _kdm_bcc = "";
125         _notification_from = "";
126         _notification_to = "";
127         _notification_cc.clear ();
128         _notification_bcc = "";
129         _check_for_updates = false;
130         _check_for_test_updates = false;
131         _maximum_j2k_bandwidth = 250000000;
132         _log_types = LogEntry::TYPE_GENERAL | LogEntry::TYPE_WARNING | LogEntry::TYPE_ERROR | LogEntry::TYPE_DISK;
133         _analyse_ebur128 = true;
134         _automatic_audio_analysis = false;
135 #ifdef DCPOMATIC_WINDOWS
136         _win32_console = false;
137 #endif
138         /* At the moment we don't write these files anywhere new after a version change, so they will be read from
139          * ~/.config/dcpomatic2 (or equivalent) and written back there.
140          */
141         _cinemas_file = read_path ("cinemas.xml");
142         _dkdm_recipients_file = read_path ("dkdm_recipients.xml");
143         _show_hints_before_make_dcp = true;
144         _confirm_kdm_email = true;
145         _kdm_container_name_format = dcp::NameFormat ("KDM %f %c");
146         _kdm_filename_format = dcp::NameFormat ("KDM %f %c %s");
147         _dkdm_filename_format = dcp::NameFormat ("DKDM %f %c %s");
148         _dcp_metadata_filename_format = dcp::NameFormat ("%t");
149         _dcp_asset_filename_format = dcp::NameFormat ("%t");
150         _jump_to_selected = true;
151         for (int i = 0; i < NAG_COUNT; ++i) {
152                 _nagged[i] = false;
153         }
154         _sound = true;
155         _sound_api = boost::none;
156         _sound_output = boost::none;
157         _last_kdm_write_type = KDM_WRITE_FLAT;
158         _last_dkdm_write_type = DKDM_WRITE_INTERNAL;
159
160         /* I think the scaling factor here should be the ratio of the longest frame
161            encode time to the shortest; if the thread count is T, longest time is L
162            and the shortest time S we could encode L/S frames per thread whilst waiting
163            for the L frame to encode so we might have to store LT/S frames.
164
165            However we don't want to use too much memory, so keep it a bit lower than we'd
166            perhaps like.  A J2K frame is typically about 1Mb so 3 here will mean we could
167            use about 240Mb with 72 encoding threads.
168         */
169         _frames_in_memory_multiplier = 3;
170         _decode_reduction = optional<int>();
171         _default_notify = false;
172         for (int i = 0; i < NOTIFICATION_COUNT; ++i) {
173                 _notification[i] = false;
174         }
175         _barco_username = optional<string>();
176         _barco_password = optional<string>();
177         _christie_username = optional<string>();
178         _christie_password = optional<string>();
179         _gdc_username = optional<string>();
180         _gdc_password = optional<string>();
181         _player_mode = PLAYER_MODE_WINDOW;
182         _image_display = 0;
183         _video_view_type = VIDEO_VIEW_SIMPLE;
184         _respect_kdm_validity_periods = true;
185         _player_debug_log_file = boost::none;
186         _player_content_directory = boost::none;
187         _player_playlist_directory = boost::none;
188         _player_kdm_directory = boost::none;
189         _audio_mapping = boost::none;
190         _custom_languages.clear ();
191         _add_files_path = boost::none;
192         _use_isdcf_name_by_default = true;
193         _write_kdms_to_disk = true;
194         _email_kdms = false;
195         _default_kdm_type = dcp::Formulation::MODIFIED_TRANSITIONAL_1;
196         _default_kdm_duration = RoughDuration(1, RoughDuration::Unit::WEEKS);
197         _auto_crop_threshold = 0.1;
198         _last_release_notes_version = boost::none;
199
200         _allowed_dcp_frame_rates.clear ();
201         _allowed_dcp_frame_rates.push_back (24);
202         _allowed_dcp_frame_rates.push_back (25);
203         _allowed_dcp_frame_rates.push_back (30);
204         _allowed_dcp_frame_rates.push_back (48);
205         _allowed_dcp_frame_rates.push_back (50);
206         _allowed_dcp_frame_rates.push_back (60);
207
208         set_kdm_email_to_default ();
209         set_notification_email_to_default ();
210         set_cover_sheet_to_default ();
211
212         _main_divider_sash_position = {};
213         _main_content_divider_sash_position = {};
214
215         _export.set_defaults();
216 }
217
218 void
219 Config::restore_defaults ()
220 {
221         Config::instance()->set_defaults ();
222         Config::instance()->changed ();
223 }
224
225 shared_ptr<dcp::CertificateChain>
226 Config::create_certificate_chain ()
227 {
228         return make_shared<dcp::CertificateChain> (
229                 openssl_path(),
230                 CERTIFICATE_VALIDITY_PERIOD,
231                 "dcpomatic.com",
232                 "dcpomatic.com",
233                 ".dcpomatic.smpte-430-2.ROOT",
234                 ".dcpomatic.smpte-430-2.INTERMEDIATE",
235                 "CS.dcpomatic.smpte-430-2.LEAF"
236                 );
237 }
238
239 void
240 Config::backup ()
241 {
242         using namespace boost::filesystem;
243
244         auto copy_adding_number = [](path const& path_to_copy) {
245
246                 auto add_number = [](path const& path, int number) {
247                         return String::compose("%1.%2", path, number);
248                 };
249
250                 int n = 1;
251                 while (n < 100 && exists(add_number(path_to_copy, n))) {
252                         ++n;
253                 }
254                 boost::system::error_code ec;
255                 copy_file(path_to_copy, add_number(path_to_copy, n), ec);
256         };
257
258         /* Make a backup copy of any config.xml, cinemas.xml, dkdm_recipients.xml that we might be about
259          * to write over.  This is more intended for the situation where we have a corrupted config.xml,
260          * and decide to overwrite it with a new one (possibly losing important details in the corrupted
261          * file).  But we might as well back up the other files while we're about it.
262          */
263
264         /* This uses the State::write_path stuff so, e.g. for a current version 2.16 we might copy
265          * ~/.config/dcpomatic2/2.16/config.xml to ~/.config/dcpomatic2/2.16/config.xml.1
266          */
267         copy_adding_number (config_write_file());
268
269         /* These do not use State::write_path, so whatever path is in the Config we will copy
270          * adding a number.
271          */
272         copy_adding_number (_cinemas_file);
273         copy_adding_number (_dkdm_recipients_file);
274 }
275
276 void
277 Config::read ()
278 {
279         read_config();
280         read_cinemas();
281         read_dkdm_recipients();
282 }
283
284
285 void
286 Config::read_config()
287 try
288 {
289         cxml::Document f ("Config");
290         f.read_file (config_read_file());
291
292         auto version = f.optional_number_child<int> ("Version");
293         if (version && *version < _current_version) {
294                 /* Back up the old config before we re-write it in a back-incompatible way */
295                 backup ();
296         }
297
298         if (f.optional_number_child<int>("NumLocalEncodingThreads")) {
299                 _master_encoding_threads = _server_encoding_threads = f.optional_number_child<int>("NumLocalEncodingThreads").get();
300         } else {
301                 _master_encoding_threads = f.number_child<int>("MasterEncodingThreads");
302                 _server_encoding_threads = f.number_child<int>("ServerEncodingThreads");
303         }
304
305         _default_directory = f.optional_string_child ("DefaultDirectory");
306         if (_default_directory && _default_directory->empty ()) {
307                 /* We used to store an empty value for this to mean "none set" */
308                 _default_directory = boost::optional<boost::filesystem::path> ();
309         }
310
311         auto b = f.optional_number_child<int> ("ServerPort");
312         if (!b) {
313                 b = f.optional_number_child<int> ("ServerPortBase");
314         }
315         _server_port_base = b.get ();
316
317         auto u = f.optional_bool_child ("UseAnyServers");
318         _use_any_servers = u.get_value_or (true);
319
320         for (auto i: f.node_children("Server")) {
321                 if (i->node_children("HostName").size() == 1) {
322                         _servers.push_back (i->string_child ("HostName"));
323                 } else {
324                         _servers.push_back (i->content ());
325                 }
326         }
327
328         _only_servers_encode = f.optional_bool_child ("OnlyServersEncode").get_value_or (false);
329         _tms_protocol = static_cast<FileTransferProtocol>(f.optional_number_child<int>("TMSProtocol").get_value_or(static_cast<int>(FileTransferProtocol::SCP)));
330         _tms_passive = f.optional_bool_child("TMSPassive").get_value_or(true);
331         _tms_ip = f.string_child ("TMSIP");
332         _tms_path = f.string_child ("TMSPath");
333         _tms_user = f.string_child ("TMSUser");
334         _tms_password = f.string_child ("TMSPassword");
335
336         _language = f.optional_string_child ("Language");
337
338         auto c = f.optional_string_child ("DefaultContainer");
339         if (c) {
340                 _default_container = Ratio::from_id (c.get ());
341         }
342
343         if (_default_container && !_default_container->used_for_container()) {
344                 Warning (_("Your default container is not valid and has been changed to Flat (1.85:1)"));
345                 _default_container = Ratio::from_id ("185");
346         }
347
348         _default_dcp_content_type = DCPContentType::from_isdcf_name(f.optional_string_child("DefaultDCPContentType").get_value_or("FTR"));
349         _default_dcp_audio_channels = f.optional_number_child<int>("DefaultDCPAudioChannels").get_value_or (6);
350
351         if (f.optional_string_child ("DCPMetadataIssuer")) {
352                 _dcp_issuer = f.string_child ("DCPMetadataIssuer");
353         } else if (f.optional_string_child ("DCPIssuer")) {
354                 _dcp_issuer = f.string_child ("DCPIssuer");
355         }
356
357         auto up = f.optional_bool_child("UploadAfterMakeDCP");
358         if (!up) {
359                 up = f.optional_bool_child("DefaultUploadAfterMakeDCP");
360         }
361         _upload_after_make_dcp = up.get_value_or (false);
362         _dcp_creator = f.optional_string_child ("DCPCreator").get_value_or ("");
363         _dcp_company_name = f.optional_string_child("DCPCompanyName").get_value_or("");
364         _dcp_product_name = f.optional_string_child("DCPProductName").get_value_or("");
365         _dcp_product_version = f.optional_string_child("DCPProductVersion").get_value_or("");
366         _dcp_j2k_comment = f.optional_string_child("DCPJ2KComment").get_value_or("");
367
368         _default_still_length = f.optional_number_child<int>("DefaultStillLength").get_value_or (10);
369         _default_j2k_bandwidth = f.optional_number_child<int>("DefaultJ2KBandwidth").get_value_or (200000000);
370         _default_audio_delay = f.optional_number_child<int>("DefaultAudioDelay").get_value_or (0);
371         _default_interop = f.optional_bool_child("DefaultInterop").get_value_or (false);
372
373         for (auto const& i: f.node_children("DefaultMetadata")) {
374                 _default_metadata[i->string_attribute("key")] = i->content();
375         }
376
377         _default_kdm_directory = f.optional_string_child("DefaultKDMDirectory");
378
379         /* Read any cinemas that are still lying around in the config file
380          * from an old version.
381          */
382         read_cinemas (f);
383
384         _mail_server = f.string_child ("MailServer");
385         _mail_port = f.optional_number_child<int> ("MailPort").get_value_or (25);
386
387         {
388                 /* Make sure this matches the code in write_config */
389                 string const protocol = f.optional_string_child("MailProtocol").get_value_or("Auto");
390                 if (protocol == "Auto") {
391                         _mail_protocol = EmailProtocol::AUTO;
392                 } else if (protocol == "Plain") {
393                         _mail_protocol = EmailProtocol::PLAIN;
394                 } else if (protocol == "STARTTLS") {
395                         _mail_protocol = EmailProtocol::STARTTLS;
396                 } else if (protocol == "SSL") {
397                         _mail_protocol = EmailProtocol::SSL;
398                 }
399         }
400
401         _mail_user = f.optional_string_child("MailUser").get_value_or ("");
402         _mail_password = f.optional_string_child("MailPassword").get_value_or ("");
403
404         _kdm_subject = f.optional_string_child ("KDMSubject").get_value_or (_("KDM delivery: $CPL_NAME"));
405         _kdm_from = f.string_child ("KDMFrom");
406         for (auto i: f.node_children("KDMCC")) {
407                 if (!i->content().empty()) {
408                         _kdm_cc.push_back (i->content ());
409                 }
410         }
411         _kdm_bcc = f.optional_string_child ("KDMBCC").get_value_or ("");
412         _kdm_email = f.string_child ("KDMEmail");
413
414         _notification_subject = f.optional_string_child("NotificationSubject").get_value_or(_("DCP-o-matic notification"));
415         _notification_from = f.optional_string_child("NotificationFrom").get_value_or("");
416         _notification_to = f.optional_string_child("NotificationTo").get_value_or("");
417         for (auto i: f.node_children("NotificationCC")) {
418                 if (!i->content().empty()) {
419                         _notification_cc.push_back (i->content ());
420                 }
421         }
422         _notification_bcc = f.optional_string_child("NotificationBCC").get_value_or("");
423         if (f.optional_string_child("NotificationEmail")) {
424                 _notification_email = f.string_child("NotificationEmail");
425         }
426
427         _check_for_updates = f.optional_bool_child("CheckForUpdates").get_value_or (false);
428         _check_for_test_updates = f.optional_bool_child("CheckForTestUpdates").get_value_or (false);
429
430         _maximum_j2k_bandwidth = f.optional_number_child<int> ("MaximumJ2KBandwidth").get_value_or (250000000);
431         _allow_any_dcp_frame_rate = f.optional_bool_child ("AllowAnyDCPFrameRate").get_value_or (false);
432         _allow_any_container = f.optional_bool_child ("AllowAnyContainer").get_value_or (false);
433         _allow_96khz_audio = f.optional_bool_child("Allow96kHzAudio").get_value_or(false);
434         _use_all_audio_channels = f.optional_bool_child("UseAllAudioChannels").get_value_or(false);
435         _show_experimental_audio_processors = f.optional_bool_child ("ShowExperimentalAudioProcessors").get_value_or (false);
436
437         _log_types = f.optional_number_child<int> ("LogTypes").get_value_or (LogEntry::TYPE_GENERAL | LogEntry::TYPE_WARNING | LogEntry::TYPE_ERROR);
438         _analyse_ebur128 = f.optional_bool_child("AnalyseEBUR128").get_value_or (true);
439         _automatic_audio_analysis = f.optional_bool_child ("AutomaticAudioAnalysis").get_value_or (false);
440 #ifdef DCPOMATIC_WINDOWS
441         _win32_console = f.optional_bool_child ("Win32Console").get_value_or (false);
442 #endif
443
444         for (auto i: f.node_children("History")) {
445                 _history.push_back (i->content ());
446         }
447
448         for (auto i: f.node_children("PlayerHistory")) {
449                 _player_history.push_back (i->content ());
450         }
451
452         auto signer = f.optional_node_child ("Signer");
453         if (signer) {
454                 auto c = make_shared<dcp::CertificateChain>();
455                 /* Read the signing certificates and private key in from the config file */
456                 for (auto i: signer->node_children ("Certificate")) {
457                         c->add (dcp::Certificate (i->content ()));
458                 }
459                 c->set_key (signer->string_child ("PrivateKey"));
460                 _signer_chain = c;
461         } else {
462                 /* Make a new set of signing certificates and key */
463                 _signer_chain = create_certificate_chain ();
464         }
465
466         auto decryption = f.optional_node_child ("Decryption");
467         if (decryption) {
468                 auto c = make_shared<dcp::CertificateChain>();
469                 for (auto i: decryption->node_children ("Certificate")) {
470                         c->add (dcp::Certificate (i->content ()));
471                 }
472                 c->set_key (decryption->string_child ("PrivateKey"));
473                 _decryption_chain = c;
474         } else {
475                 _decryption_chain = create_certificate_chain ();
476         }
477
478         /* These must be done before we call Bad as that might set one
479            of the nags.
480         */
481         for (auto i: f.node_children("Nagged")) {
482                 auto const id = i->number_attribute<int>("Id");
483                 if (id >= 0 && id < NAG_COUNT) {
484                         _nagged[id] = raw_convert<int>(i->content());
485                 }
486         }
487
488         auto bad = check_certificates ();
489         if (bad) {
490                 auto const remake = Bad(*bad);
491                 if (remake && *remake) {
492                         switch (*bad) {
493                         case BAD_SIGNER_UTF8_STRINGS:
494                         case BAD_SIGNER_INCONSISTENT:
495                         case BAD_SIGNER_VALIDITY_TOO_LONG:
496                                 _signer_chain = create_certificate_chain ();
497                                 break;
498                         case BAD_DECRYPTION_INCONSISTENT:
499                                 _decryption_chain = create_certificate_chain ();
500                                 break;
501                         }
502                 }
503         }
504
505         if (f.optional_node_child("DKDMGroup")) {
506                 /* New-style: all DKDMs in a group */
507                 _dkdms = dynamic_pointer_cast<DKDMGroup> (DKDMBase::read (f.node_child("DKDMGroup")));
508         } else {
509                 /* Old-style: one or more DKDM nodes */
510                 _dkdms = make_shared<DKDMGroup>("root");
511                 for (auto i: f.node_children("DKDM")) {
512                         _dkdms->add (DKDMBase::read (i));
513                 }
514         }
515         _cinemas_file = f.optional_string_child("CinemasFile").get_value_or(read_path("cinemas.xml").string());
516         _dkdm_recipients_file = f.optional_string_child("DKDMRecipientsFile").get_value_or(read_path("dkdm_recipients.xml").string());
517         _show_hints_before_make_dcp = f.optional_bool_child("ShowHintsBeforeMakeDCP").get_value_or (true);
518         _confirm_kdm_email = f.optional_bool_child("ConfirmKDMEmail").get_value_or (true);
519         _kdm_container_name_format = dcp::NameFormat (f.optional_string_child("KDMContainerNameFormat").get_value_or ("KDM %f %c"));
520         _kdm_filename_format = dcp::NameFormat (f.optional_string_child("KDMFilenameFormat").get_value_or ("KDM %f %c %s"));
521         _dkdm_filename_format = dcp::NameFormat (f.optional_string_child("DKDMFilenameFormat").get_value_or("DKDM %f %c %s"));
522         _dcp_metadata_filename_format = dcp::NameFormat (f.optional_string_child("DCPMetadataFilenameFormat").get_value_or ("%t"));
523         _dcp_asset_filename_format = dcp::NameFormat (f.optional_string_child("DCPAssetFilenameFormat").get_value_or ("%t"));
524         _jump_to_selected = f.optional_bool_child("JumpToSelected").get_value_or (true);
525         /* The variable was renamed but not the XML tag */
526         _sound = f.optional_bool_child("PreviewSound").get_value_or (true);
527         _sound_api = f.optional_string_child("PreviewSoundAPI");
528         _sound_output = f.optional_string_child("PreviewSoundOutput");
529         if (f.optional_string_child("CoverSheet")) {
530                 _cover_sheet = f.optional_string_child("CoverSheet").get();
531         }
532         _last_player_load_directory = f.optional_string_child("LastPlayerLoadDirectory");
533         if (f.optional_string_child("LastKDMWriteType")) {
534                 if (f.optional_string_child("LastKDMWriteType").get() == "flat") {
535                         _last_kdm_write_type = KDM_WRITE_FLAT;
536                 } else if (f.optional_string_child("LastKDMWriteType").get() == "folder") {
537                         _last_kdm_write_type = KDM_WRITE_FOLDER;
538                 } else if (f.optional_string_child("LastKDMWriteType").get() == "zip") {
539                         _last_kdm_write_type = KDM_WRITE_ZIP;
540                 }
541         }
542         if (f.optional_string_child("LastDKDMWriteType")) {
543                 if (f.optional_string_child("LastDKDMWriteType").get() == "internal") {
544                         _last_dkdm_write_type = DKDM_WRITE_INTERNAL;
545                 } else if (f.optional_string_child("LastDKDMWriteType").get() == "file") {
546                         _last_dkdm_write_type = DKDM_WRITE_FILE;
547                 }
548         }
549         _frames_in_memory_multiplier = f.optional_number_child<int>("FramesInMemoryMultiplier").get_value_or(3);
550         _decode_reduction = f.optional_number_child<int>("DecodeReduction");
551         _default_notify = f.optional_bool_child("DefaultNotify").get_value_or(false);
552
553         for (auto i: f.node_children("Notification")) {
554                 int const id = i->number_attribute<int>("Id");
555                 if (id >= 0 && id < NOTIFICATION_COUNT) {
556                         _notification[id] = raw_convert<int>(i->content());
557                 }
558         }
559
560         _barco_username = f.optional_string_child("BarcoUsername");
561         _barco_password = f.optional_string_child("BarcoPassword");
562         _christie_username = f.optional_string_child("ChristieUsername");
563         _christie_password = f.optional_string_child("ChristiePassword");
564         _gdc_username = f.optional_string_child("GDCUsername");
565         _gdc_password = f.optional_string_child("GDCPassword");
566
567         auto pm = f.optional_string_child("PlayerMode");
568         if (pm && *pm == "window") {
569                 _player_mode = PLAYER_MODE_WINDOW;
570         } else if (pm && *pm == "full") {
571                 _player_mode = PLAYER_MODE_FULL;
572         } else if (pm && *pm == "dual") {
573                 _player_mode = PLAYER_MODE_DUAL;
574         }
575
576         _image_display = f.optional_number_child<int>("ImageDisplay").get_value_or(0);
577         auto vc = f.optional_string_child("VideoViewType");
578         if (vc && *vc == "opengl") {
579                 _video_view_type = VIDEO_VIEW_OPENGL;
580         } else if (vc && *vc == "simple") {
581                 _video_view_type = VIDEO_VIEW_SIMPLE;
582         }
583         _respect_kdm_validity_periods = f.optional_bool_child("RespectKDMValidityPeriods").get_value_or(true);
584         _player_debug_log_file = f.optional_string_child("PlayerDebugLogFile");
585         _player_content_directory = f.optional_string_child("PlayerContentDirectory");
586         _player_playlist_directory = f.optional_string_child("PlayerPlaylistDirectory");
587         _player_kdm_directory = f.optional_string_child("PlayerKDMDirectory");
588
589         if (f.optional_node_child("AudioMapping")) {
590                 _audio_mapping = AudioMapping (f.node_child("AudioMapping"), Film::current_state_version);
591         }
592
593         for (auto i: f.node_children("CustomLanguage")) {
594                 try {
595                         /* This will fail if it's called before dcp::init() as it won't recognise the
596                          * tag.  That's OK because the Config will be reloaded again later.
597                          */
598                         _custom_languages.push_back (dcp::LanguageTag(i->content()));
599                 } catch (std::runtime_error& e) {}
600         }
601
602         _add_files_path = f.optional_string_child("AddFilesPath");
603         _use_isdcf_name_by_default = f.optional_bool_child("UseISDCFNameByDefault").get_value_or(true);
604         _write_kdms_to_disk = f.optional_bool_child("WriteKDMsToDisk").get_value_or(true);
605         _email_kdms = f.optional_bool_child("EmailKDMs").get_value_or(false);
606         _default_kdm_type = dcp::string_to_formulation(f.optional_string_child("DefaultKDMType").get_value_or("modified-transitional-1"));
607         if (auto duration = f.optional_node_child("DefaultKDMDuration")) {
608                 _default_kdm_duration = RoughDuration(duration);
609         } else {
610                 _default_kdm_duration = RoughDuration(1, RoughDuration::Unit::WEEKS);
611         }
612         _auto_crop_threshold = f.optional_number_child<double>("AutoCropThreshold").get_value_or(0.1);
613         _last_release_notes_version = f.optional_string_child("LastReleaseNotesVersion");
614         _main_divider_sash_position = f.optional_number_child<int>("MainDividerSashPosition");
615         _main_content_divider_sash_position = f.optional_number_child<int>("MainContentDividerSashPosition");
616
617         _export.read(f.optional_node_child("Export"));
618 }
619 catch (...) {
620         if (have_existing("config.xml")) {
621                 backup ();
622                 /* We have a config file but it didn't load */
623                 FailedToLoad(LoadFailure::CONFIG);
624         }
625         set_defaults ();
626         /* Make a new set of signing certificates and key */
627         _signer_chain = create_certificate_chain ();
628         /* And similar for decryption of KDMs */
629         _decryption_chain = create_certificate_chain ();
630         write_config();
631 }
632
633
634 void
635 Config::read_cinemas()
636 {
637         if (boost::filesystem::exists (_cinemas_file)) {
638                 try {
639                         cxml::Document f("Cinemas");
640                         f.read_file(_cinemas_file);
641                         read_cinemas(f);
642                 } catch (...) {
643                         backup();
644                         FailedToLoad(LoadFailure::CINEMAS);
645                         write_cinemas();
646                 }
647         }
648 }
649
650
651 void
652 Config::read_dkdm_recipients()
653 {
654         if (boost::filesystem::exists (_dkdm_recipients_file)) {
655                 try {
656                         cxml::Document f("DKDMRecipients");
657                         f.read_file(_dkdm_recipients_file);
658                         read_dkdm_recipients(f);
659                 } catch (...) {
660                         backup();
661                         FailedToLoad(LoadFailure::DKDM_RECIPIENTS);
662                         write_dkdm_recipients();
663                 }
664         }
665 }
666
667
668 /** @return Singleton instance */
669 Config *
670 Config::instance ()
671 {
672         if (_instance == nullptr) {
673                 _instance = new Config;
674                 _instance->read ();
675         }
676
677         return _instance;
678 }
679
680 /** Write our configuration to disk */
681 void
682 Config::write () const
683 {
684         write_config ();
685         write_cinemas ();
686         write_dkdm_recipients ();
687 }
688
689 void
690 Config::write_config () const
691 {
692         xmlpp::Document doc;
693         auto root = doc.create_root_node ("Config");
694
695         /* [XML] Version The version number of the configuration file format. */
696         root->add_child("Version")->add_child_text (raw_convert<string>(_current_version));
697         /* [XML] MasterEncodingThreads Number of encoding threads to use when running as master. */
698         root->add_child("MasterEncodingThreads")->add_child_text (raw_convert<string> (_master_encoding_threads));
699         /* [XML] ServerEncodingThreads Number of encoding threads to use when running as server. */
700         root->add_child("ServerEncodingThreads")->add_child_text (raw_convert<string> (_server_encoding_threads));
701         if (_default_directory) {
702                 /* [XML:opt] DefaultDirectory Default directory when creating a new film in the GUI. */
703                 root->add_child("DefaultDirectory")->add_child_text (_default_directory->string ());
704         }
705         /* [XML] ServerPortBase Port number to use for frame encoding requests.  <code>ServerPortBase</code> + 1 and
706            <code>ServerPortBase</code> + 2 are used for querying servers.  <code>ServerPortBase</code> + 3 is used
707            by the batch converter to listen for job requests.
708         */
709         root->add_child("ServerPortBase")->add_child_text (raw_convert<string> (_server_port_base));
710         /* [XML] UseAnyServers 1 to broadcast to look for encoding servers to use, 0 to use only those configured. */
711         root->add_child("UseAnyServers")->add_child_text (_use_any_servers ? "1" : "0");
712
713         for (auto i: _servers) {
714                 /* [XML:opt] Server IP address or hostname of an encoding server to use; you can use as many of these tags
715                    as you like.
716                 */
717                 root->add_child("Server")->add_child_text (i);
718         }
719
720         /* [XML] OnlyServersEncode 1 to set the master to do decoding of source content no JPEG2000 encoding; all encoding
721            is done by the encoding servers.  0 to set the master to do some encoding as well as coordinating the job.
722         */
723         root->add_child("OnlyServersEncode")->add_child_text (_only_servers_encode ? "1" : "0");
724         /* [XML] TMSProtocol Protocol to use to copy files to a TMS; 0 to use SCP, 1 for FTP. */
725         root->add_child("TMSProtocol")->add_child_text (raw_convert<string> (static_cast<int> (_tms_protocol)));
726         /* [XML] TMSPassive True to use PASV mode with TMS FTP connections. */
727         root->add_child("TMSPassive")->add_child_text(_tms_passive ? "1" : "0");
728         /* [XML] TMSIP IP address of TMS. */
729         root->add_child("TMSIP")->add_child_text (_tms_ip);
730         /* [XML] TMSPath Path on the TMS to copy files to. */
731         root->add_child("TMSPath")->add_child_text (_tms_path);
732         /* [XML] TMSUser Username to log into the TMS with. */
733         root->add_child("TMSUser")->add_child_text (_tms_user);
734         /* [XML] TMSPassword Password to log into the TMS with. */
735         root->add_child("TMSPassword")->add_child_text (_tms_password);
736         if (_language) {
737                 /* [XML:opt] Language Language to use in the GUI e.g. <code>fr_FR</code>. */
738                 root->add_child("Language")->add_child_text (_language.get());
739         }
740         if (_default_container) {
741                 /* [XML:opt] DefaultContainer ID of default container
742                    to use when creating new films (<code>185</code>,<code>239</code> or
743                    <code>190</code>).
744                 */
745                 root->add_child("DefaultContainer")->add_child_text (_default_container->id ());
746         }
747         if (_default_dcp_content_type) {
748                 /* [XML:opt] DefaultDCPContentType Default content type to use when creating new films (<code>FTR</code>, <code>SHR</code>,
749                    <code>TLR</code>, <code>TST</code>, <code>XSN</code>, <code>RTG</code>, <code>TSR</code>, <code>POL</code>,
750                    <code>PSA</code> or <code>ADV</code>). */
751                 root->add_child("DefaultDCPContentType")->add_child_text (_default_dcp_content_type->isdcf_name ());
752         }
753         /* [XML] DefaultDCPAudioChannels Default number of audio channels to use when creating new films. */
754         root->add_child("DefaultDCPAudioChannels")->add_child_text (raw_convert<string> (_default_dcp_audio_channels));
755         /* [XML] DCPIssuer Issuer text to write into CPL files. */
756         root->add_child("DCPIssuer")->add_child_text (_dcp_issuer);
757         /* [XML] DCPCreator Creator text to write into CPL files. */
758         root->add_child("DCPCreator")->add_child_text (_dcp_creator);
759         /* [XML] Company name to write into MXF files. */
760         root->add_child("DCPCompanyName")->add_child_text (_dcp_company_name);
761         /* [XML] Product name to write into MXF files. */
762         root->add_child("DCPProductName")->add_child_text (_dcp_product_name);
763         /* [XML] Product version to write into MXF files. */
764         root->add_child("DCPProductVersion")->add_child_text (_dcp_product_version);
765         /* [XML] Comment to write into JPEG2000 data. */
766         root->add_child("DCPJ2KComment")->add_child_text (_dcp_j2k_comment);
767         /* [XML] UploadAfterMakeDCP 1 to upload to a TMS after making a DCP, 0 for no upload. */
768         root->add_child("UploadAfterMakeDCP")->add_child_text (_upload_after_make_dcp ? "1" : "0");
769
770         /* [XML] DefaultStillLength Default length (in seconds) for still images in new films. */
771         root->add_child("DefaultStillLength")->add_child_text (raw_convert<string> (_default_still_length));
772         /* [XML] DefaultJ2KBandwidth Default bitrate (in bits per second) for JPEG2000 data in new films. */
773         root->add_child("DefaultJ2KBandwidth")->add_child_text (raw_convert<string> (_default_j2k_bandwidth));
774         /* [XML] DefaultAudioDelay Default delay to apply to audio (positive moves audio later) in milliseconds. */
775         root->add_child("DefaultAudioDelay")->add_child_text (raw_convert<string> (_default_audio_delay));
776         /* [XML] DefaultInterop 1 to default new films to Interop, 0 for SMPTE. */
777         root->add_child("DefaultInterop")->add_child_text (_default_interop ? "1" : "0");
778         for (auto const& i: _default_metadata) {
779                 auto c = root->add_child("DefaultMetadata");
780                 c->set_attribute("key", i.first);
781                 c->add_child_text(i.second);
782         }
783         if (_default_kdm_directory) {
784                 /* [XML:opt] DefaultKDMDirectory Default directory to write KDMs to. */
785                 root->add_child("DefaultKDMDirectory")->add_child_text (_default_kdm_directory->string ());
786         }
787         _default_kdm_duration.as_xml(root->add_child("DefaultKDMDuration"));
788         /* [XML] MailServer Hostname of SMTP server to use. */
789         root->add_child("MailServer")->add_child_text (_mail_server);
790         /* [XML] MailPort Port number to use on SMTP server. */
791         root->add_child("MailPort")->add_child_text (raw_convert<string> (_mail_port));
792         /* [XML] MailProtocol Protocol to use on SMTP server (Auto, Plain, STARTTLS or SSL) */
793         switch (_mail_protocol) {
794         case EmailProtocol::AUTO:
795                 root->add_child("MailProtocol")->add_child_text("Auto");
796                 break;
797         case EmailProtocol::PLAIN:
798                 root->add_child("MailProtocol")->add_child_text("Plain");
799                 break;
800         case EmailProtocol::STARTTLS:
801                 root->add_child("MailProtocol")->add_child_text("STARTTLS");
802                 break;
803         case EmailProtocol::SSL:
804                 root->add_child("MailProtocol")->add_child_text("SSL");
805                 break;
806         }
807         /* [XML] MailUser Username to use on SMTP server. */
808         root->add_child("MailUser")->add_child_text (_mail_user);
809         /* [XML] MailPassword Password to use on SMTP server. */
810         root->add_child("MailPassword")->add_child_text (_mail_password);
811
812         /* [XML] KDMSubject Subject to use for KDM emails. */
813         root->add_child("KDMSubject")->add_child_text (_kdm_subject);
814         /* [XML] KDMFrom From address to use for KDM emails. */
815         root->add_child("KDMFrom")->add_child_text (_kdm_from);
816         for (auto i: _kdm_cc) {
817                 /* [XML] KDMCC CC address to use for KDM emails; you can use as many of these tags as you like. */
818                 root->add_child("KDMCC")->add_child_text (i);
819         }
820         /* [XML] KDMBCC BCC address to use for KDM emails. */
821         root->add_child("KDMBCC")->add_child_text (_kdm_bcc);
822         /* [XML] KDMEmail Text of KDM email. */
823         root->add_child("KDMEmail")->add_child_text (_kdm_email);
824
825         /* [XML] NotificationSubject Subject to use for notification emails. */
826         root->add_child("NotificationSubject")->add_child_text (_notification_subject);
827         /* [XML] NotificationFrom From address to use for notification emails. */
828         root->add_child("NotificationFrom")->add_child_text (_notification_from);
829         /* [XML] NotificationFrom To address to use for notification emails. */
830         root->add_child("NotificationTo")->add_child_text (_notification_to);
831         for (auto i: _notification_cc) {
832                 /* [XML] NotificationCC CC address to use for notification emails; you can use as many of these tags as you like. */
833                 root->add_child("NotificationCC")->add_child_text (i);
834         }
835         /* [XML] NotificationBCC BCC address to use for notification emails. */
836         root->add_child("NotificationBCC")->add_child_text (_notification_bcc);
837         /* [XML] NotificationEmail Text of notification email. */
838         root->add_child("NotificationEmail")->add_child_text (_notification_email);
839
840         /* [XML] CheckForUpdates 1 to check dcpomatic.com for new versions, 0 to check only on request. */
841         root->add_child("CheckForUpdates")->add_child_text (_check_for_updates ? "1" : "0");
842         /* [XML] CheckForUpdates 1 to check dcpomatic.com for new text versions, 0 to check only on request. */
843         root->add_child("CheckForTestUpdates")->add_child_text (_check_for_test_updates ? "1" : "0");
844
845         /* [XML] MaximumJ2KBandwidth Maximum J2K bandwidth (in bits per second) that can be specified in the GUI. */
846         root->add_child("MaximumJ2KBandwidth")->add_child_text (raw_convert<string> (_maximum_j2k_bandwidth));
847         /* [XML] AllowAnyDCPFrameRate 1 to allow users to specify any frame rate when creating DCPs, 0 to limit the GUI to standard rates. */
848         root->add_child("AllowAnyDCPFrameRate")->add_child_text (_allow_any_dcp_frame_rate ? "1" : "0");
849         /* [XML] AllowAnyContainer 1 to allow users to user any container ratio for their DCP, 0 to limit the GUI to DCI Flat/Scope */
850         root->add_child("AllowAnyContainer")->add_child_text (_allow_any_container ? "1" : "0");
851         /* [XML] Allow96kHzAudio 1 to allow users to make DCPs with 96kHz audio, 0 to always make 48kHz DCPs */
852         root->add_child("Allow96kHzAudio")->add_child_text(_allow_96khz_audio ? "1" : "0");
853         /* [XML] UseAllAudioChannels 1 to allow users to map audio to all 16 DCP channels, 0 to limit to the channels used in standard DCPs */
854         root->add_child("UseAllAudioChannels")->add_child_text(_use_all_audio_channels ? "1" : "0");
855         /* [XML] ShowExperimentalAudioProcessors 1 to offer users the (experimental) audio upmixer processors, 0 to hide them */
856         root->add_child("ShowExperimentalAudioProcessors")->add_child_text (_show_experimental_audio_processors ? "1" : "0");
857         /* [XML] LogTypes Types of logging to write; a bitfield where 1 is general notes, 2 warnings, 4 errors, 8 debug information related
858            to 3D, 16 debug information related to encoding, 32 debug information for timing purposes, 64 debug information related
859            to sending email, 128 debug information related to the video view, 256 information about disk writing, 512 debug information
860            related to the player, 1024 debug information related to audio analyses.
861         */
862         root->add_child("LogTypes")->add_child_text (raw_convert<string> (_log_types));
863         /* [XML] AnalyseEBUR128 1 to do EBUR128 analyses when analysing audio, otherwise 0. */
864         root->add_child("AnalyseEBUR128")->add_child_text (_analyse_ebur128 ? "1" : "0");
865         /* [XML] AutomaticAudioAnalysis 1 to run audio analysis automatically when audio content is added to the film, otherwise 0. */
866         root->add_child("AutomaticAudioAnalysis")->add_child_text (_automatic_audio_analysis ? "1" : "0");
867 #ifdef DCPOMATIC_WINDOWS
868         if (_win32_console) {
869                 /* [XML] Win32Console 1 to open a console when running on Windows, otherwise 0.
870                  * We only write this if it's true, which is a bit of a hack to allow unit tests to work
871                  * more easily on Windows (without a platform-specific reference in config_write_utf8_test)
872                  */
873                 root->add_child("Win32Console")->add_child_text ("1");
874         }
875 #endif
876
877         /* [XML] Signer Certificate chain and private key to use when signing DCPs and KDMs.  Should contain <code>&lt;Certificate&gt;</code>
878            tags in order and a <code>&lt;PrivateKey&gt;</code> tag all containing PEM-encoded certificates or private keys as appropriate.
879         */
880         auto signer = root->add_child ("Signer");
881         DCPOMATIC_ASSERT (_signer_chain);
882         for (auto const& i: _signer_chain->unordered()) {
883                 signer->add_child("Certificate")->add_child_text (i.certificate (true));
884         }
885         signer->add_child("PrivateKey")->add_child_text (_signer_chain->key().get ());
886
887         /* [XML] Decryption Certificate chain and private key to use when decrypting KDMs */
888         auto decryption = root->add_child ("Decryption");
889         DCPOMATIC_ASSERT (_decryption_chain);
890         for (auto const& i: _decryption_chain->unordered()) {
891                 decryption->add_child("Certificate")->add_child_text (i.certificate (true));
892         }
893         decryption->add_child("PrivateKey")->add_child_text (_decryption_chain->key().get ());
894
895         /* [XML] History Filename of DCP to present in the <guilabel>File</guilabel> menu of the GUI; there can be more than one
896            of these tags.
897         */
898         for (auto i: _history) {
899                 root->add_child("History")->add_child_text (i.string ());
900         }
901
902         /* [XML] History Filename of DCP to present in the <guilabel>File</guilabel> menu of the player; there can be more than one
903            of these tags.
904         */
905         for (auto i: _player_history) {
906                 root->add_child("PlayerHistory")->add_child_text (i.string ());
907         }
908
909         /* [XML] DKDMGroup A group of DKDMs, each with a <code>Name</code> attribute, containing other <code>&lt;DKDMGroup&gt;</code>
910            or <code>&lt;DKDM&gt;</code> tags.
911         */
912         /* [XML] DKDM A DKDM as XML */
913         _dkdms->as_xml (root);
914
915         /* [XML] CinemasFile Filename of cinemas list file. */
916         root->add_child("CinemasFile")->add_child_text (_cinemas_file.string());
917         /* [XML] DKDMRecipientsFile Filename of DKDM recipients list file. */
918         root->add_child("DKDMRecipientsFile")->add_child_text (_dkdm_recipients_file.string());
919         /* [XML] ShowHintsBeforeMakeDCP 1 to show hints in the GUI before making a DCP, otherwise 0. */
920         root->add_child("ShowHintsBeforeMakeDCP")->add_child_text (_show_hints_before_make_dcp ? "1" : "0");
921         /* [XML] ConfirmKDMEmail 1 to confirm before sending KDM emails in the GUI, otherwise 0. */
922         root->add_child("ConfirmKDMEmail")->add_child_text (_confirm_kdm_email ? "1" : "0");
923         /* [XML] KDMFilenameFormat Format for KDM filenames. */
924         root->add_child("KDMFilenameFormat")->add_child_text (_kdm_filename_format.specification ());
925         /* [XML] KDMFilenameFormat Format for DKDM filenames. */
926         root->add_child("DKDMFilenameFormat")->add_child_text(_dkdm_filename_format.specification());
927         /* [XML] KDMContainerNameFormat Format for KDM containers (directories or ZIP files). */
928         root->add_child("KDMContainerNameFormat")->add_child_text (_kdm_container_name_format.specification ());
929         /* [XML] DCPMetadataFilenameFormat Format for DCP metadata filenames. */
930         root->add_child("DCPMetadataFilenameFormat")->add_child_text (_dcp_metadata_filename_format.specification ());
931         /* [XML] DCPAssetFilenameFormat Format for DCP asset filenames. */
932         root->add_child("DCPAssetFilenameFormat")->add_child_text (_dcp_asset_filename_format.specification ());
933         /* [XML] JumpToSelected 1 to make the GUI jump to the start of content when it is selected, otherwise 0. */
934         root->add_child("JumpToSelected")->add_child_text (_jump_to_selected ? "1" : "0");
935         /* [XML] Nagged 1 if a particular nag screen has been shown and should not be shown again, otherwise 0. */
936         for (int i = 0; i < NAG_COUNT; ++i) {
937                 xmlpp::Element* e = root->add_child ("Nagged");
938                 e->set_attribute ("Id", raw_convert<string>(i));
939                 e->add_child_text (_nagged[i] ? "1" : "0");
940         }
941         /* [XML] PreviewSound 1 to use sound in the GUI preview and player, otherwise 0. */
942         root->add_child("PreviewSound")->add_child_text (_sound ? "1" : "0");
943         if (_sound_api) {
944                 /* [XML:opt] PreviewSoundAPI ID of the audio API to use. */
945                 root->add_child("PreviewSoundAPI")->add_child_text(_sound_api.get());
946         }
947         if (_sound_output) {
948                 /* [XML:opt] PreviewSoundOutput Name of the audio output to use. */
949                 root->add_child("PreviewSoundOutput")->add_child_text (_sound_output.get());
950         }
951         /* [XML] CoverSheet Text of the cover sheet to write when making DCPs. */
952         root->add_child("CoverSheet")->add_child_text (_cover_sheet);
953         if (_last_player_load_directory) {
954                 root->add_child("LastPlayerLoadDirectory")->add_child_text(_last_player_load_directory->string());
955         }
956         /* [XML] LastKDMWriteType Last type of KDM-write: <code>flat</code> for a flat file, <code>folder</code> for a folder or <code>zip</code> for a ZIP file. */
957         if (_last_kdm_write_type) {
958                 switch (_last_kdm_write_type.get()) {
959                 case KDM_WRITE_FLAT:
960                         root->add_child("LastKDMWriteType")->add_child_text("flat");
961                         break;
962                 case KDM_WRITE_FOLDER:
963                         root->add_child("LastKDMWriteType")->add_child_text("folder");
964                         break;
965                 case KDM_WRITE_ZIP:
966                         root->add_child("LastKDMWriteType")->add_child_text("zip");
967                         break;
968                 }
969         }
970         /* [XML] LastDKDMWriteType Last type of DKDM-write: <code>file</code> for a file, <code>internal</code> to add to DCP-o-matic's list. */
971         if (_last_dkdm_write_type) {
972                 switch (_last_dkdm_write_type.get()) {
973                 case DKDM_WRITE_INTERNAL:
974                         root->add_child("LastDKDMWriteType")->add_child_text("internal");
975                         break;
976                 case DKDM_WRITE_FILE:
977                         root->add_child("LastDKDMWriteType")->add_child_text("file");
978                         break;
979                 }
980         }
981         /* [XML] FramesInMemoryMultiplier value to multiply the encoding threads count by to get the maximum number of
982            frames to be held in memory at once.
983         */
984         root->add_child("FramesInMemoryMultiplier")->add_child_text(raw_convert<string>(_frames_in_memory_multiplier));
985
986         /* [XML] DecodeReduction power of 2 to reduce DCP images by before decoding in the player. */
987         if (_decode_reduction) {
988                 root->add_child("DecodeReduction")->add_child_text(raw_convert<string>(_decode_reduction.get()));
989         }
990
991         /* [XML] DefaultNotify 1 to default jobs to notify when complete, otherwise 0. */
992         root->add_child("DefaultNotify")->add_child_text(_default_notify ? "1" : "0");
993
994         /* [XML] Notification 1 if a notification type is enabled, otherwise 0. */
995         for (int i = 0; i < NOTIFICATION_COUNT; ++i) {
996                 xmlpp::Element* e = root->add_child ("Notification");
997                 e->set_attribute ("Id", raw_convert<string>(i));
998                 e->add_child_text (_notification[i] ? "1" : "0");
999         }
1000
1001         if (_barco_username) {
1002                 /* [XML] BarcoUsername Username for logging into Barco's servers when downloading server certificates. */
1003                 root->add_child("BarcoUsername")->add_child_text(*_barco_username);
1004         }
1005         if (_barco_password) {
1006                 /* [XML] BarcoPassword Password for logging into Barco's servers when downloading server certificates. */
1007                 root->add_child("BarcoPassword")->add_child_text(*_barco_password);
1008         }
1009
1010         if (_christie_username) {
1011                 /* [XML] ChristieUsername Username for logging into Christie's servers when downloading server certificates. */
1012                 root->add_child("ChristieUsername")->add_child_text(*_christie_username);
1013         }
1014         if (_christie_password) {
1015                 /* [XML] ChristiePassword Password for logging into Christie's servers when downloading server certificates. */
1016                 root->add_child("ChristiePassword")->add_child_text(*_christie_password);
1017         }
1018
1019         if (_gdc_username) {
1020                 /* [XML] GDCUsername Username for logging into GDC's servers when downloading server certificates. */
1021                 root->add_child("GDCUsername")->add_child_text(*_gdc_username);
1022         }
1023         if (_gdc_password) {
1024                 /* [XML] GDCPassword Password for logging into GDC's servers when downloading server certificates. */
1025                 root->add_child("GDCPassword")->add_child_text(*_gdc_password);
1026         }
1027
1028         /* [XML] PlayerMode <code>window</code> for a single window, <code>full</code> for full-screen and <code>dual</code> for full screen playback
1029            with controls on another monitor.
1030         */
1031         switch (_player_mode) {
1032         case PLAYER_MODE_WINDOW:
1033                 root->add_child("PlayerMode")->add_child_text("window");
1034                 break;
1035         case PLAYER_MODE_FULL:
1036                 root->add_child("PlayerMode")->add_child_text("full");
1037                 break;
1038         case PLAYER_MODE_DUAL:
1039                 root->add_child("PlayerMode")->add_child_text("dual");
1040                 break;
1041         }
1042
1043         /* [XML] ImageDisplay Screen number to put image on in dual-screen player mode. */
1044         root->add_child("ImageDisplay")->add_child_text(raw_convert<string>(_image_display));
1045         switch (_video_view_type) {
1046         case VIDEO_VIEW_SIMPLE:
1047                 root->add_child("VideoViewType")->add_child_text("simple");
1048                 break;
1049         case VIDEO_VIEW_OPENGL:
1050                 root->add_child("VideoViewType")->add_child_text("opengl");
1051                 break;
1052         }
1053         /* [XML] RespectKDMValidityPeriods 1 to refuse to use KDMs that are out of date, 0 to ignore KDM dates. */
1054         root->add_child("RespectKDMValidityPeriods")->add_child_text(_respect_kdm_validity_periods ? "1" : "0");
1055         if (_player_debug_log_file) {
1056                 /* [XML] PlayerLogFile Filename to use for player debug logs. */
1057                 root->add_child("PlayerDebugLogFile")->add_child_text(_player_debug_log_file->string());
1058         }
1059         if (_player_content_directory) {
1060                 /* [XML] PlayerContentDirectory Directory to use for player content in the dual-screen mode. */
1061                 root->add_child("PlayerContentDirectory")->add_child_text(_player_content_directory->string());
1062         }
1063         if (_player_playlist_directory) {
1064                 /* [XML] PlayerPlaylistDirectory Directory to use for player playlists in the dual-screen mode. */
1065                 root->add_child("PlayerPlaylistDirectory")->add_child_text(_player_playlist_directory->string());
1066         }
1067         if (_player_kdm_directory) {
1068                 /* [XML] PlayerKDMDirectory Directory to use for player KDMs in the dual-screen mode. */
1069                 root->add_child("PlayerKDMDirectory")->add_child_text(_player_kdm_directory->string());
1070         }
1071         if (_audio_mapping) {
1072                 _audio_mapping->as_xml (root->add_child("AudioMapping"));
1073         }
1074         for (auto const& i: _custom_languages) {
1075                 root->add_child("CustomLanguage")->add_child_text(i.to_string());
1076         }
1077         if (_add_files_path) {
1078                 /* [XML] AddFilesPath The default path that will be offered in the picker when adding files to a film. */
1079                 root->add_child("AddFilesPath")->add_child_text(_add_files_path->string());
1080         }
1081         root->add_child("UseISDCFNameByDefault")->add_child_text(_use_isdcf_name_by_default ? "1" : "0");
1082         root->add_child("WriteKDMsToDisk")->add_child_text(_write_kdms_to_disk ? "1" : "0");
1083         root->add_child("EmailKDMs")->add_child_text(_email_kdms ? "1" : "0");
1084         root->add_child("DefaultKDMType")->add_child_text(dcp::formulation_to_string(_default_kdm_type));
1085         root->add_child("AutoCropThreshold")->add_child_text(raw_convert<string>(_auto_crop_threshold));
1086         if (_last_release_notes_version) {
1087                 root->add_child("LastReleaseNotesVersion")->add_child_text(*_last_release_notes_version);
1088         }
1089         if (_main_divider_sash_position) {
1090                 root->add_child("MainDividerSashPosition")->add_child_text(raw_convert<string>(*_main_divider_sash_position));
1091         }
1092         if (_main_content_divider_sash_position) {
1093                 root->add_child("MainContentDividerSashPosition")->add_child_text(raw_convert<string>(*_main_content_divider_sash_position));
1094         }
1095
1096         _export.write(root->add_child("Export"));
1097
1098         auto target = config_write_file();
1099
1100         try {
1101                 auto const s = doc.write_to_string_formatted ();
1102                 boost::filesystem::path tmp (string(target.string()).append(".tmp"));
1103                 dcp::File f(tmp, "w");
1104                 if (!f) {
1105                         throw FileError (_("Could not open file for writing"), tmp);
1106                 }
1107                 f.checked_write(s.c_str(), s.bytes());
1108                 f.close();
1109                 boost::filesystem::remove (target);
1110                 boost::filesystem::rename (tmp, target);
1111         } catch (xmlpp::exception& e) {
1112                 string s = e.what ();
1113                 trim (s);
1114                 throw FileError (s, target);
1115         }
1116 }
1117
1118
1119 template <class T>
1120 void
1121 write_file (string root_node, string node, string version, list<shared_ptr<T>> things, boost::filesystem::path file)
1122 {
1123         xmlpp::Document doc;
1124         auto root = doc.create_root_node (root_node);
1125         root->add_child("Version")->add_child_text(version);
1126
1127         for (auto i: things) {
1128                 i->as_xml (root->add_child(node));
1129         }
1130
1131         try {
1132                 doc.write_to_file_formatted (file.string() + ".tmp");
1133                 boost::filesystem::remove (file);
1134                 boost::filesystem::rename (file.string() + ".tmp", file);
1135         } catch (xmlpp::exception& e) {
1136                 string s = e.what ();
1137                 trim (s);
1138                 throw FileError (s, file);
1139         }
1140 }
1141
1142
1143 void
1144 Config::write_cinemas () const
1145 {
1146         write_file ("Cinemas", "Cinema", "1", _cinemas, _cinemas_file);
1147 }
1148
1149
1150 void
1151 Config::write_dkdm_recipients () const
1152 {
1153         write_file ("DKDMRecipients", "DKDMRecipient", "1", _dkdm_recipients, _dkdm_recipients_file);
1154 }
1155
1156
1157 boost::filesystem::path
1158 Config::default_directory_or (boost::filesystem::path a) const
1159 {
1160         return directory_or (_default_directory, a);
1161 }
1162
1163 boost::filesystem::path
1164 Config::default_kdm_directory_or (boost::filesystem::path a) const
1165 {
1166         return directory_or (_default_kdm_directory, a);
1167 }
1168
1169 boost::filesystem::path
1170 Config::directory_or (optional<boost::filesystem::path> dir, boost::filesystem::path a) const
1171 {
1172         if (!dir) {
1173                 return a;
1174         }
1175
1176         boost::system::error_code ec;
1177         auto const e = boost::filesystem::exists (*dir, ec);
1178         if (ec || !e) {
1179                 return a;
1180         }
1181
1182         return *dir;
1183 }
1184
1185 void
1186 Config::drop ()
1187 {
1188         delete _instance;
1189         _instance = 0;
1190 }
1191
1192 void
1193 Config::changed (Property what)
1194 {
1195         Changed (what);
1196 }
1197
1198 void
1199 Config::set_kdm_email_to_default ()
1200 {
1201         _kdm_subject = _("KDM delivery: $CPL_NAME");
1202
1203         _kdm_email = _(
1204                 "Dear Projectionist\n\n"
1205                 "Please find attached KDMs for $CPL_NAME.\n\n"
1206                 "Cinema: $CINEMA_NAME\n"
1207                 "Screen(s): $SCREENS\n\n"
1208                 "The KDMs are valid from $START_TIME until $END_TIME.\n\n"
1209                 "Best regards,\nDCP-o-matic"
1210                 );
1211 }
1212
1213 void
1214 Config::set_notification_email_to_default ()
1215 {
1216         _notification_subject = _("DCP-o-matic notification");
1217
1218         _notification_email = _(
1219                 "$JOB_NAME: $JOB_STATUS"
1220                 );
1221 }
1222
1223 void
1224 Config::reset_kdm_email ()
1225 {
1226         set_kdm_email_to_default ();
1227         changed ();
1228 }
1229
1230 void
1231 Config::reset_notification_email ()
1232 {
1233         set_notification_email_to_default ();
1234         changed ();
1235 }
1236
1237 void
1238 Config::set_cover_sheet_to_default ()
1239 {
1240         _cover_sheet = _(
1241                 "$CPL_NAME\n\n"
1242                 "CPL Filename: $CPL_FILENAME\n"
1243                 "Type: $TYPE\n"
1244                 "Format: $CONTAINER\n"
1245                 "Audio: $AUDIO\n"
1246                 "Audio Language: $AUDIO_LANGUAGE\n"
1247                 "Subtitle Language: $SUBTITLE_LANGUAGE\n"
1248                 "Length: $LENGTH\n"
1249                 "Size: $SIZE\n"
1250                 );
1251 }
1252
1253 void
1254 Config::add_to_history (boost::filesystem::path p)
1255 {
1256         add_to_history_internal (_history, p);
1257 }
1258
1259 /** Remove non-existent items from the history */
1260 void
1261 Config::clean_history ()
1262 {
1263         clean_history_internal (_history);
1264 }
1265
1266 void
1267 Config::add_to_player_history (boost::filesystem::path p)
1268 {
1269         add_to_history_internal (_player_history, p);
1270 }
1271
1272 /** Remove non-existant items from the player history */
1273 void
1274 Config::clean_player_history ()
1275 {
1276         clean_history_internal (_player_history);
1277 }
1278
1279 void
1280 Config::add_to_history_internal (vector<boost::filesystem::path>& h, boost::filesystem::path p)
1281 {
1282         /* Remove existing instances of this path in the history */
1283         h.erase (remove (h.begin(), h.end(), p), h.end ());
1284
1285         h.insert (h.begin (), p);
1286         if (h.size() > HISTORY_SIZE) {
1287                 h.pop_back ();
1288         }
1289
1290         changed (HISTORY);
1291 }
1292
1293 void
1294 Config::clean_history_internal (vector<boost::filesystem::path>& h)
1295 {
1296         auto old = h;
1297         h.clear ();
1298         for (auto i: old) {
1299                 try {
1300                         if (boost::filesystem::is_directory(i)) {
1301                                 h.push_back (i);
1302                         }
1303                 } catch (...) {
1304                         /* We couldn't find out if it's a directory for some reason; just ignore it */
1305                 }
1306         }
1307 }
1308
1309
1310 bool
1311 Config::have_existing (string file)
1312 {
1313         return boost::filesystem::exists (read_path(file));
1314 }
1315
1316
1317 void
1318 Config::read_cinemas (cxml::Document const & f)
1319 {
1320         _cinemas.clear ();
1321         for (auto i: f.node_children("Cinema")) {
1322                 /* Slightly grotty two-part construction of Cinema here so that we can use
1323                    shared_from_this.
1324                 */
1325                 auto cinema = make_shared<Cinema>(i);
1326                 cinema->read_screens (i);
1327                 _cinemas.push_back (cinema);
1328         }
1329 }
1330
1331 void
1332 Config::set_cinemas_file (boost::filesystem::path file)
1333 {
1334         if (file == _cinemas_file) {
1335                 return;
1336         }
1337
1338         _cinemas_file = file;
1339
1340         if (boost::filesystem::exists (_cinemas_file)) {
1341                 /* Existing file; read it in */
1342                 cxml::Document f ("Cinemas");
1343                 f.read_file (_cinemas_file);
1344                 read_cinemas (f);
1345         }
1346
1347         changed (CINEMAS);
1348         changed (OTHER);
1349 }
1350
1351
1352 void
1353 Config::read_dkdm_recipients (cxml::Document const & f)
1354 {
1355         _dkdm_recipients.clear ();
1356         for (auto i: f.node_children("DKDMRecipient")) {
1357                 _dkdm_recipients.push_back (make_shared<DKDMRecipient>(i));
1358         }
1359 }
1360
1361
1362 void
1363 Config::save_template (shared_ptr<const Film> film, string name) const
1364 {
1365         film->write_template (template_write_path(name));
1366 }
1367
1368
1369 list<string>
1370 Config::templates () const
1371 {
1372         if (!boost::filesystem::exists(read_path("templates"))) {
1373                 return {};
1374         }
1375
1376         list<string> n;
1377         for (auto const& i: boost::filesystem::directory_iterator(read_path("templates"))) {
1378                 n.push_back (i.path().filename().string());
1379         }
1380         return n;
1381 }
1382
1383 bool
1384 Config::existing_template (string name) const
1385 {
1386         return boost::filesystem::exists (template_read_path(name));
1387 }
1388
1389
1390 boost::filesystem::path
1391 Config::template_read_path (string name) const
1392 {
1393         return read_path("templates") / tidy_for_filename (name);
1394 }
1395
1396
1397 boost::filesystem::path
1398 Config::template_write_path (string name) const
1399 {
1400         return write_path("templates") / tidy_for_filename (name);
1401 }
1402
1403
1404 void
1405 Config::rename_template (string old_name, string new_name) const
1406 {
1407         boost::filesystem::rename (template_read_path(old_name), template_write_path(new_name));
1408 }
1409
1410 void
1411 Config::delete_template (string name) const
1412 {
1413         boost::filesystem::remove (template_write_path(name));
1414 }
1415
1416 /** @return Path to the config.xml containing the actual settings, following a link if required */
1417 boost::filesystem::path
1418 config_file (boost::filesystem::path main)
1419 {
1420         cxml::Document f ("Config");
1421         if (!boost::filesystem::exists (main)) {
1422                 /* It doesn't exist, so there can't be any links; just return it */
1423                 return main;
1424         }
1425
1426         /* See if there's a link */
1427         try {
1428                 f.read_file (main);
1429                 auto link = f.optional_string_child("Link");
1430                 if (link) {
1431                         return *link;
1432                 }
1433         } catch (xmlpp::exception& e) {
1434                 /* There as a problem reading the main configuration file,
1435                    so there can't be a link.
1436                 */
1437         }
1438
1439         return main;
1440 }
1441
1442
1443 boost::filesystem::path
1444 Config::config_read_file ()
1445 {
1446         return config_file (read_path("config.xml"));
1447 }
1448
1449
1450 boost::filesystem::path
1451 Config::config_write_file ()
1452 {
1453         return config_file (write_path("config.xml"));
1454 }
1455
1456
1457 void
1458 Config::reset_cover_sheet ()
1459 {
1460         set_cover_sheet_to_default ();
1461         changed ();
1462 }
1463
1464 void
1465 Config::link (boost::filesystem::path new_file) const
1466 {
1467         xmlpp::Document doc;
1468         doc.create_root_node("Config")->add_child("Link")->add_child_text(new_file.string());
1469         try {
1470                 doc.write_to_file_formatted(write_path("config.xml").string());
1471         } catch (xmlpp::exception& e) {
1472                 string s = e.what ();
1473                 trim (s);
1474                 throw FileError (s, write_path("config.xml"));
1475         }
1476 }
1477
1478 void
1479 Config::copy_and_link (boost::filesystem::path new_file) const
1480 {
1481         write ();
1482         boost::filesystem::copy_file (config_read_file(), new_file, boost::filesystem::copy_option::overwrite_if_exists);
1483         link (new_file);
1484 }
1485
1486 bool
1487 Config::have_write_permission () const
1488 {
1489         dcp::File f(config_write_file(), "r+");
1490         return static_cast<bool>(f);
1491 }
1492
1493 /** @param  output_channels Number of output channels in use.
1494  *  @return Audio mapping for this output channel count (may be a default).
1495  */
1496 AudioMapping
1497 Config::audio_mapping (int output_channels)
1498 {
1499         if (!_audio_mapping || _audio_mapping->output_channels() != output_channels) {
1500                 /* Set up a default */
1501                 _audio_mapping = AudioMapping (MAX_DCP_AUDIO_CHANNELS, output_channels);
1502                 if (output_channels == 2) {
1503                         /* Special case for stereo output.
1504                            Map so that Lt = L(-3dB) + Ls(-3dB) + C(-6dB) + Lfe(-10dB)
1505                            Rt = R(-3dB) + Rs(-3dB) + C(-6dB) + Lfe(-10dB)
1506                         */
1507                         _audio_mapping->set (dcp::Channel::LEFT,   0, 1 / sqrt(2));  // L   -> Lt
1508                         _audio_mapping->set (dcp::Channel::RIGHT,  1, 1 / sqrt(2));  // R   -> Rt
1509                         _audio_mapping->set (dcp::Channel::CENTRE, 0, 1 / 2.0);      // C   -> Lt
1510                         _audio_mapping->set (dcp::Channel::CENTRE, 1, 1 / 2.0);      // C   -> Rt
1511                         _audio_mapping->set (dcp::Channel::LFE,    0, 1 / sqrt(10)); // Lfe -> Lt
1512                         _audio_mapping->set (dcp::Channel::LFE,    1, 1 / sqrt(10)); // Lfe -> Rt
1513                         _audio_mapping->set (dcp::Channel::LS,     0, 1 / sqrt(2));  // Ls  -> Lt
1514                         _audio_mapping->set (dcp::Channel::RS,     1, 1 / sqrt(2));  // Rs  -> Rt
1515                 } else {
1516                         /* 1:1 mapping */
1517                         for (int i = 0; i < min (MAX_DCP_AUDIO_CHANNELS, output_channels); ++i) {
1518                                 _audio_mapping->set (i, i, 1);
1519                         }
1520                 }
1521         }
1522
1523         return *_audio_mapping;
1524 }
1525
1526 void
1527 Config::set_audio_mapping (AudioMapping m)
1528 {
1529         _audio_mapping = m;
1530         changed (AUDIO_MAPPING);
1531 }
1532
1533 void
1534 Config::set_audio_mapping_to_default ()
1535 {
1536         DCPOMATIC_ASSERT (_audio_mapping);
1537         auto const ch = _audio_mapping->output_channels ();
1538         _audio_mapping = boost::none;
1539         _audio_mapping = audio_mapping (ch);
1540         changed (AUDIO_MAPPING);
1541 }
1542
1543
1544 void
1545 Config::add_custom_language (dcp::LanguageTag tag)
1546 {
1547         if (find(_custom_languages.begin(), _custom_languages.end(), tag) == _custom_languages.end()) {
1548                 _custom_languages.push_back (tag);
1549                 changed ();
1550         }
1551 }
1552
1553
1554 optional<Config::BadReason>
1555 Config::check_certificates () const
1556 {
1557         optional<BadReason> bad;
1558
1559         for (auto const& i: _signer_chain->unordered()) {
1560                 if (i.has_utf8_strings()) {
1561                         bad = BAD_SIGNER_UTF8_STRINGS;
1562                 }
1563                 if ((i.not_after().year() - i.not_before().year()) > 15) {
1564                         bad = BAD_SIGNER_VALIDITY_TOO_LONG;
1565                 }
1566         }
1567
1568         if (!_signer_chain->chain_valid() || !_signer_chain->private_key_valid()) {
1569                 bad = BAD_SIGNER_INCONSISTENT;
1570         }
1571
1572         if (!_decryption_chain->chain_valid() || !_decryption_chain->private_key_valid()) {
1573                 bad = BAD_DECRYPTION_INCONSISTENT;
1574         }
1575
1576         return bad;
1577 }
1578
1579
1580 void
1581 save_all_config_as_zip (boost::filesystem::path zip_file)
1582 {
1583         Zipper zipper (zip_file);
1584
1585         auto config = Config::instance();
1586         zipper.add ("config.xml", dcp::file_to_string(config->config_read_file()));
1587         if (boost::filesystem::exists(config->cinemas_file())) {
1588                 zipper.add ("cinemas.xml", dcp::file_to_string(config->cinemas_file()));
1589         }
1590         if (boost::filesystem::exists(config->dkdm_recipients_file())) {
1591                 zipper.add ("dkdm_recipients.xml", dcp::file_to_string(config->dkdm_recipients_file()));
1592         }
1593
1594         zipper.close ();
1595 }
1596