X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Futil.cc;h=7089ef2a5d2f1ea74c0a0c8aeac660616e519408;hb=1629bd7df2150156109afbc7a16677cb29e82adf;hp=ddc0a297459cef504b49300b25f874752ec2ba64;hpb=f0be0f0e060e40d9a0da1b44429ef41901b8a536;p=dcpomatic.git diff --git a/src/lib/util.cc b/src/lib/util.cc index ddc0a2974..7089ef2a5 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -27,6 +27,7 @@ #include #include #include +#include #ifdef DCPOMATIC_POSIX #include #include @@ -47,10 +48,11 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include extern "C" { #include #include @@ -88,16 +90,19 @@ 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; using boost::optional; -using libdcp::Size; +using dcp::Size; static boost::thread::id ui_thread; static boost::filesystem::path backtrace_file; @@ -247,7 +252,7 @@ dependency_version_summary () << N_("libswscale ") << ffmpeg_version_to_string (swscale_version()) << N_(", ") << MagickVersion << N_(", ") << N_("libssh ") << ssh_version (0) << N_(", ") - << N_("libdcp ") << libdcp::version << N_(" git ") << libdcp::git_commit; + << N_("libdcp ") << dcp::version << N_(" git ") << dcp::git_commit; return s.str (); } @@ -271,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. */ @@ -307,9 +339,12 @@ dcpomatic_setup () boost::filesystem::path lib = app_contents (); lib /= "lib"; setenv ("LTDL_LIBRARY_PATH", lib.c_str (), 1); -#endif +#endif - libdcp::init (); + set_terminate (terminate); + + Pango::init (); + dcp::init (); Ratio::setup_ratios (); DCPContentType::setup_dcp_content_types (); @@ -350,6 +385,8 @@ dcpomatic_setup_gettext_i18n (string lang) putenv (cmd); snprintf (cmd, sizeof(cmd), "LANG=%s", lang.c_str ()); putenv (cmd); + snprintf (cmd, sizeof(cmd), "LC_ALL=%s", lang.c_str ()); + putenv (cmd); } setlocale (LC_ALL, ""); @@ -539,7 +576,7 @@ Socket::connect (boost::asio::ip::tcp::endpoint endpoint) } while (ec == boost::asio::error::would_block); if (ec) { - throw NetworkError (ec.message ()); + throw NetworkError (String::compose (_("error during async_connect (%1)"), ec.value ())); } if (!_socket.is_open ()) { @@ -563,7 +600,7 @@ Socket::accept (int port) _acceptor = 0; if (ec) { - throw NetworkError (ec.message ()); + throw NetworkError (String::compose (_("error during async_accept (%1)"), ec.value ())); } } @@ -584,7 +621,7 @@ Socket::write (uint8_t const * data, int size) } while (ec == boost::asio::error::would_block); if (ec) { - throw NetworkError (ec.message ()); + throw NetworkError (String::compose (_("error during async_write (%1)"), ec.value ())); } } @@ -612,7 +649,7 @@ Socket::read (uint8_t* data, int size) } while (ec == boost::asio::error::would_block); if (ec) { - throw NetworkError (ec.message ()); + throw NetworkError (String::compose (_("error during async_read (%1)"), ec.value ())); } } @@ -747,7 +784,7 @@ ensure_ui_thread () * @return Equivalent number of audio frames for `v'. */ int64_t -video_frames_to_audio_frames (VideoContent::Frame v, float audio_sample_rate, float frames_per_second) +video_frames_to_audio_frames (VideoFrame v, float audio_sample_rate, float frames_per_second) { return ((int64_t) v * audio_sample_rate / frames_per_second); } @@ -755,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"), @@ -767,12 +805,14 @@ audio_channel_name (int c) _("Lfe (sub)"), _("Left surround"), _("Right surround"), + _("HI"), + _("VI") }; return channels[c]; } -FrameRateConversion::FrameRateConversion (float source, int dcp) +FrameRateChange::FrameRateChange (float source, int dcp) : skip (false) , repeat (1) , change_speed (false) @@ -790,7 +830,8 @@ FrameRateConversion::FrameRateConversion (float source, int dcp) repeat = round (dcp / source); } - change_speed = !about_equal (source * factor(), dcp); + speed_up = dcp / (source * factor()); + change_speed = !about_equal (speed_up, 1.0); if (!skip && repeat == 1 && !change_speed) { description = _("Content and DCP have the same rate.\n"); @@ -852,7 +893,7 @@ tidy_for_filename (string f) return t; } -shared_ptr +shared_ptr make_signer () { boost::filesystem::path const sd = Config::instance()->signer_chain_directory (); @@ -872,45 +913,126 @@ make_signer () if (!boost::filesystem::exists (p)) { boost::filesystem::remove_all (sd); boost::filesystem::create_directories (sd); - libdcp::make_signer_chain (sd, openssl_path ()); + dcp::make_signer_chain (sd, openssl_path ()); break; } ++i; } - libdcp::CertificateChain chain; + dcp::CertificateChain chain; { boost::filesystem::path p (sd); p /= "ca.self-signed.pem"; - chain.add (shared_ptr (new libdcp::Certificate (p))); + chain.add (shared_ptr (new dcp::Certificate (p))); } { boost::filesystem::path p (sd); p /= "intermediate.signed.pem"; - chain.add (shared_ptr (new libdcp::Certificate (p))); + chain.add (shared_ptr (new dcp::Certificate (p))); } { boost::filesystem::path p (sd); p /= "leaf.signed.pem"; - chain.add (shared_ptr (new libdcp::Certificate (p))); + chain.add (shared_ptr (new dcp::Certificate (p))); } boost::filesystem::path signer_key (sd); signer_key /= "leaf.key"; - return shared_ptr (new libdcp::Signer (chain, signer_key)); + return shared_ptr (new dcp::Signer (chain, signer_key)); +} + +map +split_get_request (string url) +{ + enum { + AWAITING_QUESTION_MARK, + KEY, + VALUE + } state = AWAITING_QUESTION_MARK; + + map 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) +dcp::Size +fit_ratio_within (float ratio, dcp::Size full_frame) { if (ratio < full_frame.ratio ()) { - return libdcp::Size (rint (full_frame.height * ratio), full_frame.height); + return dcp::Size (rint (full_frame.height * ratio), full_frame.height); } - return libdcp::Size (full_frame.width, rint (full_frame.width / ratio)); + return dcp::Size (full_frame.width, rint (full_frame.width / ratio)); +} + +DCPTime +time_round_up (DCPTime t, DCPTime nearest) +{ + DCPTime const a = t + nearest - 1; + return a - (a % nearest); +} + +void * +wrapped_av_malloc (size_t s) +{ + void* p = av_malloc (s); + if (!p) { + throw bad_alloc (); + } + 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; + } }