Add config option for default KDM type.
[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 #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 "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 using std::vector;
53 using std::cout;
54 using std::ifstream;
55 using std::string;
56 using std::list;
57 using std::min;
58 using std::max;
59 using std::remove;
60 using std::shared_ptr;
61 using std::make_shared;
62 using boost::optional;
63 using std::dynamic_pointer_cast;
64 using boost::algorithm::trim;
65 using dcp::raw_convert;
66
67 Config* Config::_instance = 0;
68 int const Config::_current_version = 3;
69 boost::signals2::signal<void ()> Config::FailedToLoad;
70 boost::signals2::signal<void (string)> Config::Warning;
71 boost::signals2::signal<bool (Config::BadReason)> Config::Bad;
72
73 /** Construct default configuration */
74 Config::Config ()
75         /* DKDMs are not considered a thing to reset on set_defaults() */
76         : _dkdms (new DKDMGroup ("root"))
77 {
78         set_defaults ();
79 }
80
81 void
82 Config::set_defaults ()
83 {
84         _master_encoding_threads = max (2U, boost::thread::hardware_concurrency ());
85         _server_encoding_threads = max (2U, boost::thread::hardware_concurrency ());
86         _server_port_base = 6192;
87         _use_any_servers = true;
88         _servers.clear ();
89         _only_servers_encode = false;
90         _tms_protocol = FileTransferProtocol::SCP;
91         _tms_ip = "";
92         _tms_path = ".";
93         _tms_user = "";
94         _tms_password = "";
95         _allow_any_dcp_frame_rate = false;
96         _allow_any_container = false;
97         _show_experimental_audio_processors = false;
98         _language = optional<string> ();
99         _default_still_length = 10;
100         _default_container = Ratio::from_id ("185");
101         _default_dcp_content_type = DCPContentType::from_isdcf_name ("FTR");
102         _default_dcp_audio_channels = 6;
103         _default_j2k_bandwidth = 150000000;
104         _default_audio_delay = 0;
105         _default_interop = false;
106         _default_metadata.clear ();
107         _upload_after_make_dcp = false;
108         _mail_server = "";
109         _mail_port = 25;
110         _mail_protocol = EmailProtocol::AUTO;
111         _mail_user = "";
112         _mail_password = "";
113         _kdm_from = "";
114         _kdm_cc.clear ();
115         _kdm_bcc = "";
116         _notification_from = "";
117         _notification_to = "";
118         _notification_cc.clear ();
119         _notification_bcc = "";
120         _check_for_updates = false;
121         _check_for_test_updates = false;
122         _maximum_j2k_bandwidth = 250000000;
123         _log_types = LogEntry::TYPE_GENERAL | LogEntry::TYPE_WARNING | LogEntry::TYPE_ERROR | LogEntry::TYPE_DISK;
124         _analyse_ebur128 = true;
125         _automatic_audio_analysis = false;
126 #ifdef DCPOMATIC_WINDOWS
127         _win32_console = false;
128 #endif
129         /* At the moment we don't write these files anywhere new after a version change, so they will be read from
130          * ~/.config/dcpomatic2 (or equivalent) and written back there.
131          */
132         _cinemas_file = read_path ("cinemas.xml");
133         _dkdm_recipients_file = read_path ("dkdm_recipients.xml");
134         _show_hints_before_make_dcp = true;
135         _confirm_kdm_email = true;
136         _kdm_container_name_format = dcp::NameFormat ("KDM %f %c");
137         _kdm_filename_format = dcp::NameFormat ("KDM %f %c %s");
138         _dkdm_filename_format = dcp::NameFormat ("DKDM %f %c %s");
139         _dcp_metadata_filename_format = dcp::NameFormat ("%t");
140         _dcp_asset_filename_format = dcp::NameFormat ("%t");
141         _jump_to_selected = true;
142         for (int i = 0; i < NAG_COUNT; ++i) {
143                 _nagged[i] = false;
144         }
145         _sound = true;
146         _sound_output = optional<string> ();
147         _last_kdm_write_type = KDM_WRITE_FLAT;
148         _last_dkdm_write_type = DKDM_WRITE_INTERNAL;
149
150         /* I think the scaling factor here should be the ratio of the longest frame
151            encode time to the shortest; if the thread count is T, longest time is L
152            and the shortest time S we could encode L/S frames per thread whilst waiting
153            for the L frame to encode so we might have to store LT/S frames.
154
155            However we don't want to use too much memory, so keep it a bit lower than we'd
156            perhaps like.  A J2K frame is typically about 1Mb so 3 here will mean we could
157            use about 240Mb with 72 encoding threads.
158         */
159         _frames_in_memory_multiplier = 3;
160         _decode_reduction = optional<int>();
161         _default_notify = false;
162         for (int i = 0; i < NOTIFICATION_COUNT; ++i) {
163                 _notification[i] = false;
164         }
165         _barco_username = optional<string>();
166         _barco_password = optional<string>();
167         _christie_username = optional<string>();
168         _christie_password = optional<string>();
169         _gdc_username = optional<string>();
170         _gdc_password = optional<string>();
171         _player_mode = PLAYER_MODE_WINDOW;
172         _image_display = 0;
173         _video_view_type = VIDEO_VIEW_SIMPLE;
174         _respect_kdm_validity_periods = true;
175         _player_debug_log_file = boost::none;
176         _player_content_directory = boost::none;
177         _player_playlist_directory = boost::none;
178         _player_kdm_directory = boost::none;
179         _audio_mapping = boost::none;
180         _custom_languages.clear ();
181         _add_files_path = boost::none;
182         _use_isdcf_name_by_default = true;
183         _write_kdms_to_disk = true;
184         _email_kdms = false;
185         _default_kdm_type = dcp::Formulation::MODIFIED_TRANSITIONAL_1;
186
187         _allowed_dcp_frame_rates.clear ();
188         _allowed_dcp_frame_rates.push_back (24);
189         _allowed_dcp_frame_rates.push_back (25);
190         _allowed_dcp_frame_rates.push_back (30);
191         _allowed_dcp_frame_rates.push_back (48);
192         _allowed_dcp_frame_rates.push_back (50);
193         _allowed_dcp_frame_rates.push_back (60);
194
195         set_kdm_email_to_default ();
196         set_notification_email_to_default ();
197         set_cover_sheet_to_default ();
198 }
199
200 void
201 Config::restore_defaults ()
202 {
203         Config::instance()->set_defaults ();
204         Config::instance()->changed ();
205 }
206
207 shared_ptr<dcp::CertificateChain>
208 Config::create_certificate_chain ()
209 {
210         return make_shared<dcp::CertificateChain> (
211                 openssl_path(),
212                 CERTIFICATE_VALIDITY_PERIOD,
213                 "dcpomatic.com",
214                 "dcpomatic.com",
215                 ".dcpomatic.smpte-430-2.ROOT",
216                 ".dcpomatic.smpte-430-2.INTERMEDIATE",
217                 "CS.dcpomatic.smpte-430-2.LEAF"
218                 );
219 }
220
221 void
222 Config::backup ()
223 {
224         using namespace boost::filesystem;
225
226         auto copy_adding_number = [](path const& path_to_copy) {
227
228                 auto add_number = [](path const& path, int number) {
229                         return String::compose("%1.%2", path, number);
230                 };
231
232                 int n = 1;
233                 while (n < 100 && exists(add_number(path_to_copy, n))) {
234                         ++n;
235                 }
236                 boost::system::error_code ec;
237                 copy_file(path_to_copy, add_number(path_to_copy, n), ec);
238         };
239
240         /* Make a backup copy of any config.xml, cinemas.xml, dkdm_recipients.xml that we might be about
241          * to write over.  This is more intended for the situation where we have a corrupted config.xml,
242          * and decide to overwrite it with a new one (possibly losing important details in the corrupted
243          * file).  But we might as well back up the other files while we're about it.
244          */
245
246         /* This uses the State::write_path stuff so, e.g. for a current version 2.16 we might copy
247          * ~/.config/dcpomatic2/2.16/config.xml to ~/.config/dcpomatic2/2.16/config.xml.1
248          */
249         copy_adding_number (config_write_file());
250
251         /* These do not use State::write_path, so whatever path is in the Config we will copy
252          * adding a number.
253          */
254         copy_adding_number (_cinemas_file);
255         copy_adding_number (_dkdm_recipients_file);
256 }
257
258 void
259 Config::read ()
260 try
261 {
262         cxml::Document f ("Config");
263         f.read_file (config_read_file());
264
265         auto version = f.optional_number_child<int> ("Version");
266         if (version && *version < _current_version) {
267                 /* Back up the old config before we re-write it in a back-incompatible way */
268                 backup ();
269         }
270
271         if (f.optional_number_child<int>("NumLocalEncodingThreads")) {
272                 _master_encoding_threads = _server_encoding_threads = f.optional_number_child<int>("NumLocalEncodingThreads").get();
273         } else {
274                 _master_encoding_threads = f.number_child<int>("MasterEncodingThreads");
275                 _server_encoding_threads = f.number_child<int>("ServerEncodingThreads");
276         }
277
278         _default_directory = f.optional_string_child ("DefaultDirectory");
279         if (_default_directory && _default_directory->empty ()) {
280                 /* We used to store an empty value for this to mean "none set" */
281                 _default_directory = boost::optional<boost::filesystem::path> ();
282         }
283
284         auto b = f.optional_number_child<int> ("ServerPort");
285         if (!b) {
286                 b = f.optional_number_child<int> ("ServerPortBase");
287         }
288         _server_port_base = b.get ();
289
290         auto u = f.optional_bool_child ("UseAnyServers");
291         _use_any_servers = u.get_value_or (true);
292
293         for (auto i: f.node_children("Server")) {
294                 if (i->node_children("HostName").size() == 1) {
295                         _servers.push_back (i->string_child ("HostName"));
296                 } else {
297                         _servers.push_back (i->content ());
298                 }
299         }
300
301         _only_servers_encode = f.optional_bool_child ("OnlyServersEncode").get_value_or (false);
302         _tms_protocol = static_cast<FileTransferProtocol>(f.optional_number_child<int>("TMSProtocol").get_value_or(static_cast<int>(FileTransferProtocol::SCP)));
303         _tms_ip = f.string_child ("TMSIP");
304         _tms_path = f.string_child ("TMSPath");
305         _tms_user = f.string_child ("TMSUser");
306         _tms_password = f.string_child ("TMSPassword");
307
308         _language = f.optional_string_child ("Language");
309
310         auto c = f.optional_string_child ("DefaultContainer");
311         if (c) {
312                 _default_container = Ratio::from_id (c.get ());
313         }
314
315         if (_default_container && !_default_container->used_for_container()) {
316                 Warning (_("Your default container is not valid and has been changed to Flat (1.85:1)"));
317                 _default_container = Ratio::from_id ("185");
318         }
319
320         _default_dcp_content_type = DCPContentType::from_isdcf_name(f.optional_string_child("DefaultDCPContentType").get_value_or("FTR"));
321         _default_dcp_audio_channels = f.optional_number_child<int>("DefaultDCPAudioChannels").get_value_or (6);
322
323         if (f.optional_string_child ("DCPMetadataIssuer")) {
324                 _dcp_issuer = f.string_child ("DCPMetadataIssuer");
325         } else if (f.optional_string_child ("DCPIssuer")) {
326                 _dcp_issuer = f.string_child ("DCPIssuer");
327         }
328
329         auto up = f.optional_bool_child("UploadAfterMakeDCP");
330         if (!up) {
331                 up = f.optional_bool_child("DefaultUploadAfterMakeDCP");
332         }
333         _upload_after_make_dcp = up.get_value_or (false);
334         _dcp_creator = f.optional_string_child ("DCPCreator").get_value_or ("");
335         _dcp_company_name = f.optional_string_child("DCPCompanyName").get_value_or("");
336         _dcp_product_name = f.optional_string_child("DCPProductName").get_value_or("");
337         _dcp_product_version = f.optional_string_child("DCPProductVersion").get_value_or("");
338         _dcp_j2k_comment = f.optional_string_child("DCPJ2KComment").get_value_or("");
339
340         _default_still_length = f.optional_number_child<int>("DefaultStillLength").get_value_or (10);
341         _default_j2k_bandwidth = f.optional_number_child<int>("DefaultJ2KBandwidth").get_value_or (200000000);
342         _default_audio_delay = f.optional_number_child<int>("DefaultAudioDelay").get_value_or (0);
343         _default_interop = f.optional_bool_child("DefaultInterop").get_value_or (false);
344
345         for (auto const& i: f.node_children("DefaultMetadata")) {
346                 _default_metadata[i->string_attribute("key")] = i->content();
347         }
348
349         _default_kdm_directory = f.optional_string_child("DefaultKDMDirectory");
350
351         /* Read any cinemas that are still lying around in the config file
352          * from an old version.
353          */
354         read_cinemas (f);
355
356         _mail_server = f.string_child ("MailServer");
357         _mail_port = f.optional_number_child<int> ("MailPort").get_value_or (25);
358
359         {
360                 /* Make sure this matches the code in write_config */
361                 string const protocol = f.optional_string_child("MailProtocol").get_value_or("Auto");
362                 if (protocol == "Auto") {
363                         _mail_protocol = EmailProtocol::AUTO;
364                 } else if (protocol == "Plain") {
365                         _mail_protocol = EmailProtocol::PLAIN;
366                 } else if (protocol == "STARTTLS") {
367                         _mail_protocol = EmailProtocol::STARTTLS;
368                 } else if (protocol == "SSL") {
369                         _mail_protocol = EmailProtocol::SSL;
370                 }
371         }
372
373         _mail_user = f.optional_string_child("MailUser").get_value_or ("");
374         _mail_password = f.optional_string_child("MailPassword").get_value_or ("");
375
376         _kdm_subject = f.optional_string_child ("KDMSubject").get_value_or (_("KDM delivery: $CPL_NAME"));
377         _kdm_from = f.string_child ("KDMFrom");
378         for (auto i: f.node_children("KDMCC")) {
379                 if (!i->content().empty()) {
380                         _kdm_cc.push_back (i->content ());
381                 }
382         }
383         _kdm_bcc = f.optional_string_child ("KDMBCC").get_value_or ("");
384         _kdm_email = f.string_child ("KDMEmail");
385
386         _notification_subject = f.optional_string_child("NotificationSubject").get_value_or(_("DCP-o-matic notification"));
387         _notification_from = f.optional_string_child("NotificationFrom").get_value_or("");
388         _notification_to = f.optional_string_child("NotificationTo").get_value_or("");
389         for (auto i: f.node_children("NotificationCC")) {
390                 if (!i->content().empty()) {
391                         _notification_cc.push_back (i->content ());
392                 }
393         }
394         _notification_bcc = f.optional_string_child("NotificationBCC").get_value_or("");
395         if (f.optional_string_child("NotificationEmail")) {
396                 _notification_email = f.string_child("NotificationEmail");
397         }
398
399         _check_for_updates = f.optional_bool_child("CheckForUpdates").get_value_or (false);
400         _check_for_test_updates = f.optional_bool_child("CheckForTestUpdates").get_value_or (false);
401
402         _maximum_j2k_bandwidth = f.optional_number_child<int> ("MaximumJ2KBandwidth").get_value_or (250000000);
403         _allow_any_dcp_frame_rate = f.optional_bool_child ("AllowAnyDCPFrameRate").get_value_or (false);
404         _allow_any_container = f.optional_bool_child ("AllowAnyContainer").get_value_or (false);
405         _show_experimental_audio_processors = f.optional_bool_child ("ShowExperimentalAudioProcessors").get_value_or (false);
406
407         _log_types = f.optional_number_child<int> ("LogTypes").get_value_or (LogEntry::TYPE_GENERAL | LogEntry::TYPE_WARNING | LogEntry::TYPE_ERROR);
408         _analyse_ebur128 = f.optional_bool_child("AnalyseEBUR128").get_value_or (true);
409         _automatic_audio_analysis = f.optional_bool_child ("AutomaticAudioAnalysis").get_value_or (false);
410 #ifdef DCPOMATIC_WINDOWS
411         _win32_console = f.optional_bool_child ("Win32Console").get_value_or (false);
412 #endif
413
414         for (auto i: f.node_children("History")) {
415                 _history.push_back (i->content ());
416         }
417
418         for (auto i: f.node_children("PlayerHistory")) {
419                 _player_history.push_back (i->content ());
420         }
421
422         auto signer = f.optional_node_child ("Signer");
423         if (signer) {
424                 auto c = make_shared<dcp::CertificateChain>();
425                 /* Read the signing certificates and private key in from the config file */
426                 for (auto i: signer->node_children ("Certificate")) {
427                         c->add (dcp::Certificate (i->content ()));
428                 }
429                 c->set_key (signer->string_child ("PrivateKey"));
430                 _signer_chain = c;
431         } else {
432                 /* Make a new set of signing certificates and key */
433                 _signer_chain = create_certificate_chain ();
434         }
435
436         auto decryption = f.optional_node_child ("Decryption");
437         if (decryption) {
438                 auto c = make_shared<dcp::CertificateChain>();
439                 for (auto i: decryption->node_children ("Certificate")) {
440                         c->add (dcp::Certificate (i->content ()));
441                 }
442                 c->set_key (decryption->string_child ("PrivateKey"));
443                 _decryption_chain = c;
444         } else {
445                 _decryption_chain = create_certificate_chain ();
446         }
447
448         /* These must be done before we call Bad as that might set one
449            of the nags.
450         */
451         for (auto i: f.node_children("Nagged")) {
452                 auto const id = i->number_attribute<int>("Id");
453                 if (id >= 0 && id < NAG_COUNT) {
454                         _nagged[id] = raw_convert<int>(i->content());
455                 }
456         }
457
458         auto bad = check_certificates ();
459         if (bad) {
460                 auto const remake = Bad(*bad);
461                 if (remake && *remake) {
462                         switch (*bad) {
463                         case BAD_SIGNER_UTF8_STRINGS:
464                         case BAD_SIGNER_INCONSISTENT:
465                         case BAD_SIGNER_VALIDITY_TOO_LONG:
466                                 _signer_chain = create_certificate_chain ();
467                                 break;
468                         case BAD_DECRYPTION_INCONSISTENT:
469                                 _decryption_chain = create_certificate_chain ();
470                                 break;
471                         }
472                 }
473         }
474
475         if (f.optional_node_child("DKDMGroup")) {
476                 /* New-style: all DKDMs in a group */
477                 _dkdms = dynamic_pointer_cast<DKDMGroup> (DKDMBase::read (f.node_child("DKDMGroup")));
478         } else {
479                 /* Old-style: one or more DKDM nodes */
480                 _dkdms.reset (new DKDMGroup ("root"));
481                 for (auto i: f.node_children("DKDM")) {
482                         _dkdms->add (DKDMBase::read (i));
483                 }
484         }
485         _cinemas_file = f.optional_string_child("CinemasFile").get_value_or(read_path("cinemas.xml").string());
486         _dkdm_recipients_file = f.optional_string_child("DKDMRecipientsFile").get_value_or(read_path("dkdm_recipients.xml").string());
487         _show_hints_before_make_dcp = f.optional_bool_child("ShowHintsBeforeMakeDCP").get_value_or (true);
488         _confirm_kdm_email = f.optional_bool_child("ConfirmKDMEmail").get_value_or (true);
489         _kdm_container_name_format = dcp::NameFormat (f.optional_string_child("KDMContainerNameFormat").get_value_or ("KDM %f %c"));
490         _kdm_filename_format = dcp::NameFormat (f.optional_string_child("KDMFilenameFormat").get_value_or ("KDM %f %c %s"));
491         _dkdm_filename_format = dcp::NameFormat (f.optional_string_child("DKDMFilenameFormat").get_value_or("DKDM %f %c %s"));
492         _dcp_metadata_filename_format = dcp::NameFormat (f.optional_string_child("DCPMetadataFilenameFormat").get_value_or ("%t"));
493         _dcp_asset_filename_format = dcp::NameFormat (f.optional_string_child("DCPAssetFilenameFormat").get_value_or ("%t"));
494         _jump_to_selected = f.optional_bool_child("JumpToSelected").get_value_or (true);
495         /* The variable was renamed but not the XML tag */
496         _sound = f.optional_bool_child("PreviewSound").get_value_or (true);
497         _sound_output = f.optional_string_child("PreviewSoundOutput");
498         if (f.optional_string_child("CoverSheet")) {
499                 _cover_sheet = f.optional_string_child("CoverSheet").get();
500         }
501         _last_player_load_directory = f.optional_string_child("LastPlayerLoadDirectory");
502         if (f.optional_string_child("LastKDMWriteType")) {
503                 if (f.optional_string_child("LastKDMWriteType").get() == "flat") {
504                         _last_kdm_write_type = KDM_WRITE_FLAT;
505                 } else if (f.optional_string_child("LastKDMWriteType").get() == "folder") {
506                         _last_kdm_write_type = KDM_WRITE_FOLDER;
507                 } else if (f.optional_string_child("LastKDMWriteType").get() == "zip") {
508                         _last_kdm_write_type = KDM_WRITE_ZIP;
509                 }
510         }
511         if (f.optional_string_child("LastDKDMWriteType")) {
512                 if (f.optional_string_child("LastDKDMWriteType").get() == "internal") {
513                         _last_dkdm_write_type = DKDM_WRITE_INTERNAL;
514                 } else if (f.optional_string_child("LastDKDMWriteType").get() == "file") {
515                         _last_dkdm_write_type = DKDM_WRITE_FILE;
516                 }
517         }
518         _frames_in_memory_multiplier = f.optional_number_child<int>("FramesInMemoryMultiplier").get_value_or(3);
519         _decode_reduction = f.optional_number_child<int>("DecodeReduction");
520         _default_notify = f.optional_bool_child("DefaultNotify").get_value_or(false);
521
522         for (auto i: f.node_children("Notification")) {
523                 int const id = i->number_attribute<int>("Id");
524                 if (id >= 0 && id < NOTIFICATION_COUNT) {
525                         _notification[id] = raw_convert<int>(i->content());
526                 }
527         }
528
529         _barco_username = f.optional_string_child("BarcoUsername");
530         _barco_password = f.optional_string_child("BarcoPassword");
531         _christie_username = f.optional_string_child("ChristieUsername");
532         _christie_password = f.optional_string_child("ChristiePassword");
533         _gdc_username = f.optional_string_child("GDCUsername");
534         _gdc_password = f.optional_string_child("GDCPassword");
535
536         auto pm = f.optional_string_child("PlayerMode");
537         if (pm && *pm == "window") {
538                 _player_mode = PLAYER_MODE_WINDOW;
539         } else if (pm && *pm == "full") {
540                 _player_mode = PLAYER_MODE_FULL;
541         } else if (pm && *pm == "dual") {
542                 _player_mode = PLAYER_MODE_DUAL;
543         }
544
545         _image_display = f.optional_number_child<int>("ImageDisplay").get_value_or(0);
546         auto vc = f.optional_string_child("VideoViewType");
547         if (vc && *vc == "opengl") {
548                 _video_view_type = VIDEO_VIEW_OPENGL;
549         } else if (vc && *vc == "simple") {
550                 _video_view_type = VIDEO_VIEW_SIMPLE;
551         }
552         _respect_kdm_validity_periods = f.optional_bool_child("RespectKDMValidityPeriods").get_value_or(true);
553         _player_debug_log_file = f.optional_string_child("PlayerDebugLogFile");
554         _player_content_directory = f.optional_string_child("PlayerContentDirectory");
555         _player_playlist_directory = f.optional_string_child("PlayerPlaylistDirectory");
556         _player_kdm_directory = f.optional_string_child("PlayerKDMDirectory");
557
558         if (f.optional_node_child("AudioMapping")) {
559                 _audio_mapping = AudioMapping (f.node_child("AudioMapping"), Film::current_state_version);
560         }
561
562         for (auto i: f.node_children("CustomLanguage")) {
563                 try {
564                         /* This will fail if it's called before dcp::init() as it won't recognise the
565                          * tag.  That's OK because the Config will be reloaded again later.
566                          */
567                         _custom_languages.push_back (dcp::LanguageTag(i->content()));
568                 } catch (std::runtime_error& e) {}
569         }
570
571         _add_files_path = f.optional_string_child("AddFilesPath");
572         _use_isdcf_name_by_default = f.optional_bool_child("UseISDCFNameByDefault").get_value_or(true);
573         _write_kdms_to_disk = f.optional_bool_child("WriteKDMsToDisk").get_value_or(true);
574         _email_kdms = f.optional_bool_child("EmailKDMs").get_value_or(false);
575         _default_kdm_type = dcp::string_to_formulation(f.optional_string_child("DefaultKDMType").get_value_or("modified-transitional-1"));
576
577         if (boost::filesystem::exists (_cinemas_file)) {
578                 cxml::Document f ("Cinemas");
579                 f.read_file (_cinemas_file);
580                 read_cinemas (f);
581         }
582
583         if (boost::filesystem::exists (_dkdm_recipients_file)) {
584                 cxml::Document f ("DKDMRecipients");
585                 f.read_file (_dkdm_recipients_file);
586                 read_dkdm_recipients (f);
587         }
588 }
589 catch (...) {
590         if (have_existing("config.xml") || have_existing("cinemas.xml") || have_existing("dkdm_recipients.xml")) {
591                 backup ();
592                 /* We have a config file but it didn't load */
593                 FailedToLoad ();
594         }
595         set_defaults ();
596         /* Make a new set of signing certificates and key */
597         _signer_chain = create_certificate_chain ();
598         /* And similar for decryption of KDMs */
599         _decryption_chain = create_certificate_chain ();
600         write ();
601 }
602
603 /** @return Singleton instance */
604 Config *
605 Config::instance ()
606 {
607         if (_instance == 0) {
608                 _instance = new Config;
609                 _instance->read ();
610         }
611
612         return _instance;
613 }
614
615 /** Write our configuration to disk */
616 void
617 Config::write () const
618 {
619         write_config ();
620         write_cinemas ();
621         write_dkdm_recipients ();
622 }
623
624 void
625 Config::write_config () const
626 {
627         xmlpp::Document doc;
628         auto root = doc.create_root_node ("Config");
629
630         /* [XML] Version The version number of the configuration file format. */
631         root->add_child("Version")->add_child_text (raw_convert<string>(_current_version));
632         /* [XML] MasterEncodingThreads Number of encoding threads to use when running as master. */
633         root->add_child("MasterEncodingThreads")->add_child_text (raw_convert<string> (_master_encoding_threads));
634         /* [XML] ServerEncodingThreads Number of encoding threads to use when running as server. */
635         root->add_child("ServerEncodingThreads")->add_child_text (raw_convert<string> (_server_encoding_threads));
636         if (_default_directory) {
637                 /* [XML:opt] DefaultDirectory Default directory when creating a new film in the GUI. */
638                 root->add_child("DefaultDirectory")->add_child_text (_default_directory->string ());
639         }
640         /* [XML] ServerPortBase Port number to use for frame encoding requests.  <code>ServerPortBase</code> + 1 and
641            <code>ServerPortBase</code> + 2 are used for querying servers.  <code>ServerPortBase</code> + 3 is used
642            by the batch converter to listen for job requests.
643         */
644         root->add_child("ServerPortBase")->add_child_text (raw_convert<string> (_server_port_base));
645         /* [XML] UseAnyServers 1 to broadcast to look for encoding servers to use, 0 to use only those configured. */
646         root->add_child("UseAnyServers")->add_child_text (_use_any_servers ? "1" : "0");
647
648         for (auto i: _servers) {
649                 /* [XML:opt] Server IP address or hostname of an encoding server to use; you can use as many of these tags
650                    as you like.
651                 */
652                 root->add_child("Server")->add_child_text (i);
653         }
654
655         /* [XML] OnlyServersEncode 1 to set the master to do decoding of source content no JPEG2000 encoding; all encoding
656            is done by the encoding servers.  0 to set the master to do some encoding as well as coordinating the job.
657         */
658         root->add_child("OnlyServersEncode")->add_child_text (_only_servers_encode ? "1" : "0");
659         /* [XML] TMSProtocol Protocol to use to copy files to a TMS; 0 to use SCP, 1 for FTP. */
660         root->add_child("TMSProtocol")->add_child_text (raw_convert<string> (static_cast<int> (_tms_protocol)));
661         /* [XML] TMSIP IP address of TMS. */
662         root->add_child("TMSIP")->add_child_text (_tms_ip);
663         /* [XML] TMSPath Path on the TMS to copy files to. */
664         root->add_child("TMSPath")->add_child_text (_tms_path);
665         /* [XML] TMSUser Username to log into the TMS with. */
666         root->add_child("TMSUser")->add_child_text (_tms_user);
667         /* [XML] TMSPassword Password to log into the TMS with. */
668         root->add_child("TMSPassword")->add_child_text (_tms_password);
669         if (_language) {
670                 /* [XML:opt] Language Language to use in the GUI e.g. <code>fr_FR</code>. */
671                 root->add_child("Language")->add_child_text (_language.get());
672         }
673         if (_default_container) {
674                 /* [XML:opt] DefaultContainer ID of default container
675                    to use when creating new films (<code>185</code>,<code>239</code> or
676                    <code>190</code>).
677                 */
678                 root->add_child("DefaultContainer")->add_child_text (_default_container->id ());
679         }
680         if (_default_dcp_content_type) {
681                 /* [XML:opt] DefaultDCPContentType Default content type ot use when creating new films (<code>FTR</code>, <code>SHR</code>,
682                    <code>TLR</code>, <code>TST</code>, <code>XSN</code>, <code>RTG</code>, <code>TSR</code>, <code>POL</code>,
683                    <code>PSA</code> or <code>ADV</code>). */
684                 root->add_child("DefaultDCPContentType")->add_child_text (_default_dcp_content_type->isdcf_name ());
685         }
686         /* [XML] DefaultDCPAudioChannels Default number of audio channels to use when creating new films. */
687         root->add_child("DefaultDCPAudioChannels")->add_child_text (raw_convert<string> (_default_dcp_audio_channels));
688         /* [XML] DCPIssuer Issuer text to write into CPL files. */
689         root->add_child("DCPIssuer")->add_child_text (_dcp_issuer);
690         /* [XML] DCPCreator Creator text to write into CPL files. */
691         root->add_child("DCPCreator")->add_child_text (_dcp_creator);
692         /* [XML] Company name to write into MXF files. */
693         root->add_child("DCPCompanyName")->add_child_text (_dcp_company_name);
694         /* [XML] Product name to write into MXF files. */
695         root->add_child("DCPProductName")->add_child_text (_dcp_product_name);
696         /* [XML] Product version to write into MXF files. */
697         root->add_child("DCPProductVersion")->add_child_text (_dcp_product_version);
698         /* [XML] Comment to write into JPEG2000 data. */
699         root->add_child("DCPJ2KComment")->add_child_text (_dcp_j2k_comment);
700         /* [XML] UploadAfterMakeDCP 1 to upload to a TMS after making a DCP, 0 for no upload. */
701         root->add_child("UploadAfterMakeDCP")->add_child_text (_upload_after_make_dcp ? "1" : "0");
702
703         /* [XML] DefaultStillLength Default length (in seconds) for still images in new films. */
704         root->add_child("DefaultStillLength")->add_child_text (raw_convert<string> (_default_still_length));
705         /* [XML] DefaultJ2KBandwidth Default bitrate (in bits per second) for JPEG2000 data in new films. */
706         root->add_child("DefaultJ2KBandwidth")->add_child_text (raw_convert<string> (_default_j2k_bandwidth));
707         /* [XML] DefaultAudioDelay Default delay to apply to audio (positive moves audio later) in milliseconds. */
708         root->add_child("DefaultAudioDelay")->add_child_text (raw_convert<string> (_default_audio_delay));
709         /* [XML] DefaultInterop 1 to default new films to Interop, 0 for SMPTE. */
710         root->add_child("DefaultInterop")->add_child_text (_default_interop ? "1" : "0");
711         for (auto const& i: _default_metadata) {
712                 auto c = root->add_child("DefaultMetadata");
713                 c->set_attribute("key", i.first);
714                 c->add_child_text(i.second);
715         }
716         if (_default_kdm_directory) {
717                 /* [XML:opt] DefaultKDMDirectory Default directory to write KDMs to. */
718                 root->add_child("DefaultKDMDirectory")->add_child_text (_default_kdm_directory->string ());
719         }
720         /* [XML] MailServer Hostname of SMTP server to use. */
721         root->add_child("MailServer")->add_child_text (_mail_server);
722         /* [XML] MailPort Port number to use on SMTP server. */
723         root->add_child("MailPort")->add_child_text (raw_convert<string> (_mail_port));
724         /* [XML] MailProtocol Protocol to use on SMTP server (Auto, Plain, STARTTLS or SSL) */
725         switch (_mail_protocol) {
726         case EmailProtocol::AUTO:
727                 root->add_child("MailProtocol")->add_child_text("Auto");
728                 break;
729         case EmailProtocol::PLAIN:
730                 root->add_child("MailProtocol")->add_child_text("Plain");
731                 break;
732         case EmailProtocol::STARTTLS:
733                 root->add_child("MailProtocol")->add_child_text("STARTTLS");
734                 break;
735         case EmailProtocol::SSL:
736                 root->add_child("MailProtocol")->add_child_text("SSL");
737                 break;
738         }
739         /* [XML] MailUser Username to use on SMTP server. */
740         root->add_child("MailUser")->add_child_text (_mail_user);
741         /* [XML] MailPassword Password to use on SMTP server. */
742         root->add_child("MailPassword")->add_child_text (_mail_password);
743
744         /* [XML] KDMSubject Subject to use for KDM emails. */
745         root->add_child("KDMSubject")->add_child_text (_kdm_subject);
746         /* [XML] KDMFrom From address to use for KDM emails. */
747         root->add_child("KDMFrom")->add_child_text (_kdm_from);
748         for (auto i: _kdm_cc) {
749                 /* [XML] KDMCC CC address to use for KDM emails; you can use as many of these tags as you like. */
750                 root->add_child("KDMCC")->add_child_text (i);
751         }
752         /* [XML] KDMBCC BCC address to use for KDM emails. */
753         root->add_child("KDMBCC")->add_child_text (_kdm_bcc);
754         /* [XML] KDMEmail Text of KDM email. */
755         root->add_child("KDMEmail")->add_child_text (_kdm_email);
756
757         /* [XML] NotificationSubject Subject to use for notification emails. */
758         root->add_child("NotificationSubject")->add_child_text (_notification_subject);
759         /* [XML] NotificationFrom From address to use for notification emails. */
760         root->add_child("NotificationFrom")->add_child_text (_notification_from);
761         /* [XML] NotificationFrom To address to use for notification emails. */
762         root->add_child("NotificationTo")->add_child_text (_notification_to);
763         for (auto i: _notification_cc) {
764                 /* [XML] NotificationCC CC address to use for notification emails; you can use as many of these tags as you like. */
765                 root->add_child("NotificationCC")->add_child_text (i);
766         }
767         /* [XML] NotificationBCC BCC address to use for notification emails. */
768         root->add_child("NotificationBCC")->add_child_text (_notification_bcc);
769         /* [XML] NotificationEmail Text of notification email. */
770         root->add_child("NotificationEmail")->add_child_text (_notification_email);
771
772         /* [XML] CheckForUpdates 1 to check dcpomatic.com for new versions, 0 to check only on request. */
773         root->add_child("CheckForUpdates")->add_child_text (_check_for_updates ? "1" : "0");
774         /* [XML] CheckForUpdates 1 to check dcpomatic.com for new text versions, 0 to check only on request. */
775         root->add_child("CheckForTestUpdates")->add_child_text (_check_for_test_updates ? "1" : "0");
776
777         /* [XML] MaximumJ2KBandwidth Maximum J2K bandwidth (in bits per second) that can be specified in the GUI. */
778         root->add_child("MaximumJ2KBandwidth")->add_child_text (raw_convert<string> (_maximum_j2k_bandwidth));
779         /* [XML] AllowAnyDCPFrameRate 1 to allow users to specify any frame rate when creating DCPs, 0 to limit the GUI to standard rates. */
780         root->add_child("AllowAnyDCPFrameRate")->add_child_text (_allow_any_dcp_frame_rate ? "1" : "0");
781         /* [XML] AllowAnyContainer 1 to allow users to user any container ratio for their DCP, 0 to limit the GUI to DCI Flat/Scope */
782         root->add_child("AllowAnyContainer")->add_child_text (_allow_any_container ? "1" : "0");
783         /* [XML] ShowExperimentalAudioProcessors 1 to offer users the (experimental) audio upmixer processors, 0 to hide them */
784         root->add_child("ShowExperimentalAudioProcessors")->add_child_text (_show_experimental_audio_processors ? "1" : "0");
785         /* [XML] LogTypes Types of logging to write; a bitfield where 1 is general notes, 2 warnings, 4 errors, 8 debug information related
786            to 3D, 16 debug information related to encoding, 32 debug information for timing purposes, 64 debug information related
787            to sending email, 128 debug information related to the video view, 256 information about disk writing, 512 debug information
788            related to the player, 1024 debug information related to audio analyses.
789         */
790         root->add_child("LogTypes")->add_child_text (raw_convert<string> (_log_types));
791         /* [XML] AnalyseEBUR128 1 to do EBUR128 analyses when analysing audio, otherwise 0. */
792         root->add_child("AnalyseEBUR128")->add_child_text (_analyse_ebur128 ? "1" : "0");
793         /* [XML] AutomaticAudioAnalysis 1 to run audio analysis automatically when audio content is added to the film, otherwise 0. */
794         root->add_child("AutomaticAudioAnalysis")->add_child_text (_automatic_audio_analysis ? "1" : "0");
795 #ifdef DCPOMATIC_WINDOWS
796         if (_win32_console) {
797                 /* [XML] Win32Console 1 to open a console when running on Windows, otherwise 0.
798                  * We only write this if it's true, which is a bit of a hack to allow unit tests to work
799                  * more easily on Windows (without a platform-specific reference in config_write_utf8_test)
800                  */
801                 root->add_child("Win32Console")->add_child_text ("1");
802         }
803 #endif
804
805         /* [XML] Signer Certificate chain and private key to use when signing DCPs and KDMs.  Should contain <code>&lt;Certificate&gt;</code>
806            tags in order and a <code>&lt;PrivateKey&gt;</code> tag all containing PEM-encoded certificates or private keys as appropriate.
807         */
808         auto signer = root->add_child ("Signer");
809         DCPOMATIC_ASSERT (_signer_chain);
810         for (auto const& i: _signer_chain->unordered()) {
811                 signer->add_child("Certificate")->add_child_text (i.certificate (true));
812         }
813         signer->add_child("PrivateKey")->add_child_text (_signer_chain->key().get ());
814
815         /* [XML] Decryption Certificate chain and private key to use when decrypting KDMs */
816         auto decryption = root->add_child ("Decryption");
817         DCPOMATIC_ASSERT (_decryption_chain);
818         for (auto const& i: _decryption_chain->unordered()) {
819                 decryption->add_child("Certificate")->add_child_text (i.certificate (true));
820         }
821         decryption->add_child("PrivateKey")->add_child_text (_decryption_chain->key().get ());
822
823         /* [XML] History Filename of DCP to present in the <guilabel>File</guilabel> menu of the GUI; there can be more than one
824            of these tags.
825         */
826         for (auto i: _history) {
827                 root->add_child("History")->add_child_text (i.string ());
828         }
829
830         /* [XML] History Filename of DCP to present in the <guilabel>File</guilabel> menu of the player; there can be more than one
831            of these tags.
832         */
833         for (auto i: _player_history) {
834                 root->add_child("PlayerHistory")->add_child_text (i.string ());
835         }
836
837         /* [XML] DKDMGroup A group of DKDMs, each with a <code>Name</code> attribute, containing other <code>&lt;DKDMGroup&gt;</code>
838            or <code>&lt;DKDM&gt;</code> tags.
839         */
840         /* [XML] DKDM A DKDM as XML */
841         _dkdms->as_xml (root);
842
843         /* [XML] CinemasFile Filename of cinemas list file. */
844         root->add_child("CinemasFile")->add_child_text (_cinemas_file.string());
845         /* [XML] DKDMRecipientsFile Filename of DKDM recipients list file. */
846         root->add_child("DKDMRecipientsFile")->add_child_text (_dkdm_recipients_file.string());
847         /* [XML] ShowHintsBeforeMakeDCP 1 to show hints in the GUI before making a DCP, otherwise 0. */
848         root->add_child("ShowHintsBeforeMakeDCP")->add_child_text (_show_hints_before_make_dcp ? "1" : "0");
849         /* [XML] ConfirmKDMEmail 1 to confirm before sending KDM emails in the GUI, otherwise 0. */
850         root->add_child("ConfirmKDMEmail")->add_child_text (_confirm_kdm_email ? "1" : "0");
851         /* [XML] KDMFilenameFormat Format for KDM filenames. */
852         root->add_child("KDMFilenameFormat")->add_child_text (_kdm_filename_format.specification ());
853         /* [XML] KDMFilenameFormat Format for DKDM filenames. */
854         root->add_child("DKDMFilenameFormat")->add_child_text(_dkdm_filename_format.specification());
855         /* [XML] KDMContainerNameFormat Format for KDM containers (directories or ZIP files). */
856         root->add_child("KDMContainerNameFormat")->add_child_text (_kdm_container_name_format.specification ());
857         /* [XML] DCPMetadataFilenameFormat Format for DCP metadata filenames. */
858         root->add_child("DCPMetadataFilenameFormat")->add_child_text (_dcp_metadata_filename_format.specification ());
859         /* [XML] DCPAssetFilenameFormat Format for DCP asset filenames. */
860         root->add_child("DCPAssetFilenameFormat")->add_child_text (_dcp_asset_filename_format.specification ());
861         /* [XML] JumpToSelected 1 to make the GUI jump to the start of content when it is selected, otherwise 0. */
862         root->add_child("JumpToSelected")->add_child_text (_jump_to_selected ? "1" : "0");
863         /* [XML] Nagged 1 if a particular nag screen has been shown and should not be shown again, otherwise 0. */
864         for (int i = 0; i < NAG_COUNT; ++i) {
865                 xmlpp::Element* e = root->add_child ("Nagged");
866                 e->set_attribute ("Id", raw_convert<string>(i));
867                 e->add_child_text (_nagged[i] ? "1" : "0");
868         }
869         /* [XML] PreviewSound 1 to use sound in the GUI preview and player, otherwise 0. */
870         root->add_child("PreviewSound")->add_child_text (_sound ? "1" : "0");
871         if (_sound_output) {
872                 /* [XML:opt] PreviewSoundOutput Name of the audio output to use. */
873                 root->add_child("PreviewSoundOutput")->add_child_text (_sound_output.get());
874         }
875         /* [XML] CoverSheet Text of the cover sheet to write when making DCPs. */
876         root->add_child("CoverSheet")->add_child_text (_cover_sheet);
877         if (_last_player_load_directory) {
878                 root->add_child("LastPlayerLoadDirectory")->add_child_text(_last_player_load_directory->string());
879         }
880         /* [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. */
881         if (_last_kdm_write_type) {
882                 switch (_last_kdm_write_type.get()) {
883                 case KDM_WRITE_FLAT:
884                         root->add_child("LastKDMWriteType")->add_child_text("flat");
885                         break;
886                 case KDM_WRITE_FOLDER:
887                         root->add_child("LastKDMWriteType")->add_child_text("folder");
888                         break;
889                 case KDM_WRITE_ZIP:
890                         root->add_child("LastKDMWriteType")->add_child_text("zip");
891                         break;
892                 }
893         }
894         /* [XML] LastDKDMWriteType Last type of DKDM-write: <code>file</code> for a file, <code>internal</code> to add to DCP-o-matic's list. */
895         if (_last_dkdm_write_type) {
896                 switch (_last_dkdm_write_type.get()) {
897                 case DKDM_WRITE_INTERNAL:
898                         root->add_child("LastDKDMWriteType")->add_child_text("internal");
899                         break;
900                 case DKDM_WRITE_FILE:
901                         root->add_child("LastDKDMWriteType")->add_child_text("file");
902                         break;
903                 }
904         }
905         /* [XML] FramesInMemoryMultiplier value to multiply the encoding threads count by to get the maximum number of
906            frames to be held in memory at once.
907         */
908         root->add_child("FramesInMemoryMultiplier")->add_child_text(raw_convert<string>(_frames_in_memory_multiplier));
909
910         /* [XML] DecodeReduction power of 2 to reduce DCP images by before decoding in the player. */
911         if (_decode_reduction) {
912                 root->add_child("DecodeReduction")->add_child_text(raw_convert<string>(_decode_reduction.get()));
913         }
914
915         /* [XML] DefaultNotify 1 to default jobs to notify when complete, otherwise 0. */
916         root->add_child("DefaultNotify")->add_child_text(_default_notify ? "1" : "0");
917
918         /* [XML] Notification 1 if a notification type is enabled, otherwise 0. */
919         for (int i = 0; i < NOTIFICATION_COUNT; ++i) {
920                 xmlpp::Element* e = root->add_child ("Notification");
921                 e->set_attribute ("Id", raw_convert<string>(i));
922                 e->add_child_text (_notification[i] ? "1" : "0");
923         }
924
925         if (_barco_username) {
926                 /* [XML] BarcoUsername Username for logging into Barco's servers when downloading server certificates. */
927                 root->add_child("BarcoUsername")->add_child_text(*_barco_username);
928         }
929         if (_barco_password) {
930                 /* [XML] BarcoPassword Password for logging into Barco's servers when downloading server certificates. */
931                 root->add_child("BarcoPassword")->add_child_text(*_barco_password);
932         }
933
934         if (_christie_username) {
935                 /* [XML] ChristieUsername Username for logging into Christie's servers when downloading server certificates. */
936                 root->add_child("ChristieUsername")->add_child_text(*_christie_username);
937         }
938         if (_christie_password) {
939                 /* [XML] ChristiePassword Password for logging into Christie's servers when downloading server certificates. */
940                 root->add_child("ChristiePassword")->add_child_text(*_christie_password);
941         }
942
943         if (_gdc_username) {
944                 /* [XML] GDCUsername Username for logging into GDC's servers when downloading server certificates. */
945                 root->add_child("GDCUsername")->add_child_text(*_gdc_username);
946         }
947         if (_gdc_password) {
948                 /* [XML] GDCPassword Password for logging into GDC's servers when downloading server certificates. */
949                 root->add_child("GDCPassword")->add_child_text(*_gdc_password);
950         }
951
952         /* [XML] PlayerMode <code>window</code> for a single window, <code>full</code> for full-screen and <code>dual</code> for full screen playback
953            with controls on another monitor.
954         */
955         switch (_player_mode) {
956         case PLAYER_MODE_WINDOW:
957                 root->add_child("PlayerMode")->add_child_text("window");
958                 break;
959         case PLAYER_MODE_FULL:
960                 root->add_child("PlayerMode")->add_child_text("full");
961                 break;
962         case PLAYER_MODE_DUAL:
963                 root->add_child("PlayerMode")->add_child_text("dual");
964                 break;
965         }
966
967         /* [XML] ImageDisplay Screen number to put image on in dual-screen player mode. */
968         root->add_child("ImageDisplay")->add_child_text(raw_convert<string>(_image_display));
969         switch (_video_view_type) {
970         case VIDEO_VIEW_SIMPLE:
971                 root->add_child("VideoViewType")->add_child_text("simple");
972                 break;
973         case VIDEO_VIEW_OPENGL:
974                 root->add_child("VideoViewType")->add_child_text("opengl");
975                 break;
976         }
977         /* [XML] RespectKDMValidityPeriods 1 to refuse to use KDMs that are out of date, 0 to ignore KDM dates. */
978         root->add_child("RespectKDMValidityPeriods")->add_child_text(_respect_kdm_validity_periods ? "1" : "0");
979         if (_player_debug_log_file) {
980                 /* [XML] PlayerLogFile Filename to use for player debug logs. */
981                 root->add_child("PlayerDebugLogFile")->add_child_text(_player_debug_log_file->string());
982         }
983         if (_player_content_directory) {
984                 /* [XML] PlayerContentDirectory Directory to use for player content in the dual-screen mode. */
985                 root->add_child("PlayerContentDirectory")->add_child_text(_player_content_directory->string());
986         }
987         if (_player_playlist_directory) {
988                 /* [XML] PlayerPlaylistDirectory Directory to use for player playlists in the dual-screen mode. */
989                 root->add_child("PlayerPlaylistDirectory")->add_child_text(_player_playlist_directory->string());
990         }
991         if (_player_kdm_directory) {
992                 /* [XML] PlayerKDMDirectory Directory to use for player KDMs in the dual-screen mode. */
993                 root->add_child("PlayerKDMDirectory")->add_child_text(_player_kdm_directory->string());
994         }
995         if (_audio_mapping) {
996                 _audio_mapping->as_xml (root->add_child("AudioMapping"));
997         }
998         for (auto const& i: _custom_languages) {
999                 root->add_child("CustomLanguage")->add_child_text(i.to_string());
1000         }
1001         if (_add_files_path) {
1002                 /* [XML] AddFilesPath The default path that will be offered in the picker when adding files to a film. */
1003                 root->add_child("AddFilesPath")->add_child_text(_add_files_path->string());
1004         }
1005         root->add_child("UseISDCFNameByDefault")->add_child_text(_use_isdcf_name_by_default ? "1" : "0");
1006         root->add_child("WriteKDMsToDisk")->add_child_text(_write_kdms_to_disk ? "1" : "0");
1007         root->add_child("EmailKDMs")->add_child_text(_email_kdms ? "1" : "0");
1008         root->add_child("DefaultKDMType")->add_child_text(dcp::formulation_to_string(_default_kdm_type));
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
1468
1469 optional<Config::BadReason>
1470 Config::check_certificates () const
1471 {
1472         optional<BadReason> bad;
1473
1474         for (auto const& i: _signer_chain->unordered()) {
1475                 if (i.has_utf8_strings()) {
1476                         bad = BAD_SIGNER_UTF8_STRINGS;
1477                 }
1478                 if ((i.not_after().year() - i.not_before().year()) > 15) {
1479                         bad = BAD_SIGNER_VALIDITY_TOO_LONG;
1480                 }
1481         }
1482
1483         if (!_signer_chain->chain_valid() || !_signer_chain->private_key_valid()) {
1484                 bad = BAD_SIGNER_INCONSISTENT;
1485         }
1486
1487         if (!_decryption_chain->chain_valid() || !_decryption_chain->private_key_valid()) {
1488                 bad = BAD_DECRYPTION_INCONSISTENT;
1489         }
1490
1491         return bad;
1492 }
1493
1494
1495 void
1496 save_all_config_as_zip (boost::filesystem::path zip_file)
1497 {
1498         Zipper zipper (zip_file);
1499
1500         auto config = Config::instance();
1501         zipper.add ("config.xml", dcp::file_to_string(config->config_read_file()));
1502         if (boost::filesystem::exists(config->cinemas_file())) {
1503                 zipper.add ("cinemas.xml", dcp::file_to_string(config->cinemas_file()));
1504         }
1505         if (boost::filesystem::exists(config->dkdm_recipients_file())) {
1506                 zipper.add ("dkdm_recipients.xml", dcp::file_to_string(config->dkdm_recipients_file()));
1507         }
1508
1509         zipper.close ();
1510 }
1511