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