diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-10-10 12:14:52 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-10-10 12:14:52 +0100 |
| commit | acb1ace5884337757102bc05074b6b37f04c49cd (patch) | |
| tree | dc81cd66486ec65dd61f42de6651e04b6feed112 /src/lib | |
| parent | 406ddd165456ad769b4109535530d408a4221077 (diff) | |
Various improvements to dcpomatic_kdm.
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/kdm.cc | 209 | ||||
| -rw-r--r-- | src/lib/kdm.h | 48 | ||||
| -rw-r--r-- | src/lib/wscript | 3 |
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' |
