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