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