major rewrite

This commit is contained in:
Josh Coalson
2002-08-29 08:11:02 +00:00
parent 696bf50b63
commit 6783dd7ef6

View File

@@ -20,385 +20,49 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "id3v2.h"
#ifdef FLAC__HAS_ID3LIB
#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"
#include "FLAC/assert.h"
#include "id3v1.h" /* for genre stuff */
#include "locale_hack.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
/* local__strip() based on glib's g_strchomp() and g_strchug():
* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* (LGPL 2 follows)
*/
gboolean Id3tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
static void local__strip(char *string)
{
FILE *file;
ID3Tag *id3_tag = NULL; /* Tag defined by the id3lib */
gchar *string, *string1, *string2;
gboolean USE_CHARACTER_SET_TRANSLATION;
char *s;
USE_CHARACTER_SET_TRANSLATION = flac_cfg.convert_char_set;
if(0 == string)
return;
if (!filename || !FileTag)
return FALSE;
for(s = string; *s && isspace(*s); s++)
;
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
memmove(string, s, strlen((char*)s) + 1);
if(!*string)
return;
/* 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;
for(s = string + strlen (string) - 1; s >= string && isspace(*s); s--)
*s = '\0';
}
/*
* 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
@@ -407,23 +71,21 @@ static gchar *Id3tag_Genre_To_String (unsigned char genre_code)
* fall back to the ID3v1 tags.
* (Written by Holger Schemel).
*/
static size_t ID3Tag_Link_1 (ID3Tag *id3tag, const char *filename)
static size_t local__ID3Tag_Link_wrapper(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)
{
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);
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);
offset = ID3Tag_Link(id3tag, filename);
# endif
//g_print("ID3 TAG SIZE: %d\t%s\n",offset,g_basename(filename));
return offset;
}
@@ -431,7 +93,8 @@ static size_t ID3Tag_Link_1 (ID3Tag *id3tag, const char *filename)
/*
* 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)
/* [JEC] old id3lib versions may have used index_t for itemNum but size_t is what it wants now and seems safe enough. */
static size_t local__ID3Field_GetASCII_wrapper(const ID3Field *field, char *buffer, size_t maxChars, size_t itemNum)
{
/* Defined by id3lib: ID3LIB_MAJOR_VERSION, ID3LIB_MINOR_VERSION, ID3LIB_PATCH_VERSION
@@ -441,33 +104,266 @@ static size_t ID3Field_GetASCII_1(const ID3Field *field, char *buffer, size_t ma
* = 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)
/* (>= 3.x.x) */
# if (ID3LIB_MINOR <= 7)
// (3.0.0 to 3.7.x)
/* (3.0.0 to 3.7.x) */
# if (ID3LIB_PATCH >= 13)
// (>= 3.7.13)
return ID3Field_GetASCII(field,buffer,maxChars,itemNum);
/* (>= 3.7.13) */
return ID3Field_GetASCII(field, buffer, maxChars, itemNum);
# else
return ID3Field_GetASCII(field,buffer,maxChars,itemNum+1);
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);
/* (>= 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);
/* 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
* 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 void Strip_String (gchar *string)
static const char *local__genre_to_string(unsigned genre_code)
{
if (!string) return;
string = g_strstrip(string);
if(genre_code >= FLAC_PLUGIN__ID3V1_TAG_INVALID_GENRE)
return "";
else {
const char *s = FLAC_plugin__id3v1_tag_get_genre_as_string((unsigned)genre_code);
if(s[0] == 0)
return "Unknown";
else
return s;
}
}
/*
* 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
*/
static FLAC__bool local__get_tag(const char *filename, FLAC_Plugin__CanonicalTag *tag)
{
FILE *file;
ID3Tag *id3_tag = 0; /* Tag defined by id3lib */
char *string, *string1;
FLAC__ASSERT(0 != filename);
FLAC__ASSERT(0 != tag);
if(0 == (file = fopen(filename, "r"))) {
#ifdef DEBUG
fprintf(stderr, _("ERROR while opening file: '%s' (%s).\n\a"), filename, strerror(errno));
#endif
return false;
}
fclose(file); /* We close it cause id3lib opens/closes file itself */
/* Get data from tag */
if(0 != (id3_tag = ID3Tag_New())) {
ID3Frame *id3_frame;
ID3Field *id3_field;
luint frm_size;
luint num_chars;
size_t field_num = 0; /* First field */
/* Link the file to the tag */
frm_size = local__ID3Tag_Link_wrapper(id3_tag, filename);
string = malloc(ID3V2_MAX_STRING_LEN+1);
/*********
* Title *
*********/
if(0 != (id3_frame = ID3Tag_FindFrameWithID(id3_tag, ID3FID_TITLE))) {
if(0 != (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 = local__ID3Field_GetASCII_wrapper(id3_field, string, ID3V2_MAX_STRING_LEN, field_num)) > 0 && string != NULL) {
local__strip(string);
tag->title = strdup(string);
}
}
}
/************
* Composer *
************/
if(0 != (id3_frame = ID3Tag_FindFrameWithID(id3_tag, ID3FID_COMPOSER))) {
if(0 != (id3_field = ID3Frame_GetField(id3_frame, ID3FN_TEXT))) {
if((num_chars = local__ID3Field_GetASCII_wrapper(id3_field, string, ID3V2_MAX_STRING_LEN, field_num)) > 0 && string != NULL) {
local__strip(string);
tag->composer = strdup(string);
}
}
}
/**********
* Artist *
**********/
if(0 != (id3_frame = ID3Tag_FindFrameWithID(id3_tag, ID3FID_LEADARTIST))) {
if(0 != (id3_field = ID3Frame_GetField(id3_frame, ID3FN_TEXT))) {
if((num_chars = local__ID3Field_GetASCII_wrapper(id3_field, string, ID3V2_MAX_STRING_LEN, field_num)) > 0 && string != NULL) {
local__strip(string);
tag->performer = strdup(string);
}
}
}
/*********
* Album *
*********/
if(0 != (id3_frame = ID3Tag_FindFrameWithID(id3_tag, ID3FID_ALBUM))) {
if(0 != (id3_field = ID3Frame_GetField(id3_frame, ID3FN_TEXT))) {
if((num_chars = local__ID3Field_GetASCII_wrapper(id3_field, string, ID3V2_MAX_STRING_LEN, field_num)) > 0 && string != NULL) {
local__strip(string);
tag->album = strdup(string);
}
}
}
/********
* Year *
********/
if(0 != (id3_frame = ID3Tag_FindFrameWithID(id3_tag, ID3FID_YEAR))) {
if(0 != (id3_field = ID3Frame_GetField(id3_frame, ID3FN_TEXT))) {
if((num_chars = local__ID3Field_GetASCII_wrapper(id3_field, string, ID3V2_MAX_STRING_LEN, field_num)) > 0 && string != NULL) {
char *tmp_str;
local__strip(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 */
local__strip(string);
tag->year_recorded = strdup(string);
tag->year_performed = strdup(string);
}
}
}
/*************************
* Track and Total Track *
*************************/
if(0 != (id3_frame = ID3Tag_FindFrameWithID(id3_tag, ID3FID_TRACKNUM))) {
if(0 != (id3_field = ID3Frame_GetField(id3_frame, ID3FN_TEXT))) {
if((num_chars = local__ID3Field_GetASCII_wrapper(id3_field, string, ID3V2_MAX_STRING_LEN, field_num)) > 0 && string != NULL) {
local__strip(string);
string1 = strchr(string, '/');
if (NUMBER_TRACK_FORMATED) {
if (string1) {
/* Just to have numbers like this : '01', '05', '12', ... */
tag->tracks_in_album = malloc(64);
sprintf(tag->tracks_in_album, "%.2d", atoi(string1+1));
*string1 = '\0';
}
/* Just to have numbers like this : '01', '05', '12', ... */
tag->track_number = malloc(64);
sprintf(tag->track_number, "%.2d", atoi(string));
}
else {
if (string1) {
tag->tracks_in_album = strdup(string1+1);
*string1 = '\0';
}
tag->track_number = strdup(string);
}
}
}
}
/*********
* Genre *
*********/
if(0 != (id3_frame = ID3Tag_FindFrameWithID(id3_tag, ID3FID_CONTENTTYPE))) {
if(0 != (id3_field = ID3Frame_GetField(id3_frame, ID3FN_TEXT))) {
/*
* We manipulate only the name of the genre
*/
if((num_chars = local__ID3Field_GetASCII_wrapper(id3_field, string, ID3V2_MAX_STRING_LEN, field_num)) > 0 && string != NULL) {
char *tmp;
local__strip(string);
if((string[0]=='(') && (tmp=strchr(string, ')')) && (strlen((tmp+1))>0)) {
/* Convert a genre written as '(3)Dance' into 'Dance' */
tag->genre = strdup(tmp+1);
}
else if((string[0]=='(') && (tmp=strchr(string, ')'))) {
/* Convert a genre written as '(3)' into 'Dance' */
*tmp = 0;
tag->genre = strdup(local__genre_to_string((unsigned)atoi(string+1)));
}
else {
/* Genre is already written as 'Dance' */
tag->genre = strdup(string);
}
}
}
}
/***********
* Comment *
***********/
if(0 != (id3_frame = ID3Tag_FindFrameWithID(id3_tag, ID3FID_COMMENT))) {
if(0 != (id3_field = ID3Frame_GetField(id3_frame, ID3FN_TEXT))) {
if((num_chars = local__ID3Field_GetASCII_wrapper(id3_field, string, ID3V2_MAX_STRING_LEN, field_num)) > 0 && string != NULL) {
local__strip(string);
tag->comment = strdup(string);
}
}
#if 0
if(0 != (id3_field = ID3Frame_GetField(id3_frame, ID3FN_DESCRIPTION))) {
char *comment1 = calloc(MAX_STRING_LEN+1);
num_chars = ID3Field_GetASCII(id3_field, comment1, MAX_STRING_LEN, Item_Num);
free(comment1);
}
if(0 != (id3_field = ID3Frame_GetField(id3_frame, ID3FN_LANGUAGE))) {
char *comment2 = calloc(MAX_STRING_LEN+1);
num_chars = ID3Field_GetASCII(id3_field, comment2, MAX_STRING_LEN, Item_Num);
free(comment2);
}
#endif
}
free(string);
/* Free allocated data */
ID3Tag_Delete(id3_tag);
}
return true;
}
#endif /* ifdef FLAC__HAS_ID3LIB */
FLAC__bool FLAC_plugin__id3v2_tag_get(const char *filename, FLAC_Plugin__CanonicalTag *tag)
{
#ifdef FLAC__HAS_ID3LIB
return local__get_tag(filename, tag);
#else
return false;
#endif
}