X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Futil.cc;h=38770f4e3214f6d30d10c5f94e4567d38e6b6fd3;hb=1460bda6f80b6529e31a1a63029dc0ec5f7d0ae8;hp=1cf71ba32090a40963363d8abc37d065c9160124;hpb=ada96204dfa1456da77e2ea7469f492cfc0a5483;p=dcpomatic.git diff --git a/src/lib/util.cc b/src/lib/util.cc index 1cf71ba32..38770f4e3 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -36,8 +36,9 @@ #include "digester.h" #include "audio_processor.h" #include "compose.hpp" -#include +#include #include +#include #include #include #include @@ -52,6 +53,7 @@ extern "C" { #include #include #include +#include #include #include #ifdef DCPOMATIC_WINDOWS @@ -92,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(). @@ -115,14 +119,9 @@ seconds_to_hms (int s) int h = m / 60; m -= (h * 60); - locked_stringstream 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. @@ -136,7 +135,7 @@ seconds_to_approximate_hms (int s) int h = m / 60; m -= (h * 60); - locked_stringstream ap; + string ap; bool const hours = h > 0; bool const minutes = h < 6 && m > 0; @@ -145,14 +144,14 @@ seconds_to_approximate_hms (int s) 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_(" "); + ap += N_(" "); } } @@ -160,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 @@ -424,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])); @@ -444,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])); @@ -487,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"), @@ -511,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) { @@ -527,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) { @@ -538,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 @@ -621,13 +655,12 @@ video_asset_filename (shared_ptr asset, int reel_index, int r { dcp::NameFormat::Map values; values['t'] = "j2c"; - values['i'] = asset->id(); values['r'] = raw_convert (reel_index + 1); values['n'] = raw_convert (reel_count); if (summary) { - values['c'] = summary.get(); + values['c'] = careful_string_filter (summary.get()); } - return Config::instance()->dcp_asset_filename_format().get(values) + ".mxf"; + return Config::instance()->dcp_asset_filename_format().get(values, "_" + asset->id() + ".mxf"); } string @@ -635,13 +668,12 @@ audio_asset_filename (shared_ptr asset, int reel_index, int ree { dcp::NameFormat::Map values; values['t'] = "pcm"; - values['i'] = asset->id(); values['r'] = raw_convert (reel_index + 1); values['n'] = raw_convert (reel_count); if (summary) { - values['c'] = summary.get(); + values['c'] = careful_string_filter (summary.get()); } - return Config::instance()->dcp_asset_filename_format().get(values) + ".mxf"; + return Config::instance()->dcp_asset_filename_format().get(values, "_" + asset->id() + ".mxf"); } float @@ -656,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; }