diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-09-25 13:49:13 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-09-25 13:49:13 +0100 |
| commit | d087368dc0dcd6026b3a967f00f145feb701dd0e (patch) | |
| tree | f44d2bb828c3572f0bbb3a74ec4e2f497d54168c /src | |
| parent | 5909b9672821c1d5ea974761316dc0f3df558349 (diff) | |
Basic email of KDMs works.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/film.cc | 17 | ||||
| -rw-r--r-- | src/lib/film.h | 6 | ||||
| -rw-r--r-- | src/lib/util.cc | 51 | ||||
| -rw-r--r-- | src/tools/dcpomatic.cc | 145 | ||||
| -rw-r--r-- | src/tools/wscript | 2 | ||||
| -rw-r--r-- | src/wx/kdm_dialog.cc | 6 | ||||
| -rw-r--r-- | src/wx/kdm_dialog.h | 1 |
7 files changed, 152 insertions, 76 deletions
diff --git a/src/lib/film.cc b/src/lib/film.cc index d218524f4..8252b492c 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -895,12 +895,11 @@ Film::full_frame () const return libdcp::Size (); } -void +list<libdcp::KDM> Film::make_kdms ( list<shared_ptr<Screen> > screens, boost::posix_time::ptime from, - boost::posix_time::ptime until, - string directory + boost::posix_time::ptime until ) const { boost::filesystem::path const sd = Config::instance()->signer_chain_directory (); @@ -948,6 +947,8 @@ Film::make_kdms ( throw KDMError (_("More than one possible DCP to make KDM for")); } + list<libdcp::KDM> kdms; + for (list<shared_ptr<Screen> >::iterator i = screens.begin(); i != screens.end(); ++i) { libdcp::DCP dcp (dcps.front ()); @@ -963,14 +964,10 @@ Film::make_kdms ( string const issue_date = libdcp::tm_to_string (tm); dcp.cpls().front()->set_mxf_keys (key ()); - - libdcp::KDM kdm ( - dcp.cpls().front(), signer, (*i)->certificate, from, until, "DCP-o-matic", issue_date - ); - boost::filesystem::path out = directory; - out /= tidy_for_filename ((*i)->cinema->name) + "_" + tidy_for_filename ((*i)->name) + ".kdm.xml"; - kdm.as_xml (out); + kdms.push_back (libdcp::KDM (dcp.cpls().front(), signer, (*i)->certificate, from, until, "DCP-o-matic", issue_date)); } + + return kdms; } diff --git a/src/lib/film.h b/src/lib/film.h index 26623e69e..a30a630b9 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -32,6 +32,7 @@ #include <boost/enable_shared_from_this.hpp> #include <boost/filesystem.hpp> #include <libdcp/key.h> +#include <libdcp/kdm.h> #include "util.h" #include "types.h" #include "dci_metadata.h" @@ -115,11 +116,10 @@ public: bool has_subtitles () const; OutputVideoFrame best_video_frame_rate () const; - void make_kdms ( + std::list<libdcp::KDM> make_kdms ( std::list<boost::shared_ptr<Screen> >, boost::posix_time::ptime from, - boost::posix_time::ptime until, - std::string directory + boost::posix_time::ptime until ) const; libdcp::Key key () const { diff --git a/src/lib/util.cc b/src/lib/util.cc index 739a327d6..6746b4773 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -54,7 +54,6 @@ extern "C" { #include <libpostproc/postprocess.h> #include <libavutil/pixfmt.h> } -#include <curl/curl.h> #include "util.h" #include "exceptions.h" #include "scaler.h" @@ -817,53 +816,3 @@ tidy_for_filename (string f) return t; } - -struct EmailState -{ - string message; - int done; -}; - -static size_t -send_email_function (void* ptr, size_t size, size_t nmemb, void* userdata) -{ - EmailState* state = reinterpret_cast<EmailState*> (userdata); - - int const now = min (size * nmemb, state->message.length() - state->done); - - memcpy (ptr, state->message.c_str() + state->done, now); - state->done += now; - - return now; -} - -bool -send_email (string from, string to, string message) -{ - CURL* curl = curl_easy_init (); - if (!curl) { - return true; - } - - string const url = "smtp://" + Config::instance()->mail_server(); - - curl_easy_setopt (curl, CURLOPT_URL, url.c_str ()); - curl_easy_setopt (curl, CURLOPT_MAIL_FROM, from.c_str ()); - struct curl_slist* recipients = 0; - recipients = curl_slist_append (recipients, to.c_str ()); - curl_easy_setopt (curl, CURLOPT_READFUNCTION, send_email_function); - - EmailState state; - state.message = message; - state.done = 0; - curl_easy_setopt (curl, CURLOPT_READDATA, &state); - - if (curl_easy_perform (curl) != CURLE_OK) { - return true; - } - - curl_slist_free_all (recipients); - curl_easy_cleanup (curl); - - return false; -} diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index f61ef19e2..86886ed9e 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -29,6 +29,8 @@ #include <wx/generic/aboutdlgg.h> #include <wx/stdpaths.h> #include <wx/cmdline.h> +#include <quickmail.h> +#include <zip.h> #include "wx/film_viewer.h" #include "wx/film_editor.h" #include "wx/job_manager_view.h" @@ -49,6 +51,7 @@ #include "lib/job_manager.h" #include "lib/transcode_job.h" #include "lib/exceptions.h" +#include "lib/cinema.h" using std::cout; using std::string; @@ -223,6 +226,25 @@ setup_menu (wxMenuBar* m) m->Append (help, _("&Help")); } +struct ScreenKDM +{ + ScreenKDM (shared_ptr<Screen> s, libdcp::KDM k) + : screen (s) + , kdm (k) + {} + + shared_ptr<Screen> screen; + libdcp::KDM kdm; +}; + +/* 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; +} + class Frame : public wxFrame { public: @@ -420,19 +442,120 @@ private: } KDMDialog* d = new KDMDialog (this); - if (d->ShowModal () == wxID_OK) { - try { - film->make_kdms ( - d->screens (), - d->from (), - d->until (), - d->directory () - ); - } catch (KDMError& e) { - error_dialog (this, e.what ()); - } + if (d->ShowModal () != wxID_OK) { + d->Destroy (); + return; } + try { + list<shared_ptr<Screen> > screens = d->screens (); + list<libdcp::KDM> kdms = film->make_kdms ( + screens, + d->from (), + d->until () + ); + + 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; + } + + if (d->write_to ()) { + /* Write KDMs to the specified directory */ + for (list<ScreenKDM>::iterator i = screen_kdms.begin(); i != screen_kdms.end(); ++i) { + boost::filesystem::path out = d->directory (); + out /= tidy_for_filename (i->screen->cinema->name) + "_" + tidy_for_filename (i->screen->name) + ".kdm.xml"; + i->kdm.as_xml (out); + } + } else { + while (!screen_kdms.empty ()) { + + /* Get all the screens from a single cinema */ + + shared_ptr<Cinema> cinema; + list<ScreenKDM> cinema_screen_kdms; + + list<ScreenKDM>::iterator i = screen_kdms.begin (); + cinema = i->screen->cinema; + cinema_screen_kdms.push_back (*i); + list<ScreenKDM>::iterator j = i; + ++i; + screen_kdms.remove (*j); + + while (i != screen_kdms.end ()) { + if (i->screen->cinema == cinema) { + cinema_screen_kdms.push_back (*i); + list<ScreenKDM>::iterator j = i; + ++i; + screen_kdms.remove (*j); + } else { + ++i; + } + } + + /* Make a ZIP file of this cinema's KDMs */ + + boost::filesystem::path zip_file = boost::filesystem::temp_directory_path (); + zip_file /= boost::filesystem::unique_path().string() + ".zip"; + struct zip* zip = zip_open (zip_file.c_str(), ZIP_CREATE | ZIP_EXCL, 0); + if (!zip) { + throw FileError ("could not create ZIP file", zip_file); + } + + list<shared_ptr<string> > kdm_strings; + + for (list<ScreenKDM>::const_iterator i = cinema_screen_kdms.begin(); i != cinema_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"); + } + + /* Send email */ + + quickmail_initialize (); + quickmail mail = quickmail_create (Config::instance()->kdm_from().c_str(), "KDM delivery"); + quickmail_add_to (mail, 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.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); + + film->log()->log (String::compose ("Send KDM email to %1", cinema->email)); + } + } + + } catch (KDMError& e) { + error_dialog (this, e.what ()); + } + d->Destroy (); } diff --git a/src/tools/wscript b/src/tools/wscript index 42fc90adb..4adf84382 100644 --- a/src/tools/wscript +++ b/src/tools/wscript @@ -15,7 +15,7 @@ def build(bld): if not bld.env.DISABLE_GUI: for t in ['dcpomatic', 'dcpomatic_batch', 'dcpomatic_server']: obj = bld(features = 'cxx cxxprogram') - obj.uselib = 'DCP OPENJPEG AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC CXML WXWIDGETS' + obj.uselib = 'DCP OPENJPEG AVFORMAT AVFILTER AVCODEC AVUTIL SWSCALE POSTPROC CXML WXWIDGETS ZIP QUICKMAIL' if bld.env.STATIC: obj.uselib += ' GTK' obj.includes = ['..'] diff --git a/src/wx/kdm_dialog.cc b/src/wx/kdm_dialog.cc index 9db512780..6164f7fd9 100644 --- a/src/wx/kdm_dialog.cc +++ b/src/wx/kdm_dialog.cc @@ -385,3 +385,9 @@ KDMDialog::directory () const { return wx_to_std (_folder->GetPath ()); } + +bool +KDMDialog::write_to () const +{ + return _write_to->GetValue (); +} diff --git a/src/wx/kdm_dialog.h b/src/wx/kdm_dialog.h index 0acf9a61e..ec4a50ac3 100644 --- a/src/wx/kdm_dialog.h +++ b/src/wx/kdm_dialog.h @@ -42,6 +42,7 @@ public: boost::posix_time::ptime from () const; boost::posix_time::ptime until () const; std::string directory () const; + bool write_to () const; private: void add_cinema (boost::shared_ptr<Cinema>); |
