Hacks.
[dcpomatic.git] / src / lib / util.cc
index 183ff7d8b6431aeda75aaf235a5fda1c7c58ac3f..15efcc099555637ca58b8775305c7f14de83fabc 100644 (file)
@@ -45,6 +45,9 @@
 #include <magick/MagickCore.h>
 #include <magick/version.h>
 #include <libdcp/version.h>
+#include <libdcp/util.h>
+#include <libdcp/signer_chain.h>
+#include <libdcp/signer.h>
 extern "C" {
 #include <libavcodec/avcodec.h>
 #include <libavformat/avformat.h>
@@ -61,6 +64,8 @@ extern "C" {
 #include "sound_processor.h"
 #include "config.h"
 #include "ratio.h"
+#include "job.h"
+#include "cross.h"
 #ifdef DCPOMATIC_WINDOWS
 #include "stack.hpp"
 #endif
@@ -273,6 +278,17 @@ dcpomatic_setup ()
 #endif 
        
        avfilter_register_all ();
+
+#ifdef DCPOMATIC_OSX
+       /* Add our lib directory to the libltdl search path so that
+          xmlsec can find xmlsec1-openssl.
+       */
+       boost::filesystem::path lib = app_contents ();
+       lib /= "lib";
+       setenv ("LTDL_LIBRARY_PATH", lib.c_str (), 1);
+#endif 
+
+       libdcp::init ();
        
        Ratio::setup_ratios ();
        DCPContentType::setup_dcp_content_types ();
@@ -407,15 +423,24 @@ md5_digest (boost::filesystem::path file)
        return s.str ();
 }
 
+/** @param job Optional job for which to report progress */
 string
-md5_digest_directory (boost::filesystem::path directory)
+md5_digest_directory (boost::filesystem::path directory, shared_ptr<Job> job)
 {
        int const buffer_size = 64 * 1024;
        char buffer[buffer_size];
 
        MD5_CTX md5_context;
        MD5_Init (&md5_context);
-       
+
+       int files = 0;
+       if (job) {
+               for (boost::filesystem::directory_iterator i(directory); i != boost::filesystem::directory_iterator(); ++i) {
+                       ++files;
+               }
+       }
+
+       int j = 0;
        for (boost::filesystem::directory_iterator i(directory); i != boost::filesystem::directory_iterator(); ++i) {
                ifstream f (i->path().string().c_str(), std::ios::binary);
                if (!f.good ()) {
@@ -432,6 +457,11 @@ md5_digest_directory (boost::filesystem::path directory)
                        MD5_Update (&md5_context, buffer, t);
                        bytes -= t;
                }
+
+               if (job) {
+                       job->set_progress (float (j) / files);
+                       ++j;
+               }
        }
 
        unsigned char digest[MD5_DIGEST_LENGTH];
@@ -714,7 +744,7 @@ audio_channel_name (int c)
        assert (MAX_AUDIO_CHANNELS == 6);
 
        /* TRANSLATORS: these are the names of audio channels; Lfe (sub) is the low-frequency
-          enhancement channel (sub-woofer)./
+          enhancement channel (sub-woofer).
        */
        string const channels[] = {
                _("Left"),
@@ -730,24 +760,28 @@ audio_channel_name (int c)
 
 FrameRateConversion::FrameRateConversion (float source, int dcp)
        : skip (false)
-       , repeat (false)
+       , repeat (1)
        , change_speed (false)
 {
-       if (fabs (source / 2.0 - dcp) < (fabs (source - dcp))) {
+       if (source > (dcp * 2)) {
                skip = true;
-       } else if (fabs (source * 2 - dcp) < fabs (source - dcp)) {
-               repeat = true;
+       }
+
+       if (source < dcp) {
+               repeat = floor (dcp / source);
        }
 
        change_speed = !about_equal (source * factor(), dcp);
 
-       if (!skip && !repeat && !change_speed) {
+       if (!skip && repeat == 1 && !change_speed) {
                description = _("Content and DCP have the same rate.\n");
        } else {
                if (skip) {
                        description = _("DCP will use every other frame of the content.\n");
-               } else if (repeat) {
+               } else if (repeat == 2) {
                        description = _("Each content frame will be doubled in the DCP.\n");
+               } else if (repeat > 2) {
+                       description = String::compose (_("Each content frame will be repeated %1 more times in the DCP.\n"), repeat - 1);
                }
 
                if (change_speed) {
@@ -775,3 +809,89 @@ LocaleGuard::~LocaleGuard ()
        setlocale (LC_NUMERIC, _old);
        free (_old);
 }
+
+bool
+valid_image_file (boost::filesystem::path f)
+{
+       string ext = f.extension().string();
+       transform (ext.begin(), ext.end(), ext.begin(), ::tolower);
+       return (ext == ".tif" || ext == ".tiff" || ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".bmp" || ext == ".tga");
+}
+
+string
+tidy_for_filename (string f)
+{
+       string t;
+       for (size_t i = 0; i < f.length(); ++i) {
+               if (isalnum (f[i]) || f[i] == '_' || f[i] == '-') {
+                       t += f[i];
+               } else {
+                       t += '_';
+               }
+       }
+
+       return t;
+}
+
+shared_ptr<const libdcp::Signer>
+make_signer ()
+{
+       boost::filesystem::path const sd = Config::instance()->signer_chain_directory ();
+
+       /* Remake the chain if any of it is missing */
+       
+       list<boost::filesystem::path> files;
+       files.push_back ("ca.self-signed.pem");
+       files.push_back ("intermediate.signed.pem");
+       files.push_back ("leaf.signed.pem");
+       files.push_back ("leaf.key");
+
+       list<boost::filesystem::path>::const_iterator i = files.begin();
+       while (i != files.end()) {
+               boost::filesystem::path p (sd);
+               p /= *i;
+               if (!boost::filesystem::exists (p)) {
+                       boost::filesystem::remove_all (sd);
+                       boost::filesystem::create_directories (sd);
+                       libdcp::make_signer_chain (sd, openssl_path ());
+                       break;
+               }
+
+               ++i;
+       }
+       
+       libdcp::CertificateChain chain;
+
+       {
+               boost::filesystem::path p (sd);
+               p /= "ca.self-signed.pem";
+               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p)));
+       }
+
+       {
+               boost::filesystem::path p (sd);
+               p /= "intermediate.signed.pem";
+               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p)));
+       }
+
+       {
+               boost::filesystem::path p (sd);
+               p /= "leaf.signed.pem";
+               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p)));
+       }
+
+       boost::filesystem::path signer_key (sd);
+       signer_key /= "leaf.key";
+
+       return shared_ptr<const libdcp::Signer> (new libdcp::Signer (chain, signer_key));
+}
+
+libdcp::Size
+fit_ratio_within (float ratio, libdcp::Size full_frame)
+{
+       if (ratio < full_frame.ratio ()) {
+               return libdcp::Size (full_frame.height * ratio, full_frame.height);
+       }
+       
+       return libdcp::Size (full_frame.width, full_frame.width / ratio);
+}