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