Daisuke Shimamura's id3 v1/v2 + i18n patches

This commit is contained in:
Josh Coalson 2002-07-11 06:15:30 +00:00
parent d8ab3468fa
commit 412fa3b7a2
15 changed files with 2209 additions and 76 deletions

View File

@ -104,6 +104,49 @@ AM_CONDITIONAL(FLaC__HAS_XMMS, test x$XMMS_INPUT_PLUGIN_DIR != x)
SHARE_LIBS='$(top_builddir)/src/share/libutf8.a $(top_builddir)/src/share/libgetopt.a'
dnl check for i18n(internationalization)
AM_WITH_NLS
AM_ICONV
AM_LANGINFO_CODESET
dnl check id3lib librairies
LIBS_save_blah_blah_blah=$LIBS
LIBS=""
AC_SEARCH_LIBS(ID3Tag_Link,"id3" "id3 -lstdc++" "id3 -lz" "id3 -lz -lstdc++",
[have_id3lib=yes],
[AC_MSG_WARN([id3lib not found - ID3v2 will not be supported, internal function support only id3v1])])
AM_CONDITIONAL(FLaC__HAS_ID3LIB, [test x$have_id3lib = xyes])
if test x$have_id3lib = xyes ; then
AC_DEFINE(FLAC__HAS_ID3LIB)
ID3LIBS=$LIBS
fi
AC_SUBST(ID3LIBS)
dnl expected version for cross compiling
ID3LIB_MAJOR=3
ID3LIB_MINOR=8
ID3LIB_PATCH=0
AC_MSG_CHECKING(for id3lib version)
AC_TRY_RUN([
#include <id3.h>
#include <stdio.h>
int
main ()
{
FILE *output;
output=fopen("conftest.id3","w");
fprintf(output,"ID3LIB_MAJOR=%d\nID3LIB_MINOR=%d\nID3LIB_PATCH=%d\n",ID3LIB_MAJOR_VERSION,ID3LIB_MINOR_VERSION,ID3LIB_PATCH_VERSION);
fclose(output);
exit(0);
}
], . conftest.id3; echo "${ID3LIB_MAJOR}.${ID3LIB_MINOR}.${ID3LIB_PATCH}", AC_MSG_WARN(could not determine id3lib version),[echo $ac_n "cross compiling; assuming ${ID3LIB_MAJOR}.${ID3LIB_MINOR}.${ID3LIB_PATCH} $ac_c"])
AC_DEFINE_UNQUOTED(ID3LIB_MAJOR, $ID3LIB_MAJOR)
AC_DEFINE_UNQUOTED(ID3LIB_MINOR, $ID3LIB_MINOR)
AC_DEFINE_UNQUOTED(ID3LIB_PATCH, $ID3LIB_PATCH)
LIBS=$LIBS_save_blah_blah_blah
AC_CHECK_PROGS(NASM, nasm)
AM_CONDITIONAL(FLaC__HAS_NASM, test -n "$NASM")
if test -n "$NASM" ; then

View File

@ -20,15 +20,26 @@
#
EXTRA_DIST = \
Makefile.lite
Makefile.lite \
id3_tag.c
CFLAGS = @CFLAGS@ @XMMS_CFLAGS@
xmmsinputplugindir = @XMMS_INPUT_PLUGIN_DIR@
# Don't build a static library
LIBTOOL = $(top_builddir)/libtool-disable-static
xmmsinputplugin_LTLIBRARIES = libxmms-flac.la
libxmms_flac_la_SOURCES = plugin.c
plugin_sources = plugin.c wrap_id3.c configure.c charset.c
id3v2_sources = id3_tag.c
if FLaC__HAS_ID3LIB
libxmms_flac_la_SOURCES = $(plugin_sources) $(id3v2_sources)
else
libxmms_flac_la_SOURCES = $(plugin_sources)
endif
# work around the bug in libtool where its relinking fails with a different DESTDIR
# for libtool bug info see:
# http://mail.gnu.org/pipermail/bug-libtool/2002-February/003018.html
@ -37,5 +48,5 @@ libxmms_flac_la_SOURCES = plugin.c
# for fix info see:
# http://lists.freshrpms.net/pipermail/rpm-list/2002-April/000746.html
# the workaround is the extra '-L$(top_builddir)/src/libFLAC/.libs'
libxmms_flac_la_LIBADD = $(top_builddir)/src/libFLAC/libFLAC.la -L$(top_builddir)/src/libFLAC/.libs @XMMS_LIBS@
libxmms_flac_la_LIBADD = $(top_builddir)/src/libFLAC/libFLAC.la -L$(top_builddir)/src/libFLAC/.libs @XMMS_LIBS@ @ID3LIBS@
libxmms_flac_la_LDFLAGS = -module -avoid-version

View File

@ -24,7 +24,11 @@ INCLUDES = $(shell xmms-config --cflags) -I./include -I../../include
LIBS = ../../obj/lib/libFLAC.a
OBJS = \
plugin.o
plugin.o \
configure.o \
wrap_id3.o \
charset.o
include ../../build/lib.mk

306
src/plugin_xmms/charset.c Normal file
View File

@ -0,0 +1,306 @@
/* libxmms-flac - XMMS FLAC input plugin
* Copyright (C) 2002 Daisuke Shimamura
*
* Almost from charset.c
* EasyTAG - Tag editor for MP3 and OGG files
* Copyright (C) 1999-2001 Håvard Kvålen <havardk@xmms.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <glib.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_ICONV
#include <iconv.h>
#endif
#ifdef HAVE_LANGINFO_CODESET
#include <langinfo.h>
#endif
#include "charset.h"
#include "mylocale.h"
#include "configure.h"
/****************
* Declarations *
****************/
#define CHARSET_TRANS_ARRAY_LEN ( sizeof(charset_trans_array) / sizeof((charset_trans_array)[0]) )
const CharsetInfo charset_trans_array[] = {
{N_("Arabic (IBM-864)"), "IBM864" },
{N_("Arabic (ISO-8859-6)"), "ISO-8859-6" },
{N_("Arabic (Windows-1256)"), "windows-1256" },
{N_("Baltic (ISO-8859-13)"), "ISO-8859-13" },
{N_("Baltic (ISO-8859-4)"), "ISO-8859-4" },
{N_("Baltic (Windows-1257)"), "windows-1257" },
{N_("Celtic (ISO-8859-14)"), "ISO-8859-14" },
{N_("Central European (IBM-852)"), "IBM852" },
{N_("Central European (ISO-8859-2)"), "ISO-8859-2" },
{N_("Central European (Windows-1250)"), "windows-1250" },
{N_("Chinese Simplified (GB18030)"), "gb18030" },
{N_("Chinese Simplified (GB2312)"), "GB2312" },
{N_("Chinese Traditional (Big5)"), "Big5" },
{N_("Chinese Traditional (Big5-HKSCS)"), "Big5-HKSCS" },
{N_("Cyrillic (IBM-855)"), "IBM855" },
{N_("Cyrillic (ISO-8859-5)"), "ISO-8859-5" },
{N_("Cyrillic (ISO-IR-111)"), "ISO-IR-111" },
{N_("Cyrillic (KOI8-R)"), "KOI8-R" },
{N_("Cyrillic (Windows-1251)"), "windows-1251" },
{N_("Cyrillic/Russian (CP-866)"), "IBM866" },
{N_("Cyrillic/Ukrainian (KOI8-U)"), "KOI8-U" },
{N_("English (US-ASCII)"), "us-ascii" },
{N_("Greek (ISO-8859-7)"), "ISO-8859-7" },
{N_("Greek (Windows-1253)"), "windows-1253" },
{N_("Hebrew (IBM-862)"), "IBM862" },
{N_("Hebrew (Windows-1255)"), "windows-1255" },
{N_("Japanese (EUC-JP)"), "EUC-JP" },
{N_("Japanese (ISO-2022-JP)"), "ISO-2022-JP" },
{N_("Japanese (Shift_JIS)"), "Shift_JIS" },
{N_("Korean (EUC-KR)"), "EUC-KR" },
{N_("Nordic (ISO-8859-10)"), "ISO-8859-10" },
{N_("South European (ISO-8859-3)"), "ISO-8859-3" },
{N_("Thai (TIS-620)"), "TIS-620" },
{N_("Turkish (IBM-857)"), "IBM857" },
{N_("Turkish (ISO-8859-9)"), "ISO-8859-9" },
{N_("Turkish (Windows-1254)"), "windows-1254" },
{N_("Unicode (UTF-7)"), "UTF-7" },
{N_("Unicode (UTF-8)"), "UTF-8" },
{N_("Unicode (UTF-16BE)"), "UTF-16BE" },
{N_("Unicode (UTF-16LE)"), "UTF-16LE" },
{N_("Unicode (UTF-32BE)"), "UTF-32BE" },
{N_("Unicode (UTF-32LE)"), "UTF-32LE" },
{N_("Vietnamese (VISCII)"), "VISCII" },
{N_("Vietnamese (Windows-1258)"), "windows-1258" },
{N_("Visual Hebrew (ISO-8859-8)"), "ISO-8859-8" },
{N_("Western (IBM-850)"), "IBM850" },
{N_("Western (ISO-8859-1)"), "ISO-8859-1" },
{N_("Western (ISO-8859-15)"), "ISO-8859-15" },
{N_("Western (Windows-1252)"), "windows-1252" }
/*
* From this point, character sets aren't supported by iconv
*/
/* {N_("Arabic (IBM-864-I)"), "IBM864i" },
{N_("Arabic (ISO-8859-6-E)"), "ISO-8859-6-E" },
{N_("Arabic (ISO-8859-6-I)"), "ISO-8859-6-I" },
{N_("Arabic (MacArabic)"), "x-mac-arabic" },
{N_("Armenian (ARMSCII-8)"), "armscii-8" },
{N_("Central European (MacCE)"), "x-mac-ce" },
{N_("Chinese Simplified (GBK)"), "x-gbk" },
{N_("Chinese Simplified (HZ)"), "HZ-GB-2312" },
{N_("Chinese Traditional (EUC-TW)"), "x-euc-tw" },
{N_("Croatian (MacCroatian)"), "x-mac-croatian" },
{N_("Cyrillic (MacCyrillic)"), "x-mac-cyrillic" },
{N_("Cyrillic/Ukrainian (MacUkrainian)"), "x-mac-ukrainian" },
{N_("Farsi (MacFarsi)"), "x-mac-farsi"},
{N_("Greek (MacGreek)"), "x-mac-greek" },
{N_("Gujarati (MacGujarati)"), "x-mac-gujarati" },
{N_("Gurmukhi (MacGurmukhi)"), "x-mac-gurmukhi" },
{N_("Hebrew (ISO-8859-8-E)"), "ISO-8859-8-E" },
{N_("Hebrew (ISO-8859-8-I)"), "ISO-8859-8-I" },
{N_("Hebrew (MacHebrew)"), "x-mac-hebrew" },
{N_("Hindi (MacDevanagari)"), "x-mac-devanagari" },
{N_("Icelandic (MacIcelandic)"), "x-mac-icelandic" },
{N_("Korean (JOHAB)"), "x-johab" },
{N_("Korean (UHC)"), "x-windows-949" },
{N_("Romanian (MacRomanian)"), "x-mac-romanian" },
{N_("Turkish (MacTurkish)"), "x-mac-turkish" },
{N_("User Defined"), "x-user-defined" },
{N_("Vietnamese (TCVN)"), "x-viet-tcvn5712" },
{N_("Vietnamese (VPS)"), "x-viet-vps" },
{N_("Western (MacRoman)"), "x-mac-roman" },
// charsets whithout posibly translatable names
{"T61.8bit", "T61.8bit" },
{"x-imap4-modified-utf7", "x-imap4-modified-utf7"},
{"x-u-escaped", "x-u-escaped" },
{"windows-936", "windows-936" }
*/
};
/*************
* Functions *
*************/
char* get_current_charset (void)
{
char *charset = getenv("CHARSET");
#ifdef HAVE_LANGINFO_CODESET
if (!charset)
charset = nl_langinfo(CODESET);
#endif
if (!charset)
charset = "ISO-8859-1";
return charset;
}
#ifdef HAVE_ICONV
static char* convert_string (const char *string, char *from, char *to)
{
size_t outleft, outsize, length;
iconv_t cd;
char *out, *outptr;
const char *input = string;
if (!string)
return NULL;
length = strlen(string);
/* g_message("converting %s from %s to %s", string, from, to); */
if ((cd = iconv_open(to, from)) == (iconv_t)-1)
{
g_warning("convert_string(): Conversion not supported. Charsets: %s -> %s", from, to);
return g_strdup(string);
}
/* Due to a GLIBC bug, round outbuf_size up to a multiple of 4 */
/* + 1 for nul in case len == 1 */
outsize = ((length + 3) & ~3) + 1;
out = g_malloc(outsize);
outleft = outsize - 1;
outptr = out;
retry:
if (iconv(cd, &input, &length, &outptr, &outleft) == -1)
{
int used;
switch (errno)
{
case E2BIG:
used = outptr - out;
outsize = (outsize - 1) * 2 + 1;
out = g_realloc(out, outsize);
outptr = out + used;
outleft = outsize - 1 - used;
goto retry;
case EINVAL:
break;
case EILSEQ:
/* Invalid sequence, try to get the
rest of the string */
input++;
length = strlen(input);
goto retry;
default:
g_warning("convert_string(): Conversion failed. Inputstring: %s; Error: %s", string, strerror(errno));
break;
}
}
*outptr = '\0';
iconv_close(cd);
return out;
}
#else
static char* convert_string (const char *string, char *from, char *to)
{
if (!string)
return NULL;
return g_strdup(string);
}
#endif
/*
* Commons conversion functions
*/
char* convert_from_file_to_user (const char *string)
{
char *file_charset = flac_cfg.file_char_set;
char *user_charset = flac_cfg.user_char_set;
return convert_string(string,file_charset,user_charset);
}
char* convert_from_user_to_file (const char *string)
{
char *file_charset = flac_cfg.file_char_set;
char *user_charset = flac_cfg.user_char_set;
return convert_string(string,user_charset,file_charset);
}
GList *Charset_Create_List (void)
{
GList *list = NULL;
guint i;
for (i=0; i<CHARSET_TRANS_ARRAY_LEN; i++)
list = g_list_append(list,_(charset_trans_array[i].charset_title));
return list;
}
/*
* Return charset_name from charset_title
*/
gchar *Charset_Get_Name_From_Title (gchar *charset_title)
{
guint i;
if (charset_title)
for (i=0; i<CHARSET_TRANS_ARRAY_LEN; i++)
if ( strcasecmp(_(charset_title),_(charset_trans_array[i].charset_title)) == 0 )
return charset_trans_array[i].charset_name;
return "";
}
/*
* Return charset_title from charset_name
*/
gchar *Charset_Get_Title_From_Name (gchar *charset_name)
{
guint i;
if (charset_name)
for (i=0; i<CHARSET_TRANS_ARRAY_LEN; i++)
if ( strcasecmp(charset_name,charset_trans_array[i].charset_name) == 0 )
return _(charset_trans_array[i].charset_title);
return "";
}
/*
* Test if the conversion is supported between two character sets ('from' and 'to)
*/
#ifdef HAVE_ICONV
gboolean test_conversion_charset (char *from, char *to)
{
iconv_t cd;
if ((cd=iconv_open(to,from)) == (iconv_t)-1)
{
/* Conversion not supported */
return FALSE;
}
iconv_close(cd);
return TRUE;
}
#else
gboolean test_conversion_charset (char *from, char *to)
{
return TRUE;
}
#endif

57
src/plugin_xmms/charset.h Normal file
View File

@ -0,0 +1,57 @@
/* libxmms-flac - XMMS FLAC input plugin
* Copyright (C) 2002 Daisuke Shimamura
*
* Almost from charset.h - 2001/12/04
* EasyTAG - Tag editor for MP3 and OGG files
* Copyright (C) 1999-2001 H蛆ard Kv虱en <havardk@xmms.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CHARSET_H__
#define __CHARSET_H__
/***************
* Declaration *
***************/
typedef struct {
gchar *charset_title;
gchar *charset_name;
} CharsetInfo;
/* translated charset titles */
extern const CharsetInfo charset_trans_array[];
/**************
* Prototypes *
**************/
gchar* get_current_charset (void);
gchar* convert_from_file_to_user (const gchar *string);
gchar* convert_from_user_to_file (const gchar *string);
GList *Charset_Create_List (void);
gchar *Charset_Get_Name_From_Title (gchar *charset_title);
gchar *Charset_Get_Title_From_Name (gchar *charset_name);
gboolean test_conversion_charset (char *from, char *to);
#endif /* __CHARSET_H__ */

258
src/plugin_xmms/configure.c Normal file
View File

@ -0,0 +1,258 @@
/* libxmms-flac - XMMS FLAC input plugin
* Copyright (C) 2002 Daisuke Shimamura
*
* Based on mpg123 plugin
* and prefs.c - 2000/05/06
* EasyTAG - Tag editor for MP3 and OGG files
* Copyright (C) 2000-2002 Jerome Couderc <j.couderc@ifrance.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <pthread.h>
#include <xmms/configfile.h>
#include <xmms/dirbrowser.h>
#include <xmms/titlestring.h>
#include <xmms/util.h>
#include <xmms/plugin.h>
#include "mylocale.h"
#include "charset.h"
#include "configure.h"
/*
* Initialize Global Valueable
*/
flac_config_t flac_cfg = {
FALSE,
NULL,
FALSE,
NULL,
NULL
};
static GtkWidget *flac_configurewin = NULL;
static GtkWidget *vbox, *notebook;
static GtkWidget *title_tag_override, *title_tag_box, *title_tag_entry, *title_desc;
static GtkWidget *convert_char_set, *fileCharacterSetEntry, *userCharacterSetEntry;
static gchar *gtk_entry_get_text_1 (GtkWidget *widget);
static void flac_configurewin_ok(GtkWidget * widget, gpointer data);
static void configure_destroy(GtkWidget * w, gpointer data);
static void title_tag_override_cb(GtkWidget * w, gpointer data);
static void convert_char_set_cb(GtkWidget * w, gpointer data);
static void flac_configurewin_ok(GtkWidget * widget, gpointer data)
{
ConfigFile *cfg;
gchar *filename;
g_free(flac_cfg.tag_format);
flac_cfg.tag_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(title_tag_entry)));
flac_cfg.file_char_set = Charset_Get_Name_From_Title(gtk_entry_get_text_1(fileCharacterSetEntry));
flac_cfg.user_char_set = Charset_Get_Name_From_Title(gtk_entry_get_text_1(userCharacterSetEntry));
filename = g_strconcat(g_get_home_dir(), "/.xmms/config", NULL);
cfg = xmms_cfg_open_file(filename);
if (!cfg)
cfg = xmms_cfg_new();
xmms_cfg_write_boolean(cfg, "flac", "tag_override", flac_cfg.tag_override);
xmms_cfg_write_string(cfg, "flac", "tag_format", flac_cfg.tag_format);
xmms_cfg_write_boolean(cfg, "flac", "convert_char_set", flac_cfg.convert_char_set);
xmms_cfg_write_string(cfg, "flac", "file_char_set", flac_cfg.file_char_set);
xmms_cfg_write_string(cfg, "flac", "user_char_set", flac_cfg.user_char_set);
xmms_cfg_write_file(cfg, filename);
xmms_cfg_free(cfg);
g_free(filename);
gtk_widget_destroy(flac_configurewin);
}
static void configure_destroy(GtkWidget * w, gpointer data)
{
}
static void title_tag_override_cb(GtkWidget * w, gpointer data)
{
flac_cfg.tag_override = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(title_tag_override));
gtk_widget_set_sensitive(title_tag_box, flac_cfg.tag_override);
gtk_widget_set_sensitive(title_desc, flac_cfg.tag_override);
}
static void convert_char_set_cb(GtkWidget * w, gpointer data)
{
flac_cfg.convert_char_set = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(convert_char_set));
gtk_widget_set_sensitive(fileCharacterSetEntry, flac_cfg.convert_char_set);
gtk_widget_set_sensitive(userCharacterSetEntry, flac_cfg.convert_char_set);
}
void FLAC_XMMS__configure(void)
{
GtkWidget *title_frame, *title_tag_vbox, *title_tag_label;
GtkWidget *label, *hbox;
GtkWidget *bbox, *ok, *cancel;
GList *list;
if (flac_configurewin != NULL) {
gdk_window_raise(flac_configurewin->window);
return;
}
flac_configurewin = gtk_window_new(GTK_WINDOW_DIALOG);
gtk_signal_connect(GTK_OBJECT(flac_configurewin), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &flac_configurewin);
gtk_signal_connect(GTK_OBJECT(flac_configurewin), "destroy", GTK_SIGNAL_FUNC(configure_destroy), &flac_configurewin);
gtk_window_set_title(GTK_WINDOW(flac_configurewin), _("Flac Configuration"));
gtk_window_set_policy(GTK_WINDOW(flac_configurewin), FALSE, FALSE, FALSE);
gtk_container_border_width(GTK_CONTAINER(flac_configurewin), 10);
vbox = gtk_vbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(flac_configurewin), vbox);
notebook = gtk_notebook_new();
gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
/* Title config.. */
title_frame = gtk_frame_new(_("ID3 Tags:"));
gtk_container_border_width(GTK_CONTAINER(title_frame), 5);
title_tag_vbox = gtk_vbox_new(FALSE, 10);
gtk_container_border_width(GTK_CONTAINER(title_tag_vbox), 5);
gtk_container_add(GTK_CONTAINER(title_frame), title_tag_vbox);
/* Convert Char Set */
convert_char_set = gtk_check_button_new_with_label(_("Convert Character Set"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(convert_char_set), flac_cfg.convert_char_set);
gtk_signal_connect(GTK_OBJECT(convert_char_set), "clicked", convert_char_set_cb, NULL);
gtk_box_pack_start(GTK_BOX(title_tag_vbox), convert_char_set, FALSE, FALSE, 0);
// Combo boxes...
hbox = gtk_hbox_new(FALSE,4);
gtk_container_add(GTK_CONTAINER(title_tag_vbox),hbox);
label = gtk_label_new(_("Convert character set from :"));
gtk_box_pack_start(GTK_BOX(hbox),label,FALSE,FALSE,0);
fileCharacterSetEntry = gtk_combo_new();
gtk_box_pack_start(GTK_BOX(hbox),fileCharacterSetEntry,TRUE,TRUE,0);
label = gtk_label_new (_("to :"));
gtk_box_pack_start(GTK_BOX(hbox),label,FALSE,FALSE,0);
userCharacterSetEntry = gtk_combo_new();
gtk_box_pack_start(GTK_BOX(hbox),userCharacterSetEntry,TRUE,TRUE,0);
gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(fileCharacterSetEntry)->entry),FALSE);
gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(userCharacterSetEntry)->entry),FALSE);
gtk_combo_set_value_in_list(GTK_COMBO(fileCharacterSetEntry),TRUE,FALSE);
gtk_combo_set_value_in_list(GTK_COMBO(userCharacterSetEntry),TRUE,FALSE);
list = Charset_Create_List();
gtk_combo_set_popdown_strings(GTK_COMBO(fileCharacterSetEntry),list);
gtk_combo_set_popdown_strings(GTK_COMBO(userCharacterSetEntry),list);
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(fileCharacterSetEntry)->entry),Charset_Get_Title_From_Name(flac_cfg.file_char_set));
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(userCharacterSetEntry)->entry),Charset_Get_Title_From_Name(flac_cfg.user_char_set));
gtk_widget_set_sensitive(fileCharacterSetEntry, flac_cfg.convert_char_set);
gtk_widget_set_sensitive(userCharacterSetEntry, flac_cfg.convert_char_set);
/* Override Tagging Format */
title_tag_override = gtk_check_button_new_with_label(_("Override generic titles"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(title_tag_override), flac_cfg.tag_override);
gtk_signal_connect(GTK_OBJECT(title_tag_override), "clicked", title_tag_override_cb, NULL);
gtk_box_pack_start(GTK_BOX(title_tag_vbox), title_tag_override, FALSE, FALSE, 0);
title_tag_box = gtk_hbox_new(FALSE, 5);
gtk_widget_set_sensitive(title_tag_box, flac_cfg.tag_override);
gtk_box_pack_start(GTK_BOX(title_tag_vbox), title_tag_box, FALSE, FALSE, 0);
title_tag_label = gtk_label_new(_("Title format:"));
gtk_box_pack_start(GTK_BOX(title_tag_box), title_tag_label, FALSE, FALSE, 0);
title_tag_entry = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(title_tag_entry), flac_cfg.tag_format);
gtk_box_pack_start(GTK_BOX(title_tag_box), title_tag_entry, TRUE, TRUE, 0);
title_desc = xmms_titlestring_descriptions("pafFetnygc", 2);
gtk_widget_set_sensitive(title_desc, flac_cfg.tag_override);
gtk_box_pack_start(GTK_BOX(title_tag_vbox), title_desc, FALSE, FALSE, 0);
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), title_frame, gtk_label_new(_("Title")));
/* Buttons */
bbox = gtk_hbutton_box_new();
gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
ok = gtk_button_new_with_label(_("Ok"));
gtk_signal_connect(GTK_OBJECT(ok), "clicked", GTK_SIGNAL_FUNC(flac_configurewin_ok), NULL);
GTK_WIDGET_SET_FLAGS(ok, GTK_CAN_DEFAULT);
gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0);
gtk_widget_grab_default(ok);
cancel = gtk_button_new_with_label(_("Cancel"));
gtk_signal_connect_object(GTK_OBJECT(cancel), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(flac_configurewin));
GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT);
gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0);
gtk_widget_show_all(flac_configurewin);
}
void FLAC_XMMS__aboutbox()
{
static GtkWidget *about_window;
if (about_window)
gdk_window_raise(about_window->window);
about_window = xmms_show_message(
_("About Flac Plugin"),
_("Flac Plugin by Josh Coalson\n"
"contributions by\n"
"......\n"
"......\n"
"and\n"
"Daisuke Shimamura\n"
"Visit http://flac.sourceforge.net/"),
_("Ok"), FALSE, NULL, NULL);
gtk_signal_connect(GTK_OBJECT(about_window), "destroy",
GTK_SIGNAL_FUNC(gtk_widget_destroyed),
&about_window);
}
/*
* Get text of an Entry or a ComboBox
*/
static gchar *gtk_entry_get_text_1 (GtkWidget *widget)
{
if (GTK_IS_COMBO(widget))
{
return gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(widget)->entry));
}else if (GTK_IS_ENTRY(widget))
{
return gtk_entry_get_text(GTK_ENTRY(widget));
}else
{
return NULL;
}
}

View File

@ -0,0 +1,42 @@
/* libxmms-flac - XMMS FLAC input plugin
* Copyright (C) 2002 Daisuke Shimamura
*
* Based on mpg123 plugin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __CONFIGURE_H__
#define __CONFIGURE_H__
#include <glib.h>
typedef struct {
gboolean tag_override;
gchar *tag_format;
gboolean convert_char_set;
gchar *file_char_set;
gchar *user_char_set;
} flac_config_t;
extern flac_config_t flac_cfg;
extern void FLAC_XMMS__configure(void);
extern void FLAC_XMMS__aboutbox();
#endif

325
src/plugin_xmms/fileinfo.c Normal file
View File

@ -0,0 +1,325 @@
/* XMMS - Cross-platform multimedia player
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
* Copyright (C) 1999,2000 Håvard Kvålen
* Copyright (C) 2002 Daisuke Shimamura
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include "FLAC/all.h"
#include "id3_tag.h"
#include "configure.h"
gboolean get_file_info(char *filename, flac_file_info_struct *tmp_file_info)
{
FLAC__StreamMetadata streaminfo;
if(0 == filename)
filename = "";
if(!FLAC__metadata_get_streaminfo(filename, &streaminfo)) {
return FALSE;
}
tmp_file_info->sample_rate = streaminfo.data.stream_info.sample_rate;
tmp_file_info->channels = streaminfo.data.stream_info.channels;
tmp_file_info->bits_per_sample = streaminfo.data.stream_info.bits_per_sample;
tmp_file_info->total_samples = streaminfo.data.stream_info.total_samples;
tmp_file_info->length_in_msec = streaminfo.data.stream_info.total_samples * 10 / (streaminfo.data.stream_info.sample_rate / 100);
return TRUE;
}
static GtkWidget *window = NULL;
static GtkWidget *filename_entry, *id3_frame;
static GtkWidget *title_entry, *artist_entry, *album_entry, *year_entry, *tracknum_entry, *comment_entry;
static GtkWidget *genre_combo;
static GtkWidget *flac_level, *flac_bitrate, *flac_samplerate, *flac_flags;
static GtkWidget *flac_fileinfo, *flac_genre;
static gchar *current_filename = NULL;
extern gchar *flac_filename;
extern gint flac_bitrate, flac_frequency, flac_layer, flac_lsf, flac_mode;
extern gboolean flac_stereo, flac_flac25;
#define MAX_STR_LEN 100
static void set_entry_tag(GtkEntry * entry, gchar * tag, gint length)
{
gint stripped_len;
gchar *text;
stripped_len = flac_strip_spaces(tag, length);
text = g_strdup_printf("%-*.*s", stripped_len, stripped_len, tag);
gtk_entry_set_text(entry, text);
g_free(text);
}
static void get_entry_tag(GtkEntry * entry, gchar * tag, gint length)
{
gchar *text;
text = gtk_entry_get_text(entry);
memset(tag, ' ', length);
memcpy(tag, text, strlen(text) > length ? length : strlen(text));
}
static gint genre_comp_func(gconstpointer a, gconstpointer b)
{
return strcasecmp(a, b);
}
static gchar* channel_mode_name(int mode)
{
static const gchar *channel_mode[] =
{N_("Mono"), N_("Stereo")};
if (mode < 1 || mode > 2)
return "";
return gettext(channel_mode[mode]);
}
void FLAC_XMMS__file_info_box(char *filename)
{
gint i;
FILE *fh;
gchar *tmp, *title;
gboolean rc;
#ifdef FLAC__HAS_ID3LIB
File_Tag tag;
Initialize_File_Tag_Item (&tag);
rc = Id3tag_Read_File_Tag (filename, &tag);
#else
id3v2_struct tag;
memset(&tag, 0, sizeof(tag));
rc = get_id3v1_tag_as_v2_(filename, &tag);
#endif
if (!window)
{
GtkWidget *vbox, *hbox, *left_vbox, *table;
GtkWidget *flac_frame, *flac_box;
GtkWidget *label, *filename_hbox;
GtkWidget *bbox, *save, *remove_id3, *cancel;
window = gtk_window_new(GTK_WINDOW_DIALOG);
gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &window);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
vbox = gtk_vbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(window), vbox);
filename_hbox = gtk_hbox_new(FALSE, 5);
gtk_box_pack_start(GTK_BOX(vbox), filename_hbox, FALSE, TRUE, 0);
label = gtk_label_new(_("Filename:"));
gtk_box_pack_start(GTK_BOX(filename_hbox), label, FALSE, TRUE, 0);
filename_entry = gtk_entry_new();
gtk_editable_set_editable(GTK_EDITABLE(filename_entry), FALSE);
gtk_box_pack_start(GTK_BOX(filename_hbox), filename_entry, TRUE, TRUE, 0);
hbox = gtk_hbox_new(FALSE, 10);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
left_vbox = gtk_vbox_new(FALSE, 10);
gtk_box_pack_start(GTK_BOX(hbox), left_vbox, FALSE, FALSE, 0);
id3_frame = gtk_frame_new(_("ID3 Tag:"));
gtk_box_pack_start(GTK_BOX(left_vbox), id3_frame, FALSE, FALSE, 0);
table = gtk_table_new(5, 5, FALSE);
gtk_container_set_border_width(GTK_CONTAINER(table), 5);
gtk_container_add(GTK_CONTAINER(id3_frame), table);
label = gtk_label_new(_("Title:"));
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 5, 5);
title_entry = gtk_entry_new_with_max_length(30);
gtk_table_attach(GTK_TABLE(table), title_entry, 1, 4, 0, 1, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
label = gtk_label_new(_("Artist:"));
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 5, 5);
artist_entry = gtk_entry_new_with_max_length(30);
gtk_table_attach(GTK_TABLE(table), artist_entry, 1, 4, 1, 2, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
label = gtk_label_new(_("Album:"));
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 5, 5);
album_entry = gtk_entry_new_with_max_length(30);
gtk_table_attach(GTK_TABLE(table), album_entry, 1, 4, 2, 3, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
label = gtk_label_new(_("Comment:"));
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 5, 5);
comment_entry = gtk_entry_new_with_max_length(30);
gtk_table_attach(GTK_TABLE(table), comment_entry, 1, 4, 3, 4, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
label = gtk_label_new(_("Year:"));
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 5, 5);
year_entry = gtk_entry_new_with_max_length(4);
gtk_widget_set_usize(year_entry, 40, -1);
gtk_table_attach(GTK_TABLE(table), year_entry, 1, 2, 4, 5, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
label = gtk_label_new(_("Track number:"));
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 2, 3, 4, 5, GTK_FILL, GTK_FILL, 5, 5);
tracknum_entry = gtk_entry_new_with_max_length(3);
gtk_widget_set_usize(tracknum_entry, 40, -1);
gtk_table_attach(GTK_TABLE(table), tracknum_entry, 3, 4, 4, 5, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
label = gtk_label_new(_("Genre:"));
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6, GTK_FILL, GTK_FILL, 5, 5);
genre_combo = gtk_combo_new();
gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(genre_combo)->entry), FALSE);
if (!genre_list)
{
for (i = 0; i < GENRE_MAX; i++)
genre_list = g_list_prepend(genre_list, (char *) flac_id3_genres[i]);
genre_list = g_list_prepend(genre_list, "");
genre_list = g_list_sort(genre_list, genre_comp_func);
}
gtk_combo_set_popdown_strings(GTK_COMBO(genre_combo), genre_list);
gtk_table_attach(GTK_TABLE(table), genre_combo, 1, 4, 5, 6, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
bbox = gtk_hbutton_box_new();
gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
gtk_box_pack_start(GTK_BOX(left_vbox), bbox, FALSE, FALSE, 0);
save = gtk_button_new_with_label(_("Save"));
gtk_signal_connect(GTK_OBJECT(save), "clicked", GTK_SIGNAL_FUNC(save_cb), NULL);
GTK_WIDGET_SET_FLAGS(save, GTK_CAN_DEFAULT);
gtk_box_pack_start(GTK_BOX(bbox), save, TRUE, TRUE, 0);
gtk_widget_grab_default(save);
remove_id3 = gtk_button_new_with_label(_("Remove ID3"));
gtk_signal_connect(GTK_OBJECT(remove_id3), "clicked", GTK_SIGNAL_FUNC(remove_id3_cb), NULL);
GTK_WIDGET_SET_FLAGS(remove_id3, GTK_CAN_DEFAULT);
gtk_box_pack_start(GTK_BOX(bbox), remove_id3, TRUE, TRUE, 0);
cancel = gtk_button_new_with_label(_("Cancel"));
gtk_signal_connect_object(GTK_OBJECT(cancel), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window));
GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT);
gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0);
flac_frame = gtk_frame_new(_("FLAC Info:"));
gtk_box_pack_start(GTK_BOX(hbox), flac_frame, FALSE, FALSE, 0);
flac_box = gtk_vbox_new(FALSE, 5);
gtk_container_add(GTK_CONTAINER(flac_frame), flac_box);
gtk_container_set_border_width(GTK_CONTAINER(flac_box), 10);
gtk_box_set_spacing(GTK_BOX(flac_box), 0);
flac_level = gtk_label_new("");
gtk_widget_set_usize(flac_level, 120, -2);
gtk_misc_set_alignment(GTK_MISC(flac_level), 0, 0);
gtk_box_pack_start(GTK_BOX(flac_box), flac_level, FALSE, FALSE, 0);
flac_bitrate = gtk_label_new("");
gtk_misc_set_alignment(GTK_MISC(flac_bitrate), 0, 0);
gtk_label_set_justify(GTK_LABEL(flac_bitrate), GTK_JUSTIFY_LEFT);
gtk_box_pack_start(GTK_BOX(flac_box), flac_bitrate, FALSE, FALSE, 0);
flac_samplerate = gtk_label_new("");
gtk_misc_set_alignment(GTK_MISC(flac_samplerate), 0, 0);
gtk_box_pack_start(GTK_BOX(flac_box), flac_samplerate, FALSE, FALSE, 0);
flac_flags = gtk_label_new("");
gtk_misc_set_alignment(GTK_MISC(flac_flags), 0, 0);
gtk_label_set_justify(GTK_LABEL(flac_flags), GTK_JUSTIFY_LEFT);
gtk_box_pack_start(GTK_BOX(flac_box), flac_flags, FALSE, FALSE, 0);
flac_fileinfo = gtk_label_new("");
gtk_misc_set_alignment(GTK_MISC(flac_fileinfo), 0, 0);
gtk_label_set_justify(GTK_LABEL(flac_fileinfo), GTK_JUSTIFY_LEFT);
gtk_box_pack_start(GTK_BOX(flac_box), flac_fileinfo, FALSE, FALSE, 0);
gtk_widget_show_all(window);
}
if (current_filename)
g_free(current_filename);
current_filename = g_strdup(filename);
title = g_strdup_printf(_("File Info - %s"), g_basename(filename));
gtk_window_set_title(GTK_WINDOW(window), title);
g_free(title);
gtk_entry_set_text(GTK_ENTRY(filename_entry), filename);
gtk_editable_set_position(GTK_EDITABLE(filename_entry), -1);
if (tag.title != NULL && strlen(tag.title) > 0)
{
gtk_entry_set_text(GTK_ENTRY(title_entry), tag.title);
}
else
{
title = g_strdup(g_basename(filename));
if ((tmp = strrchr(title, '.')) != NULL)
*tmp = '\0';
gtk_entry_set_text(GTK_ENTRY(title_entry), title);
g_free(title);
}
gtk_entry_set_text(GTK_ENTRY(artist_entry), tag.artist);
gtk_entry_set_text(GTK_ENTRY(album_entry), tag.album);
gtk_entry_set_text(GTK_ENTRY(year_entry), tag.year);
gtk_entry_set_text(GTK_ENTRY(tracknum_entry), tag.track);
gtk_entry_set_text(GTK_ENTRY(comment_entry), tag.comment);
gtk_entry_set_text(GTK_ENTRY(genre_entry), tag.genre);
gtk_label_set_text(GTK_LABEL(flac_level), "");
gtk_label_set_text(GTK_LABEL(flac_bitrate), "");
gtk_label_set_text(GTK_LABEL(flac_samplerate), "");
gtk_label_set_text(GTK_LABEL(flac_flags), "");
gtk_label_set_text(GTK_LABEL(flac_fileinfo), "");
if (!strncasecmp(filename, "http://", 7))
{
file_info_http(filename);
return;
}
gtk_widget_set_sensitive(id3_frame, TRUE);
label_set_text(flac_bitrate, _("Bits/Samples: %d"), tmp_file_info->bits_per_sample);
/* tmp_file_info->length_in_msec */
label_set_text(flac_samplerate, _("Samplerate: %ld Hz"), tmp_file_info->sample_rate);
label_set_text(flac_channel, _("Channel: %s"), channel_mode_name(tmp_file_info->channel);
#if 0
label_set_text(flac_fileinfo, _("%d frames\nFilesize: %lu B"), num_frames, ftell(fh));
#endif
}

187
src/plugin_xmms/genres.h Normal file
View File

@ -0,0 +1,187 @@
/* libxmms-flac - XMMS FLAC input plugin
* Copyright (C) 2002 Daisuke Shimamura
*
* Based on genres.h - EasyTAG - Jerome Couderc 2000/05/29
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GENRES_H__
#define __GENRES_H__
/* GENRE_MAX is the last genre number that can be used */
#define GENRE_MAX ( sizeof(id3_genres)/sizeof(id3_genres[0]) - 1 )
#define ID3_INVALID_GENRE 255
/*
* Do not sort genres!!
* Last Update: 2000/04/30
*/
static char *id3_genres[] =
{
"Blues", /* 0 */
"Classic Rock",
"Country",
"Dance",
"Disco",
"Funk", /* 5 */
"Grunge",
"Hip-Hop",
"Jazz",
"Metal",
"New Age", /* 10 */
"Oldies",
"Other",
"Pop",
"R&B",
"Rap", /* 15 */
"Reggae",
"Rock",
"Techno",
"Industrial",
"Alternative", /* 20 */
"Ska",
"Death Metal",
"Pranks",
"Soundtrack",
"Euro-Techno", /* 25 */
"Ambient",
"Trip-Hop",
"Vocal",
"Jazz+Funk",
"Fusion", /* 30 */
"Trance",
"Classical",
"Instrumental",
"Acid",
"House", /* 35 */
"Game",
"Sound Clip",
"Gospel",
"Noise",
"Altern Rock", /* 40 */
"Bass",
"Soul",
"Punk",
"Space",
"Meditative", /* 45 */
"Instrumental Pop",
"Instrumental Rock",
"Ethnic",
"Gothic",
"Darkwave", /* 50 */
"Techno-Industrial",
"Electronic",
"Pop-Folk",
"Eurodance",
"Dream", /* 55 */
"Southern Rock",
"Comedy",
"Cult",
"Gangsta",
"Top 40", /* 60 */
"Christian Rap",
"Pop/Funk",
"Jungle",
"Native American",
"Cabaret", /* 65 */
"New Wave",
"Psychadelic",
"Rave",
"Showtunes",
"Trailer", /* 70 */
"Lo-Fi",
"Tribal",
"Acid Punk",
"Acid Jazz",
"Polka", /* 75 */
"Retro",
"Musical",
"Rock & Roll",
"Hard Rock",
"Folk", /* 80 */
"Folk/Rock",
"National Folk",
"Fast Fusion",
"Swing",
"Bebob", /* 85 */
"Latin",
"Revival",
"Celtic",
"Bluegrass",
"Avantgarde", /* 90 */
"Gothic Rock",
"Progressive Rock",
"Psychedelic Rock",
"Symphonic Rock",
"Slow Rock", /* 95 */
"Big Band",
"Chorus",
"Easy Listening",
"Acoustic",
"Humour", /* 100 */
"Speech",
"Chanson",
"Opera",
"Chamber Music",
"Sonata", /* 105 */
"Symphony",
"Booty Bass",
"Primus",
"Porn Groove",
"Satire", /* 110 */
"Slow Jam",
"Club",
"Tango",
"Samba",
"Folklore", /* 115 */
"Ballad",
"Power Ballad",
"Rhythmic Soul",
"Freestyle",
"Duet", /* 120 */
"Punk Rock",
"Drum Solo",
"A Capella",
"Euro-House",
"Dance Hall", /* 125 */
"Goa",
"Drum & Bass",
"Club-House",
"Hardcore",
"Terror", /* 130 */
"Indie",
"BritPop",
"Negerpunk",
"Polsk Punk",
"Beat", /* 135 */
"Christian Gangsta Rap",
"Heavy Metal",
"Black Metal",
"Crossover",
"Contemporary Christian",/* 140 */
"Christian Rock",
"Merengue",
"Salsa",
"Thrash Metal",
"Anime", /* 145 */
"JPop",
"Synthpop"
};
#endif /* __GENRES_H__ */

508
src/plugin_xmms/id3_tag.c Normal file
View File

@ -0,0 +1,508 @@
/* libxmms-flac - XMMS FLAC input plugin
* Copyright (C) 2002 Daisuke Shimamura
*
* Almost from id3_tag.c - 2001/02/16
* EasyTAG - Tag editor for MP3 and OGG files
* Copyright (C) 2001-2002 Jerome Couderc <j.couderc@ifrance.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <id3.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include "configure.h"
#include "genres.h"
#include "charset.h"
#include "mylocale.h"
#include "id3_tag.h"
/****************
* Declarations *
****************/
#define ID3V2_MAX_STRING_LEN 4096
#define NUMBER_TRACK_FORMATED 1
/**************
* Prototypes *
**************/
static size_t ID3Tag_Link_1 (ID3Tag *id3tag, const char *filename);
static size_t ID3Field_GetASCII_1 (const ID3Field *field, char *buffer, size_t maxChars, index_t itemNum);
static gchar *Id3tag_Genre_To_String (unsigned char genre_code);
static void Strip_String (gchar *string);
/*************
* Functions *
*************/
/*
* Read id3v1.x / id3v2 tag and load data into the File_Tag structure using id3lib functions.
* Returns TRUE on success, else FALSE.
* If a tag entry exists (ex: title), we allocate memory, else value stays to NULL
*/
gboolean Id3tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
{
FILE *file;
ID3Tag *id3_tag = NULL; /* Tag defined by the id3lib */
gchar *string, *string1, *string2;
gboolean USE_CHARACTER_SET_TRANSLATION;
USE_CHARACTER_SET_TRANSLATION = flac_cfg.convert_char_set;
if (!filename || !FileTag)
return FALSE;
if ( (file=fopen(filename,"r"))==NULL )
{
g_print(_("ERROR while opening file: '%s' (%s).\n\a"),filename,g_strerror(errno));
return FALSE;
}
fclose(file); // We close it cause id3lib opens/closes file itself
/* Get data from tag */
if ( (id3_tag = ID3Tag_New()) )
{
ID3Frame *id3_frame;
ID3Field *id3_field;
luint frm_size;
luint num_chars;
guint field_num = 0; // First field
/* Link the file to the tag */
frm_size = ID3Tag_Link_1(id3_tag,filename);
string = g_malloc(ID3V2_MAX_STRING_LEN+1);
/*********
* Title *
*********/
if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_TITLE)) )
{
if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
{
// Note: if 'num_chars' is equal to 0, then the field is empty or corrupted!
if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
&& string != NULL )
{
if (USE_CHARACTER_SET_TRANSLATION)
{
string1 = convert_from_file_to_user(string);
Strip_String(string1);
FileTag->title = g_strdup(string1);
g_free(string1);
}else
{
Strip_String(string);
FileTag->title = g_strdup(string);
}
}
}
}
/**********
* Artist *
**********/
if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_LEADARTIST)) )
{
if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
{
if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
&& string != NULL )
{
if (USE_CHARACTER_SET_TRANSLATION)
{
string1 = convert_from_file_to_user(string);
Strip_String(string1);
FileTag->artist = g_strdup(string1);
g_free(string1);
}else
{
Strip_String(string);
FileTag->artist = g_strdup(string);
}
}
}
}
/*********
* Album *
*********/
if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_ALBUM)) )
{
if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
{
if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
&& string != NULL )
{
if (USE_CHARACTER_SET_TRANSLATION)
{
string1 = convert_from_file_to_user(string);
Strip_String(string1);
FileTag->album = g_strdup(string1);
g_free(string1);
}else
{
Strip_String(string);
FileTag->album = g_strdup(string);
}
}
}
}
/********
* Year *
********/
if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_YEAR)) )
{
if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
{
if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
&& string != NULL )
{
gchar *tmp_str;
Strip_String(string);
/* Fix for id3lib 3.7.x: if the id3v1.x tag was filled with spaces
* instead of zeroes, then the year field contains garbages! */
tmp_str = string;
while (isdigit(*tmp_str)) tmp_str++;
*tmp_str = 0;
/* End of fix for id3lib 3.7.x */
if (USE_CHARACTER_SET_TRANSLATION)
{
string1 = convert_from_file_to_user(string);
Strip_String(string1);
FileTag->year = g_strdup(string1);
g_free(string1);
}else
{
Strip_String(string);
FileTag->year = g_strdup(string);
}
}
}
}
/*************************
* Track and Total Track *
*************************/
if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_TRACKNUM)) )
{
if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
{
if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
&& string != NULL )
{
Strip_String(string);
if (USE_CHARACTER_SET_TRANSLATION)
{
string1 = convert_from_file_to_user(string);
string2 = strchr(string1,'/');
if (NUMBER_TRACK_FORMATED)
{
if (string2)
{
FileTag->track_total = g_strdup_printf("%.2d",atoi(string2+1)); // Just to have numbers like this : '01', '05', '12', ...
*string2 = '\0';
}
FileTag->track = g_strdup_printf("%.2d",atoi(string1)); // Just to have numbers like this : '01', '05', '12', ...
}else
{
if (string2)
{
FileTag->track_total = g_strdup(string2+1);
*string2 = '\0';
}
FileTag->track = g_strdup(string1);
}
g_free(string1);
}else
{
string2 = strchr(string,'/');
if (NUMBER_TRACK_FORMATED)
{
if (string2)
{
FileTag->track_total = g_strdup_printf("%.2d",atoi(string2+1)); // Just to have numbers like this : '01', '05', '12', ...
*string2 = '\0';
}
FileTag->track = g_strdup_printf("%.2d",atoi(string)); // Just to have numbers like this : '01', '05', '12', ...
}else
{
if (string2)
{
FileTag->track_total = g_strdup(string2+1);
*string2 = '\0';
}
FileTag->track = g_strdup(string);
}
}
}
}
}
/*********
* Genre *
*********/
if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_CONTENTTYPE)) )
{
if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
{
/*
* We manipulate only the name of the genre
*/
if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
&& string != NULL )
{
gchar *tmp;
Strip_String(string);
if ( (string[0]=='(') && (tmp=strchr(string,')')) && (strlen((tmp+1))>0) )
{
/* Convert a genre written as '(3)Dance' into 'Dance' */
if (USE_CHARACTER_SET_TRANSLATION)
{
string1 = convert_from_file_to_user(tmp+1);
FileTag->genre = g_strdup(string1);
g_free(string1);
}else
{
FileTag->genre = g_strdup(tmp+1);
}
}else if ( (string[0]=='(') && (tmp=strchr(string,')')) )
{
/* Convert a genre written as '(3)' into 'Dance' */
*tmp = 0;
if (USE_CHARACTER_SET_TRANSLATION)
{
string1 = convert_from_file_to_user(Id3tag_Genre_To_String(atoi(string+1)));
FileTag->genre = g_strdup(string1);
g_free(string1);
}else
{
FileTag->genre = g_strdup(Id3tag_Genre_To_String(atoi(string+1)));
}
}else
{
/* Genre is already written as 'Dance' */
if (USE_CHARACTER_SET_TRANSLATION)
{
string1 = convert_from_file_to_user(string);
FileTag->genre = g_strdup(string1);
g_free(string1);
}else
{
FileTag->genre = g_strdup(string);
}
}
}
}
}
/***********
* Comment *
***********/
if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_COMMENT)) )
{
if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
{
if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
&& string != NULL )
{
if (USE_CHARACTER_SET_TRANSLATION)
{
string1 = convert_from_file_to_user(string);
Strip_String(string1);
FileTag->comment = g_strdup(string1);
g_free(string1);
}else
{
Strip_String(string);
FileTag->comment = g_strdup(string);
}
}
}
/*if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_DESCRIPTION)) )
{
gchar *comment1 = g_malloc0(MAX_STRING_LEN+1);
num_chars = ID3Field_GetASCII(id3_field,comment1,MAX_STRING_LEN,Item_Num);
g_free(comment1);
}
if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_LANGUAGE)) )
{
gchar *comment2 = g_malloc0(MAX_STRING_LEN+1);
num_chars = ID3Field_GetASCII(id3_field,comment2,MAX_STRING_LEN,Item_Num);
g_free(comment2);
}*/
}
g_free(string);
/* Free allocated data */
ID3Tag_Delete(id3_tag);
}
return TRUE;
}
void Initialize_File_Tag_Item (File_Tag *FileTag)
{
if (FileTag)
{
FileTag->key = 0;
FileTag->saved = FALSE;
FileTag->title = NULL;
FileTag->artist = NULL;
FileTag->album = NULL;
FileTag->track = NULL;
FileTag->track_total = NULL;
FileTag->year = NULL;
FileTag->genre = NULL;
FileTag->comment = NULL;
}
}
/*
* Frees a File_Tag item.
*/
gboolean Free_File_Tag_Item (File_Tag *FileTag)
{
if (!FileTag) return FALSE;
if (FileTag->title) g_free(FileTag->title);
if (FileTag->artist) g_free(FileTag->artist);
if (FileTag->album) g_free(FileTag->album);
if (FileTag->year) g_free(FileTag->year);
if (FileTag->track) g_free(FileTag->track);
if (FileTag->track_total) g_free(FileTag->track_total);
if (FileTag->genre) g_free(FileTag->genre);
if (FileTag->comment) g_free(FileTag->comment);
return TRUE;
}
/*
* Returns the name of a genre code if found
* Three states for genre code :
* - defined (0 to GENRE_MAX)
* - undefined/unknown (GENRE_MAX+1 to ID3_INVALID_GENRE-1)
* - invalid (>ID3_INVALID_GENRE)
*/
static gchar *Id3tag_Genre_To_String (unsigned char genre_code)
{
if (genre_code>=ID3_INVALID_GENRE) /* empty */
return "";
else if (genre_code>GENRE_MAX) /* unknown tag */
return "Unknown";
else /* known tag */
return id3_genres[genre_code];
}
/*
* As the ID3Tag_Link function of id3lib-3.8.0pre2 returns the ID3v1 tags
* when a file has both ID3v1 and ID3v2 tags, we first try to explicitely
* get the ID3v2 tags with ID3Tag_LinkWithFlags and, if we cannot get them,
* fall back to the ID3v1 tags.
* (Written by Holger Schemel).
*/
static size_t ID3Tag_Link_1 (ID3Tag *id3tag, const char *filename)
{
size_t offset;
# if ( (ID3LIB_MAJOR >= 3) && (ID3LIB_MINOR >= 8) )
/* First, try to get the ID3v2 tags */
offset = ID3Tag_LinkWithFlags(id3tag,filename,ID3TT_ID3V2);
if (offset == 0)
{
/* No ID3v2 tags available => try to get the ID3v1 tags */
offset = ID3Tag_LinkWithFlags(id3tag,filename,ID3TT_ID3V1);
}
# else
/* Function 'ID3Tag_LinkWithFlags' is not defined up to id3lib-.3.7.13 */
offset = ID3Tag_Link(id3tag,filename);
# endif
//g_print("ID3 TAG SIZE: %d\t%s\n",offset,g_basename(filename));
return offset;
}
/*
* As the ID3Field_GetASCII function differs with the version of id3lib, we must redefine it.
*/
static size_t ID3Field_GetASCII_1(const ID3Field *field, char *buffer, size_t maxChars, index_t itemNum)
{
/* Defined by id3lib: ID3LIB_MAJOR_VERSION, ID3LIB_MINOR_VERSION, ID3LIB_PATCH_VERSION
* Defined by autoconf: ID3LIB_MAJOR, ID3LIB_MINOR, ID3LIB_PATCH
*
* <= 3.7.12 : first item num is 1 for ID3Field_GetASCII
* = 3.7.13 : first item num is 0 for ID3Field_GetASCII
* >= 3.8.0 : doesn't need item num for ID3Field_GetASCII
*/
//g_print("id3lib version: %d.%d.%d\n",ID3LIB_MAJOR,ID3LIB_MINOR,ID3LIB_PATCH);
# if (ID3LIB_MAJOR >= 3)
// (>= 3.x.x)
# if (ID3LIB_MINOR <= 7)
// (3.0.0 to 3.7.x)
# if (ID3LIB_PATCH >= 13)
// (>= 3.7.13)
return ID3Field_GetASCII(field,buffer,maxChars,itemNum);
# else
return ID3Field_GetASCII(field,buffer,maxChars,itemNum+1);
# endif
# else
// (>= to 3.8.0)
//return ID3Field_GetASCII(field,buffer,maxChars);
return ID3Field_GetASCIIItem(field,buffer,maxChars,itemNum);
# endif
# else
// Not tested (< 3.x.x)
return ID3Field_GetASCII(field,buffer,maxChars,itemNum+1);
# endif
}
/*
* Delete spaces at the end and the beginning of the string
*/
static void Strip_String (gchar *string)
{
if (!string) return;
string = g_strstrip(string);
}

67
src/plugin_xmms/id3_tag.h Normal file
View File

@ -0,0 +1,67 @@
/* libxmms-flac - XMMS FLAC input plugin
* Copyright (C) 2002 Daisuke Shimamura
*
* Based on id3_tag.h - 2001/02/16
* et_core.h - 2001/10/21
* EasyTAG - Tag editor for MP3 and OGG files
* Copyright (C) 2001-2002 Jerome Couderc <j.couderc@ifrance.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __ID3TAG_H__
#define __ID3TAG_H__
#include <glib.h>
/***************
* Declaration *
***************/
#ifndef MAX
# define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
# define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
/*
* Description of each item of the TagList list
*/
typedef struct _File_Tag File_Tag;
struct _File_Tag
{
gulong key; /* Incremented value */
gboolean saved; /* Set to TRUE if this tag had been saved */
gchar *title; /* Title of track */
gchar *artist; /* Artist name */
gchar *album; /* Album name */
gchar *year; /* Year of track */
gchar *track; /* Position of track in the album */
gchar *track_total; /* The number of tracks for the album (ex: 12/20) */
gchar *genre; /* Genre of song */
gchar *comment; /* Comment */
};
/**************
* Prototypes *
**************/
void Initialize_File_Tag_Item (File_Tag *FileTag);
gboolean Free_File_Tag_Item (File_Tag *FileTag);
gboolean Id3tag_Read_File_Tag (gchar *filename, File_Tag *FileTag);
#endif /* __ID3TAG_H__ */

View File

@ -0,0 +1,55 @@
/* libxmms-flac - XMMS FLAC input plugin
*
* locale.h - 2000/05/05 13:10 Jerome Couderc
* EasyTAG - Tag editor for MP3 and OGG files
* Copyright (C) 1999-2001 H蛆ard Kv虱en <havardk@xmms.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Gettext support for EasyTAG
*/
#ifndef __MY_LOCALE_H__
#define __MY_LOCALE_H__
#include <locale.h>
/*
* Standard gettext macros.
*/
#ifdef ENABLE_NLS
# include <libintl.h>
# define _(String) gettext (String)
# ifdef gettext_noop
# define N_(String) gettext_noop (String)
# else
# define N_(String) (String)
# endif
#else
# define textdomain(String) (String)
# define gettext(String) (String)
# define dgettext(Domain,Message) (Message)
# define dcgettext(Domain,Message,Type) (Message)
# define bindtextdomain(Domain,Directory) (Domain)
# define _(String) (String)
# define N_(String) (String)
#endif
#endif /* __MY_LOCALE_H__ */

View File

@ -22,27 +22,25 @@
#include <stdio.h>
#include <glib.h>
#include "xmms/plugin.h"
#include "xmms/util.h"
#include <xmms/plugin.h>
#include <xmms/util.h>
#include <xmms/configfile.h>
#include <xmms/titlestring.h>
#ifdef HAVE_LANGINFO_CODESET
#include <langinfo.h>
#endif
#include "FLAC/all.h"
#include "configure.h"
#include "wrap_id3.h"
#include "charset.h"
#ifdef min
#undef min
#endif
#define min(x,y) ((x)<(y)?(x):(y))
typedef struct {
FLAC__byte raw[128];
char title[31];
char artist[31];
char album[31];
char comment[31];
unsigned year;
unsigned track; /* may be 0 if v1 (not v1.1) tag */
unsigned genre;
char description[1024]; /* the formatted description passed to xmms */
} id3v1_struct;
typedef struct {
FLAC__bool abort_flag;
FLAC__bool is_playing;
@ -67,7 +65,6 @@ static int FLAC_XMMS__get_time();
static void FLAC_XMMS__cleanup();
static void FLAC_XMMS__get_song_info(char *filename, char **title, int *length);
static FLAC__bool get_id3v1_tag_(const char *filename, id3v1_struct *tag);
static void *play_loop_(void *arg);
static FLAC__bool safe_decoder_init_(const char *filename, FLAC__FileDecoder *decoder);
static void safe_decoder_finish_(FLAC__FileDecoder *decoder);
@ -76,15 +73,14 @@ static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *d
static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
InputPlugin flac_ip =
{
NULL,
NULL,
"FLAC Player v" FLAC__VERSION_STRING,
FLAC_XMMS__init,
NULL,
NULL,
FLAC_XMMS__aboutbox,
FLAC_XMMS__configure,
FLAC_XMMS__is_our_file,
NULL,
FLAC_XMMS__play_file,
@ -101,7 +97,7 @@ InputPlugin flac_ip =
NULL,
NULL,
FLAC_XMMS__get_song_info,
NULL, /* file_info_box */
NULL, /* file_info_box */
NULL
};
@ -122,6 +118,30 @@ InputPlugin *get_iplugin_info()
void FLAC_XMMS__init()
{
ConfigFile *cfg;
flac_cfg.tag_override = FALSE;
g_free(flac_cfg.tag_format);
flac_cfg.convert_char_set = FALSE;
cfg = xmms_cfg_open_default_file();
xmms_cfg_read_boolean(cfg, "flac", "tag_override", &flac_cfg.tag_override);
if (!xmms_cfg_read_string(cfg, "flac", "tag_format",
&flac_cfg.tag_format))
flac_cfg.tag_format = g_strdup("%p - %t");
xmms_cfg_read_boolean(cfg, "flac", "convert_char_set", &flac_cfg.convert_char_set);
if (!xmms_cfg_read_string(cfg, "flac", "file_char_set",
&flac_cfg.file_char_set))
{
flac_cfg.file_char_set = get_current_charset();
}
if (!xmms_cfg_read_string(cfg, "flac", "user_char_set",
&flac_cfg.user_char_set))
{
flac_cfg.user_char_set = get_current_charset();
}
decoder_ = FLAC__file_decoder_new();
}
@ -139,7 +159,7 @@ int FLAC_XMMS__is_our_file(char *filename)
void FLAC_XMMS__play_file(char *filename)
{
FILE *f;
id3v1_struct tag;
gchar *ret;
reservoir_samples_ = 0;
audio_error_ = false;
@ -166,8 +186,10 @@ void FLAC_XMMS__play_file(char *filename)
return;
}
(void)get_id3v1_tag_(filename, &tag);
flac_ip.set_info(tag.description, file_info_.length_in_msec, file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample, file_info_.sample_rate, file_info_.channels);
ret = flac_format_song_title(filename);
flac_ip.set_info(ret, file_info_.length_in_msec, file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample, file_info_.sample_rate, file_info_.channels);
g_free(ret);
file_info_.seek_to_in_sec = -1;
file_info_.play_thread_open = true;
@ -219,7 +241,6 @@ void FLAC_XMMS__cleanup()
void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec)
{
id3v1_struct tag;
FLAC__StreamMetadata streaminfo;
if(0 == filename)
@ -238,9 +259,7 @@ void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec)
}
if(title) {
(void)get_id3v1_tag_(filename, &tag);
*title = g_malloc(strlen(tag.description)+1);
strcpy(*title, tag.description);
*title = flac_format_song_title(filename);
}
if(length_in_msec)
*length_in_msec = streaminfo.data.stream_info.total_samples * 10 / (streaminfo.data.stream_info.sample_rate / 100);
@ -250,52 +269,6 @@ void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec)
* local routines
**********************************************************************/
FLAC__bool get_id3v1_tag_(const char *filename, id3v1_struct *tag)
{
const char *temp;
FILE *f = fopen(filename, "rb");
memset(tag, 0, sizeof(id3v1_struct));
/* set the title and description to the filename by default */
temp = strrchr(filename, '/');
if(!temp)
temp = filename;
else
temp++;
strcpy(tag->description, temp);
*strrchr(tag->description, '.') = '\0';
strncpy(tag->title, tag->description, 30); tag->title[30] = '\0';
if(0 == f)
return false;
if(-1 == fseek(f, -128, SEEK_END)) {
fclose(f);
return false;
}
if(fread(tag->raw, 1, 128, f) < 128) {
fclose(f);
return false;
}
fclose(f);
if(strncmp(tag->raw, "TAG", 3))
return false;
else {
char year_str[5];
memcpy(tag->title, tag->raw+3, 30);
memcpy(tag->artist, tag->raw+33, 30);
memcpy(tag->album, tag->raw+63, 30);
memcpy(year_str, tag->raw+93, 4); year_str[4] = '\0'; tag->year = atoi(year_str);
memcpy(tag->comment, tag->raw+97, 30);
tag->genre = (unsigned)((FLAC__byte)tag->raw[127]);
tag->track = (unsigned)((FLAC__byte)tag->raw[126]);
sprintf(tag->description, "%s - %s", tag->artist, tag->title);
return true;
}
}
void *play_loop_(void *arg)
{
(void)arg;
@ -463,3 +436,4 @@ void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorS
if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)
file_info->abort_flag = true;
}

272
src/plugin_xmms/wrap_id3.c Normal file
View File

@ -0,0 +1,272 @@
/* libxmms-flac - XMMS FLAC input plugin
* Copyright (C) 2000,2001,2002 Josh Coalson
* Copyright (C) 2002 Daisuke Shimamura
*
* Based on FLAC plugin.c and mpg123 plugin
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <glib.h>
#include <xmms/plugin.h>
#include <xmms/util.h>
#include <xmms/configfile.h>
#include <xmms/titlestring.h>
#include "mylocale.h"
#include "configure.h"
#ifdef FLAC__HAS_ID3LIB
#include <id3.h>
#include "id3_tag.h"
#else
#include "charset.h"
#include "genres.h"
typedef struct id3v1tag_t {
char tag[3]; /* always "TAG": defines ID3v1 tag 128 bytes before EOF */
char title[30];
char artist[30];
char album[30];
char year[4];
union {
struct {
char comment[30];
} v1_0;
struct {
char comment[28];
char __zero;
unsigned char track;
} v1_1;
} u;
unsigned char genre;
} id3v1_struct;
typedef struct id3tag_t {
char title[64];
char artist[64];
char album[64];
char comment[256];
char genre[256];
char year[16];
char track[16];
} id3v2_struct;
static gboolean get_id3v1_tag_as_v2_(const char *filename, id3v2_struct *tag);
static void flac_id3v1_to_id3v2(id3v1_struct *v1, id3v2_struct *v2);
static const char *flac_get_id3_genre(unsigned char genre_code);
#endif /* FLAC__HAS_ID3LIB */
static gchar *extname(const char *filename);
static char* flac_getstr(char* str);
static int flac_getnum(char* str);
/*
* Function flac_format_song_title (tag, filename)
*
* Create song title according to `tag' and/or `filename' and
* return it. The title must be subsequently freed using g_free().
*
*/
gchar *flac_format_song_title(gchar * filename)
{
gchar *ret = NULL;
TitleInput *input = NULL;
gboolean rc;
#ifdef FLAC__HAS_ID3LIB
File_Tag tag;
Initialize_File_Tag_Item (&tag);
rc = Id3tag_Read_File_Tag (filename, &tag);
#else
id3v2_struct tag;
memset(&tag, 0, sizeof(tag));
rc = get_id3v1_tag_as_v2_(filename, &tag);
#endif
XMMS_NEW_TITLEINPUT(input);
if (rc)
{
input->performer = flac_getstr(tag.artist);
input->album_name = flac_getstr(tag.album);
input->track_name = flac_getstr(tag.title);
input->track_number = flac_getnum(tag.track);
input->year = flac_getnum(tag.year);
input->genre = flac_getstr(tag.genre);
input->comment = flac_getstr(tag.comment);
}
input->file_name = g_basename(filename);
input->file_path = filename;
input->file_ext = extname(filename);
ret = xmms_get_titlestring(flac_cfg.tag_override ?
flac_cfg.tag_format :
xmms_get_gentitle_format(), input);
g_free(input);
if (!ret)
{
/*
* Format according to filename.
*/
ret = g_strdup(g_basename(filename));
if (extname(ret) != NULL)
*(extname(ret) - 1) = '\0'; /* removes period */
}
#ifdef FLAC__HAS_ID3LIB
Free_File_Tag_Item (&tag);
#endif
return ret;
}
/*
* Function extname (filename)
*
* Return pointer within filename to its extenstion, or NULL if
* filename has no extension.
*
*/
static gchar *extname(const char *filename)
{
gchar *ext = strrchr(filename, '.');
if (ext != NULL)
++ext;
return ext;
}
static char* flac_getstr(char* str)
{
if (str && strlen(str) > 0)
return str;
return NULL;
}
static int flac_getnum(char* str)
{
if (str && strlen(str) > 0)
return atoi(str);
return 0;
}
#ifndef FLAC__HAS_ID3LIB
/*
* Function get_idv2_tag_(filename, ID3v2tag)
*
* Get ID3v2 tag from file.
*
*/
static gboolean get_id3v1_tag_as_v2_(const char *filename, id3v2_struct *id3v2tag)
{
FILE *file;
id3v1_struct id3v1tag;
memset(id3v2tag, 0, sizeof(id3v2_struct));
if ((file = fopen(filename, "rb")) != 0)
{
if ((fseek(file, -1 * sizeof (id3v1tag), SEEK_END) == 0) &&
(fread(&id3v1tag, 1, sizeof (id3v1tag), file) == sizeof (id3v1tag)) &&
(strncmp(id3v1tag.tag, "TAG", 3) == 0))
{
flac_id3v1_to_id3v2(&id3v1tag, id3v2tag);
if (flac_cfg.convert_char_set)
{
gchar *string;
string = convert_from_file_to_user(id3v2tag->title);
strcpy(id3v2tag->title, string);
g_free(string);
string = convert_from_file_to_user(id3v2tag->artist);
strcpy(id3v2tag->artist, string);
g_free(string);
string = convert_from_file_to_user(id3v2tag->album);
strcpy(id3v2tag->album, string);
g_free(string);
string = convert_from_file_to_user(id3v2tag->comment);
strcpy(id3v2tag->comment, string);
g_free(string);
string = convert_from_file_to_user(id3v2tag->genre);
strcpy(id3v2tag->genre, string);
g_free(string);
string = convert_from_file_to_user(id3v2tag->year);
strcpy(id3v2tag->year, string);
g_free(string);
string = convert_from_file_to_user(id3v2tag->track);
strcpy(id3v2tag->track, string);
g_free(string);
}
}
}
else
{
return FALSE;
}
return TRUE;
}
/*
* Function flac_id3v1_to_id3v2 (v1, v2)
*
* Convert ID3v1 tag `v1' to ID3v2 tag `v2'.
*
*/
static void flac_id3v1_to_id3v2(id3v1_struct *v1, id3v2_struct *v2)
{
memset(v2,0,sizeof(id3v2_struct));
strncpy(v2->title, v1->title, 30);
strncpy(v2->artist, v1->artist, 30);
strncpy(v2->album, v1->album, 30);
strncpy(v2->comment, v1->u.v1_0.comment, 30);
strncpy(v2->genre, flac_get_id3_genre(v1->genre), sizeof (v2->genre));
strncpy(v2->year, v1->year, 4);
/* Check for v1.1 tags. */
if (v1->u.v1_1.__zero == 0)
sprintf(v2->track, "%d", v1->u.v1_1.track);
else
strcpy(v2->track, "0");
g_strstrip(v2->title);
g_strstrip(v2->artist);
g_strstrip(v2->album);
g_strstrip(v2->comment);
g_strstrip(v2->genre);
g_strstrip(v2->year);
g_strstrip(v2->track);
}
static const char *flac_get_id3_genre(unsigned char genre_code)
{
if (genre_code < GENRE_MAX)
return gettext(id3_genres[genre_code]);
return "";
}
#endif /* ifndef FLAC__HAS_ID3LIB */

View File

@ -0,0 +1,24 @@
/* libxmms-flac - XMMS FLAC input plugin
* Copyright (C) 2002 Daisuke Shimamura
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __FLAC_ID3_H__
#define __FLAC_ID3_H__
gchar *flac_format_song_title(gchar * filename);
#endif