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