Re: Handling ID3 tags with non-latin1 encoding
Kurt Roeckx <[email protected]> Wed, 7 Jun 2006 08:46:47 +0200
| Newsgroups | gmane.comp.audio.mad.devel |
|---|---|
| Message-ID | <[email protected]> |
On Tue, Jun 06, 2006 at 06:38:04PM -0700, Rob Leslie wrote:
> >I'm not sure what's the best way to convert it from ucs4 to wchar_t
> >though, and can't think of a portable way, and I'd love if someone
> >could point me out how to do it.
> >
> >(On Linux (glibc), casting it from a id3_ucs4_t to a wchar_t seems
> >to work, but it's not portable.)
>
> There's nothing wrong with this per se as long as wchar_t is at least
> 21 bits wide (for example, when __STDC_ISO_10646__ is defined) or you
> are sure the UCS-4 code point in question can otherwise be
> represented by a wchar_t -- and the relevant locale is compatible.
The biggest problem being that "the locale is compatible" means
it's not very portable.
> Note that casting id3_ucs4_t to wchar_t is not the same as casting
> (id3_ucs4_t *) to (wchar_t *); the latter is definitely not portable
> though it may work if the underlying types happen to have the same size.
As I pointed out, on 64 bit arches, they're typicaly of different
size, so break.
> A simple way to translate a UCS-4 string to wchar_t might be (untested):
>
> wchar_t *ucs4_to_wchar(id3_ucs4_t const *ucs4)
> {
> wchar_t *wchar;
>
> wchar = malloc(id3_ucs4_size(ucs4) * sizeof(wchar_t));
> if (wchar) {
> wchar_t *ptr = wchar;
> while ((*ptr++ = (wchar_t) *ucs4++))
> ;
> }
>
> return wchar;
> }
I've used the following code:
wchar_t *ucs4_to_wchar_strdup(const id3_ucs4_t *ucs4)
{
id3_length_t size = id3_ucs4_size(ucs4);
wchar_t *s = malloc(size * sizeof(wchar_t));
id3_length_t i;
for (i = 0; i < size; i++)
{
s[i] = ucs4[i];
}
return s;
}
Which basicly does about the same, but doesn't do error
checking, and seems to work. The problem however is that
id3_ucs4_size isn't exported in the header files that get
installed.
Anyway, I think now what might be more portable is that you just
run iconv() to convert it from ucs4 to nl_langinfo(CODESET); If
you want, you can then convert things with something like
mbtowc() to a wchar_t afterwards, but this isn't needed.
Note that iconv() might not be able to represent everything in
CODESET, but you'll have that problem anyway once you try to
output it.
I'll try and send a patch for madplayer/player.c later, if you
think this should work and is acceptable. I'm just not sure how
happy you are about things that are SUS/POSIX specific, since both
iconv() and nl_langinfo() are.
Kurt