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