diff --git a/macros/ltoptions.m4 b/macros/ltoptions.m4 index 94b0829..b0b5e9c 100644 --- a/macros/ltoptions.m4 +++ b/macros/ltoptions.m4 @@ -1,7 +1,7 @@ # Helper functions for option handling. -*- Autoconf -*- # -# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software -# Foundation, Inc. +# Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free +# Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives diff --git a/macros/ltsugar.m4 b/macros/ltsugar.m4 index 48bc934..902508b 100644 --- a/macros/ltsugar.m4 +++ b/macros/ltsugar.m4 @@ -1,6 +1,6 @@ # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # -# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software +# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # diff --git a/macros/ltversion.m4 b/macros/ltversion.m4 index fa04b52..0026c21 100644 --- a/macros/ltversion.m4 +++ b/macros/ltversion.m4 @@ -1,6 +1,7 @@ # ltversion.m4 -- version numbers -*- Autoconf -*- # -# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. +# Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation, +# Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives @@ -9,15 +10,15 @@ # @configure_input@ -# serial 4179 ltversion.m4 +# serial 4249 ltversion.m4 # This file is part of GNU Libtool -m4_define([LT_PACKAGE_VERSION], [2.4.6]) -m4_define([LT_PACKAGE_REVISION], [2.4.6]) +m4_define([LT_PACKAGE_VERSION], [2.4.7.4-1ec8f-dirty]) +m4_define([LT_PACKAGE_REVISION], [2.4.7.4]) AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.4.6' -macro_revision='2.4.6' +[macro_version='2.4.7.4-1ec8f-dirty' +macro_revision='2.4.7.4' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) diff --git a/macros/lt~obsolete.m4 b/macros/lt~obsolete.m4 index c6b26f8..0f7a875 100644 --- a/macros/lt~obsolete.m4 +++ b/macros/lt~obsolete.m4 @@ -1,7 +1,7 @@ # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # -# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software -# Foundation, Inc. +# Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free +# Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives diff --git a/scribbu/charsets.cc b/scribbu/charsets.cc index d9fcd89..0d5a37f 100644 --- a/scribbu/charsets.cc +++ b/scribbu/charsets.cc @@ -344,6 +344,36 @@ namespace scribbu { return os << TBL.at(x); } + + std::istream &operator>>(std::istream &is, on_no_encoding &x) + { + using namespace std; + static const unordered_map> TBL{ + { "fail", on_no_encoding::fail }, + { "ignore", on_no_encoding::ignore }, + { "transliterate", on_no_encoding::transliterate }, + }; + + string text; + is >> text; + + x = TBL.at(text); + + return is; + } + + std::ostream &operator<<(std::ostream &os, const on_no_encoding &x) + { + using namespace std; + static const unordered_map> TBL{ + { on_no_encoding::fail, "fail" }, + { on_no_encoding::ignore, "ignore" }, + { on_no_encoding::transliterate, "transliterate" }, + }; + + return os << TBL.at(x); + } + } namespace scribbu { diff --git a/scribbu/charsets.hh b/scribbu/charsets.hh index 4afcc07..9764e42 100644 --- a/scribbu/charsets.hh +++ b/scribbu/charsets.hh @@ -136,6 +136,9 @@ namespace scribbu { fail, transliterate, ignore }; + std::istream& operator>>(std::istream &is, on_no_encoding &x); + std::ostream& operator<<(std::ostream &os, const on_no_encoding &x); + namespace detail { /////////////////////////////////////////////////////////////////////////// diff --git a/scribbu/scheme.cc b/scribbu/scheme.cc index 944e265..d7c3148 100644 --- a/scribbu/scheme.cc +++ b/scribbu/scheme.cc @@ -184,6 +184,13 @@ namespace { SCM_BOOL_F); } + if (!scm_is_exact_integer(scm_ver)) { + scm_error(sym_for_utf8("unexpected-type"), "scm_to_id3v2_tag", + "expected exact integer for ID3v2 version, got ~A", scm, + SCM_BOOL_F); + + } + int version = scm_to_int(scm_ver); bool fexp = false; diff --git a/scribbu/scribbu.cc b/scribbu/scribbu.cc index cfdd24a..2a5e39e 100644 --- a/scribbu/scribbu.cc +++ b/scribbu/scribbu.cc @@ -419,5 +419,3 @@ scribbu::urldecode(const std::string &text) return out; } - - diff --git a/src/m3u.cc b/src/m3u.cc index ff0b90e..3e6394d 100644 --- a/src/m3u.cc +++ b/src/m3u.cc @@ -90,13 +90,17 @@ playlist in UTF-8 format, say: Summary of options: - -s SRC, --source-encoding=SRC Specify the text encoding in which textual - ID3 tags like artist & title are written - -o OUT, --output=OUT Specify that output be written to file OUT - -a, --append Append, don't overwrite OUT + -v, --verbose Produce more verbose output -8, --use-utf-8 Write the output in utf-8, not the system locale's encoding - -v, --verbose Produce more verbose output + -a, --append Append, don't overwrite OUT + -e RSP, --on-encoding-failure=RSP + Specify how to handle encoding errors; may + be one of 'fail', 'transliterate', or 'ignore' + (defaults to 'fail') + -o OUT, --output=OUT Specify that output be written to file OUT + -s SRC, --source-encoding=SRC Specify the text encoding in which textual + ID3 tags like artist & title are written For detailed help, say `scribbu m3u --help'. To see the manual, say `info "scribbu (m3u)"'. @@ -113,8 +117,9 @@ namespace { { public: m3u(std::ostream& os, boost::optional src_enc, bool verbose, - scribbu::encoding dst_enc): - os_(os), src_enc_(src_enc), dst_enc_(dst_enc), verbose_(verbose) + scribbu::encoding dst_enc, scribbu::on_no_encoding on_enc_fail): + os_(os), src_enc_(src_enc), dst_enc_(dst_enc), verbose_(verbose), + on_enc_fail_(on_enc_fail) { } public: @@ -135,8 +140,11 @@ namespace { boost::optional src_enc_; scribbu::encoding dst_enc_; bool verbose_; + scribbu::on_no_encoding on_enc_fail_; }; + /// Guess a display title for a tagset. Return boost::none if unable to do so + /// (e.g. no ID3 tags, or unable to convert the character encodings therein), template boost::optional m3u::guess_display_title(forward_input_iterator ptagv2_0, @@ -146,33 +154,38 @@ namespace { using namespace std; using namespace scribbu; - forward_input_iterator p = - find_if(ptagv2_0, ptagv2_1, - [](const unique_ptr& ptag) { - return ptag->has_artist() && ptag->has_title(); - }); + try { + forward_input_iterator p = + find_if(ptagv2_0, ptagv2_1, + [](const unique_ptr& ptag) { + return ptag->has_artist() && ptag->has_title(); + }); - if (p != ptagv2_1) { + if (p != ptagv2_1) { - string a = (*p)->artist(dst_enc_, on_no_encoding::fail, src_enc_);; - string t = (*p)->title(dst_enc_, on_no_encoding::fail, src_enc_); + string a = (*p)->artist(dst_enc_, on_enc_fail_, src_enc_);; + string t = (*p)->title(dst_enc_, on_enc_fail_, src_enc_); - if (!a.empty() && !t.empty()) { - return a + " - " + t; + if (!a.empty() && !t.empty()) { + return a + " - " + t; + } } - } - if (ptagv1) { - string a = ptagv1->artist(src_enc_, dst_enc_); - string t = ptagv1->title(src_enc_, dst_enc_); + if (ptagv1) { + string a = ptagv1->artist(src_enc_, dst_enc_, on_enc_fail_); + string t = ptagv1->title(src_enc_, dst_enc_, on_enc_fail_); if (!a.empty() && !t.empty()) { return a + " - " + t; } + } + } catch (const iconv_error &ex) { + if (verbose()) { + cerr << "Character encoding error: " << ex.what() << endl; + } } return boost::none; - } void @@ -189,7 +202,7 @@ namespace { string display; boost::optional gdt; - if (gdt = guess_display_title(id3v2.begin(), id3v2.end(), pid3v1.get())) { + if ((gdt = guess_display_title(id3v2.begin(), id3v2.end(), pid3v1.get()))) { display = *gdt; } else { display = pth.stem().native(); @@ -207,12 +220,16 @@ namespace { class m3u_to_stdout: public m3u { public: - m3u_to_stdout(boost::optional src_enc, bool verbose); + m3u_to_stdout(boost::optional src_enc, bool verbose, + scribbu::on_no_encoding on_enc_fail); }; - m3u_to_stdout::m3u_to_stdout(boost::optional src_enc, bool verbose): - m3u(std::cout, src_enc, verbose, scribbu::encoding_from_system_locale()) + m3u_to_stdout::m3u_to_stdout(boost::optional src_enc, + bool verbose, + scribbu::on_no_encoding on_enc_fail) + : m3u(std::cout, src_enc, verbose, scribbu::encoding_from_system_locale(), + on_enc_fail) { } ////////////////////////////////////////////////////////////////////////////// @@ -225,9 +242,10 @@ namespace { public: m3u_to_file(boost::optional src_enc, bool verbose, - const fs::path &out, - bool append, - bool use_utf8); + const fs::path &out, + bool append, + bool use_utf8, + scribbu::on_no_encoding on_enc_fail); private: std::ofstream ofs_; @@ -235,12 +253,12 @@ namespace { }; m3u_to_file::m3u_to_file(boost::optional src_enc, - bool verbose, - const fs::path &out, - bool append, - bool use_utf8): - m3u(ofs_, src_enc, verbose, - use_utf8 ? scribbu::encoding::UTF_8 : scribbu::encoding_from_system_locale()) + bool verbose, const fs::path &out, bool append, + bool use_utf8, scribbu::on_no_encoding on_enc_fail) + : m3u(ofs_, src_enc, verbose, + use_utf8 ? scribbu::encoding::UTF_8 + : scribbu::encoding_from_system_locale(), + on_enc_fail) { using namespace std; @@ -312,13 +330,17 @@ namespace { po::options_description opts("general options"); opts.add_options() + ("append,a", po::bool_switch(), "append to instead of overwriting the " + "output file (only applies if -o is given)") + ("on-encoding-failure,e", po::value()->default_value( + on_no_encoding::fail), + "specify how to handle encoding errors; may be one of 'fail', " + "'transliterate', or 'ignore' (defaults to 'fail')") + ("output,o", po::value(), "specify that output be written to " + "file instead of stdout") ("source-encoding,s", po::value()->default_value(encoding::CP1252), "specify the text encoding in which textual ID3 tags like artist & title " "are written") - ("output,o", po::value(), "specify that output be written to " - "file instead of stdout") - ("append,a", po::bool_switch(), "append to instead of overwriting the " - "output file (only applies if -o is given)") ("use-utf8,8", po::bool_switch(), "write the output in utf-8, not the " "system locale's encoding (only applies if -o is given)") ("verbose,v", po::bool_switch(), "produce more verbose output"); @@ -378,6 +400,7 @@ namespace { if (use_utf8 && out.empty()) { throw po::error("--use-utf8 is only relevant when --output is given"); } + on_no_encoding on_enc_fail = vm["on-encoding-failure"].as(); // Workaround to https://svn.boost.org/trac/boost/ticket/8535 std::vector args; @@ -386,10 +409,10 @@ namespace { } if (out.empty()) { - m3u_to_stdout F(src_enc, verbose); + m3u_to_stdout F(src_enc, verbose, on_enc_fail); process_dirent_args(args.begin(), args.end(), F); } else { - m3u_to_file F(src_enc, verbose, out, append, use_utf8); + m3u_to_file F(src_enc, verbose, out, append, use_utf8, on_enc_fail); process_dirent_args(args.begin(), args.end(), F); }