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