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