LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1646|回复: 3

audacious写入id3tag乱码问题

[复制链接]
发表于 2006-11-11 14:20:31 | 显示全部楼层 |阅读模式

背景:
  • audacious是由bmp fork出来的,而bmp是从xmms fork出来的,所以外观很相似,而且皮肤可以通用。
  • 我使用gentoo,所以下文里有些东西只适用于gentoo,比如USE flag和overlay。


版本:
我的audacious和audacious-plugins的版本及USE flag如下:
media-sound/audacious Installed: 1.2.1(chardet -gnome nls)
media-plugins/audacious-plugins Installed: 1.2.2-r1(aac alsa arts chardet -esd flac -jack -lirc -modplug mp3 -musepack nls -oss -pulseaudio -sid -sndfile timidity vorbis wma)
值得注意的一点是,我都加上了chardet USE flag,这样在UTF-8环境下就不必为本来encoding为GB码的mp3文件里的id3tag转码了。

设置:
只需要稍微设置一下:
Preference->laylit->Metadata:
auto character encoding detector for: Chinese
fallback character encoding: gbk
还有一点是,如果主窗口显示不出汉字。看看你是否选择了这个选项:
Preference->Appearance->Fonts->Use bitmap fonts if available
请不要选中这一项试试。如果使用微软雅黑,同时选中这个选项,主窗口的歌曲名如果是汉字就会乱码。而不选则不乱码。

问题和解决思路:
这两个地方设置过后,audacious已经几近完美了。不过还有一个问题,就是修改id3tag保存后,再打开该文件会发现id3tag乱码。
经过我的分析,原因大概是这样:
1. id3v2.4.0标准里定义了tag可以有4种encoding,可以在tag里标明,占用一个字节,其中UTF8的值为3。
2. 如果指定encoding为utf8,taglib在写入时会遵循标准的约定,在tag里用一个字节表示encoding,就是3。
TextIdentificationFrame::renderFields()
3. 但是在读取tag的时候,我发现似乎taglib根本没有考虑这里还有个字节表示encoding。而是把3看作字符串的一部分。
StringList::toString()仅仅是把list里的String相加。
这样当然就会乱码了。
这恐怕应该算是taglib的一个flaw吧,暂时的解决办法,我想可以不指定以utf8为encoding写入。那样的话,就是Latin1,而它的值是0,这样有也就相当于没有。

此外,在保存id3v1 tag的时候,还有另外一个问题。就是如果指定了encoding为utf8,保存时就已经乱码了。
TagPrivate::stringHandler->render(d->title)
d->title这个时候已经是以utf16(这是taglib内部保存字符串的形式,参见prepare())保存的了。我们看StringHandler::render的实现
ByteVector ID3v1::StringHandler::render(const String &s) const
{
return s.data(String:atin1);
}
实际上这个时候只有以String::UTF8调用data才能把utf16转回utf8,可惜的是这里居然是不做任何判断的就用了String:atin1。

补丁:
注意,这个补丁恐怕只是权宜之计。gentoo用户可以在layman -S之后,直接emerge -1 audacious-plugins。
diff -urN audacious-plugins-1.2.2.orig/src/mpg123/fileinfo.c audacious-plugins-1.2.2/src/mpg123/fileinfo.c
--- audacious-plugins-1.2.2.orig/src/mpg123/fileinfo.c  2006-11-11 02:41:10.000000000 +0800
+++ audacious-plugins-1.2.2/src/mpg123/fileinfo.c       2006-11-11 02:42:14.000000000 +0800
@@ -117,7 +117,7 @@
   if (str_has_prefix_nocase(current_filename, "http://"))
     return;

-  taglib_set_strings_unicode(1);
+  taglib_set_strings_unicode(0);

   /* XXX: Gnome VFS workaround. -nenolod */
   if (str_has_prefix_nocase(current_filename, "file://"))
diff -urN audacious-plugins-1.2.2.orig/src/mpg123/tag_c_hacked.cxx audacious-plugins-1.2.2/src/mpg123/tag_c_hacked.cxx
--- audacious-plugins-1.2.2.orig/src/mpg123/tag_c_hacked.cxx    2006-11-11 02:42:34.000000000 +0800
+++ audacious-plugins-1.2.2/src/mpg123/tag_c_hacked.cxx 2006-09-18 18:14:20.000000000 +0800
@@ -9,6 +9,6 @@
using namespace ID3v2;
void taglib_set_id3v2_default_text_encoding()
{
-  TagLib::ID3v2::FrameFactory::instance()->setDefaultTextEncoding(TagLib::String::UTF8);
+  TagLib::ID3v2::FrameFactory::instance()->setDefaultTextEncoding(TagLib::String:atin1);
}
发表于 2006-11-11 14:38:57 | 显示全部楼层
强烈支持!!

audacious 现在可以算完美了
回复 支持 反对

使用道具 举报

发表于 2006-11-12 13:55:20 | 显示全部楼层
赞!原来有chardet这个USE,以后不用转tag了!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-12 14:03:41 | 显示全部楼层
我重写了补丁,可以尝试提交了
diff -urN audacious-plugins-1.2.2.orig/src/mpg123/fileinfo.c audacious-plugins-1.2.2/src/mpg123/fileinfo.c
--- audacious-plugins-1.2.2.orig/src/mpg123/fileinfo.c        2006-10-16 00:41:42.000000000 +0800
+++ audacious-plugins-1.2.2/src/mpg123/fileinfo.c        2006-11-12 00:11:30.000000000 +0800
@@ -117,7 +117,9 @@
   if (str_has_prefix_nocase(current_filename, "http://"))
     return;

+#ifndef USE_CHARDET
   taglib_set_strings_unicode(1);
+#endif

   /* XXX: Gnome VFS workaround. -nenolod */
   if (str_has_prefix_nocase(current_filename, "file://"))
@@ -129,7 +131,9 @@
     taglib_ap = taglib_file_audioproperties(taglib_file);
   } else return;

+#ifndef USE_CHARDET
   taglib_set_id3v2_default_text_encoding();
+#endif
   taglib_tag_set_title(taglib_tag, gtk_entry_get_text(GTK_ENTRY(title_entry)));
   taglib_tag_set_artist(taglib_tag, gtk_entry_get_text(GTK_ENTRY(artist_entry)));
   taglib_tag_set_album(taglib_tag, gtk_entry_get_text(GTK_ENTRY(album_entry)));
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表