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