Various bits related to subtitle font handling, particularly copying fonts to the...
[dcpomatic.git] / src / lib / util.cc
index 807883ca0906ffc787ff8da0f54533c50566df9e..f98e5960bb20e807f8bf2c9df0c0594a38f54926 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 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
@@ -23,7 +23,6 @@
 
 #include "util.h"
 #include "exceptions.h"
-#include "scaler.h"
 #include "dcp_content_type.h"
 #include "filter.h"
 #include "cinema_sound_processor.h"
 #include "md5_digester.h"
 #include "audio_processor.h"
 #include "safe_stringstream.h"
-#include <dcp/version.h>
 #include <dcp/util.h>
 #include <dcp/signer.h>
-#include <dcp/raw_convert.h>
-extern "C" {
-#include <libavcodec/avcodec.h>
-#include <libavformat/avformat.h>
-#include <libswscale/swscale.h>
-#include <libavfilter/avfiltergraph.h>
-#include <libavutil/pixfmt.h>
-}
 #include <glib.h>
-#include <openjpeg.h>
 #include <pangomm/init.h>
-#ifdef DCPOMATIC_IMAGE_MAGICK
-#include <magick/MagickCore.h>
-#else
-#include <magick/common.h>
-#include <magick/magick_config.h>
-#endif
-#include <magick/version.h>
-#include <libssh/libssh.h>
 #include <boost/algorithm/string.hpp>
 #include <boost/bind.hpp>
 #include <boost/lambda/lambda.hpp>
@@ -87,6 +68,7 @@ using std::endl;
 using std::vector;
 using std::min;
 using std::max;
+using std::map;
 using std::list;
 using std::multimap;
 using std::istream;
@@ -98,7 +80,6 @@ using boost::shared_ptr;
 using boost::thread;
 using boost::optional;
 using dcp::Size;
-using dcp::raw_convert;
 
 /** Path to our executable, required by the stacktrace stuff and filled
  *  in during App::onInit().
@@ -187,17 +168,6 @@ seconds_to_approximate_hms (int s)
        return ap.str ();
 }
 
-/** @param v Version as used by FFmpeg.
- *  @return A string representation of v.
- */
-static string
-ffmpeg_version_to_string (int v)
-{
-       SafeStringStream s;
-       s << ((v & 0xff0000) >> 16) << N_(".") << ((v & 0xff00) >> 8) << N_(".") << (v & 0xff);
-       return s.str ();
-}
-
 double
 seconds (struct timeval t)
 {
@@ -354,7 +324,6 @@ dcpomatic_setup ()
        Ratio::setup_ratios ();
        VideoContentScale::setup_scales ();
        DCPContentType::setup_dcp_content_types ();
-       Scaler::setup_scalers ();
        Filter::setup_filters ();
        CinemaSoundProcessor::setup_cinema_sound_processors ();
        AudioProcessor::setup_audio_processors ();
@@ -412,7 +381,7 @@ dcpomatic_setup_gettext_i18n (string lang)
 #endif 
 
 #ifdef DCPOMATIC_LINUX
-       bindtextdomain ("libdcpomatic", POSIX_LOCALE_PREFIX);
+       bindtextdomain ("libdcpomatic", LINUX_LOCALE_PREFIX);
 #endif
 }
 
@@ -454,7 +423,7 @@ md5_digest_head_tail (vector<boost::filesystem::path> files, boost::uintmax_t si
                }
 
                boost::uintmax_t this_time = min (to_do, boost::filesystem::file_size (files[i]));
-               fseek (f, -this_time, SEEK_END);
+               dcpomatic_fseek (f, -this_time, SEEK_END);
                fread (p, 1, this_time, f);
                p += this_time;
                to_do -= this_time;
@@ -480,135 +449,6 @@ dcp_audio_frame_rate (int fs)
        return 96000;
 }
 
-Socket::Socket (int timeout)
-       : _deadline (_io_service)
-       , _socket (_io_service)
-       , _acceptor (0)
-       , _timeout (timeout)
-{
-       _deadline.expires_at (boost::posix_time::pos_infin);
-       check ();
-}
-
-Socket::~Socket ()
-{
-       delete _acceptor;
-}
-
-void
-Socket::check ()
-{
-       if (_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now ()) {
-               if (_acceptor) {
-                       _acceptor->cancel ();
-               } else {
-                       _socket.close ();
-               }
-               _deadline.expires_at (boost::posix_time::pos_infin);
-       }
-
-       _deadline.async_wait (boost::bind (&Socket::check, this));
-}
-
-/** Blocking connect.
- *  @param endpoint End-point to connect to.
- */
-void
-Socket::connect (boost::asio::ip::tcp::endpoint endpoint)
-{
-       _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
-       boost::system::error_code ec = boost::asio::error::would_block;
-       _socket.async_connect (endpoint, boost::lambda::var(ec) = boost::lambda::_1);
-       do {
-               _io_service.run_one();
-       } while (ec == boost::asio::error::would_block);
-
-       if (ec) {
-               throw NetworkError (String::compose (_("error during async_connect (%1)"), ec.value ()));
-       }
-
-       if (!_socket.is_open ()) {
-               throw NetworkError (_("connect timed out"));
-       }
-}
-
-void
-Socket::accept (int port)
-{
-       _acceptor = new boost::asio::ip::tcp::acceptor (_io_service, boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), port));
-       
-       _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
-       boost::system::error_code ec = boost::asio::error::would_block;
-       _acceptor->async_accept (_socket, boost::lambda::var(ec) = boost::lambda::_1);
-       do {
-               _io_service.run_one ();
-       } while (ec == boost::asio::error::would_block);
-
-       delete _acceptor;
-       _acceptor = 0;
-       
-       if (ec) {
-               throw NetworkError (String::compose (_("error during async_accept (%1)"), ec.value ()));
-       }
-}
-
-/** Blocking write.
- *  @param data Buffer to write.
- *  @param size Number of bytes to write.
- */
-void
-Socket::write (uint8_t const * data, int size)
-{
-       _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
-       boost::system::error_code ec = boost::asio::error::would_block;
-
-       boost::asio::async_write (_socket, boost::asio::buffer (data, size), boost::lambda::var(ec) = boost::lambda::_1);
-       
-       do {
-               _io_service.run_one ();
-       } while (ec == boost::asio::error::would_block);
-
-       if (ec) {
-               throw NetworkError (String::compose (_("error during async_write (%1)"), ec.value ()));
-       }
-}
-
-void
-Socket::write (uint32_t v)
-{
-       v = htonl (v);
-       write (reinterpret_cast<uint8_t*> (&v), 4);
-}
-
-/** Blocking read.
- *  @param data Buffer to read to.
- *  @param size Number of bytes to read.
- */
-void
-Socket::read (uint8_t* data, int size)
-{
-       _deadline.expires_from_now (boost::posix_time::seconds (_timeout));
-       boost::system::error_code ec = boost::asio::error::would_block;
-
-       boost::asio::async_read (_socket, boost::asio::buffer (data, size), boost::lambda::var(ec) = boost::lambda::_1);
-
-       do {
-               _io_service.run_one ();
-       } while (ec == boost::asio::error::would_block);
-       
-       if (ec) {
-               throw NetworkError (String::compose (_("error during async_read (%1)"), ec.value ()));
-       }
-}
-
-uint32_t
-Socket::read_uint32 ()
-{
-       uint32_t v;
-       read (reinterpret_cast<uint8_t *> (&v), 4);
-       return ntohl (v);
-}
-
 /** Round a number up to the nearest multiple of another number.
  *  @param c Index.
  *  @param s Array of numbers to round, indexed by c.
@@ -721,24 +561,6 @@ wrapped_av_malloc (size_t s)
        return p;
 }
                
-/** Return a user-readable string summarising the versions of our dependencies */
-string
-dependency_version_summary ()
-{
-       SafeStringStream s;
-       s << N_("libopenjpeg ") << opj_version () << N_(", ")
-         << N_("libavcodec ") << ffmpeg_version_to_string (avcodec_version()) << N_(", ")
-         << N_("libavfilter ") << ffmpeg_version_to_string (avfilter_version()) << N_(", ")
-         << N_("libavformat ") << ffmpeg_version_to_string (avformat_version()) << N_(", ")
-         << N_("libavutil ") << ffmpeg_version_to_string (avutil_version()) << N_(", ")
-         << N_("libswscale ") << ffmpeg_version_to_string (swscale_version()) << N_(", ")
-         << MagickVersion << N_(", ")
-         << N_("libssh ") << ssh_version (0) << N_(", ")
-         << N_("libdcp ") << dcp::version << N_(" git ") << dcp::git_commit;
-
-       return s.str ();
-}
-
 ContentTimePeriod
 subtitle_period (AVSubtitle const & sub)
 {
@@ -751,3 +573,93 @@ subtitle_period (AVSubtitle const & sub)
 
        return period;
 }
+
+map<string, string>
+split_get_request (string url)
+{
+       enum {
+               AWAITING_QUESTION_MARK,
+               KEY,
+               VALUE
+       } state = AWAITING_QUESTION_MARK;
+       
+       map<string, string> r;
+       string k;
+       string v;
+       for (size_t i = 0; i < url.length(); ++i) {
+               switch (state) {
+               case AWAITING_QUESTION_MARK:
+                       if (url[i] == '?') {
+                               state = KEY;
+                       }
+                       break;
+               case KEY:
+                       if (url[i] == '=') {
+                               v.clear ();
+                               state = VALUE;
+                       } else {
+                               k += url[i];
+                       }
+                       break;
+               case VALUE:
+                       if (url[i] == '&') {
+                               r.insert (make_pair (k, v));
+                               k.clear ();
+                               state = KEY;
+                       } else {
+                               v += url[i];
+                       }
+                       break;
+               }
+       }
+
+       if (state == VALUE) {
+               r.insert (make_pair (k, v));
+       }
+
+       return r;
+}
+
+long
+frame_info_position (int frame, Eyes eyes)
+{
+       static int const info_size = 48;
+       
+       switch (eyes) {
+       case EYES_BOTH:
+               return frame * info_size;
+       case EYES_LEFT:
+               return frame * info_size * 2;
+       case EYES_RIGHT:
+               return frame * info_size * 2 + info_size;
+       default:
+               DCPOMATIC_ASSERT (false);
+       }
+
+       DCPOMATIC_ASSERT (false);
+}
+
+dcp::FrameInfo
+read_frame_info (FILE* file, int frame, Eyes eyes)
+{
+       dcp::FrameInfo info;
+       dcpomatic_fseek (file, frame_info_position (frame, eyes), SEEK_SET);
+       fread (&info.offset, sizeof (info.offset), 1, file);
+       fread (&info.size, sizeof (info.size), 1, file);
+       
+       char hash_buffer[33];
+       fread (hash_buffer, 1, 32, file);
+       hash_buffer[32] = '\0';
+       info.hash = hash_buffer;
+
+       return info;
+}
+
+void
+write_frame_info (FILE* file, int frame, Eyes eyes, dcp::FrameInfo info)
+{
+       dcpomatic_fseek (file, frame_info_position (frame, eyes), SEEK_SET);
+       fwrite (&info.offset, sizeof (info.offset), 1, file);
+       fwrite (&info.size, sizeof (info.size), 1, file);
+       fwrite (info.hash.c_str(), 1, info.hash.size(), file);
+}