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