1 /* libxmms-flac - XMMS FLAC input plugin
2 * Copyright (C) 2002 Daisuke Shimamura
4 * Almost from id3_tag.c - 2001/02/16
5 * EasyTAG - Tag editor for MP3 and OGG files
6 * Copyright (C) 2001-2002 Jerome Couderc <j.couderc@ifrance.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include "configure.h"
40 #define ID3V2_MAX_STRING_LEN 4096
41 #define NUMBER_TRACK_FORMATED 1
46 static size_t ID3Tag_Link_1 (ID3Tag *id3tag, const char *filename);
47 static size_t ID3Field_GetASCII_1 (const ID3Field *field, char *buffer, size_t maxChars, index_t itemNum);
49 static gchar *Id3tag_Genre_To_String (unsigned char genre_code);
50 static void Strip_String (gchar *string);
56 * Read id3v1.x / id3v2 tag and load data into the File_Tag structure using id3lib functions.
57 * Returns TRUE on success, else FALSE.
58 * If a tag entry exists (ex: title), we allocate memory, else value stays to NULL
60 gboolean Id3tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
63 ID3Tag *id3_tag = NULL; /* Tag defined by the id3lib */
64 gchar *string, *string1, *string2;
65 gboolean USE_CHARACTER_SET_TRANSLATION;
67 USE_CHARACTER_SET_TRANSLATION = flac_cfg.convert_char_set;
69 if (!filename || !FileTag)
72 if ( (file=fopen(filename,"r"))==NULL )
74 g_print(_("ERROR while opening file: '%s' (%s).\n\a"),filename,g_strerror(errno));
77 fclose(file); // We close it cause id3lib opens/closes file itself
80 /* Get data from tag */
81 if ( (id3_tag = ID3Tag_New()) )
87 guint field_num = 0; // First field
89 /* Link the file to the tag */
90 frm_size = ID3Tag_Link_1(id3_tag,filename);
92 string = g_malloc(ID3V2_MAX_STRING_LEN+1);
97 if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_TITLE)) )
99 if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
101 // Note: if 'num_chars' is equal to 0, then the field is empty or corrupted!
102 if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
105 if (USE_CHARACTER_SET_TRANSLATION)
107 string1 = convert_from_file_to_user(string);
108 Strip_String(string1);
109 FileTag->title = g_strdup(string1);
113 Strip_String(string);
114 FileTag->title = g_strdup(string);
124 if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_LEADARTIST)) )
126 if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
128 if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
131 if (USE_CHARACTER_SET_TRANSLATION)
133 string1 = convert_from_file_to_user(string);
134 Strip_String(string1);
135 FileTag->artist = g_strdup(string1);
139 Strip_String(string);
140 FileTag->artist = g_strdup(string);
150 if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_ALBUM)) )
152 if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
154 if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
157 if (USE_CHARACTER_SET_TRANSLATION)
159 string1 = convert_from_file_to_user(string);
160 Strip_String(string1);
161 FileTag->album = g_strdup(string1);
165 Strip_String(string);
166 FileTag->album = g_strdup(string);
176 if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_YEAR)) )
178 if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
180 if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
185 Strip_String(string);
187 /* Fix for id3lib 3.7.x: if the id3v1.x tag was filled with spaces
188 * instead of zeroes, then the year field contains garbages! */
190 while (isdigit(*tmp_str)) tmp_str++;
192 /* End of fix for id3lib 3.7.x */
194 if (USE_CHARACTER_SET_TRANSLATION)
196 string1 = convert_from_file_to_user(string);
197 Strip_String(string1);
198 FileTag->year = g_strdup(string1);
202 Strip_String(string);
203 FileTag->year = g_strdup(string);
210 /*************************
211 * Track and Total Track *
212 *************************/
213 if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_TRACKNUM)) )
215 if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
217 if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
221 Strip_String(string);
223 if (USE_CHARACTER_SET_TRANSLATION)
225 string1 = convert_from_file_to_user(string);
226 string2 = strchr(string1,'/');
227 if (NUMBER_TRACK_FORMATED)
231 FileTag->track_total = g_strdup_printf("%.2d",atoi(string2+1)); // Just to have numbers like this : '01', '05', '12', ...
234 FileTag->track = g_strdup_printf("%.2d",atoi(string1)); // Just to have numbers like this : '01', '05', '12', ...
239 FileTag->track_total = g_strdup(string2+1);
242 FileTag->track = g_strdup(string1);
247 string2 = strchr(string,'/');
248 if (NUMBER_TRACK_FORMATED)
252 FileTag->track_total = g_strdup_printf("%.2d",atoi(string2+1)); // Just to have numbers like this : '01', '05', '12', ...
255 FileTag->track = g_strdup_printf("%.2d",atoi(string)); // Just to have numbers like this : '01', '05', '12', ...
260 FileTag->track_total = g_strdup(string2+1);
263 FileTag->track = g_strdup(string);
274 if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_CONTENTTYPE)) )
276 if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
279 * We manipulate only the name of the genre
281 if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
286 Strip_String(string);
288 if ( (string[0]=='(') && (tmp=strchr(string,')')) && (strlen((tmp+1))>0) )
291 /* Convert a genre written as '(3)Dance' into 'Dance' */
292 if (USE_CHARACTER_SET_TRANSLATION)
294 string1 = convert_from_file_to_user(tmp+1);
295 FileTag->genre = g_strdup(string1);
299 FileTag->genre = g_strdup(tmp+1);
302 }else if ( (string[0]=='(') && (tmp=strchr(string,')')) )
305 /* Convert a genre written as '(3)' into 'Dance' */
307 if (USE_CHARACTER_SET_TRANSLATION)
309 string1 = convert_from_file_to_user(Id3tag_Genre_To_String(atoi(string+1)));
310 FileTag->genre = g_strdup(string1);
314 FileTag->genre = g_strdup(Id3tag_Genre_To_String(atoi(string+1)));
320 /* Genre is already written as 'Dance' */
321 if (USE_CHARACTER_SET_TRANSLATION)
323 string1 = convert_from_file_to_user(string);
324 FileTag->genre = g_strdup(string1);
328 FileTag->genre = g_strdup(string);
340 if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_COMMENT)) )
342 if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
344 if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
347 if (USE_CHARACTER_SET_TRANSLATION)
349 string1 = convert_from_file_to_user(string);
350 Strip_String(string1);
351 FileTag->comment = g_strdup(string1);
355 Strip_String(string);
356 FileTag->comment = g_strdup(string);
360 /*if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_DESCRIPTION)) )
362 gchar *comment1 = g_malloc0(MAX_STRING_LEN+1);
363 num_chars = ID3Field_GetASCII(id3_field,comment1,MAX_STRING_LEN,Item_Num);
366 if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_LANGUAGE)) )
368 gchar *comment2 = g_malloc0(MAX_STRING_LEN+1);
369 num_chars = ID3Field_GetASCII(id3_field,comment2,MAX_STRING_LEN,Item_Num);
375 /* Free allocated data */
376 ID3Tag_Delete(id3_tag);
382 void Initialize_File_Tag_Item (File_Tag *FileTag)
387 FileTag->saved = FALSE;
388 FileTag->title = NULL;
389 FileTag->artist = NULL;
390 FileTag->album = NULL;
391 FileTag->track = NULL;
392 FileTag->track_total = NULL;
393 FileTag->year = NULL;
394 FileTag->genre = NULL;
395 FileTag->comment = NULL;
400 * Frees a File_Tag item.
402 gboolean Free_File_Tag_Item (File_Tag *FileTag)
404 if (!FileTag) return FALSE;
406 if (FileTag->title) g_free(FileTag->title);
407 if (FileTag->artist) g_free(FileTag->artist);
408 if (FileTag->album) g_free(FileTag->album);
409 if (FileTag->year) g_free(FileTag->year);
410 if (FileTag->track) g_free(FileTag->track);
411 if (FileTag->track_total) g_free(FileTag->track_total);
412 if (FileTag->genre) g_free(FileTag->genre);
413 if (FileTag->comment) g_free(FileTag->comment);
419 * Returns the name of a genre code if found
420 * Three states for genre code :
421 * - defined (0 to GENRE_MAX)
422 * - undefined/unknown (GENRE_MAX+1 to ID3_INVALID_GENRE-1)
423 * - invalid (>ID3_INVALID_GENRE)
425 static gchar *Id3tag_Genre_To_String (unsigned char genre_code)
427 if (genre_code>=ID3_INVALID_GENRE) /* empty */
429 else if (genre_code>GENRE_MAX) /* unknown tag */
432 return id3_genres[genre_code];
438 * As the ID3Tag_Link function of id3lib-3.8.0pre2 returns the ID3v1 tags
439 * when a file has both ID3v1 and ID3v2 tags, we first try to explicitely
440 * get the ID3v2 tags with ID3Tag_LinkWithFlags and, if we cannot get them,
441 * fall back to the ID3v1 tags.
442 * (Written by Holger Schemel).
444 static size_t ID3Tag_Link_1 (ID3Tag *id3tag, const char *filename)
448 # if ( (ID3LIB_MAJOR >= 3) && (ID3LIB_MINOR >= 8) )
449 /* First, try to get the ID3v2 tags */
450 offset = ID3Tag_LinkWithFlags(id3tag,filename,ID3TT_ID3V2);
453 /* No ID3v2 tags available => try to get the ID3v1 tags */
454 offset = ID3Tag_LinkWithFlags(id3tag,filename,ID3TT_ID3V1);
457 /* Function 'ID3Tag_LinkWithFlags' is not defined up to id3lib-.3.7.13 */
458 offset = ID3Tag_Link(id3tag,filename);
460 //g_print("ID3 TAG SIZE: %d\t%s\n",offset,g_basename(filename));
466 * As the ID3Field_GetASCII function differs with the version of id3lib, we must redefine it.
468 static size_t ID3Field_GetASCII_1(const ID3Field *field, char *buffer, size_t maxChars, index_t itemNum)
471 /* Defined by id3lib: ID3LIB_MAJOR_VERSION, ID3LIB_MINOR_VERSION, ID3LIB_PATCH_VERSION
472 * Defined by autoconf: ID3LIB_MAJOR, ID3LIB_MINOR, ID3LIB_PATCH
474 * <= 3.7.12 : first item num is 1 for ID3Field_GetASCII
475 * = 3.7.13 : first item num is 0 for ID3Field_GetASCII
476 * >= 3.8.0 : doesn't need item num for ID3Field_GetASCII
478 //g_print("id3lib version: %d.%d.%d\n",ID3LIB_MAJOR,ID3LIB_MINOR,ID3LIB_PATCH);
479 # if (ID3LIB_MAJOR >= 3)
481 # if (ID3LIB_MINOR <= 7)
483 # if (ID3LIB_PATCH >= 13)
485 return ID3Field_GetASCII(field,buffer,maxChars,itemNum);
487 return ID3Field_GetASCII(field,buffer,maxChars,itemNum+1);
491 //return ID3Field_GetASCII(field,buffer,maxChars);
492 return ID3Field_GetASCIIItem(field,buffer,maxChars,itemNum);
495 // Not tested (< 3.x.x)
496 return ID3Field_GetASCII(field,buffer,maxChars,itemNum+1);
501 * Delete spaces at the end and the beginning of the string
503 static void Strip_String (gchar *string)
506 string = g_strstrip(string);