Merge 1.0 in.
[dcpomatic.git] / src / lib / util.cc
index e1bc560c613e9fc21267435255d5b93e7edb89ef..b8bc1fc9e467680646f924c2ab3385d195911efb 100644 (file)
@@ -45,6 +45,7 @@
 #include <magick/MagickCore.h>
 #include <magick/version.h>
 #include <libdcp/version.h>
+#include <libdcp/util.h>
 extern "C" {
 #include <libavcodec/avcodec.h>
 #include <libavformat/avformat.h>
@@ -56,13 +57,13 @@ extern "C" {
 #include "util.h"
 #include "exceptions.h"
 #include "scaler.h"
-#include "format.h"
 #include "dcp_content_type.h"
 #include "filter.h"
 #include "sound_processor.h"
 #include "config.h"
-#include "container.h"
-#ifdef DVDOMATIC_WINDOWS
+#include "ratio.h"
+#include "job.h"
+#ifdef DCPOMATIC_WINDOWS
 #include "stack.hpp"
 #endif
 
@@ -92,8 +93,8 @@ using boost::lexical_cast;
 using boost::optional;
 using libdcp::Size;
 
-boost::thread::id ui_thread;
-boost::filesystem::path backtrace_file;
+static boost::thread::id ui_thread;
+static boost::filesystem::path backtrace_file;
 
 /** Convert some number of seconds to a string representation
  *  in hours, minutes and seconds.
@@ -120,12 +121,6 @@ seconds_to_hms (int s)
        return hms.str ();
 }
 
-string
-time_to_hms (Time t)
-{
-       return seconds_to_hms (t / TIME_HZ);
-}
-
 /** @param s Number of seconds.
  *  @return String containing an approximate description of s (e.g. "about 2 hours")
  */
@@ -208,15 +203,11 @@ void
 stacktrace (ostream& out, int levels)
 {
        void *array[200];
-       size_t size;
-       char **strings;
-       size_t i;
-     
-       size = backtrace (array, 200);
-       strings = backtrace_symbols (array, size);
+       size_t size = backtrace (array, 200);
+       char** strings = backtrace_symbols (array, size);
      
        if (strings) {
-               for (i = 0; i < size && (levels == 0 || i < size_t(levels)); i++) {
+               for (size_t i = 0; i < size && (levels == 0 || i < size_t(levels)); i++) {
                        out << N_("  ") << demangle (strings[i]) << "\n";
                }
                
@@ -261,7 +252,7 @@ seconds (struct timeval t)
        return t.tv_sec + (double (t.tv_usec) / 1e6);
 }
 
-#ifdef DVDOMATIC_WINDOWS
+#ifdef DCPOMATIC_WINDOWS
 LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *)
 {
        dbg::stack s;
@@ -271,13 +262,13 @@ LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *)
 }
 #endif
 
-/** Call the required functions to set up DVD-o-matic's static arrays, etc.
+/** Call the required functions to set up DCP-o-matic's static arrays, etc.
  *  Must be called from the UI thread, if there is one.
  */
 void
 dcpomatic_setup ()
 {
-#ifdef DVDOMATIC_WINDOWS
+#ifdef DCPOMATIC_WINDOWS
        backtrace_file /= g_get_user_config_dir ();
        backtrace_file /= "backtrace.txt";
        SetUnhandledExceptionFilter(exception_handler);
@@ -285,8 +276,7 @@ dcpomatic_setup ()
        
        avfilter_register_all ();
        
-       Format::setup_formats ();
-       Container::setup_containers ();
+       Ratio::setup_ratios ();
        DCPContentType::setup_dcp_content_types ();
        Scaler::setup_scalers ();
        Filter::setup_filters ();
@@ -340,18 +330,6 @@ dcpomatic_setup_gettext_i18n (string lang)
 #endif
 }
 
-/** @param start Start position for the crop within the image.
- *  @param size Size of the cropped area.
- *  @return FFmpeg crop filter string.
- */
-string
-crop_string (Position start, libdcp::Size size)
-{
-       stringstream s;
-       s << N_("crop=") << size.width << N_(":") << size.height << N_(":") << start.x << N_(":") << start.y;
-       return s.str ();
-}
-
 /** @param s A string.
  *  @return Parts of the string split at spaces, except when a space is within quotation marks.
  */
@@ -431,6 +409,58 @@ 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, 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 ()) {
+                       throw OpenFileError (i->path().string());
+               }
+       
+               f.seekg (0, std::ios::end);
+               int bytes = f.tellg ();
+               f.seekg (0, std::ios::beg);
+
+               while (bytes > 0) {
+                       int const t = min (bytes, buffer_size);
+                       f.read (buffer, t);
+                       MD5_Update (&md5_context, buffer, t);
+                       bytes -= t;
+               }
+
+               if (job) {
+                       job->set_progress (float (j) / files);
+                       ++j;
+               }
+       }
+
+       unsigned char digest[MD5_DIGEST_LENGTH];
+       MD5_Final (digest, &md5_context);
+
+       stringstream s;
+       for (int i = 0; i < MD5_DIGEST_LENGTH; ++i) {
+               s << std::hex << std::setfill('0') << std::setw(2) << ((int) digest[i]);
+       }
+
+       return s.str ();
+}
+
 static bool
 about_equal (float a, float b)
 {
@@ -471,23 +501,6 @@ dcp_audio_frame_rate (int fs)
        return 96000;
 }
 
-/** @param index Colour LUT index.
- *  @return Human-readable name.
- */
-string
-colour_lut_index_to_name (int index)
-{
-       switch (index) {
-       case 0:
-               return _("sRGB");
-       case 1:
-               return _("Rec 709");
-       }
-
-       assert (false);
-       return N_("");
-}
-
 Socket::Socket (int timeout)
        : _deadline (_io_service)
        , _socket (_io_service)
@@ -596,12 +609,6 @@ stride_round_up (int c, int const * stride, int t)
        return a - (a % t);
 }
 
-int
-stride_lookup (int c, int const * stride)
-{
-       return stride[c];
-}
-
 /** Read a sequence of key / value pairs from a text stream;
  *  the keys are the first words on the line, and the values are
  *  the remainder of the line following the key.  Lines beginning
@@ -712,37 +719,11 @@ ensure_ui_thread ()
  *  @return Equivalent number of audio frames for `v'.
  */
 int64_t
-video_frames_to_audio_frames (ContentVideoFrame v, float audio_sample_rate, float frames_per_second)
+video_frames_to_audio_frames (VideoContent::Frame v, float audio_sample_rate, float frames_per_second)
 {
        return ((int64_t) v * audio_sample_rate / frames_per_second);
 }
 
-/** @return A pair containing CPU model name and the number of processors */
-pair<string, int>
-cpu_info ()
-{
-       pair<string, int> info;
-       info.second = 0;
-       
-#ifdef DCPOMATIC_POSIX
-       ifstream f (N_("/proc/cpuinfo"));
-       while (f.good ()) {
-               string l;
-               getline (f, l);
-               if (boost::algorithm::starts_with (l, N_("model name"))) {
-                       string::size_type const c = l.find (':');
-                       if (c != string::npos) {
-                               info.first = l.substr (c + 2);
-                       }
-               } else if (boost::algorithm::starts_with (l, N_("processor"))) {
-                       ++info.second;
-               }
-       }
-#endif 
-
-       return info;
-}
-
 string
 audio_channel_name (int c)
 {
@@ -777,17 +758,17 @@ FrameRateConversion::FrameRateConversion (float source, int dcp)
        change_speed = !about_equal (source * factor(), dcp);
 
        if (!skip && !repeat && !change_speed) {
-               description = _("DCP and source have the same rate.\n");
+               description = _("Content and DCP have the same rate.\n");
        } else {
                if (skip) {
-                       description = _("DCP will use every other frame of the source.\n");
+                       description = _("DCP will use every other frame of the content.\n");
                } else if (repeat) {
-                       description = _("Each source frame will be doubled in the DCP.\n");
+                       description = _("Each content frame will be doubled in the DCP.\n");
                }
 
                if (change_speed) {
                        float const pc = dcp * 100 / (source * factor());
-                       description += String::compose (_("DCP will run at %1%% of the source speed.\n"), pc);
+                       description += String::compose (_("DCP will run at %1%% of the content speed.\n"), pc);
                }
        }
 }
@@ -797,12 +778,12 @@ LocaleGuard::LocaleGuard ()
 {
        char const * old = setlocale (LC_NUMERIC, 0);
 
-        if (old) {
-                _old = strdup (old);
-                if (strcmp (_old, "C")) {
-                        setlocale (LC_NUMERIC, "C");
-                }
-        }
+       if (old) {
+               _old = strdup (old);
+               if (strcmp (_old, "C")) {
+                       setlocale (LC_NUMERIC, "C");
+               }
+       }
 }
 
 LocaleGuard::~LocaleGuard ()
@@ -810,3 +791,12 @@ 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");
+}
+