Add support for no-scale of the input video.
[dcpomatic.git] / src / lib / util.cc
index 190bb42b19ab01ec7fe5dc4ca291a1e4d16b6c37..48b418d37634fe6ecdd41bb507ae6d54830485d5 100644 (file)
@@ -70,6 +70,7 @@ extern "C" {
 #include "ratio.h"
 #include "job.h"
 #include "cross.h"
+#include "video_content.h"
 #ifdef DCPOMATIC_WINDOWS
 #include "stack.hpp"
 #endif
@@ -89,12 +90,14 @@ using std::min;
 using std::max;
 using std::list;
 using std::multimap;
+using std::map;
 using std::istream;
 using std::numeric_limits;
 using std::pair;
 using std::cout;
 using std::bad_alloc;
 using std::streampos;
+using std::set_terminate;
 using boost::shared_ptr;
 using boost::thread;
 using boost::lexical_cast;
@@ -273,6 +276,33 @@ LONG WINAPI exception_handler(struct _EXCEPTION_POINTERS *)
 }
 #endif
 
+/* From http://stackoverflow.com/questions/2443135/how-do-i-find-where-an-exception-was-thrown-in-c */
+void
+terminate ()
+{
+       static bool tried_throw = false;
+
+       try {
+               // try once to re-throw currently active exception
+               if (!tried_throw++) {
+                       throw;
+               }
+       }
+       catch (const std::exception &e) {
+               std::cerr << __FUNCTION__ << " caught unhandled exception. what(): "
+                         << e.what() << std::endl;
+       }
+       catch (...) {
+               std::cerr << __FUNCTION__ << " caught unknown/unhandled exception." 
+                         << std::endl;
+       }
+
+#ifdef DCPOMATIC_POSIX
+       stacktrace (cout, 50);
+#endif
+       abort();
+}
+
 /** 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.
  */
@@ -309,11 +339,14 @@ dcpomatic_setup ()
        boost::filesystem::path lib = app_contents ();
        lib /= "lib";
        setenv ("LTDL_LIBRARY_PATH", lib.c_str (), 1);
-#endif 
+#endif
+
+       set_terminate (terminate);
 
        libdcp::init ();
        
        Ratio::setup_ratios ();
+       VideoContentScale::setup_scales ();
        DCPContentType::setup_dcp_content_types ();
        Scaler::setup_scalers ();
        Filter::setup_filters ();
@@ -759,10 +792,11 @@ video_frames_to_audio_frames (VideoContent::Frame v, float audio_sample_rate, fl
 string
 audio_channel_name (int c)
 {
-       assert (MAX_AUDIO_CHANNELS == 6);
+       assert (MAX_AUDIO_CHANNELS == 8);
 
        /* TRANSLATORS: these are the names of audio channels; Lfe (sub) is the low-frequency
-          enhancement channel (sub-woofer).
+          enhancement channel (sub-woofer).  HI is the hearing-impaired audio track and
+          VI is the visually-impaired audio track (audio describe).
        */
        string const channels[] = {
                _("Left"),
@@ -771,6 +805,8 @@ audio_channel_name (int c)
                _("Lfe (sub)"),
                _("Left surround"),
                _("Right surround"),
+               _("HI"),
+               _("VI")
        };
 
        return channels[c];
@@ -909,6 +945,52 @@ make_signer ()
        return shared_ptr<const libdcp::Signer> (new libdcp::Signer (chain, signer_key));
 }
 
+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;
+}
+
 libdcp::Size
 fit_ratio_within (float ratio, libdcp::Size full_frame)
 {
@@ -929,3 +1011,20 @@ wrapped_av_malloc (size_t s)
        return p;
 }
                
+string
+entities_to_text (string e)
+{
+       boost::algorithm::replace_all (e, "%3A", ":");
+       boost::algorithm::replace_all (e, "%2F", "/");
+       return e;
+}
+
+int64_t
+divide_with_round (int64_t a, int64_t b)
+{
+       if (a % b >= (b / 2)) {
+               return (a + b - 1) / b;
+       } else {
+               return a / b;
+       }
+}