+++ /dev/null
-/*
- Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
-
- This file is part of DCP-o-matic.
-
- DCP-o-matic is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- DCP-o-matic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include "exceptions.h"
-#include "cinema_kdms.h"
-#include "cinema.h"
-#include "screen.h"
-#include "config.h"
-#include "util.h"
-#include "emailer.h"
-#include "compose.hpp"
-#include "log.h"
-#include "zipper.h"
-#include "dcpomatic_log.h"
-#include <boost/foreach.hpp>
-
-#include "i18n.h"
-
-using std::list;
-using std::cout;
-using std::string;
-using std::runtime_error;
-using boost::shared_ptr;
-using boost::function;
-
-void
-CinemaKDMs::make_zip_file (boost::filesystem::path zip_file, dcp::NameFormat name_format, dcp::NameFormat::Map name_values) const
-{
- Zipper zipper (zip_file);
-
- name_values['c'] = cinema->name;
-
- BOOST_FOREACH (shared_ptr<ScreenKDM> i, screen_kdms) {
- name_values['s'] = i->screen->name;
- name_values['i'] = i->kdm_id ();
- string const name = careful_string_filter(name_format.get(name_values, ".xml"));
- zipper.add (name, i->kdm_as_xml());
- }
-
- zipper.close ();
-}
-
-/** Collect a list of ScreenKDMs into a list of CinemaKDMs so that each
- * CinemaKDM contains the KDMs for its cinema.
- */
-list<CinemaKDMs>
-CinemaKDMs::collect (list<shared_ptr<ScreenKDM> > screen_kdms)
-{
- list<CinemaKDMs> cinema_kdms;
-
- while (!screen_kdms.empty ()) {
-
- /* Get all the screens from a single cinema */
-
- CinemaKDMs ck;
-
- list<shared_ptr<ScreenKDM> >::iterator i = screen_kdms.begin ();
- ck.cinema = (*i)->screen->cinema;
- ck.screen_kdms.push_back (*i);
- list<shared_ptr<ScreenKDM> >::iterator j = i;
- ++i;
- screen_kdms.remove (*j);
-
- while (i != screen_kdms.end ()) {
- if ((*i)->screen->cinema == ck.cinema) {
- ck.screen_kdms.push_back (*i);
- list<shared_ptr<ScreenKDM> >::iterator j = i;
- ++i;
- screen_kdms.remove (*j);
- } else {
- ++i;
- }
- }
-
- cinema_kdms.push_back (ck);
- }
-
- return cinema_kdms;
-}
-
-/** Write one directory per cinema into another directory */
-int
-CinemaKDMs::write_directories (
- list<CinemaKDMs> cinema_kdms,
- boost::filesystem::path directory,
- dcp::NameFormat container_name_format,
- dcp::NameFormat filename_format,
- dcp::NameFormat::Map name_values,
- function<bool (boost::filesystem::path)> confirm_overwrite
- )
-{
- /* No specific screen */
- name_values['s'] = "";
-
- int written = 0;
-
- BOOST_FOREACH (CinemaKDMs const & i, cinema_kdms) {
- boost::filesystem::path path = directory;
- name_values['c'] = i.cinema->name;
- path /= container_name_format.get(name_values, "");
- if (!boost::filesystem::exists (path) || confirm_overwrite (path)) {
- boost::filesystem::create_directories (path);
- ScreenKDM::write_files (i.screen_kdms, path, filename_format, name_values, confirm_overwrite);
- }
- written += i.screen_kdms.size();
- }
-
- return written;
-}
-
-/** Write one ZIP file per cinema into a directory */
-int
-CinemaKDMs::write_zip_files (
- list<CinemaKDMs> cinema_kdms,
- boost::filesystem::path directory,
- dcp::NameFormat container_name_format,
- dcp::NameFormat filename_format,
- dcp::NameFormat::Map name_values,
- function<bool (boost::filesystem::path)> confirm_overwrite
- )
-{
- /* No specific screen */
- name_values['s'] = "";
-
- int written = 0;
-
- BOOST_FOREACH (CinemaKDMs const & i, cinema_kdms) {
- boost::filesystem::path path = directory;
- name_values['c'] = i.cinema->name;
- path /= container_name_format.get(name_values, ".zip");
- if (!boost::filesystem::exists (path) || confirm_overwrite (path)) {
- if (boost::filesystem::exists (path)) {
- /* Creating a new zip file over an existing one is an error */
- boost::filesystem::remove (path);
- }
- i.make_zip_file (path, filename_format, name_values);
- written += i.screen_kdms.size();
- }
- }
-
- return written;
-}
-
-/** Email one ZIP file per cinema to the cinema.
- * @param cinema_kdms KDMS to email.
- * @param container_name_format Format of folder / ZIP to use.
- * @param filename_format Format of filenames to use.
- * @param name_values Values to substitute into \p container_name_format and \p filename_format.
- * @param cpl_name Name of the CPL that the KDMs are for.
- */
-void
-CinemaKDMs::email (
- list<CinemaKDMs> cinema_kdms,
- dcp::NameFormat container_name_format,
- dcp::NameFormat filename_format,
- dcp::NameFormat::Map name_values,
- string cpl_name
- )
-{
- Config* config = Config::instance ();
-
- if (config->mail_server().empty()) {
- throw NetworkError (_("No mail server configured in preferences"));
- }
-
- /* No specific screen */
- name_values['s'] = "";
-
- BOOST_FOREACH (CinemaKDMs const & i, cinema_kdms) {
-
- if (i.cinema->emails.empty()) {
- continue;
- }
-
- name_values['c'] = i.cinema->name;
-
- boost::filesystem::path zip_file = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
- boost::filesystem::create_directories (zip_file);
- zip_file /= container_name_format.get(name_values, ".zip");
- i.make_zip_file (zip_file, filename_format, name_values);
-
- string subject = config->kdm_subject();
- boost::algorithm::replace_all (subject, "$CPL_NAME", cpl_name);
- boost::algorithm::replace_all (subject, "$START_TIME", name_values['b']);
- boost::algorithm::replace_all (subject, "$END_TIME", name_values['e']);
- boost::algorithm::replace_all (subject, "$CINEMA_NAME", i.cinema->name);
-
- string body = config->kdm_email().c_str();
- boost::algorithm::replace_all (body, "$CPL_NAME", cpl_name);
- boost::algorithm::replace_all (body, "$START_TIME", name_values['b']);
- boost::algorithm::replace_all (body, "$END_TIME", name_values['e']);
- boost::algorithm::replace_all (body, "$CINEMA_NAME", i.cinema->name);
-
- string screens;
- BOOST_FOREACH (shared_ptr<ScreenKDM> j, i.screen_kdms) {
- screens += j->screen->name + ", ";
- }
- boost::algorithm::replace_all (body, "$SCREENS", screens.substr (0, screens.length() - 2));
-
- Emailer email (config->kdm_from(), i.cinema->emails, subject, body);
-
- BOOST_FOREACH (string i, config->kdm_cc()) {
- email.add_cc (i);
- }
- if (!config->kdm_bcc().empty ()) {
- email.add_bcc (config->kdm_bcc ());
- }
-
- email.add_attachment (zip_file, container_name_format.get(name_values, ".zip"), "application/zip");
-
- Config* c = Config::instance ();
-
- try {
- email.send (c->mail_server(), c->mail_port(), c->mail_protocol(), c->mail_user(), c->mail_password());
- } catch (...) {
- boost::filesystem::remove (zip_file);
- dcpomatic_log->log ("Email content follows", LogEntry::TYPE_DEBUG_EMAIL);
- dcpomatic_log->log (email.email(), LogEntry::TYPE_DEBUG_EMAIL);
- dcpomatic_log->log ("Email session follows", LogEntry::TYPE_DEBUG_EMAIL);
- dcpomatic_log->log (email.notes(), LogEntry::TYPE_DEBUG_EMAIL);
- throw;
- }
-
- boost::filesystem::remove (zip_file);
-
- dcpomatic_log->log ("Email content follows", LogEntry::TYPE_DEBUG_EMAIL);
- dcpomatic_log->log (email.email(), LogEntry::TYPE_DEBUG_EMAIL);
- dcpomatic_log->log ("Email session follows", LogEntry::TYPE_DEBUG_EMAIL);
- dcpomatic_log->log (email.notes(), LogEntry::TYPE_DEBUG_EMAIL);
- }
-}
+++ /dev/null
-/*
- Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
-
- This file is part of DCP-o-matic.
-
- DCP-o-matic is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- DCP-o-matic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include "screen_kdm.h"
-
-class Cinema;
-class Job;
-class Log;
-
-class CinemaKDMs
-{
-public:
- void make_zip_file (boost::filesystem::path zip_file, dcp::NameFormat name_format, dcp::NameFormat::Map name_values) const;
-
- static std::list<CinemaKDMs> collect (std::list<boost::shared_ptr<ScreenKDM> > kdms);
-
- static int write_directories (
- std::list<CinemaKDMs> cinema_kdms,
- boost::filesystem::path directory,
- dcp::NameFormat container_name_format,
- dcp::NameFormat filename_format,
- dcp::NameFormat::Map name_values,
- boost::function<bool (boost::filesystem::path)> confirm_overwrite
- );
-
- static int write_zip_files (
- std::list<CinemaKDMs> cinema_kdms,
- boost::filesystem::path directory,
- dcp::NameFormat container_name_format,
- dcp::NameFormat filename_format,
- dcp::NameFormat::Map name_values,
- boost::function<bool (boost::filesystem::path)> confirm_overwrite
- );
-
- static void email (
- std::list<CinemaKDMs> cinema_kdms,
- dcp::NameFormat container_name_format,
- dcp::NameFormat filename_format,
- dcp::NameFormat::Map name_values,
- std::string cpl_name
- );
-
- boost::shared_ptr<Cinema> cinema;
- std::list<boost::shared_ptr<ScreenKDM> > screen_kdms;
-};
/*
- Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include "dkdm_wrapper.h"
#include "compose.hpp"
#include "crypto.h"
+#include "dkdm_recipient.h"
#include <dcp/raw_convert.h>
#include <dcp/name_format.h>
#include <dcp/certificate_chain.h>
_win32_console = false;
#endif
_cinemas_file = path ("cinemas.xml");
+ _dkdm_recipients_file = path ("dkdm_recipients.xml");
_show_hints_before_make_dcp = true;
_confirm_kdm_email = true;
_kdm_container_name_format = dcp::NameFormat ("KDM %f %c");
_kdm_filename_format = dcp::NameFormat ("KDM %f %c %s");
+ _dkdm_filename_format = dcp::NameFormat ("DKDM %f %c %s");
_dcp_metadata_filename_format = dcp::NameFormat ("%t");
_dcp_asset_filename_format = dcp::NameFormat ("%t");
_jump_to_selected = true;
boost::filesystem::copy_file(path("config.xml", false), path(String::compose("config.xml.%1", n), false));
boost::filesystem::copy_file(path("cinemas.xml", false), path(String::compose("cinemas.xml.%1", n), false));
+ boost::filesystem::copy_file(path("dkdm_recipients.xml", false), path(String::compose("dkdm_recipients.xml.%1", n), false));
} catch (...) {}
}
_default_interop = f.optional_bool_child("DefaultInterop").get_value_or (false);
_default_kdm_directory = f.optional_string_child("DefaultKDMDirectory");
- /* Load any cinemas from config.xml */
+ /* Read any cinemas that are still lying around in the config file
+ * from an old version.
+ */
read_cinemas (f);
_mail_server = f.string_child ("MailServer");
}
}
_cinemas_file = f.optional_string_child("CinemasFile").get_value_or (path ("cinemas.xml").string ());
+ _dkdm_recipients_file = f.optional_string_child("DKDMRecipientsFile").get_value_or (path("dkdm_recipients.xml").string());
_show_hints_before_make_dcp = f.optional_bool_child("ShowHintsBeforeMakeDCP").get_value_or (true);
_confirm_kdm_email = f.optional_bool_child("ConfirmKDMEmail").get_value_or (true);
_kdm_container_name_format = dcp::NameFormat (f.optional_string_child("KDMContainerNameFormat").get_value_or ("KDM %f %c"));
_kdm_filename_format = dcp::NameFormat (f.optional_string_child("KDMFilenameFormat").get_value_or ("KDM %f %c %s"));
+ _dkdm_filename_format = dcp::NameFormat (f.optional_string_child("DKDMFilenameFormat").get_value_or("DKDM %f %c %s"));
_dcp_metadata_filename_format = dcp::NameFormat (f.optional_string_child("DCPMetadataFilenameFormat").get_value_or ("%t"));
_dcp_asset_filename_format = dcp::NameFormat (f.optional_string_child("DCPAssetFilenameFormat").get_value_or ("%t"));
_jump_to_selected = f.optional_bool_child("JumpToSelected").get_value_or (true);
_player_lock_file = f.optional_string_child("PlayerLockFile");
#endif
- /* Replace any cinemas from config.xml with those from the configured file */
if (boost::filesystem::exists (_cinemas_file)) {
cxml::Document f ("Cinemas");
f.read_file (_cinemas_file);
read_cinemas (f);
}
+
+ if (boost::filesystem::exists (_dkdm_recipients_file)) {
+ cxml::Document f ("DKDMRecipients");
+ f.read_file (_dkdm_recipients_file);
+ read_dkdm_recipients (f);
+ }
}
catch (...) {
if (have_existing ("config.xml")) {
{
write_config ();
write_cinemas ();
+ write_dkdm_recipients ();
}
void
/* [XML] CinemasFile Filename of cinemas list file. */
root->add_child("CinemasFile")->add_child_text (_cinemas_file.string());
+ /* [XML] DKDMRecipientsFile Filename of DKDM recipients list file. */
+ root->add_child("DKDMRecipientsFile")->add_child_text (_dkdm_recipients_file.string());
/* [XML] ShowHintsBeforeMakeDCP 1 to show hints in the GUI before making a DCP, otherwise 0. */
root->add_child("ShowHintsBeforeMakeDCP")->add_child_text (_show_hints_before_make_dcp ? "1" : "0");
/* [XML] ConfirmKDMEmail 1 to confirm before sending KDM emails in the GUI, otherwise 0. */
root->add_child("ConfirmKDMEmail")->add_child_text (_confirm_kdm_email ? "1" : "0");
/* [XML] KDMFilenameFormat Format for KDM filenames. */
root->add_child("KDMFilenameFormat")->add_child_text (_kdm_filename_format.specification ());
+ /* [XML] KDMFilenameFormat Format for DKDM filenames. */
+ root->add_child("DKDMFilenameFormat")->add_child_text(_dkdm_filename_format.specification());
/* [XML] KDMContainerNameFormat Format for KDM containers (directories or ZIP files). */
root->add_child("KDMContainerNameFormat")->add_child_text (_kdm_container_name_format.specification ());
/* [XML] DCPMetadataFilenameFormat Format for DCP metadata filenames. */
}
}
+
+template <class T>
void
-Config::write_cinemas () const
+write_file (string root_node, string node, string version, list<shared_ptr<T> > things, boost::filesystem::path file)
{
xmlpp::Document doc;
- xmlpp::Element* root = doc.create_root_node ("Cinemas");
- root->add_child("Version")->add_child_text ("1");
+ xmlpp::Element* root = doc.create_root_node (root_node);
+ root->add_child("Version")->add_child_text(version);
- BOOST_FOREACH (shared_ptr<Cinema> i, _cinemas) {
- i->as_xml (root->add_child ("Cinema"));
+ BOOST_FOREACH (shared_ptr<T> i, things) {
+ i->as_xml (root->add_child(node));
}
try {
- doc.write_to_file_formatted (_cinemas_file.string() + ".tmp");
- boost::filesystem::remove (_cinemas_file);
- boost::filesystem::rename (_cinemas_file.string() + ".tmp", _cinemas_file);
+ doc.write_to_file_formatted (file.string() + ".tmp");
+ boost::filesystem::remove (file);
+ boost::filesystem::rename (file.string() + ".tmp", file);
} catch (xmlpp::exception& e) {
string s = e.what ();
trim (s);
- throw FileError (s, _cinemas_file);
+ throw FileError (s, file);
}
}
+
+void
+Config::write_cinemas () const
+{
+ write_file ("Cinemas", "Cinema", "1", _cinemas, _cinemas_file);
+}
+
+
+void
+Config::write_dkdm_recipients () const
+{
+ write_file ("DKDMRecipients", "DKDMRecipient", "1", _dkdm_recipients, _dkdm_recipients_file);
+}
+
+
boost::filesystem::path
Config::default_directory_or (boost::filesystem::path a) const
{
changed (OTHER);
}
+
+void
+Config::read_dkdm_recipients (cxml::Document const & f)
+{
+ _dkdm_recipients.clear ();
+ list<cxml::NodePtr> cin = f.node_children ("DKDMRecipient");
+ BOOST_FOREACH (cxml::ConstNodePtr i, f.node_children("DKDMRecipient")) {
+ _dkdm_recipients.push_back (shared_ptr<DKDMRecipient>(new DKDMRecipient(i)));
+ }
+}
+
+void
+Config::set_dkdm_recipients_file (boost::filesystem::path file)
+{
+ if (file == _dkdm_recipients_file) {
+ return;
+ }
+
+ _dkdm_recipients_file = file;
+
+ if (boost::filesystem::exists (_dkdm_recipients_file)) {
+ /* Existing file; read it in */
+ cxml::Document f ("DKDMRecipients");
+ f.read_file (_dkdm_recipients_file);
+ read_dkdm_recipients (f);
+ }
+
+ changed (OTHER);
+}
+
+
void
Config::save_template (shared_ptr<const Film> film, string name) const
{
class Cinema;
class Film;
class DKDMGroup;
+class DKDMRecipient;
/** @class Config
* @brief A singleton class holding configuration.
USE_ANY_SERVERS,
SERVERS,
CINEMAS,
+ DKDM_RECIPIENTS,
SOUND,
SOUND_OUTPUT,
INTERFACE_COMPLEXITY,
return _cinemas;
}
+ std::list<boost::shared_ptr<DKDMRecipient> > dkdm_recipients () const {
+ return _dkdm_recipients;
+ }
+
std::list<int> allowed_dcp_frame_rates () const {
return _allowed_dcp_frame_rates;
}
return _cinemas_file;
}
+ boost::filesystem::path dkdm_recipients_file () const {
+ return _dkdm_recipients_file;
+ }
+
bool show_hints_before_make_dcp () const {
return _show_hints_before_make_dcp;
}
return _kdm_filename_format;
}
+ dcp::NameFormat dkdm_filename_format () const {
+ return _dkdm_filename_format;
+ }
+
dcp::NameFormat dcp_metadata_filename_format () const {
return _dcp_metadata_filename_format;
}
changed (CINEMAS);
}
+ void add_dkdm_recipient (boost::shared_ptr<DKDMRecipient> c) {
+ _dkdm_recipients.push_back (c);
+ changed (DKDM_RECIPIENTS);
+ }
+
+ void remove_dkdm_recipient (boost::shared_ptr<DKDMRecipient> c) {
+ _dkdm_recipients.remove (c);
+ changed (DKDM_RECIPIENTS);
+ }
+
void set_allowed_dcp_frame_rates (std::list<int> const & r) {
maybe_set (_allowed_dcp_frame_rates, r);
}
void set_cinemas_file (boost::filesystem::path file);
+ void set_dkdm_recipients_file (boost::filesystem::path file);
+
void set_show_hints_before_make_dcp (bool s) {
maybe_set (_show_hints_before_make_dcp, s);
}
maybe_set (_kdm_filename_format, n);
}
+ void set_dkdm_filename_format (dcp::NameFormat n) {
+ maybe_set (_dkdm_filename_format, n);
+ }
+
void set_dcp_metadata_filename_format (dcp::NameFormat n) {
maybe_set (_dcp_metadata_filename_format, n);
}
void write () const;
void write_config () const;
void write_cinemas () const;
+ void write_dkdm_recipients () const;
void link (boost::filesystem::path new_file) const;
void copy_and_link (boost::filesystem::path new_file) const;
bool have_write_permission () const;
void set_notification_email_to_default ();
void set_cover_sheet_to_default ();
void read_cinemas (cxml::Document const & f);
+ void read_dkdm_recipients (cxml::Document const & f);
boost::shared_ptr<dcp::CertificateChain> create_certificate_chain ();
boost::filesystem::path directory_or (boost::optional<boost::filesystem::path> dir, boost::filesystem::path a) const;
void add_to_history_internal (std::vector<boost::filesystem::path>& h, boost::filesystem::path p);
boost::optional<boost::filesystem::path> _default_kdm_directory;
bool _default_upload_after_make_dcp;
std::list<boost::shared_ptr<Cinema> > _cinemas;
+ std::list<boost::shared_ptr<DKDMRecipient> > _dkdm_recipients;
std::string _mail_server;
int _mail_port;
EmailProtocol _mail_protocol;
std::vector<boost::filesystem::path> _player_history;
boost::shared_ptr<DKDMGroup> _dkdms;
boost::filesystem::path _cinemas_file;
+ boost::filesystem::path _dkdm_recipients_file;
bool _show_hints_before_make_dcp;
bool _confirm_kdm_email;
dcp::NameFormat _kdm_filename_format;
+ dcp::NameFormat _dkdm_filename_format;
dcp::NameFormat _kdm_container_name_format;
dcp::NameFormat _dcp_metadata_filename_format;
dcp::NameFormat _dcp_asset_filename_format;
#include "text_content.h"
#include "ffmpeg_content.h"
#include "dcp_content.h"
-#include "screen_kdm.h"
+#include "kdm_with_metadata.h"
#include "cinema.h"
#include "change_signaller.h"
#include "check_content_change_job.h"
).encrypt (signer, recipient, trusted_devices, formulation, disable_forensic_marking_picture, disable_forensic_marking_audio);
}
-/** @param screens Screens to make KDMs for.
- * @param cpl_file Path to CPL to make KDMs for.
- * @param from KDM from time expressed as a local time in the time zone of the Screen's Cinema.
- * @param until KDM to time expressed as a local time in the time zone of the Screen's Cinema.
- * @param formulation KDM formulation to use.
- * @param disable_forensic_marking_picture true to disable forensic marking of picture.
- * @param disable_forensic_marking_audio if not set, don't disable forensic marking of audio. If set to 0,
- * disable all forensic marking; if set above 0, disable forensic marking above that channel.
- */
-list<shared_ptr<ScreenKDM> >
-Film::make_kdms (
- list<shared_ptr<Screen> > screens,
- boost::filesystem::path cpl_file,
- boost::posix_time::ptime from,
- boost::posix_time::ptime until,
- dcp::Formulation formulation,
- bool disable_forensic_marking_picture,
- optional<int> disable_forensic_marking_audio
- ) const
-{
- list<shared_ptr<ScreenKDM> > kdms;
-
- BOOST_FOREACH (shared_ptr<Screen> i, screens) {
- if (i->recipient) {
- dcp::EncryptedKDM const kdm = make_kdm (
- i->recipient.get(),
- i->trusted_device_thumbprints(),
- cpl_file,
- dcp::LocalTime (from, i->cinema ? i->cinema->utc_offset_hour() : 0, i->cinema ? i->cinema->utc_offset_minute() : 0),
- dcp::LocalTime (until, i->cinema ? i->cinema->utc_offset_hour() : 0, i->cinema ? i->cinema->utc_offset_minute() : 0),
- formulation,
- disable_forensic_marking_picture,
- disable_forensic_marking_audio
- );
-
- kdms.push_back (shared_ptr<ScreenKDM>(new DCPScreenKDM(i, kdm)));
- }
- }
-
- return kdms;
-}
/** @return The approximate disk space required to encode a DCP of this film with the
* current settings, in bytes.
/*
- Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
class AudioMapping;
class Ratio;
class Job;
-class ScreenKDM;
class Film;
struct isdcf_name_test;
boost::optional<int> disable_forensic_marking_audio
) const;
- std::list<boost::shared_ptr<ScreenKDM> > make_kdms (
- std::list<boost::shared_ptr<dcpomatic::Screen> > screens,
- boost::filesystem::path cpl_file,
- boost::posix_time::ptime from,
- boost::posix_time::ptime until,
- dcp::Formulation formulation,
- bool disable_forensic_marking_picture,
- boost::optional<int> disable_forensic_marking_audio
- ) const;
-
int state_version () const {
return _state_version;
}
--- /dev/null
+/*
+ Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "kdm_recipient.h"
+
+KDMRecipient::KDMRecipient (cxml::ConstNodePtr node)
+ : name (node->string_child("Name"))
+ , notes (node->optional_string_child("Notes").get_value_or (""))
+{
+ if (node->optional_string_child("Certificate")) {
+ recipient = dcp::Certificate (node->string_child("Certificate"));
+ } else if (node->optional_string_child("Recipient")) {
+ recipient = dcp::Certificate (node->string_child("Recipient"));
+ }
+}
+
+
+void
+KDMRecipient::as_xml (xmlpp::Element* parent) const
+{
+ parent->add_child("Name")->add_child_text(name);
+ if (recipient) {
+ parent->add_child("Recipient")->add_child_text(recipient->certificate(true));
+ }
+
+ parent->add_child("Notes")->add_child_text(notes);
+}
+
--- /dev/null
+/*
+ Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef DCPOMATIC_KDM_RECIPIENT_H
+#define DCPOMATIC_KDM_RECIPIENT_H
+
+#include <dcp/certificate.h>
+#include <libcxml/cxml.h>
+#include <libxml++/libxml++.h>
+#include <boost/optional.hpp>
+#include <string>
+
+class KDMRecipient
+{
+public:
+ KDMRecipient (std::string const& name_, std::string const& notes_, boost::optional<dcp::Certificate> recipient_)
+ : name (name_)
+ , notes (notes_)
+ , recipient (recipient_)
+ {}
+
+ explicit KDMRecipient (cxml::ConstNodePtr);
+
+ virtual void as_xml (xmlpp::Element *) const;
+
+ std::string name;
+ std::string notes;
+ boost::optional<dcp::Certificate> recipient;
+};
+
+#endif
--- /dev/null
+/*
+ Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "kdm_with_metadata.h"
+#include "cinema.h"
+#include "screen.h"
+#include "util.h"
+#include "zipper.h"
+#include "config.h"
+#include "dcpomatic_log.h"
+#include "emailer.h"
+#include <boost/foreach.hpp>
+#include <boost/function.hpp>
+#include <boost/function.hpp>
+
+#include "i18n.h"
+
+using std::string;
+using std::cout;
+using std::list;
+using boost::shared_ptr;
+using boost::optional;
+using boost::function;
+
+int
+write_files (
+ list<KDMWithMetadataPtr> kdms,
+ boost::filesystem::path directory,
+ dcp::NameFormat name_format,
+ boost::function<bool (boost::filesystem::path)> confirm_overwrite
+ )
+{
+ int written = 0;
+
+ if (directory == "-") {
+ /* Write KDMs to the stdout */
+ BOOST_FOREACH (KDMWithMetadataPtr i, kdms) {
+ cout << i->kdm_as_xml ();
+ ++written;
+ }
+
+ return written;
+ }
+
+ if (!boost::filesystem::exists (directory)) {
+ boost::filesystem::create_directories (directory);
+ }
+
+ /* Write KDMs to the specified directory */
+ BOOST_FOREACH (KDMWithMetadataPtr i, kdms) {
+ boost::filesystem::path out = directory / careful_string_filter(name_format.get(i->name_values(), ".xml"));
+ if (!boost::filesystem::exists (out) || confirm_overwrite (out)) {
+ i->kdm_as_xml (out);
+ ++written;
+ }
+ }
+
+ return written;
+}
+
+
+optional<string>
+KDMWithMetadata::get (char k) const
+{
+ dcp::NameFormat::Map::const_iterator i = _name_values.find (k);
+ if (i == _name_values.end()) {
+ return optional<string>();
+ }
+
+ return i->second;
+}
+
+
+void
+make_zip_file (list<KDMWithMetadataPtr> kdms, boost::filesystem::path zip_file, dcp::NameFormat name_format)
+{
+ Zipper zipper (zip_file);
+
+ BOOST_FOREACH (KDMWithMetadataPtr i, kdms) {
+ string const name = careful_string_filter(name_format.get(i->name_values(), ".xml"));
+ zipper.add (name, i->kdm_as_xml());
+ }
+
+ zipper.close ();
+}
+
+
+/** Collect a list of KDMWithMetadatas into a list of lists so that
+ * each list contains the KDMs for one list.
+ */
+list<list<KDMWithMetadataPtr> >
+collect (list<KDMWithMetadataPtr> kdms)
+{
+ list<list<KDMWithMetadataPtr> > grouped;
+
+ BOOST_FOREACH (KDMWithMetadataPtr i, kdms) {
+
+ list<list<KDMWithMetadataPtr> >::iterator j = grouped.begin ();
+
+ while (j != grouped.end()) {
+ if (j->front()->group() == i->group()) {
+ j->push_back (i);
+ break;
+ }
+ ++j;
+ }
+
+ if (j == grouped.end()) {
+ grouped.push_back (list<KDMWithMetadataPtr>());
+ grouped.back().push_back (i);
+ }
+ }
+
+ return grouped;
+}
+
+
+/** Write one directory per list into another directory */
+int
+write_directories (
+ list<list<KDMWithMetadataPtr> > kdms,
+ boost::filesystem::path directory,
+ dcp::NameFormat container_name_format,
+ dcp::NameFormat filename_format,
+ function<bool (boost::filesystem::path)> confirm_overwrite
+ )
+{
+ int written = 0;
+
+ BOOST_FOREACH (list<KDMWithMetadataPtr> const & i, kdms) {
+ boost::filesystem::path path = directory;
+ path /= container_name_format.get(i.front()->name_values(), "", "s");
+ if (!boost::filesystem::exists (path) || confirm_overwrite (path)) {
+ boost::filesystem::create_directories (path);
+ write_files (i, path, filename_format, confirm_overwrite);
+ }
+ written += i.size();
+ }
+
+ return written;
+}
+
+
+/** Write one ZIP file per cinema into a directory */
+int
+write_zip_files (
+ list<list<KDMWithMetadataPtr> > kdms,
+ boost::filesystem::path directory,
+ dcp::NameFormat container_name_format,
+ dcp::NameFormat filename_format,
+ function<bool (boost::filesystem::path)> confirm_overwrite
+ )
+{
+ int written = 0;
+
+ BOOST_FOREACH (list<KDMWithMetadataPtr> const & i, kdms) {
+ boost::filesystem::path path = directory;
+ path /= container_name_format.get(i.front()->name_values(), ".zip", "s");
+ if (!boost::filesystem::exists (path) || confirm_overwrite (path)) {
+ if (boost::filesystem::exists (path)) {
+ /* Creating a new zip file over an existing one is an error */
+ boost::filesystem::remove (path);
+ }
+ make_zip_file (i, path, filename_format);
+ written += i.size();
+ }
+ }
+
+ return written;
+}
+
+
+/** Email one ZIP file per cinema to the cinema.
+ * @param kdms KDMs to email.
+ * @param container_name_format Format of folder / ZIP to use.
+ * @param filename_format Format of filenames to use.
+ * @param name_values Values to substitute into \p container_name_format and \p filename_format.
+ * @param cpl_name Name of the CPL that the KDMs are for.
+ */
+void
+email (
+ list<list<KDMWithMetadataPtr> > kdms,
+ dcp::NameFormat container_name_format,
+ dcp::NameFormat filename_format,
+ string cpl_name
+ )
+{
+ Config* config = Config::instance ();
+
+ if (config->mail_server().empty()) {
+ throw NetworkError (_("No mail server configured in preferences"));
+ }
+
+ BOOST_FOREACH (list<KDMWithMetadataPtr> const & i, kdms) {
+
+ if (i.front()->emails().empty()) {
+ continue;
+ }
+
+ boost::filesystem::path zip_file = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
+ boost::filesystem::create_directories (zip_file);
+ zip_file /= container_name_format.get(i.front()->name_values(), ".zip");
+ make_zip_file (i, zip_file, filename_format);
+
+ string subject = config->kdm_subject();
+ boost::algorithm::replace_all (subject, "$CPL_NAME", cpl_name);
+ boost::algorithm::replace_all (subject, "$START_TIME", i.front()->get('b').get_value_or(""));
+ boost::algorithm::replace_all (subject, "$END_TIME", i.front()->get('e').get_value_or(""));
+ boost::algorithm::replace_all (subject, "$CINEMA_NAME", i.front()->get('c').get_value_or(""));
+
+ string body = config->kdm_email().c_str();
+ boost::algorithm::replace_all (body, "$CPL_NAME", cpl_name);
+ boost::algorithm::replace_all (body, "$START_TIME", i.front()->get('b').get_value_or(""));
+ boost::algorithm::replace_all (body, "$END_TIME", i.front()->get('e').get_value_or(""));
+ boost::algorithm::replace_all (body, "$CINEMA_NAME", i.front()->get('c').get_value_or(""));
+
+ string screens;
+ BOOST_FOREACH (KDMWithMetadataPtr j, i) {
+ optional<string> screen_name = j->get('n');
+ if (screen_name) {
+ screens += *screen_name + ", ";
+ }
+ }
+ boost::algorithm::replace_all (body, "$SCREENS", screens.substr (0, screens.length() - 2));
+
+ Emailer email (config->kdm_from(), i.front()->emails(), subject, body);
+
+ BOOST_FOREACH (string i, config->kdm_cc()) {
+ email.add_cc (i);
+ }
+ if (!config->kdm_bcc().empty ()) {
+ email.add_bcc (config->kdm_bcc ());
+ }
+
+ email.add_attachment (zip_file, container_name_format.get(i.front()->name_values(), ".zip"), "application/zip");
+
+ Config* c = Config::instance ();
+
+ try {
+ email.send (c->mail_server(), c->mail_port(), c->mail_protocol(), c->mail_user(), c->mail_password());
+ } catch (...) {
+ boost::filesystem::remove (zip_file);
+ dcpomatic_log->log ("Email content follows", LogEntry::TYPE_DEBUG_EMAIL);
+ dcpomatic_log->log (email.email(), LogEntry::TYPE_DEBUG_EMAIL);
+ dcpomatic_log->log ("Email session follows", LogEntry::TYPE_DEBUG_EMAIL);
+ dcpomatic_log->log (email.notes(), LogEntry::TYPE_DEBUG_EMAIL);
+ throw;
+ }
+
+ boost::filesystem::remove (zip_file);
+
+ dcpomatic_log->log ("Email content follows", LogEntry::TYPE_DEBUG_EMAIL);
+ dcpomatic_log->log (email.email(), LogEntry::TYPE_DEBUG_EMAIL);
+ dcpomatic_log->log ("Email session follows", LogEntry::TYPE_DEBUG_EMAIL);
+ dcpomatic_log->log (email.notes(), LogEntry::TYPE_DEBUG_EMAIL);
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef DCPOMATIC_KDM_WITH_METADATA_H
+#define DCPOMATIC_KDM_WITH_METADATA_H
+
+#ifdef DCPOMATIC_VARIANT_SWAROOP
+#include "encrypted_ecinema_kdm.h"
+#endif
+#include <dcp/encrypted_kdm.h>
+#include <dcp/name_format.h>
+#include <boost/shared_ptr.hpp>
+
+class Cinema;
+
+class KDMWithMetadata
+{
+public:
+ KDMWithMetadata (dcp::NameFormat::Map const& name_values, void const* group, std::list<std::string> emails)
+ : _name_values (name_values)
+ , _group (group)
+ , _emails (emails)
+ {}
+
+ virtual ~KDMWithMetadata () {}
+
+ virtual std::string kdm_as_xml () const = 0;
+ virtual void kdm_as_xml (boost::filesystem::path out) const = 0;
+
+ dcp::NameFormat::Map const& name_values () const {
+ return _name_values;
+ }
+
+ boost::optional<std::string> get (char k) const;
+
+ void const* group () const {
+ return _group;
+ }
+
+ std::list<std::string> emails () const {
+ return _emails;
+ }
+
+private:
+ dcp::NameFormat::Map _name_values;
+ void const* _group;
+ std::list<std::string> _emails;
+};
+
+
+typedef boost::shared_ptr<KDMWithMetadata> KDMWithMetadataPtr;
+
+
+int write_files (
+ std::list<KDMWithMetadataPtr> screen_kdms, boost::filesystem::path directory,
+ dcp::NameFormat name_format, boost::function<bool (boost::filesystem::path)> confirm_overwrite
+ );
+
+
+void make_zip_file (std::list<KDMWithMetadataPtr> kdms, boost::filesystem::path zip_file, dcp::NameFormat name_format);
+
+
+std::list<std::list<KDMWithMetadataPtr> > collect (std::list<KDMWithMetadataPtr> kdms);
+
+
+int write_directories (
+ std::list<std::list<KDMWithMetadataPtr> > kdms,
+ boost::filesystem::path directory,
+ dcp::NameFormat container_name_format,
+ dcp::NameFormat filename_format,
+ boost::function<bool (boost::filesystem::path)> confirm_overwrite
+ );
+
+
+int write_zip_files (
+ std::list<std::list<KDMWithMetadataPtr> > kdms,
+ boost::filesystem::path directory,
+ dcp::NameFormat container_name_format,
+ dcp::NameFormat filename_format,
+ boost::function<bool (boost::filesystem::path)> confirm_overwrite
+ );
+
+
+void email (
+ std::list<std::list<KDMWithMetadataPtr> > kdms,
+ dcp::NameFormat container_name_format,
+ dcp::NameFormat filename_format,
+ std::string cpl_name
+ );
+
+
+template <class T>
+class SpecialKDMWithMetadata : public KDMWithMetadata
+{
+public:
+ SpecialKDMWithMetadata (dcp::NameFormat::Map const& name_values, void const* group, std::list<std::string> emails, T k)
+ : KDMWithMetadata (name_values, group, emails)
+ , kdm (k)
+ {}
+
+ std::string kdm_as_xml () const {
+ return kdm.as_xml ();
+ }
+
+ void kdm_as_xml (boost::filesystem::path out) const {
+ return kdm.as_xml (out);
+ }
+
+ T kdm;
+};
+
+typedef SpecialKDMWithMetadata<dcp::EncryptedKDM> DCPKDMWithMetadata;
+#ifdef DCPOMATIC_VARIANT_SWAROOP
+typedef SpecialKDMWithMetadata<EncryptedECinemaKDM> ECinemaKDMWithMetadata;
+#endif
+
+#endif
+
/*
- Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2020 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
*/
#include "screen.h"
+#include "kdm_with_metadata.h"
+#include "film.h"
+#include "cinema.h"
#include <libxml++/libxml++.h>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
using std::string;
using std::vector;
+using std::list;
+using boost::shared_ptr;
+using boost::optional;
using namespace dcpomatic;
Screen::Screen (cxml::ConstNodePtr node)
- : name (node->string_child("Name"))
- , notes (node->optional_string_child("Notes").get_value_or (""))
+ : KDMRecipient (node)
{
- if (node->optional_string_child ("Certificate")) {
- recipient = dcp::Certificate (node->string_child ("Certificate"));
- } else if (node->optional_string_child ("Recipient")) {
- recipient = dcp::Certificate (node->string_child ("Recipient"));
- }
-
BOOST_FOREACH (cxml::ConstNodePtr i, node->node_children ("TrustedDevice")) {
if (boost::algorithm::starts_with(i->content(), "-----BEGIN CERTIFICATE-----")) {
trusted_devices.push_back (TrustedDevice(dcp::Certificate(i->content())));
void
Screen::as_xml (xmlpp::Element* parent) const
{
- parent->add_child("Name")->add_child_text (name);
- if (recipient) {
- parent->add_child("Recipient")->add_child_text (recipient->certificate (true));
- }
-
- parent->add_child("Notes")->add_child_text (notes);
-
+ KDMRecipient::as_xml (parent);
BOOST_FOREACH (TrustedDevice i, trusted_devices) {
parent->add_child("TrustedDevice")->add_child_text(i.as_string());
}
return t;
}
-TrustedDevice::TrustedDevice (string thumbprint)
- : _thumbprint (thumbprint)
-{
-
-}
-
-TrustedDevice::TrustedDevice (dcp::Certificate certificate)
- : _certificate (certificate)
-{
-
-}
-string
-TrustedDevice::as_string () const
+KDMWithMetadataPtr
+kdm_for_screen (
+ shared_ptr<const Film> film,
+ boost::filesystem::path cpl,
+ shared_ptr<const dcpomatic::Screen> screen,
+ boost::posix_time::ptime valid_from,
+ boost::posix_time::ptime valid_to,
+ dcp::Formulation formulation,
+ bool disable_forensic_marking_picture,
+ optional<int> disable_forensic_marking_audio
+ )
{
- if (_certificate) {
- return _certificate->certificate(true);
+ if (!screen->recipient) {
+ return KDMWithMetadataPtr();
}
- return *_thumbprint;
-}
-
-string
-TrustedDevice::thumbprint () const
-{
- if (_certificate) {
- return _certificate->thumbprint ();
+ shared_ptr<const Cinema> cinema = screen->cinema;
+ dcp::LocalTime const begin(valid_from, cinema ? cinema->utc_offset_hour() : 0, cinema ? cinema->utc_offset_minute() : 0);
+ dcp::LocalTime const end (valid_to, cinema ? cinema->utc_offset_hour() : 0, cinema ? cinema->utc_offset_minute() : 0);
+
+ dcp::EncryptedKDM const kdm = film->make_kdm (
+ screen->recipient.get(),
+ screen->trusted_device_thumbprints(),
+ cpl,
+ begin,
+ end,
+ formulation,
+ disable_forensic_marking_picture,
+ disable_forensic_marking_audio
+ );
+
+ dcp::NameFormat::Map name_values;
+ if (cinema) {
+ name_values['c'] = cinema->name;
}
+ name_values['s'] = screen->name;
+ name_values['f'] = film->name();
+ name_values['b'] = begin.date() + " " + begin.time_of_day(true, false);
+ name_values['e'] = end.date() + " " + end.time_of_day(true, false);
+ name_values['i'] = kdm.cpl_id();
- return *_thumbprint;
+ return KDMWithMetadataPtr(new DCPKDMWithMetadata(name_values, cinema.get(), cinema ? cinema->emails : list<string>(), kdm));
}
+
#ifndef DCPOMATIC_SCREEN_H
#define DCPOMATIC_SCREEN_H
+#include "kdm_with_metadata.h"
+#include "kdm_recipient.h"
+#include "trusted_device.h"
#include <dcp/certificate.h>
#include <libcxml/cxml.h>
#include <boost/optional.hpp>
#include <string>
class Cinema;
-
-class TrustedDevice
-{
-public:
- explicit TrustedDevice (std::string);
- explicit TrustedDevice (dcp::Certificate);
-
- boost::optional<dcp::Certificate> certificate () const {
- return _certificate;
- }
-
- std::string thumbprint () const;
- std::string as_string () const;
-
-private:
- boost::optional<dcp::Certificate> _certificate;
- boost::optional<std::string> _thumbprint;
-};
+class Film;
namespace dcpomatic {
* `recipient' (i.e. the mediablock) and the certificates/thumbprints
* of any trusted devices.
*/
-class Screen
+class Screen : public KDMRecipient
{
public:
- Screen (std::string const & na, std::string const & no, boost::optional<dcp::Certificate> rec, std::vector<TrustedDevice> td)
- : name (na)
- , notes (no)
- , recipient (rec)
- , trusted_devices (td)
+ Screen (std::string const & name_, std::string const & notes_, boost::optional<dcp::Certificate> recipient_, std::vector<TrustedDevice> trusted_devices_)
+ : KDMRecipient (name_, notes_, recipient_)
+ , trusted_devices (trusted_devices_)
{}
explicit Screen (cxml::ConstNodePtr);
std::vector<std::string> trusted_device_thumbprints () const;
boost::shared_ptr<Cinema> cinema;
- std::string name;
- std::string notes;
- boost::optional<dcp::Certificate> recipient;
std::vector<TrustedDevice> trusted_devices;
};
}
+KDMWithMetadataPtr
+kdm_for_screen (
+ boost::shared_ptr<const Film> film,
+ boost::filesystem::path cpl,
+ boost::shared_ptr<const dcpomatic::Screen> screen,
+ boost::posix_time::ptime valid_from,
+ boost::posix_time::ptime valid_to,
+ dcp::Formulation formulation,
+ bool disable_forensic_marking_picture,
+ boost::optional<int> disable_forensic_marking_audio
+ );
+
+
#endif
+++ /dev/null
-/*
- Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
-
- This file is part of DCP-o-matic.
-
- DCP-o-matic is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- DCP-o-matic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include "screen_kdm.h"
-#include "cinema.h"
-#include "screen.h"
-#include "util.h"
-#include <boost/foreach.hpp>
-
-using std::string;
-using std::cout;
-using std::list;
-using boost::shared_ptr;
-
-int
-ScreenKDM::write_files (
- list<shared_ptr<ScreenKDM> > screen_kdms,
- boost::filesystem::path directory,
- dcp::NameFormat name_format,
- dcp::NameFormat::Map name_values,
- boost::function<bool (boost::filesystem::path)> confirm_overwrite
- )
-{
- int written = 0;
-
- if (directory == "-") {
- /* Write KDMs to the stdout */
- BOOST_FOREACH (shared_ptr<ScreenKDM> i, screen_kdms) {
- cout << i->kdm_as_xml ();
- ++written;
- }
-
- return written;
- }
-
- if (!boost::filesystem::exists (directory)) {
- boost::filesystem::create_directories (directory);
- }
-
- /* Write KDMs to the specified directory */
- BOOST_FOREACH (shared_ptr<ScreenKDM> i, screen_kdms) {
- name_values['c'] = i->screen->cinema ? i->screen->cinema->name : "";
- name_values['s'] = i->screen->name;
- name_values['i'] = i->kdm_id ();
- boost::filesystem::path out = directory / careful_string_filter(name_format.get(name_values, ".xml"));
- if (!boost::filesystem::exists (out) || confirm_overwrite (out)) {
- i->kdm_as_xml (out);
- ++written;
- }
- }
-
- return written;
-}
+++ /dev/null
-/*
- Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
-
- This file is part of DCP-o-matic.
-
- DCP-o-matic is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- DCP-o-matic is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef DCPOMATIC_SCREEN_KDM_H
-#define DCPOMATIC_SCREEN_KDM_H
-
-#ifdef DCPOMATIC_VARIANT_SWAROOP
-#include "encrypted_ecinema_kdm.h"
-#endif
-#include <dcp/encrypted_kdm.h>
-#include <dcp/name_format.h>
-#include <boost/shared_ptr.hpp>
-
-namespace dcpomatic {
- class Screen;
-}
-
-/** Simple class to collect a screen and an encrypted KDM */
-class ScreenKDM
-{
-public:
- ScreenKDM (boost::shared_ptr<dcpomatic::Screen> s)
- : screen (s)
- {}
-
- virtual ~ScreenKDM () {}
-
- virtual std::string kdm_as_xml () const = 0;
- virtual void kdm_as_xml (boost::filesystem::path out) const = 0;
- virtual std::string kdm_id () const = 0;
-
- static int write_files (
- std::list<boost::shared_ptr<ScreenKDM> > screen_kdms, boost::filesystem::path directory,
- dcp::NameFormat name_format, dcp::NameFormat::Map name_values,
- boost::function<bool (boost::filesystem::path)> confirm_overwrite
- );
-
- boost::shared_ptr<dcpomatic::Screen> screen;
-};
-
-class DCPScreenKDM : public ScreenKDM
-{
-public:
- DCPScreenKDM (boost::shared_ptr<dcpomatic::Screen> s, dcp::EncryptedKDM k)
- : ScreenKDM (s)
- , kdm (k)
- {}
-
- std::string kdm_as_xml () const {
- return kdm.as_xml ();
- }
-
- void kdm_as_xml (boost::filesystem::path out) const {
- return kdm.as_xml (out);
- }
-
- std::string kdm_id () const {
- return kdm.cpl_id ();
- }
-
- dcp::EncryptedKDM kdm;
-};
-
-#ifdef DCPOMATIC_VARIANT_SWAROOP
-class ECinemaScreenKDM : public ScreenKDM
-{
-public:
- ECinemaScreenKDM (boost::shared_ptr<dcpomatic::Screen> s, EncryptedECinemaKDM k)
- : ScreenKDM (s)
- , kdm (k)
- {}
-
- std::string kdm_as_xml () const {
- return kdm.as_xml ();
- }
-
- void kdm_as_xml (boost::filesystem::path out) const {
- return kdm.as_xml (out);
- }
-
- std::string kdm_id () const {
- return kdm.id ();
- }
-
- EncryptedECinemaKDM kdm;
-};
-#endif
-
-#endif
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2020 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include "send_kdm_email_job.h"
#include "compose.hpp"
+#include "kdm_with_metadata.h"
#include "film.h"
-#include "cinema_kdms.h"
#include <list>
#include "i18n.h"
using std::string;
using std::list;
using boost::shared_ptr;
+using boost::optional;
-/** @param cinema_kdms KDMs to email.
+SendKDMEmailJob::SendKDMEmailJob (
+ list<KDMWithMetadataPtr> kdms,
+ dcp::NameFormat container_name_format,
+ dcp::NameFormat filename_format,
+ string cpl_name
+ )
+ : Job (shared_ptr<Film>())
+ , _container_name_format (container_name_format)
+ , _filename_format (filename_format)
+ , _cpl_name (cpl_name)
+{
+ BOOST_FOREACH (KDMWithMetadataPtr i, kdms) {
+ list<KDMWithMetadataPtr> s;
+ s.push_back (i);
+ _kdms.push_back (s);
+ }
+}
+
+/** @param kdms KDMs to email.
* @param container_name_format Format to ues for folders / ZIP files.
* @param filename_format Format to use for filenames.
* @param name_values Values to substitute into \p container_name_format and \p filename_format.
* @param cpl_name Name of the CPL that the KDMs are for.
*/
SendKDMEmailJob::SendKDMEmailJob (
- list<CinemaKDMs> cinema_kdms,
+ list<list<KDMWithMetadataPtr> > kdms,
dcp::NameFormat container_name_format,
dcp::NameFormat filename_format,
- dcp::NameFormat::Map name_values,
string cpl_name
)
: Job (shared_ptr<Film>())
, _container_name_format (container_name_format)
, _filename_format (filename_format)
- , _name_values (name_values)
, _cpl_name (cpl_name)
- , _cinema_kdms (cinema_kdms)
+ , _kdms (kdms)
{
}
string
SendKDMEmailJob::name () const
{
- dcp::NameFormat::Map::const_iterator i = _name_values.find ('f');
- if (i == _name_values.end() || i->second.empty ()) {
+ optional<string> f = _kdms.front().front()->get('f');
+ if (!f || f->empty()) {
return _("Email KDMs");
}
- return String::compose (_("Email KDMs for %1"), i->second);
+ return String::compose (_("Email KDMs for %2"), *f);
}
string
SendKDMEmailJob::run ()
{
set_progress_unknown ();
- CinemaKDMs::email (_cinema_kdms, _container_name_format, _filename_format, _name_values, _cpl_name);
+ email (_kdms, _container_name_format, _filename_format, _cpl_name);
set_progress (1);
set_state (FINISHED_OK);
}
*/
#include "job.h"
+#include "kdm_with_metadata.h"
#include <dcp/types.h>
#include <dcp/name_format.h>
#include <boost/filesystem.hpp>
class Screen;
}
-class CinemaKDMs;
class Log;
class SendKDMEmailJob : public Job
{
public:
SendKDMEmailJob (
- std::list<CinemaKDMs> cinema_kdms,
+ std::list<KDMWithMetadataPtr> kdms,
dcp::NameFormat container_name_format,
dcp::NameFormat filename_format,
- dcp::NameFormat::Map name_values,
std::string cpl_name
);
+
+ SendKDMEmailJob (
+ std::list<std::list<KDMWithMetadataPtr> > kdms,
+ dcp::NameFormat container_name_format,
+ dcp::NameFormat filename_format,
+ std::string cpl_name
+ );
+
~SendKDMEmailJob ();
std::string name () const;
private:
dcp::NameFormat _container_name_format;
dcp::NameFormat _filename_format;
- dcp::NameFormat::Map _name_values;
std::string _cpl_name;
- std::list<CinemaKDMs> _cinema_kdms;
+ std::list<std::list<KDMWithMetadataPtr> > _kdms;
};
--- /dev/null
+/*
+ Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "trusted_device.h"
+
+using std::string;
+
+TrustedDevice::TrustedDevice (string thumbprint)
+ : _thumbprint (thumbprint)
+{
+
+}
+
+TrustedDevice::TrustedDevice (dcp::Certificate certificate)
+ : _certificate (certificate)
+{
+
+}
+
+string
+TrustedDevice::as_string () const
+{
+ if (_certificate) {
+ return _certificate->certificate(true);
+ }
+
+ return *_thumbprint;
+}
+
+string
+TrustedDevice::thumbprint () const
+{
+ if (_certificate) {
+ return _certificate->thumbprint ();
+ }
+
+ return *_thumbprint;
+}
+
--- /dev/null
+/*
+ Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef DCPOMATIC_TRUSTED_DEVICE_H
+#define DCPOMATIC_TRUSTED_DEVICE_H
+
+#include <dcp/certificate.h>
+#include <boost/optional.hpp>
+#include <string>
+
+class TrustedDevice
+{
+public:
+ explicit TrustedDevice (std::string);
+ explicit TrustedDevice (dcp::Certificate);
+
+ boost::optional<dcp::Certificate> certificate () const {
+ return _certificate;
+ }
+
+ std::string thumbprint () const;
+ std::string as_string () const;
+
+private:
+ boost::optional<dcp::Certificate> _certificate;
+ boost::optional<std::string> _thumbprint;
+};
+
+#endif
checker.cc
check_content_change_job.cc
cinema.cc
- cinema_kdms.cc
cinema_sound_processor.cc
colour_conversion.cc
config.cc
decoder_part.cc
decrypted_ecinema_kdm.cc
digester.cc
+ dkdm_recipient.cc
dkdm_wrapper.cc
dolby_cp750.cc
edid.cc
job_manager.cc
j2k_encoder.cc
json_server.cc
+ kdm_with_metadata.cc
+ kdm_recipient.cc
lock_file_checker.cc
log.cc
log_entry.cc
scoped_temporary.cc
scp_uploader.cc
screen.cc
- screen_kdm.cc
send_kdm_email_job.cc
send_notification_email_job.cc
send_problem_report_job.cc
text_ring_buffers.cc
timer.cc
transcode_job.cc
+ trusted_device.cc
types.cc
signal_manager.cc
stdout_log.cc
#include "wx/recreate_chain_dialog.h"
#include "wx/about_dialog.h"
#include "wx/kdm_dialog.h"
+#include "wx/dkdm_dialog.h"
#include "wx/self_dkdm_dialog.h"
#include "wx/servers_list_dialog.h"
#include "wx/hints_dialog.h"
#include "lib/job_manager.h"
#include "lib/exceptions.h"
#include "lib/cinema.h"
-#include "lib/screen_kdm.h"
+#include "lib/kdm_with_metadata.h"
#include "lib/send_kdm_email_job.h"
#include "lib/encode_server_finder.h"
#include "lib/update_checker.h"
#include "lib/cross.h"
#include "lib/content_factory.h"
#include "lib/compose.hpp"
-#include "lib/cinema_kdms.h"
#include "lib/dcpomatic_socket.h"
#include "lib/hints.h"
#include "lib/dcp_content.h"
ID_jobs_make_dcp,
ID_jobs_make_dcp_batch,
ID_jobs_make_kdms,
+ ID_jobs_make_dkdms,
ID_jobs_make_self_dkdm,
ID_jobs_export,
ID_jobs_send_dcp_to_tms,
, _servers_list_dialog (0)
, _config_dialog (0)
, _kdm_dialog (0)
+ , _dkdm_dialog (0)
, _templates_dialog (0)
, _file_menu (0)
, _history_items (0)
Bind (wxEVT_MENU, boost::bind (&DOMFrame::content_scale_to_fit_height, this), ID_content_scale_to_fit_height);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_dcp, this), ID_jobs_make_dcp);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_kdms, this), ID_jobs_make_kdms);
+ Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_dkdms, this), ID_jobs_make_dkdms);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_dcp_batch, this), ID_jobs_make_dcp_batch);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_make_self_dkdm, this), ID_jobs_make_self_dkdm);
Bind (wxEVT_MENU, boost::bind (&DOMFrame::jobs_export, this), ID_jobs_export);
_kdm_dialog->Show ();
}
+ void jobs_make_dkdms ()
+ {
+ if (!_film) {
+ return;
+ }
+
+ if (_dkdm_dialog) {
+ _dkdm_dialog->Destroy ();
+ _dkdm_dialog = 0;
+ }
+
+ _dkdm_dialog = new DKDMDialog (this, _film);
+ _dkdm_dialog->Show ();
+ }
+
/** @return false if we succeeded, true if not */
bool send_to_other_tool (int port, function<void(boost::filesystem::path)> start, string message)
{
add_item (jobs_menu, _("Make DCP in &batch converter\tCtrl-B"), ID_jobs_make_dcp_batch, NEEDS_FILM | NOT_DURING_DCP_CREATION);
jobs_menu->AppendSeparator ();
add_item (jobs_menu, _("Make &KDMs...\tCtrl-K"), ID_jobs_make_kdms, NEEDS_FILM);
+ add_item (jobs_menu, _("Make &DKDMs...\tCtrl-D"), ID_jobs_make_dkdms, NEEDS_FILM);
add_item (jobs_menu, _("Make DKDM for DCP-o-matic..."), ID_jobs_make_self_dkdm, NEEDS_FILM | NEEDS_ENCRYPTION);
jobs_menu->AppendSeparator ();
add_item (jobs_menu, _("Export...\tCtrl-E"), ID_jobs_export, NEEDS_FILM);
ServersListDialog* _servers_list_dialog;
wxPreferencesEditor* _config_dialog;
KDMDialog* _kdm_dialog;
+ DKDMDialog* _dkdm_dialog;
TemplatesDialog* _templates_dialog;
wxMenu* _file_menu;
shared_ptr<Film> _film;
#include "lib/util.h"
#include "lib/screen.h"
#include "lib/job_manager.h"
-#include "lib/screen_kdm.h"
+#include "lib/kdm_with_metadata.h"
#include "lib/exceptions.h"
-#include "lib/cinema_kdms.h"
#include "lib/send_kdm_email_job.h"
#include "lib/compose.hpp"
#include "lib/cinema.h"
return;
}
- list<shared_ptr<ScreenKDM> > screen_kdms;
+ list<KDMWithMetadataPtr> kdms;
string title;
#ifdef DCPOMATIC_VARIANT_SWAROOP
continue;
}
+ dcp::LocalTime begin(_timing->from(), i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute());
+ dcp::LocalTime end(_timing->until(), i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute());
+
DecryptedECinemaKDM kdm (
decrypted.id(),
decrypted.name(),
decrypted.key(),
- dcp::LocalTime (_timing->from(), i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
- dcp::LocalTime (_timing->until(), i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute())
+ begin,
+ end
);
+ dcp::NameFormat::Map name_values;
+ name_values['c'] = i->cinema->name;
+ name_values['s'] = i->name;
+ name_values['f'] = title;
+ name_values['b'] = begin.date() + " " + begin.time_of_day(true, false);
+ name_values['e'] = end.date() + " " + end.time_of_day(true, false);
+ name_values['i'] = kdm.id();
+
/* Encrypt */
- screen_kdms.push_back (
- shared_ptr<ScreenKDM>(
- new ECinemaScreenKDM(i, kdm.encrypt(i->recipient.get()))
+ kdms.push_back (
+ KDMWithMetadataPtr(
+ new ECinemaKDMWithMetadata(name_values, i->cinema, kdm.encrypt(i->recipient.get()))
)
);
}
continue;
}
+ dcp::LocalTime begin(_timing->from(), i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute());
+ dcp::LocalTime end(_timing->until(), i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute());
+
/* Make an empty KDM */
dcp::DecryptedKDM kdm (
- dcp::LocalTime (_timing->from(), i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
- dcp::LocalTime (_timing->until(), i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
+ begin,
+ end,
decrypted.annotation_text().get_value_or (""),
decrypted.content_title_text(),
dcp::LocalTime().as_string()
kdm.add_key (j);
}
+ dcp::EncryptedKDM const encrypted = kdm.encrypt(
+ signer, i->recipient.get(), i->trusted_device_thumbprints(), _output->formulation(),
+ !_output->forensic_mark_video(), _output->forensic_mark_audio() ? boost::optional<int>() : 0
+ );
+
+ dcp::NameFormat::Map name_values;
+ name_values['c'] = i->cinema->name;
+ name_values['s'] = i->name;
+ name_values['f'] = title;
+ name_values['b'] = begin.date() + " " + begin.time_of_day(true, false);
+ name_values['e'] = end.date() + " " + end.time_of_day(true, false);
+ name_values['i'] = encrypted.cpl_id ();
+
/* Encrypt */
- screen_kdms.push_back (
- shared_ptr<ScreenKDM>(
- new DCPScreenKDM(
- i,
- kdm.encrypt(
- signer, i->recipient.get(), i->trusted_device_thumbprints(), _output->formulation(),
- !_output->forensic_mark_video(), _output->forensic_mark_audio() ? boost::optional<int>() : 0
- )
- )
+ kdms.push_back (
+ KDMWithMetadataPtr(
+ new DCPKDMWithMetadata(name_values, i->cinema.get(), i->cinema->emails, encrypted)
)
);
}
}
- if (screen_kdms.empty()) {
+ if (kdms.empty()) {
return;
}
pair<shared_ptr<Job>, int> result = _output->make (
- screen_kdms, title, _timing, bind (&DOMFrame::confirm_overwrite, this, _1)
+ kdms, title, bind (&DOMFrame::confirm_overwrite, this, _1)
);
if (result.first) {
#include "lib/film.h"
#include "lib/cinema.h"
-#include "lib/screen_kdm.h"
-#include "lib/cinema_kdms.h"
+#include "lib/kdm_with_metadata.h"
#include "lib/config.h"
#include "lib/exceptions.h"
#include "lib/emailer.h"
void
write_files (
- list<shared_ptr<ScreenKDM> > screen_kdms,
+ list<KDMWithMetadataPtr> kdms,
bool zip,
boost::filesystem::path output,
dcp::NameFormat container_name_format,
dcp::NameFormat filename_format,
- dcp::NameFormat::Map values,
bool verbose
)
{
if (zip) {
- int const N = CinemaKDMs::write_zip_files (
- CinemaKDMs::collect (screen_kdms),
+ int const N = write_zip_files (
+ collect (kdms),
output,
container_name_format,
filename_format,
- values,
bind (&always_overwrite)
);
cout << "Wrote " << N << " ZIP files to " << output << "\n";
}
} else {
- int const N = ScreenKDM::write_files (
- screen_kdms, output, filename_format, values,
+ int const N = write_files (
+ kdms, output, filename_format,
bind (&always_overwrite)
);
boost::filesystem::path cpl = cpls.front().cpl_file;
- dcp::NameFormat::Map values;
- values['f'] = film->name();
- values['b'] = dcp::LocalTime(valid_from).date() + " " + dcp::LocalTime(valid_from).time_of_day(true, false);
- values['e'] = dcp::LocalTime(valid_to).date() + " " + dcp::LocalTime(valid_to).time_of_day(true, false);
-
try {
- list<shared_ptr<ScreenKDM> > screen_kdms = film->make_kdms (
- screens, cpl, valid_from, valid_to, formulation, disable_forensic_marking_picture, disable_forensic_marking_audio
- );
-
- write_files (screen_kdms, zip, output, container_name_format, filename_format, values, verbose);
+ list<KDMWithMetadataPtr> kdms;
+ BOOST_FOREACH (shared_ptr<Screen> i, screens) {
+ KDMWithMetadataPtr p = kdm_for_screen (film, cpl, i, valid_from, valid_to, formulation, disable_forensic_marking_picture, disable_forensic_marking_audio);
+ if (p) {
+ kdms.push_back (p);
+ }
+ }
+ write_files (kdms, zip, output, container_name_format, filename_format, verbose);
} catch (FileError& e) {
cerr << program_name << ": " << e.what() << " (" << e.file().string() << ")\n";
exit (EXIT_FAILURE);
)
{
dcp::NameFormat::Map values;
- values['f'] = dkdm.annotation_text().get_value_or("");
- values['b'] = dcp::LocalTime(valid_from).date() + " " + dcp::LocalTime(valid_from).time_of_day(true, false);
- values['e'] = dcp::LocalTime(valid_to).date() + " " + dcp::LocalTime(valid_to).time_of_day(true, false);
try {
- list<shared_ptr<ScreenKDM> > screen_kdms;
+ list<KDMWithMetadataPtr> kdms;
BOOST_FOREACH (shared_ptr<Screen> i, screens) {
if (!i->recipient) {
continue;
}
- screen_kdms.push_back (
- shared_ptr<ScreenKDM>(
- new DCPScreenKDM(
- i,
- kdm_from_dkdm(
+ dcp::LocalTime begin(valid_from, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute());
+ dcp::LocalTime end(valid_to, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute());
+
+ dcp::EncryptedKDM const kdm = kdm_from_dkdm(
dkdm,
i->recipient.get(),
i->trusted_device_thumbprints(),
- dcp::LocalTime(valid_from, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
- dcp::LocalTime(valid_to, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
+ begin,
+ end,
formulation,
disable_forensic_marking_picture,
disable_forensic_marking_audio
- )
- )
- )
- );
+ );
+
+ dcp::NameFormat::Map name_values;
+ name_values['c'] = i->cinema->name;
+ name_values['s'] = i->name;
+ name_values['f'] = dkdm.annotation_text().get_value_or("");
+ name_values['b'] = begin.date() + " " + begin.time_of_day(true, false);
+ name_values['e'] = end.date() + " " + end.time_of_day(true, false);
+ name_values['i'] = kdm.cpl_id();
+
+ kdms.push_back (KDMWithMetadataPtr(new DCPKDMWithMetadata(name_values, i->cinema.get(), i->cinema->emails, kdm)));
}
- write_files (screen_kdms, zip, output, container_name_format, filename_format, values, verbose);
+ write_files (kdms, zip, output, container_name_format, filename_format, verbose);
} catch (FileError& e) {
cerr << program_name << ": " << e.what() << " (" << e.file().string() << ")\n";
exit (EXIT_FAILURE);
overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
}
- _offsets.push_back (Offset (_("UTC-11"), -11, 0));
- _offsets.push_back (Offset (_("UTC-10"), -10, 0));
- _offsets.push_back (Offset (_("UTC-9"), -9, 0));
- _offsets.push_back (Offset (_("UTC-8"), -8, 0));
- _offsets.push_back (Offset (_("UTC-7"), -7, 0));
- _offsets.push_back (Offset (_("UTC-6"), -6, 0));
- _offsets.push_back (Offset (_("UTC-5"), -5, 0));
- _offsets.push_back (Offset (_("UTC-4:30"), -4, 30));
- _offsets.push_back (Offset (_("UTC-4"), -4, 0));
- _offsets.push_back (Offset (_("UTC-3:30"), -3, 30));
- _offsets.push_back (Offset (_("UTC-3"), -3, 0));
- _offsets.push_back (Offset (_("UTC-2"), -2, 0));
- _offsets.push_back (Offset (_("UTC-1"), -1, 0));
- _offsets.push_back (Offset (_("UTC") , 0, 0));
- _offsets.push_back (Offset (_("UTC+1"), 1, 0));
- _offsets.push_back (Offset (_("UTC+2"), 2, 0));
- _offsets.push_back (Offset (_("UTC+3"), 3, 0));
- _offsets.push_back (Offset (_("UTC+4"), 4, 0));
- _offsets.push_back (Offset (_("UTC+5"), 5, 0));
- _offsets.push_back (Offset (_("UTC+5:30"), 5, 30));
- _offsets.push_back (Offset (_("UTC+6"), 6, 0));
- _offsets.push_back (Offset (_("UTC+7"), 7, 0));
- _offsets.push_back (Offset (_("UTC+8"), 8, 0));
- _offsets.push_back (Offset (_("UTC+9"), 9, 0));
- _offsets.push_back (Offset (_("UTC+9:30"), 9, 30));
- _offsets.push_back (Offset (_("UTC+10"), 10, 0));
- _offsets.push_back (Offset (_("UTC+11"), 11, 0));
- _offsets.push_back (Offset (_("UTC+12"), 12, 0));
-
/* Default to UTC */
- size_t sel = 13;
+ size_t sel = get_offsets (_offsets);
for (size_t i = 0; i < _offsets.size(); ++i) {
_utc_offset->Append (_offsets[i].name);
if (_offsets[i].hour == utc_offset_hour && _offsets[i].minute == utc_offset_minute) {
EditableList<std::string, EmailDialog>* _email_list;
std::vector<std::string> _emails;
wxChoice* _utc_offset;
-
- struct Offset
- {
- Offset (wxString n, int h, int m)
- : name (n)
- , hour (h)
- , minute (m)
- {}
-
- wxString name;
- int hour;
- int minute;
- };
-
std::vector<Offset> _offsets;
};
#include "static_text.h"
#include "check_box.h"
#include "lib/config.h"
-#include "lib/cinema_kdms.h"
#include <boost/foreach.hpp>
using std::list;
#include "dcpomatic_button.h"
#include "lib/film.h"
#include "lib/screen.h"
-#include "lib/screen_kdm.h"
+#include "lib/kdm_with_metadata.h"
#include "lib/job_manager.h"
-#include "lib/cinema_kdms.h"
#include "lib/config.h"
#include "lib/cinema.h"
#include <libcxml/cxml.h>
shared_ptr<const Film> film = _film.lock ();
DCPOMATIC_ASSERT (film);
- list<shared_ptr<ScreenKDM> > screen_kdms;
+ list<KDMWithMetadataPtr> kdms;
try {
/* Start off by enabling forensic marking for all */
optional<int> for_audio;
/* Forensic mark up to this channel; disabled on channels greater than this */
for_audio = _output->forensic_mark_audio_up_to();
}
- screen_kdms = film->make_kdms (
- _screens->screens(), _cpl->cpl(), _timing->from(), _timing->until(), _output->formulation(),
- !_output->forensic_mark_video(), for_audio
- );
+ BOOST_FOREACH (shared_ptr<dcpomatic::Screen> i, _screens->screens()) {
+ KDMWithMetadataPtr p = kdm_for_screen (film, _cpl->cpl(), i, _timing->from(), _timing->until(), _output->formulation(), !_output->forensic_mark_video(), for_audio);
+ if (p) {
+ kdms.push_back (p);
+ }
+ }
} catch (dcp::BadKDMDateError& e) {
if (e.starts_too_early()) {
error_dialog (this, _("The KDM start period is before (or close to) the start of the signing certificate's validity period. Use a later start time for this KDM."));
return;
}
- pair<shared_ptr<Job>, int> result = _output->make (screen_kdms, film->name(), _timing, bind (&KDMDialog::confirm_overwrite, this, _1));
+ pair<shared_ptr<Job>, int> result = _output->make (kdms, film->name(), bind (&KDMDialog::confirm_overwrite, this, _1));
if (result.first) {
JobManager::instance()->add (result.first);
}
#include "lib/config.h"
#include "lib/cinema.h"
-#include "lib/cinema_kdms.h"
#include "lib/send_kdm_email_job.h"
#include "kdm_output_panel.h"
#include "kdm_timing_panel.h"
, _forensic_mark_audio_up_to (12)
{
wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, 0);
+ table->AddGrowableCol (1);
add_label_to_sizer (table, this, _("KDM type"), true);
pair<shared_ptr<Job>, int>
KDMOutputPanel::make (
- list<shared_ptr<ScreenKDM> > screen_kdms, string name, KDMTimingPanel* timing, function<bool (boost::filesystem::path)> confirm_overwrite
+ list<KDMWithMetadataPtr> kdms, string name, function<bool (boost::filesystem::path)> confirm_overwrite
)
{
- list<CinemaKDMs> const cinema_kdms = CinemaKDMs::collect (screen_kdms);
+ list<list<KDMWithMetadataPtr> > const cinema_kdms = collect (kdms);
/* Decide whether to proceed */
}
bool cinemas_with_no_email = false;
- BOOST_FOREACH (CinemaKDMs i, cinema_kdms) {
- if (i.cinema->emails.empty ()) {
+ BOOST_FOREACH (list<KDMWithMetadataPtr> i, cinema_kdms) {
+ if (i.front()->emails().empty()) {
cinemas_with_no_email = true;
}
}
if (proceed && Config::instance()->confirm_kdm_email ()) {
list<string> emails;
- BOOST_FOREACH (CinemaKDMs i, cinema_kdms) {
- BOOST_FOREACH (string j, i.cinema->emails) {
+ BOOST_FOREACH (list<KDMWithMetadataPtr> const& i, cinema_kdms) {
+ BOOST_FOREACH (string j, i.front()->emails()) {
emails.push_back (j);
}
}
shared_ptr<Job> job;
try {
- dcp::NameFormat::Map name_values;
- name_values['f'] = name;
- name_values['b'] = dcp::LocalTime(timing->from()).date() + " " + dcp::LocalTime(timing->from()).time_of_day(false, false);
- name_values['e'] = dcp::LocalTime(timing->until()).date() + " " + dcp::LocalTime(timing->until()).time_of_day(false, false);
if (_write_to->GetValue()) {
if (_write_flat->GetValue()) {
- written = ScreenKDM::write_files (
- screen_kdms,
+ written = write_files (
+ kdms,
directory(),
_filename_format->get(),
- name_values,
confirm_overwrite
);
} else if (_write_folder->GetValue()) {
- written = CinemaKDMs::write_directories (
- CinemaKDMs::collect (screen_kdms),
+ written = write_directories (
+ collect (kdms),
directory(),
_container_name_format->get(),
_filename_format->get(),
- name_values,
confirm_overwrite
);
} else if (_write_zip->GetValue()) {
- written = CinemaKDMs::write_zip_files (
- CinemaKDMs::collect (screen_kdms),
+ written = write_zip_files (
+ collect (kdms),
directory(),
_container_name_format->get(),
_filename_format->get(),
- name_values,
confirm_overwrite
);
}
cinema_kdms,
_container_name_format->get(),
_filename_format->get(),
- name_values,
name
)
);
*/
-#include "lib/screen_kdm.h"
+#include "lib/kdm_with_metadata.h"
#include "wx_util.h"
#include "name_format_editor.h"
#include <dcp/types.h>
}
std::pair<boost::shared_ptr<Job>, int> make (
- std::list<boost::shared_ptr<ScreenKDM> > screen_kdms,
+ std::list<KDMWithMetadataPtr > screen_kdms,
std::string name,
- KDMTimingPanel* timing,
boost::function<bool (boost::filesystem::path)> confirm_overwrite
);
#include "static_text.h"
#include "check_box.h"
#include "lib/config.h"
-#include "lib/cinema_kdms.h"
#include <boost/foreach.hpp>
using std::list;
dcp_panel.cc
dcpomatic_button.cc
disk_warning_dialog.cc
+ dkdm_output_panel.cc
drive_wipe_warning_dialog.cc
email_dialog.cc
image_sequence_dialog.cc
isdcf_metadata_dialog.cc
dcp_text_track_dialog.cc
dir_picker_ctrl.cc
+ dkdm_dialog.cc
dolby_doremi_certificate_panel.cc
download_certificate_dialog.cc
download_certificate_panel.cc
question_dialog.cc
rating_dialog.cc
qube_certificate_panel.cc
+ recipients_panel.cc
+ recipient_dialog.cc
recreate_chain_dialog.cc
repeat_dialog.cc
report_problem_dialog.cc
return ok;
}
+
+
+int
+get_offsets (vector<Offset>& offsets)
+{
+ offsets.push_back (Offset(_("UTC-11"), -11, 0));
+ offsets.push_back (Offset(_("UTC-10"), -10, 0));
+ offsets.push_back (Offset(_("UTC-9"), -9, 0));
+ offsets.push_back (Offset(_("UTC-8"), -8, 0));
+ offsets.push_back (Offset(_("UTC-7"), -7, 0));
+ offsets.push_back (Offset(_("UTC-6"), -6, 0));
+ offsets.push_back (Offset(_("UTC-5"), -5, 0));
+ offsets.push_back (Offset(_("UTC-4:30"), -4, 30));
+ offsets.push_back (Offset(_("UTC-4"), -4, 0));
+ offsets.push_back (Offset(_("UTC-3:30"), -3, 30));
+ offsets.push_back (Offset(_("UTC-3"), -3, 0));
+ offsets.push_back (Offset(_("UTC-2"), -2, 0));
+ offsets.push_back (Offset(_("UTC-1"), -1, 0));
+ int utc = offsets.size();
+ offsets.push_back (Offset(_("UTC") , 0, 0));
+ offsets.push_back (Offset(_("UTC+1"), 1, 0));
+ offsets.push_back (Offset(_("UTC+2"), 2, 0));
+ offsets.push_back (Offset(_("UTC+3"), 3, 0));
+ offsets.push_back (Offset(_("UTC+4"), 4, 0));
+ offsets.push_back (Offset(_("UTC+5"), 5, 0));
+ offsets.push_back (Offset(_("UTC+5:30"), 5, 30));
+ offsets.push_back (Offset(_("UTC+6"), 6, 0));
+ offsets.push_back (Offset(_("UTC+7"), 7, 0));
+ offsets.push_back (Offset(_("UTC+8"), 8, 0));
+ offsets.push_back (Offset(_("UTC+9"), 9, 0));
+ offsets.push_back (Offset(_("UTC+9:30"), 9, 30));
+ offsets.push_back (Offset(_("UTC+10"), 10, 0));
+ offsets.push_back (Offset(_("UTC+11"), 11, 0));
+ offsets.push_back (Offset(_("UTC+12"), 12, 0));
+
+ return utc;
+}
extern bool display_progress (wxString title, wxString task);
extern bool report_errors_from_last_job (wxWindow* parent);
+
+struct Offset
+{
+ Offset (wxString n, int h, int m)
+ : name (n)
+ , hour (h)
+ , minute (m)
+ {}
+
+ wxString name;
+ int hour;
+ int minute;
+};
+
+extern int get_offsets (std::vector<Offset>& offsets);
+
+
extern void checked_set (FilePickerCtrl* widget, boost::filesystem::path value);
extern void checked_set (wxDirPickerCtrl* widget, boost::filesystem::path value);
extern void checked_set (wxSpinCtrl* widget, int value);
--- /dev/null
+/*
+ Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "lib/cinema.h"
+#include "lib/screen.h"
+#include "lib/config.h"
+#include "lib/content_factory.h"
+#include "lib/film.h"
+#include "lib/kdm_with_metadata.h"
+#include "test.h"
+#include <boost/test/unit_test.hpp>
+#include <boost/shared_ptr.hpp>
+
+using std::list;
+using std::string;
+using std::vector;
+using boost::shared_ptr;
+using boost::optional;
+using boost::dynamic_pointer_cast;
+
+static
+bool
+confirm_overwrite (boost::filesystem::path)
+{
+ return true;
+}
+
+static shared_ptr<dcpomatic::Screen> cinema_a_screen_1;
+static shared_ptr<dcpomatic::Screen> cinema_a_screen_2;
+static shared_ptr<dcpomatic::Screen> cinema_b_screen_x;
+static shared_ptr<dcpomatic::Screen> cinema_b_screen_y;
+static shared_ptr<dcpomatic::Screen> cinema_b_screen_z;
+
+BOOST_AUTO_TEST_CASE (single_kdm_naming_test)
+{
+ Config* c = Config::instance();
+
+ dcp::Certificate cert = c->decryption_chain()->leaf();
+
+ /* Cinema A: UTC +4:30 */
+ shared_ptr<Cinema> cinema_a (new Cinema("Cinema A", list<string>(), "", 4, 30));
+ cinema_a_screen_1.reset(new dcpomatic::Screen("Screen 1", "", cert, vector<TrustedDevice>()));
+ cinema_a->add_screen (cinema_a_screen_1);
+ cinema_a_screen_2.reset(new dcpomatic::Screen("Screen 2", "", cert, vector<TrustedDevice>()));
+ cinema_a->add_screen (cinema_a_screen_2);
+ c->add_cinema (cinema_a);
+
+ /* Cinema B: UTC -1:00 */
+ shared_ptr<Cinema> cinema_b (new Cinema("Cinema B", list<string>(), "", -1, 0));
+ cinema_b_screen_x.reset(new dcpomatic::Screen("Screen X", "", cert, vector<TrustedDevice>()));
+ cinema_b->add_screen (cinema_b_screen_x);
+ cinema_b_screen_y.reset(new dcpomatic::Screen("Screen Y", "", cert, vector<TrustedDevice>()));
+ cinema_b->add_screen (cinema_b_screen_y);
+ cinema_b_screen_z.reset(new dcpomatic::Screen("Screen Z", "", cert, vector<TrustedDevice>()));
+ cinema_b->add_screen (cinema_b_screen_z);
+ c->add_cinema (cinema_a);
+
+ /* Film */
+ boost::filesystem::remove_all ("build/test/single_kdm_naming_test");
+ shared_ptr<Film> film = new_test_film2 ("single_kdm_naming_test");
+ film->set_name ("my_great_film");
+ film->examine_and_add_content (content_factory("test/data/flat_black.png").front());
+ BOOST_REQUIRE (!wait_for_jobs());
+ film->set_encrypted (true);
+ film->make_dcp ();
+ BOOST_REQUIRE (!wait_for_jobs());
+ film->write_metadata ();
+ vector<CPLSummary> cpls = film->cpls ();
+ BOOST_REQUIRE(cpls.size() == 1);
+
+ dcp::LocalTime from (cert.not_before());
+ from.add_months (2);
+ dcp::LocalTime until (cert.not_after());
+ until.add_months (-2);
+
+ string const from_string = from.date() + " " + from.time_of_day(true, false);
+ string const until_string = until.date() + " " + until.time_of_day(true, false);
+
+ boost::filesystem::path cpl = cpls.front().cpl_file;
+ KDMWithMetadataPtr kdm = kdm_for_screen (
+ film,
+ cpls.front().cpl_file,
+ cinema_a_screen_1,
+ boost::posix_time::time_from_string(from_string),
+ boost::posix_time::time_from_string(until_string),
+ dcp::MODIFIED_TRANSITIONAL_1,
+ false,
+ optional<int>()
+ );
+
+ list<KDMWithMetadataPtr> kdms;
+ kdms.push_back (kdm);
+
+ write_files (
+ kdms,
+ boost::filesystem::path("build/test/single_kdm_naming_test"),
+ dcp::NameFormat("KDM %c - %s - %f - %b - %e"),
+ &confirm_overwrite
+ );
+
+ string from_time = from.time_of_day (true, false);
+ boost::algorithm::replace_all (from_time, ":", "-");
+ string until_time = until.time_of_day (true, false);
+ boost::algorithm::replace_all (until_time, ":", "-");
+
+ string const ref = String::compose("KDM_Cinema_A_-_Screen_1_-_my_great_film_-_%1_%2_-_%3_%4.xml", from.date(), from_time, until.date(), until_time);
+ BOOST_CHECK_MESSAGE (boost::filesystem::exists("build/test/single_kdm_naming_test/" + ref), "File " << ref << " not found");
+}
+
+
+BOOST_AUTO_TEST_CASE (directory_kdm_naming_test, * boost::unit_test::depends_on("single_kdm_naming_test"))
+{
+ using boost::filesystem::path;
+
+ dcp::Certificate cert = Config::instance()->decryption_chain()->leaf();
+
+ /* Film */
+ boost::filesystem::remove_all ("build/test/directory_kdm_naming_test");
+ shared_ptr<Film> film = new_test_film2 ("directory_kdm_naming_test");
+ film->set_name ("my_great_film");
+ film->examine_and_add_content (content_factory("test/data/flat_black.png").front());
+ BOOST_REQUIRE (!wait_for_jobs());
+ film->set_encrypted (true);
+ film->make_dcp ();
+ BOOST_REQUIRE (!wait_for_jobs());
+ film->write_metadata ();
+ vector<CPLSummary> cpls = film->cpls ();
+ BOOST_REQUIRE(cpls.size() == 1);
+
+ dcp::LocalTime from (cert.not_before());
+ from.add_months (2);
+ dcp::LocalTime until (cert.not_after());
+ until.add_months (-2);
+
+ string const from_string = from.date() + " " + from.time_of_day(true, false);
+ string const until_string = until.date() + " " + until.time_of_day(true, false);
+
+ list<shared_ptr<dcpomatic::Screen> > screens;
+ screens.push_back (cinema_a_screen_2);
+ screens.push_back (cinema_b_screen_x);
+ screens.push_back (cinema_a_screen_1);
+ screens.push_back (cinema_b_screen_z);
+
+ path const cpl = cpls.front().cpl_file;
+ string const cpl_id = cpls.front().cpl_id;
+
+ list<KDMWithMetadataPtr> kdms;
+ BOOST_FOREACH (shared_ptr<dcpomatic::Screen> i, screens) {
+ KDMWithMetadataPtr kdm = kdm_for_screen (
+ film,
+ cpls.front().cpl_file,
+ i,
+ boost::posix_time::time_from_string(from_string),
+ boost::posix_time::time_from_string(until_string),
+ dcp::MODIFIED_TRANSITIONAL_1,
+ false,
+ optional<int>()
+ );
+
+ kdms.push_back (kdm);
+ }
+
+ write_directories (
+ collect(kdms),
+ path("build/test/directory_kdm_naming_test"),
+ dcp::NameFormat("%c - %s - %f - %b - %e"),
+ dcp::NameFormat("KDM %c - %s - %f - %b - %e - %i"),
+ &confirm_overwrite
+ );
+
+ string from_time = from.time_of_day (true, false);
+ boost::algorithm::replace_all (from_time, ":", "-");
+ string until_time = until.time_of_day (true, false);
+ boost::algorithm::replace_all (until_time, ":", "-");
+
+ path const base = "build/test/directory_kdm_naming_test";
+
+ path dir_a = String::compose("Cinema_A_-_%s_-_my_great_film_-_%1_%2_-_%3_%4", from.date(), from_time, until.date(), until_time);
+ BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_a), "Directory " << dir_a << " not found");
+ path dir_b = String::compose("Cinema_B_-_%s_-_my_great_film_-_%1_%2_-_%3_%4", from.date(), from_time, until.date(), until_time);
+ BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_b), "Directory " << dir_b << " not found");
+
+ path ref = String::compose("KDM_Cinema_A_-_Screen_2_-_my_great_film_-_%1_%2_-_%3_%4_-_%5.xml", from.date(), from_time, until.date(), until_time, cpl_id);
+ BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_a / ref), "File " << ref << " not found");
+
+ ref = String::compose("KDM_Cinema_B_-_Screen_X_-_my_great_film_-_%1_%2_-_%3_%4_-_%5.xml", from.date(), from_time, until.date(), until_time, cpl_id);
+ BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_b / ref), "File " << ref << " not found");
+
+ ref = String::compose("KDM_Cinema_A_-_Screen_1_-_my_great_film_-_%1_%2_-_%3_%4_-_%5.xml", from.date(), from_time, until.date(), until_time, cpl_id);
+ BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_a / ref), "File " << ref << " not found");
+
+ ref = String::compose("KDM_Cinema_B_-_Screen_Z_-_my_great_film_-_%1_%2_-_%3_%4_-_%5.xml", from.date(), from_time, until.date(), until_time, cpl_id);
+ BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_b / ref), "File " << ref << " not found");
+}
+
isdcf_name_test.cc
j2k_bandwidth_test.cc
job_test.cc
+ kdm_naming_test.cc
make_black_test.cc
optimise_stills_test.cc
pixel_formats_test.cc