Skip to content

Commit

Permalink
Improve both the m3u sub-command and the Scheme interface.
Browse files Browse the repository at this point in the history
This patch is an accumulation of a few things:

    - change the `m3u` sub-command to make progress on character
      encoding failures
    - add a new `m3u` option to help userse control character
      encoding conversions
    - add a check in the Scheme interface (alright-- this was
      laying around in my local repo & I'm now picking it up)
  • Loading branch information
sp1ff committed Dec 22, 2023
1 parent b108761 commit b770279
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 54 deletions.
4 changes: 2 additions & 2 deletions macros/ltoptions.m4
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion macros/ltsugar.m4
Original file line number Diff line number Diff line change
@@ -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
#
Expand Down
13 changes: 7 additions & 6 deletions macros/ltversion.m4
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)
])
4 changes: 2 additions & 2 deletions macros/lt~obsolete.m4
Original file line number Diff line number Diff line change
@@ -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
Expand Down
30 changes: 30 additions & 0 deletions scribbu/charsets.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, on_no_encoding, hash<string>> 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<on_no_encoding, string, hash<on_no_encoding>> TBL{
{ on_no_encoding::fail, "fail" },
{ on_no_encoding::ignore, "ignore" },
{ on_no_encoding::transliterate, "transliterate" },
};

return os << TBL.at(x);
}

}

namespace scribbu {
Expand Down
3 changes: 3 additions & 0 deletions scribbu/charsets.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

///////////////////////////////////////////////////////////////////////////
Expand Down
7 changes: 7 additions & 0 deletions scribbu/scheme.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 0 additions & 2 deletions scribbu/scribbu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -419,5 +419,3 @@ scribbu::urldecode(const std::string &text)

return out;
}


105 changes: 64 additions & 41 deletions src/m3u.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)"'.
Expand All @@ -113,8 +117,9 @@ namespace {
{
public:
m3u(std::ostream& os, boost::optional<scribbu::encoding> 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:
Expand All @@ -135,8 +140,11 @@ namespace {
boost::optional<scribbu::encoding> 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 <typename forward_input_iterator>
boost::optional<std::string>
m3u::guess_display_title(forward_input_iterator ptagv2_0,
Expand All @@ -146,33 +154,38 @@ namespace {
using namespace std;
using namespace scribbu;

forward_input_iterator p =
find_if(ptagv2_0, ptagv2_1,
[](const unique_ptr<id3v2_tag>& ptag) {
return ptag->has_artist() && ptag->has_title();
});
try {
forward_input_iterator p =
find_if(ptagv2_0, ptagv2_1,
[](const unique_ptr<id3v2_tag>& 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<string>(src_enc_, dst_enc_);
string t = ptagv1->title<string>(src_enc_, dst_enc_);
if (ptagv1) {
string a = ptagv1->artist<string>(src_enc_, dst_enc_, on_enc_fail_);
string t = ptagv1->title<string>(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
Expand All @@ -189,7 +202,7 @@ namespace {

string display;
boost::optional<string> 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();
Expand All @@ -207,12 +220,16 @@ namespace {
class m3u_to_stdout: public m3u
{
public:
m3u_to_stdout(boost::optional<scribbu::encoding> src_enc, bool verbose);
m3u_to_stdout(boost::optional<scribbu::encoding> src_enc, bool verbose,
scribbu::on_no_encoding on_enc_fail);

};

m3u_to_stdout::m3u_to_stdout(boost::optional<scribbu::encoding> src_enc, bool verbose):
m3u(std::cout, src_enc, verbose, scribbu::encoding_from_system_locale())
m3u_to_stdout::m3u_to_stdout(boost::optional<scribbu::encoding> 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)
{ }

//////////////////////////////////////////////////////////////////////////////
Expand All @@ -225,22 +242,23 @@ namespace {
public:
m3u_to_file(boost::optional<scribbu::encoding> 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_;

};

m3u_to_file::m3u_to_file(boost::optional<scribbu::encoding> 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;

Expand Down Expand Up @@ -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<on_no_encoding>()->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<fs::path>(), "specify that output be written to "
"file instead of stdout")
("source-encoding,s", po::value<encoding>()->default_value(encoding::CP1252),
"specify the text encoding in which textual ID3 tags like artist & title "
"are written")
("output,o", po::value<fs::path>(), "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");
Expand Down Expand Up @@ -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<on_no_encoding>();

// Workaround to https://svn.boost.org/trac/boost/ticket/8535
std::vector<fs::path> args;
Expand All @@ -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);
}

Expand Down

0 comments on commit b770279

Please sign in to comment.