summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-10-10 12:14:52 +0100
committerCarl Hetherington <cth@carlh.net>2013-10-10 12:14:52 +0100
commitacb1ace5884337757102bc05074b6b37f04c49cd (patch)
treedc81cd66486ec65dd61f42de6651e04b6feed112 /src/lib
parent406ddd165456ad769b4109535530d408a4221077 (diff)
Various improvements to dcpomatic_kdm.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/kdm.cc209
-rw-r--r--src/lib/kdm.h48
-rw-r--r--src/lib/wscript3
3 files changed, 259 insertions, 1 deletions
diff --git a/src/lib/kdm.cc b/src/lib/kdm.cc
new file mode 100644
index 000000000..3503306e7
--- /dev/null
+++ b/src/lib/kdm.cc
@@ -0,0 +1,209 @@
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <list>
+#include <boost/shared_ptr.hpp>
+#include <quickmail.h>
+#include <zip.h>
+#include <libdcp/kdm.h>
+#include "kdm.h"
+#include "cinema.h"
+#include "exceptions.h"
+#include "util.h"
+#include "film.h"
+#include "config.h"
+
+using std::list;
+using std::string;
+using boost::shared_ptr;
+
+struct ScreenKDM
+{
+ ScreenKDM (shared_ptr<Screen> s, libdcp::KDM k)
+ : screen (s)
+ , kdm (k)
+ {}
+
+ shared_ptr<Screen> screen;
+ libdcp::KDM kdm;
+};
+
+struct CinemaKDMs
+{
+ shared_ptr<Cinema> cinema;
+ list<ScreenKDM> screen_kdms;
+
+ void make_zip_file (boost::filesystem::path zip_file) const
+ {
+ int error;
+ struct zip* zip = zip_open (zip_file.string().c_str(), ZIP_CREATE | ZIP_EXCL, &error);
+ if (!zip) {
+ if (error == ZIP_ER_EXISTS) {
+ throw FileError ("ZIP file already exists", zip_file);
+ }
+ throw FileError ("could not create ZIP file", zip_file);
+ }
+
+ list<shared_ptr<string> > kdm_strings;
+
+ for (list<ScreenKDM>::const_iterator i = screen_kdms.begin(); i != screen_kdms.end(); ++i) {
+ shared_ptr<string> kdm (new string (i->kdm.as_xml ()));
+ kdm_strings.push_back (kdm);
+
+ struct zip_source* source = zip_source_buffer (zip, kdm->c_str(), kdm->length(), 0);
+ if (!source) {
+ throw StringError ("could not create ZIP source");
+ }
+
+ string const name = tidy_for_filename (i->screen->cinema->name) + "_" +
+ tidy_for_filename (i->screen->name) + ".kdm.xml";
+
+ if (zip_add (zip, name.c_str(), source) == -1) {
+ throw StringError ("failed to add KDM to ZIP archive");
+ }
+ }
+
+ if (zip_close (zip) == -1) {
+ throw StringError ("failed to close ZIP archive");
+ }
+ }
+};
+
+/* Not complete but sufficient for our purposes (we're using
+ ScreenKDM in a list where all the screens will be unique).
+*/
+bool
+operator== (ScreenKDM const & a, ScreenKDM const & b)
+{
+ return a.screen == b.screen;
+}
+
+static list<ScreenKDM>
+make_screen_kdms (shared_ptr<Film> film, list<shared_ptr<Screen> > screens, boost::posix_time::ptime from, boost::posix_time::ptime to)
+{
+ list<libdcp::KDM> kdms = film->make_kdms (screens, from, to);
+
+ list<ScreenKDM> screen_kdms;
+
+ list<shared_ptr<Screen> >::iterator i = screens.begin ();
+ list<libdcp::KDM>::iterator j = kdms.begin ();
+ while (i != screens.end() && j != kdms.end ()) {
+ screen_kdms.push_back (ScreenKDM (*i, *j));
+ ++i;
+ ++j;
+ }
+
+ return screen_kdms;
+}
+
+static list<CinemaKDMs>
+make_cinema_kdms (shared_ptr<Film> film, list<shared_ptr<Screen> > screens, boost::posix_time::ptime from, boost::posix_time::ptime to)
+{
+ list<ScreenKDM> screen_kdms = make_screen_kdms (film, screens, from, to);
+ list<CinemaKDMs> cinema_kdms;
+
+ while (!screen_kdms.empty ()) {
+
+ /* Get all the screens from a single cinema */
+
+ CinemaKDMs ck;
+
+ list<ScreenKDM>::iterator i = screen_kdms.begin ();
+ ck.cinema = i->screen->cinema;
+ ck.screen_kdms.push_back (*i);
+ list<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<ScreenKDM>::iterator j = i;
+ ++i;
+ screen_kdms.remove (*j);
+ } else {
+ ++i;
+ }
+ }
+
+ cinema_kdms.push_back (ck);
+ }
+
+ return cinema_kdms;
+}
+
+void
+write_kdm_files (
+ shared_ptr<Film> film, list<shared_ptr<Screen> > screens, boost::posix_time::ptime from, boost::posix_time::ptime to, boost::filesystem::path directory
+ )
+{
+ list<ScreenKDM> screen_kdms = make_screen_kdms (film, screens, from, to);
+
+ /* Write KDMs to the specified directory */
+ for (list<ScreenKDM>::iterator i = screen_kdms.begin(); i != screen_kdms.end(); ++i) {
+ boost::filesystem::path out = directory;
+ out /= tidy_for_filename (i->screen->cinema->name) + "_" + tidy_for_filename (i->screen->name) + ".kdm.xml";
+ i->kdm.as_xml (out);
+ }
+}
+
+void
+write_kdm_zip_files (
+ shared_ptr<Film> film, list<shared_ptr<Screen> > screens, boost::posix_time::ptime from, boost::posix_time::ptime to, boost::filesystem::path directory
+ )
+{
+ list<CinemaKDMs> cinema_kdms = make_cinema_kdms (film, screens, from, to);
+
+ for (list<CinemaKDMs>::const_iterator i = cinema_kdms.begin(); i != cinema_kdms.end(); ++i) {
+ boost::filesystem::path path = directory;
+ path /= tidy_for_filename (i->cinema->name) + ".zip";
+ i->make_zip_file (path);
+ }
+}
+
+void
+email_kdms (shared_ptr<Film> film, list<shared_ptr<Screen> > screens, boost::posix_time::ptime from, boost::posix_time::ptime to)
+{
+ list<CinemaKDMs> cinema_kdms = make_cinema_kdms (film, screens, from, to);
+
+ for (list<CinemaKDMs>::const_iterator i = cinema_kdms.begin(); i != cinema_kdms.end(); ++i) {
+
+ boost::filesystem::path zip_file = boost::filesystem::temp_directory_path ();
+ zip_file /= boost::filesystem::unique_path().string() + ".zip";
+ i->make_zip_file (zip_file);
+
+ /* Send email */
+
+ quickmail_initialize ();
+ quickmail mail = quickmail_create (Config::instance()->kdm_from().c_str(), "KDM delivery");
+ quickmail_add_to (mail, i->cinema->email.c_str ());
+
+ string body = Config::instance()->kdm_email().c_str();
+ boost::algorithm::replace_all (body, "$DCP_NAME", film->dcp_name ());
+
+ quickmail_set_body (mail, body.c_str());
+ quickmail_add_attachment_file (mail, zip_file.string().c_str());
+ char const* error = quickmail_send (mail, Config::instance()->mail_server().c_str(), 25, "", "");
+ if (error) {
+ quickmail_destroy (mail);
+ throw StringError (String::compose ("Failed to send KDM email (%1)", error));
+ }
+ quickmail_destroy (mail);
+ }
+}
diff --git a/src/lib/kdm.h b/src/lib/kdm.h
new file mode 100644
index 000000000..f79656b93
--- /dev/null
+++ b/src/lib/kdm.h
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/date_time.hpp>
+#include <boost/filesystem.hpp>
+
+class Screen;
+class Film;
+
+extern void write_kdm_files (
+ boost::shared_ptr<Film> film,
+ std::list<boost::shared_ptr<Screen> > screens,
+ boost::posix_time::ptime from,
+ boost::posix_time::ptime to,
+ boost::filesystem::path directory
+ );
+
+extern void write_kdm_zip_files (
+ boost::shared_ptr<Film> film,
+ std::list<boost::shared_ptr<Screen> > screens,
+ boost::posix_time::ptime from,
+ boost::posix_time::ptime to,
+ boost::filesystem::path directory
+ );
+
+extern void email_kdms (
+ boost::shared_ptr<Film> film,
+ std::list<boost::shared_ptr<Screen> > screens,
+ boost::posix_time::ptime from,
+ boost::posix_time::ptime to
+ );
+
diff --git a/src/lib/wscript b/src/lib/wscript
index 8c02ff158..e27cf3cc7 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -32,6 +32,7 @@ sources = """
image.cc
job.cc
job_manager.cc
+ kdm.cc
log.cc
moving_image_content.cc
moving_image_decoder.cc
@@ -74,7 +75,7 @@ def build(bld):
AVCODEC AVUTIL AVFORMAT AVFILTER SWSCALE SWRESAMPLE
BOOST_FILESYSTEM BOOST_THREAD BOOST_DATETIME BOOST_SIGNALS2
SNDFILE OPENJPEG POSTPROC TIFF MAGICK SSH DCP CXML GLIB LZMA XML++
- CURL
+ CURL ZIP QUICKMAIL
"""
obj.source = sources + ' version.cc'