X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Futil.cc;h=38770f4e3214f6d30d10c5f94e4567d38e6b6fd3;hb=1460bda6f80b6529e31a1a63029dc0ec5f7d0ae8;hp=92b3b22fd1cd72096e96d5dece3e23bea23d20b5;hpb=a306df9145d16046e51e8b7ff5222e341e98fdbd;p=dcpomatic.git diff --git a/src/lib/util.cc b/src/lib/util.cc index 92b3b22fd..38770f4e3 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -35,9 +35,10 @@ #include "rect.h" #include "digester.h" #include "audio_processor.h" -#include "safe_stringstream.h" #include "compose.hpp" +#include #include +#include #include #include #include @@ -46,9 +47,13 @@ extern "C" { #include } #include +#ifdef DCPOMATIC_GRAPHICS_MAGICK +#include +#endif #include #include #include +#include #include #include #ifdef DCPOMATIC_WINDOWS @@ -89,6 +94,8 @@ using boost::optional; using boost::lexical_cast; using boost::bad_lexical_cast; using dcp::Size; +using dcp::raw_convert; +using dcp::locale_convert; /** Path to our executable, required by the stacktrace stuff and filled * in during App::onInit(). @@ -112,14 +119,9 @@ seconds_to_hms (int s) int h = m / 60; m -= (h * 60); - SafeStringStream hms; - hms << h << N_(":"); - hms.width (2); - hms << setfill ('0') << m << N_(":"); - hms.width (2); - hms << setfill ('0') << s; - - return hms.str (); + char buffer[64]; + snprintf (buffer, sizeof(buffer), "%d:%02d:%02d", h, m, s); + return buffer; } /** @param s Number of seconds. @@ -133,23 +135,23 @@ seconds_to_approximate_hms (int s) int h = m / 60; m -= (h * 60); - SafeStringStream ap; + string ap; bool const hours = h > 0; - bool const minutes = h < 10 && m > 0; - bool const seconds = m < 10 && s > 0; + bool const minutes = h < 6 && m > 0; + bool const seconds = h == 0 && m < 10 && s > 0; if (hours) { if (m > 30 && !minutes) { /// TRANSLATORS: h here is an abbreviation for hours - ap << (h + 1) << _("h"); + ap += locale_convert(h + 1) + _("h"); } else { /// TRANSLATORS: h here is an abbreviation for hours - ap << h << _("h"); + ap += locale_convert(h) + _("h"); } - if (minutes | seconds) { - ap << N_(" "); + if (minutes || seconds) { + ap += N_(" "); } } @@ -157,24 +159,24 @@ seconds_to_approximate_hms (int s) /* Minutes */ if (s > 30 && !seconds) { /// TRANSLATORS: m here is an abbreviation for minutes - ap << (m + 1) << _("m"); + ap += locale_convert(m + 1) + _("m"); } else { /// TRANSLATORS: m here is an abbreviation for minutes - ap << m << _("m"); + ap += locale_convert(m) + _("m"); } if (seconds) { - ap << N_(" "); + ap += N_(" "); } } if (seconds) { /* Seconds */ /// TRANSLATORS: s here is an abbreviation for seconds - ap << s << _("s"); + ap += locale_convert(s) + _("s"); } - return ap.str (); + return ap; } double @@ -346,6 +348,10 @@ dcpomatic_setup () curl_global_init (CURL_GLOBAL_ALL); +#ifdef DCPOMATIC_GRAPHICS_MAGICK + Magick::InitializeMagick (0); +#endif + ui_thread = boost::this_thread::get_id (); } @@ -417,7 +423,7 @@ digest_head_tail (vector files, boost::uintmax_t size) while (i < int64_t (files.size()) && to_do > 0) { FILE* f = fopen_boost (files[i], "rb"); if (!f) { - throw OpenFileError (files[i].string()); + throw OpenFileError (files[i].string(), errno, true); } boost::uintmax_t this_time = min (to_do, boost::filesystem::file_size (files[i])); @@ -437,7 +443,7 @@ digest_head_tail (vector files, boost::uintmax_t size) while (i >= 0 && to_do > 0) { FILE* f = fopen_boost (files[i], "rb"); if (!f) { - throw OpenFileError (files[i].string()); + throw OpenFileError (files[i].string(), errno, true); } boost::uintmax_t this_time = min (to_do, boost::filesystem::file_size (files[i])); @@ -480,8 +486,7 @@ audio_channel_name (int c) DCPOMATIC_ASSERT (MAX_DCP_AUDIO_CHANNELS == 16); /// TRANSLATORS: these are the names of audio channels; Lfe (sub) is the low-frequency - /// enhancement channel (sub-woofer). HI is the hearing-impaired audio track and - /// VI is the visually-impaired audio track (audio describe). + /// enhancement channel (sub-woofer). string const channels[] = { _("Left"), _("Right"), @@ -504,6 +509,38 @@ audio_channel_name (int c) return channels[c]; } +string +short_audio_channel_name (int c) +{ + DCPOMATIC_ASSERT (MAX_DCP_AUDIO_CHANNELS == 16); + + /// TRANSLATORS: these are short names of audio channels; Lfe is the low-frequency + /// enhancement channel (sub-woofer). HI is the hearing-impaired audio track and + /// VI is the visually-impaired audio track (audio describe). DBP is the D-BOX + /// primary channel and DBS is the D-BOX secondary channel. + string const channels[] = { + _("L"), + _("R"), + _("C"), + _("Lfe"), + _("Ls"), + _("Rs"), + _("HI"), + _("VI"), + _("Lc"), + _("Rc"), + _("BsL"), + _("BsR"), + _("DBP"), + _("DBS"), + "", + "" + }; + + return channels[c]; +} + + bool valid_image_file (boost::filesystem::path f) { @@ -520,6 +557,18 @@ valid_image_file (boost::filesystem::path f) ); } +bool +valid_sound_file (boost::filesystem::path f) +{ + if (boost::starts_with (f.leaf().string(), "._")) { + return false; + } + + string ext = f.extension().string(); + transform (ext.begin(), ext.end(), ext.begin(), ::tolower); + return (ext == ".wav" || ext == ".mp3" || ext == ".aif" || ext == ".aiff"); +} + bool valid_j2k_file (boost::filesystem::path f) { @@ -531,16 +580,8 @@ valid_j2k_file (boost::filesystem::path f) 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; + boost::replace_if (f, boost::is_any_of ("\\/:"), '_'); + return f; } dcp::Size @@ -610,15 +651,29 @@ split_get_request (string url) } string -video_asset_filename (shared_ptr asset) +video_asset_filename (shared_ptr asset, int reel_index, int reel_count, optional summary) { - return "j2c_" + asset->id() + ".mxf"; + dcp::NameFormat::Map values; + values['t'] = "j2c"; + values['r'] = raw_convert (reel_index + 1); + values['n'] = raw_convert (reel_count); + if (summary) { + values['c'] = careful_string_filter (summary.get()); + } + return Config::instance()->dcp_asset_filename_format().get(values, "_" + asset->id() + ".mxf"); } string -audio_asset_filename (shared_ptr asset) +audio_asset_filename (shared_ptr asset, int reel_index, int reel_count, optional summary) { - return "pcm_" + asset->id() + ".mxf"; + dcp::NameFormat::Map values; + values['t'] = "pcm"; + values['r'] = raw_convert (reel_index + 1); + values['n'] = raw_convert (reel_count); + if (summary) { + values['c'] = careful_string_filter (summary.get()); + } + return Config::instance()->dcp_asset_filename_format().get(values, "_" + asset->id() + ".mxf"); } float @@ -633,8 +688,21 @@ relaxed_string_to_float (string s) } } -bool -string_not_empty (string s) +string +careful_string_filter (string s) { - return !s.empty (); + /* Filter out `bad' characters which `may' cause problems with some systems (either for DCP name or filename). + There's no apparent list of what really is allowed, so this is a guess. + Safety first and all that. + */ + + string out; + string const allowed = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_%."; + for (size_t i = 0; i < s.size(); ++i) { + if (allowed.find (s[i]) != string::npos) { + out += s[i]; + } + } + + return out; }