~jcowgill/ubuntu/trusty/easytag/bug-1295882

« back to all changes in this revision

Viewing changes to src/id3_tag.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2006-04-15 15:47:47 UTC
  • mfrom: (1.2.2 upstream) (3.1.1 dapper)
  • Revision ID: james.westby@ubuntu.com-20060415154747-vr4eqoxwcrgs2ps1
* New upstream version:
  - New logo and icons,
  - Added ability to display all albums of an artist in the 'Artist / Album'
    view,
  - Added detection of the bugged version of id3lib when writting ID3 tag to 
    Unicode to inform the user (a patch for id3lib is supplied in package
    source),
  - For Ogg files, the field DESCRIPTION is also used for the comment,
  - Fixed stack corruption bugs in Fill Tag scanner,
  - Fixed loading disk number for FLAC tag,
  - Fixed error that displays MP3 files in red when no tag is present,
  - Fixed a crash in the CDDB window when getting tracks of a album,
  - Fixed playlist name bug when creating it in the parent directory,
  - Fixed manual CDDB search when using Squid,
  - Little fix for FLAC tags,
  - Fixed various bugs,
  - Russian translation updated,
  - Greek translation updated,
  - Spanish translation updated,
  - Japanese translation updated,
  - Czech translation updated,
  - Brazilian Portuguese translation updated
  - Danish translation updated,
  - Italian translation updated,
  - Hungarian translation updated,
  - German translation updated.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* id3tag.c - 2001/02/16 */
2
2
/*
3
3
 *  EasyTAG - Tag editor for MP3 and Ogg Vorbis files
4
 
 *  Copyright (C) 2001-2003  Jerome Couderc <j.couderc@ifrance.com>
 
4
 *  Copyright (C) 2001-2003  Jerome Couderc <easytag@gmail.com>
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
20
20
 
21
21
#include <config.h>
22
22
 
23
 
#include <id3.h>
24
23
#include <gtk/gtk.h>
25
24
#include <glib/gi18n-lib.h>
26
25
#include <stdio.h>
30
29
#include <unistd.h>
31
30
 
32
31
#include "id3_tag.h"
 
32
#include "id3lib/id3_bugfix.h"
33
33
#include "picture.h"
34
 
#include "genres.h"
35
34
#include "easytag.h"
36
35
#include "browser.h"
 
36
#include "genres.h"
37
37
#include "setting.h"
38
38
#include "misc.h"
39
39
#include "et_core.h"
 
40
#include "msgbox.h"
40
41
#include "charset.h"
41
42
 
 
43
#ifdef ENABLE_MP3
 
44
 
 
45
#include <id3.h>
 
46
 
42
47
 
43
48
/****************
44
49
 * Declarations *
46
51
#define ID3V2_MAX_STRING_LEN 4096
47
52
#define MULTIFIELD_SEPARATOR " - "
48
53
 
49
 
#define HANDLE_TRANSLATION_READ(target, string)                           \
50
 
    if (USE_CHARACTER_SET_TRANSLATION)                                    \
51
 
        (target) = convert_string((string), FILE_CHARACTER_SET, "utf-8"); \
52
 
    else if (USE_ISO_8859_1_CHARACTER_SET_TRANSLATION)                    \
53
 
        (target) = convert_string((string), "iso-8859-1", "utf-8");       \
54
 
    else                                                                  \
55
 
        (target) = convert_to_utf8((string));
56
 
 
57
 
#define HANDLE_TRANSLATION_SAVE(temp, string, id3field)                   \
58
 
    if (USE_CHARACTER_SET_TRANSLATION)                                    \
59
 
        (temp) = convert_string((string), "utf-8", FILE_CHARACTER_SET);   \
60
 
    else if (USE_ISO_8859_1_CHARACTER_SET_TRANSLATION)                    \
61
 
        (temp) = convert_string((string), "utf-8", "iso-8859-1");         \
62
 
    else                                                                  \
63
 
        (temp) = convert_from_utf8((string));                             \
64
 
    ID3Field_SetASCII(id3field,temp);                                     \
65
 
    g_free(temp);
66
 
 
67
 
 
68
54
 
69
55
/**************
70
56
 * Prototypes *
71
57
 **************/
72
58
gchar *Id3tag_Get_Error_Message (ID3_Err error);
73
59
gint   Id3tag_Get_Id3v2_Version (gchar *filename);
74
 
gchar *Id3tag_Get_Frame_Text    (const ID3Tag *id3tag, ID3_FrameID id3frameid);
 
60
void   Id3tag_Prepare_ID3v1     (ID3Tag *id3_tag);
 
61
gchar *Id3tag_Rules_For_ISO_Fields (const gchar *string, const gchar *from_codeset, const gchar *to_codeset);
 
62
gchar *Id3tag_Get_Field         (const ID3Frame *id3_frame, ID3_FieldID id3_fieldid);
 
63
ID3_TextEnc Id3tag_Set_Field    (const ID3Frame *id3_frame, ID3_FieldID id3_fieldid, gchar *string);
 
64
 
75
65
ID3_C_EXPORT size_t ID3Tag_Link_1         (ID3Tag *id3tag, const char *filename);
76
66
ID3_C_EXPORT size_t ID3Field_GetASCII_1   (const ID3Field *field, char *buffer,      size_t maxChars, size_t itemNum);
77
67
ID3_C_EXPORT size_t ID3Field_GetUNICODE_1 (const ID3Field *field, unicode_t *buffer, size_t maxChars, size_t itemNum);
78
68
 
 
69
gboolean Id3tag_Check_If_File_Is_Corrupted (gchar *filename);
 
70
 
 
71
gboolean Id3tag_Check_If_Id3lib_Is_Bugged (void);
 
72
 
79
73
 
80
74
 
81
75
/*************
95
89
    ID3Frame *id3_frame, *id3_first_frame;
96
90
    ID3Field *id3_field;
97
91
    size_t offset;
98
 
    luint num_chars;
99
 
    guint field_num = 0; // First field
100
92
    Picture *prev_pic = NULL;
 
93
    unsigned char tmp[4];
 
94
    gboolean has_id3v1_tag = TRUE;
 
95
    gboolean has_id3v2_tag = TRUE;
101
96
 
102
97
    if (!filename || !FileTag)
103
98
        return FALSE;
104
99
 
105
 
    if ( (file=fopen(filename,"r"))==NULL )
 
100
    if ( (file=fopen(filename,"rb"))==NULL )
106
101
    {
107
102
        gchar *filename_utf8 = filename_to_display(filename);
108
103
        g_print(_("ERROR while opening file: '%s' (%s).\n\a"),filename_utf8,g_strerror(errno));
109
104
        g_free(filename_utf8);
110
105
        return FALSE;
111
106
    }
 
107
    
 
108
    // Check if the file has an ID3v2 tag or/and an ID3v1 tags
 
109
    // 1) ID3v2 tag
 
110
    if (fread(tmp, 1, 4, file) != 4)
 
111
    {
 
112
        fclose(file);
 
113
        return FALSE;
 
114
    }
 
115
    if (tmp[0] != 'I' || tmp[1] != 'D' || tmp[2] != '3' || tmp[3] >= 0xFF) // ID3v2 tag skipeer $49 44 33 yy yy xx zz zz zz zz [zz size]
 
116
    {
 
117
        // ID3v2 tag not found!
 
118
        has_id3v2_tag = FALSE;
 
119
    }
 
120
    // 2) ID3v1 tag
 
121
    if (fseek(file,-128, SEEK_END)!=0 // Go to the beginning of ID3v1 tag
 
122
    ||  fread(tmp,1,3,file) != 3)
 
123
    {
 
124
        fclose(file);
 
125
        return FALSE;
 
126
    }
 
127
    if (tmp[0] != 'T' || tmp[1] != 'A' || tmp[2] != 'G')
 
128
    {
 
129
        // ID3v1 tag not found!
 
130
        has_id3v1_tag = FALSE;
 
131
    }
112
132
    fclose(file); // We close it cause id3lib opens/closes file itself
113
133
 
 
134
    /* We mark the file as unsaved (in color red in file list), if the tags 
 
135
     * version found doesn't match with the settings to force to save the tag 
 
136
     * (but only if there are data to save!) */
 
137
    if (WRITE_ID3V2_TAG && !has_id3v2_tag && has_id3v1_tag) // Save ID3v2 if there is data in ID3v1 tag
 
138
        FileTag->saved = FALSE;
 
139
    if (WRITE_ID3V1_TAG && !has_id3v1_tag && has_id3v2_tag) // Save ID3v1 if there is data in ID3v2 tag
 
140
        FileTag->saved = FALSE;
 
141
    
 
142
    /* This is a protection against a bug in id3lib that generate an infinite
 
143
     * loop with corrupted MP3 files (files containing only zeroes) */
 
144
    if (Id3tag_Check_If_File_Is_Corrupted(filename))
 
145
        return FALSE;
 
146
 
 
147
    // If no tag found, it isn't useful to try to read it with id3lib
 
148
    if (!has_id3v1_tag && !has_id3v2_tag)
 
149
        return FALSE;
 
150
 
114
151
    /* Get data from tag */
115
152
    if ( (id3_tag = ID3Tag_New()) == NULL )
116
153
        return FALSE;
126
163
    }
127
164
 
128
165
    /* If the specified tags (in preferences window) aren't in the file => we save it
129
 
     * (Note: the file must be linked with the both tags) */ 
 
166
     * (Note: the file must be linked with the both tags) */
 
167
/*** // Disabled (see on top on replacement) as we don't link the file with the both tags (because may cause damage to unicode strings)
130
168
#   if ( (ID3LIB_MAJOR >= 3) && (ID3LIB_MINOR >= 8) && (ID3LIB_PATCH >= 1) )
131
169
    if (ID3Tag_HasTagType(id3_tag,ID3TT_ID3V1) != WRITE_ID3V1_TAG
132
170
    ||  ID3Tag_HasTagType(id3_tag,ID3TT_ID3V2) != WRITE_ID3V2_TAG)
133
171
        FileTag->saved = FALSE;
134
172
#   endif
 
173
****/
135
174
 
136
175
    /* Protection against invalid ID3v2 tag, for example ID3v2.4 in
137
176
     * id3lib-3.8.0 : if offset is not nul and the tag contains no
143
182
 
144
183
    string = g_malloc(ID3V2_MAX_STRING_LEN+1);
145
184
 
 
185
 
146
186
    /****************
147
187
     * Title (TIT2) *
148
188
     ****************/
149
 
    //testing
150
 
    //FileTag->title = Id3tag_Get_Frame_Text(id3_tag,ID3FID_TITLE);
151
189
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_TITLE)) )
152
190
    {
153
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
154
 
        {
155
 
            //testing:check encoding
156
 
            //id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
157
 
            //g_print(">>> Encoding '%d'\n",ID3Field_GetINT(id3_field_encoding));
158
 
 
159
 
            // FIX ME : 'ID3FrameInfo_NumFields' would be better...
160
 
            // Note: if 'num_chars' is equal to 0, then the field is empty or corrupted!
161
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
162
 
                 && string != NULL )
163
 
            {
164
 
                HANDLE_TRANSLATION_READ(FileTag->title, string);
165
 
            }
166
 
        }
 
191
        FileTag->title = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
167
192
    }
168
193
 
 
194
 
169
195
    /*****************
170
196
     * Artist (TPE1) *
171
197
     *****************/
172
198
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_LEADARTIST)) )
173
199
    {
174
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
175
 
        {
176
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
177
 
                 && string != NULL )
178
 
            {
179
 
                HANDLE_TRANSLATION_READ(FileTag->artist, string);
180
 
            }
181
 
        }
 
200
        FileTag->artist = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
182
201
    }
183
202
 
184
203
 
187
206
     ****************/
188
207
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_ALBUM)) )
189
208
    {
190
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
191
 
        {
192
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
193
 
                 && string != NULL )
194
 
            {
195
 
                HANDLE_TRANSLATION_READ(FileTag->album, string);
196
 
            }
197
 
        }
 
209
        FileTag->album = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
 
210
    }
 
211
 
 
212
 
 
213
    /************************
 
214
     * Part of a set (TPOS) *
 
215
     ************************/
 
216
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_PARTINSET)) )
 
217
    {
 
218
        FileTag->disc_number = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
198
219
    }
199
220
 
200
221
 
203
224
     ***************/
204
225
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_YEAR)) )
205
226
    {
206
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
 
227
        if ( (string1 = Id3tag_Get_Field(id3_frame,ID3FN_TEXT)) )
207
228
        {
208
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
209
 
                 && string != NULL )
210
 
            {
211
 
                gchar *tmp_str;
212
 
 
213
 
                Strip_String(string);
214
 
 
215
 
                /* Fix for id3lib 3.7.x: if the id3v1.x tag was filled with spaces
216
 
                 * instead of zeroes, then the year field contains garbages! */
217
 
                tmp_str = string;
218
 
                while (isdigit(*tmp_str)) tmp_str++;
219
 
                *tmp_str = 0;
220
 
                /* End of fix for id3lib 3.7.x */
221
 
                HANDLE_TRANSLATION_READ(FileTag->year, string);
222
 
            }
 
229
            gchar *tmp_str;
 
230
    
 
231
            Strip_String(string1);
 
232
    
 
233
            /* Fix for id3lib 3.7.x: if the id3v1.x tag was filled with spaces
 
234
             * instead of zeroes, then the year field contains garbages! */
 
235
            tmp_str = string1;
 
236
            while (isdigit((guchar)*tmp_str)) tmp_str++;
 
237
            *tmp_str = 0;
 
238
            /* End of fix for id3lib 3.7.x */
 
239
            FileTag->year = string1;
223
240
        }
224
241
    }
225
242
 
229
246
     ********************************/
230
247
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_TRACKNUM)) )
231
248
    {
232
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
 
249
        if ( (string1 = Id3tag_Get_Field(id3_frame,ID3FN_TEXT)) )
233
250
        {
234
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
235
 
                 && string != NULL )
236
 
            {
237
 
 
238
 
                if (USE_CHARACTER_SET_TRANSLATION)
239
 
                {
240
 
                    string1 = convert_string(string, FILE_CHARACTER_SET, "utf-8");
241
 
                    string2 = strchr(string1,'/');
242
 
                    if (NUMBER_TRACK_FORMATED)
243
 
                    {
244
 
                        if (string2)
245
 
                        {
246
 
                            FileTag->track_total = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string2+1)); // Just to have numbers like this : '01', '05', '12', ...
247
 
                            *string2 = '\0';
248
 
                        }
249
 
                        FileTag->track = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string1)); // Just to have numbers like this : '01', '05', '12', ...
250
 
                    }else
251
 
                    {
252
 
                        if (string2)
253
 
                        {
254
 
                            FileTag->track_total = g_strdup(string2+1);
255
 
                            *string2 = '\0';
256
 
                        }
257
 
                        FileTag->track = g_strdup(string1);
258
 
                    }
259
 
                    g_free(string1);
260
 
                }else if (USE_ISO_8859_1_CHARACTER_SET_TRANSLATION)
261
 
                {
262
 
                    string1 = convert_string(string, "iso-8859-1", "utf-8");
263
 
                    string2 = strchr(string1,'/');
264
 
                    if (NUMBER_TRACK_FORMATED)
265
 
                    {
266
 
                        if (string2)
267
 
                        {
268
 
                            FileTag->track_total = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string2+1)); // Just to have numbers like this : '01', '05', '12', ...
269
 
                            *string2 = '\0';
270
 
                        }
271
 
                        FileTag->track = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string1)); // Just to have numbers like this : '01', '05', '12', ...
272
 
                    }else
273
 
                    {
274
 
                        if (string2)
275
 
                        {
276
 
                            FileTag->track_total = g_strdup(string2+1);
277
 
                            *string2 = '\0';
278
 
                        }
279
 
                        FileTag->track = g_strdup(string1);
280
 
                    }
281
 
                    g_free(string1);
282
 
                }else
283
 
                {
284
 
                    string1 = convert_to_utf8(string);
285
 
                    string2 = strchr(string,'/');
286
 
                    if (NUMBER_TRACK_FORMATED)
287
 
                    {
288
 
                        if (string2)
289
 
                        {
290
 
                            FileTag->track_total = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string2+1)); // Just to have numbers like this : '01', '05', '12', ...
291
 
                            *string2 = '\0';
292
 
                        }
293
 
                        FileTag->track = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string1)); // Just to have numbers like this : '01', '05', '12', ...
294
 
                    }else
295
 
                    {
296
 
                        if (string2)
297
 
                        {
298
 
                            FileTag->track_total = g_strdup(string2+1);
299
 
                            *string2 = '\0';
300
 
                        }
301
 
                        FileTag->track = g_strdup(string1);
302
 
                        g_free(string1);
303
 
                    }
304
 
                }
 
251
            string2 = g_utf8_strchr(string1,-1,'/');
 
252
    
 
253
            if (NUMBER_TRACK_FORMATED)
 
254
            {
 
255
                if (string2)
 
256
                {
 
257
                    FileTag->track_total = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string2+1)); // Just to have numbers like this : '01', '05', '12', ...
 
258
                    *string2 = '\0';
 
259
                }
 
260
                FileTag->track = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string1)); // Just to have numbers like this : '01', '05', '12', ...
 
261
            }else
 
262
            {
 
263
                if (string2)
 
264
                {
 
265
                    FileTag->track_total = g_strdup(string2+1);
 
266
                    *string2 = '\0';
 
267
                }
 
268
                FileTag->track = g_strdup(string1);
305
269
            }
 
270
            g_free(string1);
 
271
            
306
272
        }
307
273
    }
308
274
 
312
278
     ****************/
313
279
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_CONTENTTYPE)) )
314
280
    {
315
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
 
281
        if ( (string1 = Id3tag_Get_Field(id3_frame,ID3FN_TEXT)) )
316
282
        {
317
283
            /*
318
284
             * We manipulate only the name of the genre
321
287
             *    - "<genre_name>"              -> "Dance"
322
288
             *    - "(<genre_id>)<refinement>"  -> "(3)EuroDance"
323
289
             */
324
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
325
 
                 && string != NULL )
326
 
            {
327
 
                gchar *tmp;
328
 
 
329
 
                if ( (string[0]=='(') && (tmp=strchr(string,')')) && (strlen((tmp+1))>0) )
330
 
                    /* Convert a genre written as '(3)EuroDance' into 'EuroDance' */
331
 
                {
332
 
                    HANDLE_TRANSLATION_READ(FileTag->genre, tmp+1);
333
 
                } else if ( (string[0]=='(') && (tmp=strchr(string,')')) )
334
 
                {
335
 
                    /* Convert a genre written as '(3)' into 'Dance' */
336
 
                    HANDLE_TRANSLATION_READ(FileTag->genre, Id3tag_Genre_To_String(atoi(string+1)));
337
 
                } else
338
 
                {
339
 
                    /* Genre is already written as 'Dance' */
340
 
                    HANDLE_TRANSLATION_READ(FileTag->genre, string);
341
 
                }
 
290
            gchar *tmp;
 
291
    
 
292
            if ( (string1[0]=='(') && (tmp=strchr(string1,')')) && (tmp+1) && (strlen((tmp+1))>0) )
 
293
                /* Convert a genre written as '(3)EuroDance' into 'EuroDance' */
 
294
            {
 
295
                FileTag->genre = g_strdup(tmp+1);
 
296
            } else if ( (string1[0]=='(') && (tmp=strchr(string1,')')) )
 
297
            {
 
298
                /* Convert a genre written as '(3)' into 'Dance' */
 
299
                FileTag->genre = g_strdup( Id3tag_Genre_To_String(atoi(string1+1)) );
 
300
            } else
 
301
            {
 
302
                /* Genre is already written as 'Dance' */
 
303
                FileTag->genre = g_strdup(string1);
342
304
            }
 
305
            g_free(string1);
343
306
        }
344
307
    }
345
308
 
349
312
     ******************/
350
313
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_COMMENT)) )
351
314
    {
352
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
353
 
        {
354
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
355
 
                 && string != NULL )
356
 
            {
357
 
                HANDLE_TRANSLATION_READ(FileTag->comment, string);
358
 
            }
359
 
        }
360
 
        /*if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_DESCRIPTION)) )
361
 
        {
362
 
        gchar *comment1 = g_malloc0(MAX_STRING_LEN+1);
363
 
        num_chars = ID3Field_GetASCII(id3_field,comment1,MAX_STRING_LEN,Item_Num);
364
 
        g_free(comment1);
365
 
        }
366
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_LANGUAGE)) )
367
 
        {
368
 
        gchar *comment2 = g_malloc0(MAX_STRING_LEN+1);
369
 
        num_chars = ID3Field_GetASCII(id3_field,comment2,MAX_STRING_LEN,Item_Num);
370
 
        g_free(comment2);
 
315
        FileTag->comment = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
 
316
        /*{
 
317
            gchar *comment1 = Id3tag_Get_Field(id3_frame,ID3FN_DESCRIPTION)
 
318
            gchar *comment2 = Id3tag_Get_Field(id3_frame,ID3FN_LANGUAGE)
371
319
        }*/
372
320
    }
373
321
 
377
325
     *******************/
378
326
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_COMPOSER)) )
379
327
    {
380
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
381
 
        {
382
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
383
 
                 && string != NULL )
384
 
            {
385
 
                HANDLE_TRANSLATION_READ(FileTag->composer, string);
386
 
            }
387
 
        }
 
328
        FileTag->composer = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
388
329
    }
389
330
 
390
331
 
393
334
     **************************/
394
335
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_ORIGARTIST)) )
395
336
    {
396
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
397
 
        {
398
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
399
 
                 && string != NULL )
400
 
            {
401
 
                HANDLE_TRANSLATION_READ(FileTag->orig_artist, string);
402
 
            }
403
 
        }
 
337
        FileTag->orig_artist = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
404
338
    }
405
339
 
406
340
 
409
343
     *******************/
410
344
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_COPYRIGHT)) )
411
345
    {
412
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
413
 
        {
414
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
415
 
                 && string != NULL )
416
 
            {
417
 
                HANDLE_TRANSLATION_READ(FileTag->copyright, string);
418
 
            }
419
 
        }
 
346
        FileTag->copyright = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
420
347
    }
421
348
 
422
349
 
425
352
     **************/
426
353
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_WWWUSER)) )
427
354
    {
428
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_URL)) )
429
 
        {
430
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
431
 
                 && string != NULL )
432
 
            {
433
 
                HANDLE_TRANSLATION_READ(FileTag->url, string);
434
 
            }
435
 
        }
 
355
        FileTag->url = Id3tag_Get_Field(id3_frame,ID3FN_URL);
436
356
    }
437
357
 
438
358
 
441
361
     *********************/
442
362
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_ENCODEDBY)) )
443
363
    {
444
 
        if ( (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
445
 
        {
446
 
            if ( (num_chars=ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,field_num)) > 0
447
 
                 && string != NULL )
448
 
            {
449
 
                HANDLE_TRANSLATION_READ(FileTag->encoded_by, string);
450
 
            }
451
 
        }
 
364
        FileTag->encoded_by = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
452
365
    }
453
366
 
454
367
 
455
 
    /***********
456
 
     * Picture *
457
 
     ***********/
 
368
    /******************
 
369
     * Picture (APIC) *
 
370
     ******************/
 
371
    // Have a look to id3/misc_support.h (id3lib)
458
372
    id3_first_frame = NULL;
459
373
    for(;;)
460
374
    {
473
387
            prev_pic->next = pic;
474
388
        prev_pic = pic;
475
389
        
 
390
        // Picture file data
476
391
        if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_DATA)) )
477
392
        {
478
393
            pic->size = ID3Field_Size(id3_field);
479
394
            pic->data = g_malloc(pic->size);
480
395
            ID3Field_GetBINARY(id3_field, pic->data, pic->size);
481
396
        }
 
397
        
 
398
        // Picture type
482
399
        if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_PICTURETYPE)) )
483
400
            pic->type = ID3Field_GetINT(id3_field);
484
 
        if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_DESCRIPTION)) )
485
 
            if ( (num_chars = ID3Field_GetASCII_1(id3_field, string,ID3V2_MAX_STRING_LEN, field_num)) > 0 
486
 
            &&   string != NULL )
487
 
                pic->description = g_strdup(string);
 
401
        
 
402
        // Picture description
 
403
        pic->description = Id3tag_Get_Field(id3_frame, ID3FN_DESCRIPTION);
 
404
            
 
405
        //g_print("Image format : '%s'\n",Id3tag_Get_Field(id3_frame, ID3FN_IMAGEFORMAT));
488
406
    }
489
407
 
490
408
 
 
409
    /*****************
 
410
     * Lyrics (SYLC) *
 
411
     *****************/
 
412
    /** see also id3/misc_support.h  **
 
413
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_SYNCEDLYRICS)) )
 
414
    {
 
415
        gulong  size = 0;
 
416
        guchar *data = NULL;
 
417
        gchar  *description = NULL;
 
418
        gchar  *language = NULL;
 
419
        gint timestamp_format = 0;
 
420
        gint sync_type = 0;
 
421
    
 
422
        // SyncLyrics data
 
423
        if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_DATA)) )
 
424
        {
 
425
            size = ID3Field_Size(id3_field);
 
426
            data = g_malloc(size);
 
427
            ID3Field_GetBINARY(id3_field, data, size);
 
428
        }
 
429
 
 
430
        // SyncLyrics description
 
431
        description = Id3tag_Get_Field(id3_frame, ID3FN_DESCRIPTION);
 
432
 
 
433
        // SyncLyrics language
 
434
        language = Id3tag_Get_Field(id3_frame, ID3FN_LANGUAGE);
 
435
 
 
436
        // SyncLyrics timestamp field
 
437
        if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_TIMESTAMPFORMAT)) )
 
438
        {
 
439
            timestamp_format = ID3Field_GetINT(id3_field);
 
440
        }
 
441
        
 
442
        // SyncLyrics content type
 
443
        if ( (id3_field = ID3Frame_GetField(id3_frame, ID3FN_CONTENTTYPE)) )
 
444
        {
 
445
            sync_type = ID3Field_GetINT(id3_field);
 
446
        }
 
447
 
 
448
        // Print data
 
449
        // j.a. Pouwelse - pouwelse :
 
450
        //      http://sourceforge.net/tracker/index.php?func=detail&aid=401873&group_id=979&atid=300979
 
451
        {
 
452
            char tag[255];
 
453
            unsigned int time;
 
454
            luint pos = 0;
 
455
            
 
456
            g_print("SyncLyrics/description      : %s\n",description);
 
457
            g_print("SyncLyrics/language         : %s\n",language);
 
458
            g_print("SyncLyrics/timestamp format : %s (%d)\n",timestamp_format==ID3TSF_FRAME ? "ID3TSF_FRAME" : timestamp_format==ID3TSF_MS ? "ID3TSF_MS" : "" ,timestamp_format);
 
459
            g_print("SyncLyrics/sync type        : %s (%d)\n",sync_type==ID3CT_LYRICS ? "ID3CT_LYRICS" : "",sync_type);
 
460
            
 
461
            
 
462
            g_print("SyncLyrics size             : %d\n", size);
 
463
            g_print("Lyrics/data :\n");
 
464
            while (pos < size)
 
465
            {
 
466
                strcpy(tag,data+pos);
 
467
                //g_print("txt start=%d ",pos);
 
468
                pos+=strlen(tag)+1;             // shift string and terminating \0
 
469
                //g_print("txt end=%d ",pos);
 
470
                memcpy(&time,data+pos,4);
 
471
                pos+=4;
 
472
                //g_print("%d -> %s\n",time,tag);
 
473
                g_print("%s",tag);
 
474
            }
 
475
        }
 
476
        
 
477
    } **/
 
478
 
 
479
 
491
480
    g_free(string);
492
481
 
493
482
    /* Free allocated data */
514
503
    ID3_Err   error_update_id3v2 = ID3E_NoError;
515
504
    gint error = 0;
516
505
    gint number_of_frames;
517
 
    gboolean has_title       = 1;
518
 
    gboolean has_artist      = 1;
519
 
    gboolean has_album       = 1;
520
 
    gboolean has_year        = 1;
521
 
    gboolean has_track       = 1;
522
 
    gboolean has_genre       = 1;
523
 
    gboolean has_comment     = 1;
524
 
    gboolean has_composer    = 1;
525
 
    gboolean has_orig_artist = 1;
526
 
    gboolean has_copyright   = 1;
527
 
    gboolean has_url         = 1;
528
 
    gboolean has_encoded_by  = 1;
529
 
    gboolean has_picture     = 1;
530
 
    gboolean has_song_len    = 1;
 
506
    gboolean has_title       = FALSE;
 
507
    gboolean has_artist      = FALSE;
 
508
    gboolean has_album       = FALSE;
 
509
    gboolean has_disc_number = FALSE;
 
510
    gboolean has_year        = FALSE;
 
511
    gboolean has_track       = FALSE;
 
512
    gboolean has_genre       = FALSE;
 
513
    gboolean has_comment     = FALSE;
 
514
    gboolean has_composer    = FALSE;
 
515
    gboolean has_orig_artist = FALSE;
 
516
    gboolean has_copyright   = FALSE;
 
517
    gboolean has_url         = FALSE;
 
518
    gboolean has_encoded_by  = FALSE;
 
519
    gboolean has_picture     = FALSE;
 
520
    gboolean has_song_len    = FALSE;
 
521
    static gboolean flag_first_check = TRUE;
 
522
    static gboolean flag_id3lib_bugged = TRUE;
531
523
 
532
524
    ID3Frame *id3_frame;
533
525
    ID3Field *id3_field;
534
 
    gchar *string, *string1;
 
526
    //gchar *string;
 
527
    gchar *string1;
535
528
    Picture *pic;
536
529
 
 
530
 
 
531
    // When writing the first MP3 file, we check if the version of id3lib of the 
 
532
    // system doesn't contain a bug when writting Unicode tags
 
533
    if (flag_first_check 
 
534
    && (USE_ID3_ISO_8859_1_THEN_UNICODE_CHARACTER_SET || USE_ID3_UNICODE_CHARACTER_SET) )
 
535
    {
 
536
        flag_first_check = FALSE;
 
537
        flag_id3lib_bugged = Id3tag_Check_If_Id3lib_Is_Bugged();
 
538
    }
 
539
 
537
540
    if (!ETFile || !ETFile->FileTag)
538
541
        return FALSE;
539
542
 
540
 
    FileTag = (File_Tag *)ETFile->FileTag->data;
 
543
    FileTag  = (File_Tag *)ETFile->FileTag->data;
541
544
    filename = ((File_Name *)ETFile->FileNameCur->data)->value;
542
545
 
543
546
    /* Test to know if we can write into the file */
550
553
    }
551
554
    fclose(file);
552
555
 
 
556
    /* This is a protection against a bug in id3lib that generate an infinite
 
557
     * loop with corrupted MP3 files (files containing only zeroes) */
 
558
    if (Id3tag_Check_If_File_Is_Corrupted(filename))
 
559
        return FALSE;
 
560
 
553
561
    /* We get again the tag from the file to keep also unused data (by EasyTAG), then
554
562
     * we replace the changed data */
555
563
    if ( (id3_tag = ID3Tag_New()) == NULL )
576
584
    {
577
585
        id3_frame = ID3Frame_NewID(ID3FID_TITLE);
578
586
        ID3Tag_AttachFrame(id3_tag,id3_frame);
579
 
 
580
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
581
 
        {
582
 
            HANDLE_TRANSLATION_SAVE(string, FileTag->title, id3_field);
583
 
        }
584
 
    } else
585
 
    {
586
 
        has_title = 0;
 
587
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, FileTag->title);
 
588
        has_title = TRUE;
587
589
    }
588
590
 
 
591
 
589
592
    /**********
590
593
     * Artist *
591
594
     **********/
595
598
    {
596
599
        id3_frame = ID3Frame_NewID(ID3FID_LEADARTIST);
597
600
        ID3Tag_AttachFrame(id3_tag,id3_frame);
598
 
 
599
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
600
 
        {
601
 
            HANDLE_TRANSLATION_SAVE(string, FileTag->artist, id3_field);
602
 
        }
603
 
 
604
 
    } else
605
 
    {
606
 
        has_artist = 0;
 
601
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, FileTag->artist);
 
602
        has_artist = TRUE;
607
603
    }
608
604
 
609
605
 
616
612
    {
617
613
        id3_frame = ID3Frame_NewID(ID3FID_ALBUM);
618
614
        ID3Tag_AttachFrame(id3_tag,id3_frame);
619
 
 
620
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
621
 
        {
622
 
            HANDLE_TRANSLATION_SAVE(string, FileTag->album, id3_field);
623
 
        }
624
 
    } else
 
615
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, FileTag->album);
 
616
        has_album = TRUE;
 
617
    }
 
618
 
 
619
 
 
620
    /***************
 
621
     * Part of set *
 
622
     ***************/
 
623
    while ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_PARTINSET)) )
 
624
        ID3Tag_RemoveFrame(id3_tag,id3_frame);
 
625
    if (FileTag->disc_number && g_utf8_strlen(FileTag->disc_number, -1) > 0)
625
626
    {
626
 
        has_album = 0;
 
627
        id3_frame = ID3Frame_NewID(ID3FID_PARTINSET);
 
628
        ID3Tag_AttachFrame(id3_tag,id3_frame);
 
629
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, FileTag->disc_number);
 
630
        has_disc_number = TRUE;
627
631
    }
628
632
 
629
633
 
636
640
    {
637
641
        id3_frame = ID3Frame_NewID(ID3FID_YEAR);
638
642
        ID3Tag_AttachFrame(id3_tag,id3_frame);
639
 
 
640
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
641
 
        {
642
 
            HANDLE_TRANSLATION_SAVE(string, FileTag->year, id3_field);
643
 
        }
644
 
    } else
645
 
    {
646
 
        has_year = 0;
 
643
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, FileTag->year);
 
644
        has_year = TRUE;
647
645
    }
648
646
 
649
647
 
657
655
        id3_frame = ID3Frame_NewID(ID3FID_TRACKNUM);
658
656
        ID3Tag_AttachFrame(id3_tag,id3_frame);
659
657
 
660
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
661
 
        {
662
 
            if ( FileTag->track_total && g_utf8_strlen(FileTag->track_total, -1) > 0)
663
 
                string1 = g_strconcat(FileTag->track,"/",FileTag->track_total,NULL);
664
 
            else
665
 
                string1 = g_strdup(FileTag->track);
 
658
        if ( FileTag->track_total && g_utf8_strlen(FileTag->track_total, -1) > 0)
 
659
            string1 = g_strconcat(FileTag->track,"/",FileTag->track_total,NULL);
 
660
        else
 
661
            string1 = g_strdup(FileTag->track);
666
662
 
667
 
            HANDLE_TRANSLATION_SAVE(string, string1, id3_field);
668
 
            g_free(string1);
669
 
        }
670
 
    } else
671
 
    {
672
 
        has_track = 0;
 
663
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, string1);
 
664
        g_free(string1);
 
665
        has_track = TRUE;
673
666
    }
674
667
 
675
668
 
684
677
        ID3Tag_RemoveFrame(id3_tag,id3_frame);
685
678
    if (FileTag->genre && strlen(FileTag->genre)>0 )
686
679
    {
 
680
        gchar *genre_string_tmp;
 
681
        guchar genre_value;
 
682
 
687
683
        id3_frame = ID3Frame_NewID(ID3FID_CONTENTTYPE);
688
684
        ID3Tag_AttachFrame(id3_tag,id3_frame);
689
685
 
690
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
691
 
        {
692
 
            gchar *genre_string_tmp;
693
 
            guchar genre_value;
694
 
 
695
 
            if (USE_CHARACTER_SET_TRANSLATION)
696
 
            {
697
 
                string = convert_string(FileTag->genre, "utf-8", FILE_CHARACTER_SET);
698
 
                genre_value = Id3tag_String_To_Genre(string);
699
 
                /* If genre not defined don't write genre value between brackets! (priority problem noted with some tools) */
700
 
                if (genre_value == ID3_INVALID_GENRE)
701
 
                    genre_string_tmp = g_strdup_printf("%s",string);
702
 
                else
703
 
                    genre_string_tmp = g_strdup_printf("(%d)",genre_value);
704
 
                ID3Field_SetASCII(id3_field,genre_string_tmp);
705
 
            }else if (USE_ISO_8859_1_CHARACTER_SET_TRANSLATION)
706
 
            {
707
 
                string = convert_string(FileTag->genre, "utf-8", "iso-8859-1");
708
 
                genre_value = Id3tag_String_To_Genre(string);
709
 
                /* If genre not defined don't write genre value between brackets! (priority problem noted with some tools) */
710
 
                if (genre_value == ID3_INVALID_GENRE)
711
 
                    genre_string_tmp = g_strdup_printf("%s",string);
712
 
                else
713
 
                    genre_string_tmp = g_strdup_printf("(%d)",genre_value);
714
 
                ID3Field_SetASCII(id3_field,genre_string_tmp);
715
 
            }else
716
 
            {
717
 
                string = convert_from_utf8(FileTag->genre);
718
 
                genre_value = Id3tag_String_To_Genre(string);
719
 
                if (genre_value == ID3_INVALID_GENRE)
720
 
                    genre_string_tmp = g_strdup_printf("%s",string);
721
 
                else
722
 
                    genre_string_tmp = g_strdup_printf("(%d)",genre_value);
723
 
                ID3Field_SetASCII(id3_field,genre_string_tmp);
724
 
            }
725
 
            g_free(genre_string_tmp);
726
 
            g_free(string);
727
 
        }
728
 
 
729
 
    } else
730
 
    {
731
 
        has_genre = 0;
 
686
        genre_value = Id3tag_String_To_Genre(FileTag->genre);
 
687
        // If genre not defined don't write genre value between brackets! (priority problem noted with some tools)
 
688
        if (genre_value == ID3_INVALID_GENRE)
 
689
            genre_string_tmp = g_strdup_printf("%s",FileTag->genre);
 
690
        else
 
691
            genre_string_tmp = g_strdup_printf("(%d)",genre_value);
 
692
 
 
693
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, genre_string_tmp);
 
694
        g_free(genre_string_tmp);
 
695
        has_genre = TRUE;
732
696
    }
733
697
 
734
698
 
741
705
    {
742
706
        id3_frame = ID3Frame_NewID(ID3FID_COMMENT);
743
707
        ID3Tag_AttachFrame(id3_tag,id3_frame);
744
 
 
745
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
746
 
        {
747
 
            HANDLE_TRANSLATION_SAVE(string, FileTag->comment, id3_field);
748
 
        }
749
 
 
750
 
        /* These 2 following fields allow synchronisation between id3v2 and id3v1 tags with id3lib */
751
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_DESCRIPTION)))
752
 
            ID3Field_SetASCII(id3_field,"ID3v1 Comment");
753
 
 
754
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_LANGUAGE)))
755
 
            ID3Field_SetASCII(id3_field,"XXX");
756
 
 
757
 
    } else
758
 
    {
759
 
        has_comment = 0;
 
708
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, FileTag->comment);
 
709
        // These 2 following fields allow synchronisation between id3v2 and id3v1 tags with id3lib
 
710
        // Disabled as when using unicode, the comment field stay in ISO.
 
711
        //Id3tag_Set_Field(id3_frame, ID3FN_DESCRIPTION, "ID3v1 Comment");
 
712
        //Id3tag_Set_Field(id3_frame, ID3FN_LANGUAGE, "XXX");
 
713
        has_comment = TRUE;
760
714
    }
761
715
 
762
716
 
769
723
    {
770
724
        id3_frame = ID3Frame_NewID(ID3FID_COMPOSER);
771
725
        ID3Tag_AttachFrame(id3_tag,id3_frame);
772
 
 
773
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
774
 
        {
775
 
            HANDLE_TRANSLATION_SAVE(string, FileTag->composer, id3_field);
776
 
        }
777
 
    } else
778
 
    {
779
 
        has_composer = 0;
 
726
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, FileTag->composer);
 
727
        has_composer = TRUE;
780
728
    }
781
729
 
782
730
 
789
737
    {
790
738
        id3_frame = ID3Frame_NewID(ID3FID_ORIGARTIST);
791
739
        ID3Tag_AttachFrame(id3_tag,id3_frame);
792
 
 
793
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
794
 
        {
795
 
            HANDLE_TRANSLATION_SAVE(string, FileTag->orig_artist, id3_field);
796
 
        }
797
 
    } else
798
 
    {
799
 
        has_orig_artist = 0;
 
740
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, FileTag->orig_artist);
 
741
        has_orig_artist = TRUE;
800
742
    }
801
743
 
802
744
 
809
751
    {
810
752
        id3_frame = ID3Frame_NewID(ID3FID_COPYRIGHT);
811
753
        ID3Tag_AttachFrame(id3_tag,id3_frame);
812
 
 
813
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
814
 
        {
815
 
            HANDLE_TRANSLATION_SAVE(string, FileTag->copyright, id3_field);
816
 
        }
817
 
    } else
818
 
    {
819
 
        has_copyright = 0;
 
754
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, FileTag->copyright);
 
755
        has_copyright = TRUE;
820
756
    }
821
757
 
822
758
 
829
765
    {
830
766
        id3_frame = ID3Frame_NewID(ID3FID_WWWUSER);
831
767
        ID3Tag_AttachFrame(id3_tag,id3_frame);
832
 
 
833
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_URL)))
834
 
        {
835
 
            HANDLE_TRANSLATION_SAVE(string, FileTag->url, id3_field);
836
 
        }
837
 
    } else
838
 
    {
839
 
        has_composer = 0;
 
768
        Id3tag_Set_Field(id3_frame, ID3FN_URL, FileTag->url);
 
769
        has_composer = TRUE;
840
770
    }
841
771
 
842
772
 
849
779
    {
850
780
        id3_frame = ID3Frame_NewID(ID3FID_ENCODEDBY);
851
781
        ID3Tag_AttachFrame(id3_tag,id3_frame);
852
 
 
853
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
854
 
        {
855
 
            HANDLE_TRANSLATION_SAVE(string, FileTag->encoded_by, id3_field);
856
 
        }
857
 
    } else
858
 
    {
859
 
        has_encoded_by = 0;
 
782
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, FileTag->encoded_by);
 
783
        has_encoded_by = TRUE;
860
784
    }
861
785
 
862
786
 
868
792
    pic = FileTag->picture;
869
793
    if (!pic)
870
794
        has_picture = 0;
871
 
    while(pic)
 
795
    while (pic)
872
796
    {
873
797
        id3_frame = ID3Frame_NewID(ID3FID_PICTURE);
874
798
        ID3Tag_AttachFrame(id3_tag,id3_frame);
875
799
 
876
 
        switch(Picture_Format(pic))
 
800
        switch (Picture_Format(pic))
877
801
        {
878
802
            case PICTURE_FORMAT_JPEG:
879
803
                if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_MIMETYPE)))
892
816
        
893
817
        if ((id3_field = ID3Frame_GetField(id3_frame, ID3FN_PICTURETYPE)))
894
818
            ID3Field_SetINT(id3_field, pic->type);
895
 
        if (pic->description
896
 
        && (id3_field = ID3Frame_GetField(id3_frame,ID3FN_DESCRIPTION)))
897
 
        {
898
 
            HANDLE_TRANSLATION_SAVE(string, pic->description, id3_field);
899
 
        }
 
819
 
 
820
        if (pic->description)
 
821
            Id3tag_Set_Field(id3_frame, ID3FN_DESCRIPTION, pic->description);
 
822
        
900
823
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_DATA)))
901
824
            ID3Field_SetBINARY(id3_field, pic->data, pic->size);
902
825
        
903
826
        pic = pic->next;
 
827
        has_picture = TRUE;
904
828
    }
905
829
 
906
830
 
911
835
        ID3Tag_RemoveFrame(id3_tag,id3_frame);
912
836
    if (ETFile->ETFileInfo && ((ET_File_Info *)ETFile->ETFileInfo)->duration > 0 )
913
837
    {
 
838
        gchar *string;
 
839
        
914
840
        id3_frame = ID3Frame_NewID(ID3FID_SONGLEN);
915
841
        ID3Tag_AttachFrame(id3_tag,id3_frame);
916
842
 
917
 
        if ((id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)))
918
 
        {
919
 
            gchar *string = g_strdup_printf("%d",((ET_File_Info *)ETFile->ETFileInfo)->duration * 1000);
920
 
            ID3Field_SetASCII(id3_field,string);
921
 
            g_free(string);
922
 
        }
923
 
    } else
924
 
    {
925
 
        has_song_len = 0;
 
843
        string = g_strdup_printf("%d",((ET_File_Info *)ETFile->ETFileInfo)->duration * 1000);
 
844
        Id3tag_Set_Field(id3_frame, ID3FN_TEXT, string);
 
845
        g_free(string);
 
846
        has_song_len = TRUE;
926
847
    }
927
848
 
928
849
 
934
855
    number_of_frames = ID3Tag_NumFrames(id3_tag);
935
856
 
936
857
    /* If all fields (managed in the UI) are empty and option STRIP_TAG_WHEN_EMPTY_FIELDS
937
 
     * is set to 1, we strip the ID3v1.x and ID3v2 tags. Else let see... :)
 
858
     * is set to 1, we strip the ID3v1.x and ID3v2 tags. Else, write ID3v2 and/or ID3v1
938
859
     */
939
860
    if ( STRIP_TAG_WHEN_EMPTY_FIELDS
940
861
    && !has_title      && !has_artist   && !has_album       && !has_year      && !has_track
941
862
    && !has_genre      && !has_composer && !has_orig_artist && !has_copyright && !has_url
942
 
    && !has_encoded_by && !has_picture  && !has_comment )//&& !has_song_len )
 
863
    && !has_encoded_by && !has_picture  && !has_comment     && !has_disc_number)//&& !has_song_len )
943
864
    {
944
865
        error_strip_id3v1 = ID3Tag_Strip(id3_tag,ID3TT_ID3V1);
945
866
        error_strip_id3v2 = ID3Tag_Strip(id3_tag,ID3TT_ID3V2);
963
884
         */
964
885
        error_strip_id3v1 = ID3Tag_Strip(id3_tag,ID3TT_ID3V1);
965
886
 
966
 
        /* ID3v1 tag */
 
887
        /*
 
888
         * ID3v2 tag
 
889
         */
 
890
        if (WRITE_ID3V2_TAG && number_of_frames!=0)
 
891
        {
 
892
            error_update_id3v2 = ID3Tag_UpdateByTagType(id3_tag,ID3TT_ID3V2);
 
893
            if (error_update_id3v2 != ID3E_NoError)
 
894
            {
 
895
                g_print(_("Error while updating ID3v2 tag of '%s' (%s)\n"),basename_utf8,Id3tag_Get_Error_Message(error_update_id3v2));
 
896
                error++;
 
897
            }else
 
898
            {
 
899
                /* See known problem on the top : [ 1016290 ] Unicode16 writing bug.
 
900
                 * When we write the tag in Unicode, we try to check if it was correctly
 
901
                 * written. So to test it : we read again the tag, and then compare 
 
902
                 * with the previous one. We check up to find an error (as only some
 
903
                 * characters are affected).
 
904
                 * If the patch to id3lib was applied to fix the problem (tested 
 
905
                 * by Id3tag_Check_If_Id3lib_Is_Bugged) we didn't make the following
 
906
                 * test => OK */
 
907
                if (flag_id3lib_bugged 
 
908
                && (USE_ID3_ISO_8859_1_THEN_UNICODE_CHARACTER_SET || USE_ID3_UNICODE_CHARACTER_SET) )
 
909
                {
 
910
                    File_Tag  *FileTag_tmp = ET_File_Tag_Item_New();
 
911
                    if (Id3tag_Read_File_Tag(filename,FileTag_tmp) == TRUE
 
912
                    &&  ET_Detect_Changes_Of_File_Tag(FileTag,FileTag_tmp) == TRUE)
 
913
                    {
 
914
                        GtkWidget *msgbox = NULL;
 
915
                        gchar *msg;
 
916
                        gchar *filename_utf8 = filename_to_display(filename);
 
917
 
 
918
                        msg = g_strdup_printf(_("You have tried to save this tag to Unicode "
 
919
                            "but it was detected that your version of id3lib is bugged.\n"
 
920
                            "If you reload this file, some characters in the tag may be not "
 
921
                            "displayed correctly...\nPlease, apply to id3lib the patch "
 
922
                            "src/id3lib/patch_id3lib_3.8.3_UTF16_writing_bug.diff\n"
 
923
                            "available in EasyTAG package sources.\n"
 
924
                            "Note that this message will appear only one time.\n\n"
 
925
                            "File : %s"),filename_utf8);
 
926
                        g_free(filename_utf8);
 
927
                        //g_print(msg);
 
928
                        
 
929
                        msgbox = msg_box_new (_("Error..."),msg,GTK_STOCK_DIALOG_ERROR,BUTTON_OK,0);
 
930
                        g_free(msg);
 
931
                        msg_box_hide_check_button(MSG_BOX(msgbox));
 
932
                        msg_box_run(MSG_BOX(msgbox));
 
933
                        gtk_widget_destroy(msgbox);
 
934
                        flag_id3lib_bugged = FALSE; // To display the message only one time
 
935
                    }
 
936
                    ET_Free_File_Tag_Item(FileTag_tmp);
 
937
                }
 
938
 
 
939
            }
 
940
        }else
 
941
        {
 
942
            error_strip_id3v2 = ID3Tag_Strip(id3_tag,ID3TT_ID3V2);
 
943
            if (error_strip_id3v2 != ID3E_NoError)
 
944
            {
 
945
                g_print(_("Error while removing ID3v2 tag of '%s' (%s)\n"),basename_utf8,Id3tag_Get_Error_Message(error_strip_id3v2));
 
946
                error++;
 
947
            }
 
948
        }
 
949
 
 
950
        /*
 
951
         * ID3v1 tag
 
952
         * Must be set after ID3v2 or ID3Tag_UpdateByTagType cause damage to unicode strings
 
953
         */
 
954
        // id3lib writes incorrectly the ID3v2 tag if unicode used when writing ID3v1 tag
967
955
        if (WRITE_ID3V1_TAG && number_of_frames!=0)
968
956
        {
 
957
            // By default id3lib converts id3tag to ISO-8859-1 (single byte character set)
 
958
            // If USE_NON_STANDARD_ID3_WRITING_CHARACTER_SET is activated, the character set
 
959
            // in ID3_FILE_WRITING_CHARACTER_SET will be used, but must be also a single
 
960
            // byte character set.
 
961
            // Note : converting UTF-16 string (two bytes character set) to ISO-8859-1
 
962
            //        remove only the second byte => a strange string appears...
 
963
            Id3tag_Prepare_ID3v1(id3_tag);
 
964
            
969
965
            error_update_id3v1 = ID3Tag_UpdateByTagType(id3_tag,ID3TT_ID3V1);
970
966
            if (error_update_id3v1 != ID3E_NoError)
971
967
            {
982
978
            }
983
979
        }
984
980
 
985
 
        /* ID3v2 tag */
986
 
        if (WRITE_ID3V2_TAG && number_of_frames!=0)
987
 
        {
988
 
            error_update_id3v2 = ID3Tag_UpdateByTagType(id3_tag,ID3TT_ID3V2);
989
 
            if (error_update_id3v2 != ID3E_NoError)
990
 
            {
991
 
                g_print(_("Error while updating ID3v2 tag of '%s' (%s)\n"),basename_utf8,Id3tag_Get_Error_Message(error_update_id3v2));
992
 
                error++;
993
 
            }
994
 
        }else
995
 
        {
996
 
            error_strip_id3v2 = ID3Tag_Strip(id3_tag,ID3TT_ID3V2);
997
 
            if (error_strip_id3v2 != ID3E_NoError)
998
 
            {
999
 
                g_print(_("Error while removing ID3v2 tag of '%s' (%s)\n"),basename_utf8,Id3tag_Get_Error_Message(error_strip_id3v2));
1000
 
                error++;
1001
 
            }
1002
 
        }
1003
 
 
1004
981
        if (error == 0)
1005
982
            g_print(_("Updated tag of '%s'\n"),basename_utf8);
1006
983
 
1090
1067
 
1091
1068
 
1092
1069
/*
1093
 
 * Returns the corresponding genre value of the input string (for ID3v1.x),
1094
 
 * else returns 0xFF (unknown genre, but not invalid).
1095
 
 */
1096
 
guchar Id3tag_String_To_Genre (gchar *genre)
1097
 
{
1098
 
    guint i;
1099
 
 
1100
 
    for (i=0; i<=GENRE_MAX; i++)
1101
 
        if (strcasecmp(genre,id3_genres[i])==0)
1102
 
            return (guchar)i;
1103
 
    return (guchar)0xFF;
1104
 
}
1105
 
 
1106
 
 
1107
 
/*
1108
 
 * Returns the name of a genre code if found
1109
 
 * Three states for genre code :
1110
 
 *    - defined (0 to GENRE_MAX)
1111
 
 *    - undefined/unknown (GENRE_MAX+1 to ID3_INVALID_GENRE-1)
1112
 
 *    - invalid (>ID3_INVALID_GENRE)
1113
 
 */
1114
 
gchar *Id3tag_Genre_To_String (unsigned char genre_code)
1115
 
{
1116
 
    if (genre_code>=ID3_INVALID_GENRE)    /* empty */
1117
 
        return "";
1118
 
    else if (genre_code>GENRE_MAX)        /* unknown tag */
1119
 
        return "Unknown";
1120
 
    else                                  /* known tag */
1121
 
        return id3_genres[genre_code];
1122
 
}
1123
 
 
1124
 
 
1125
 
 
1126
 
/*
1127
1070
 * As the ID3Tag_Link function of id3lib-3.8.0pre2 returns the ID3v1 tags
1128
1071
 * when a file has both ID3v1 and ID3v2 tags, we first try to explicitely
1129
1072
 * get the ID3v2 tags with ID3Tag_LinkWithFlags and, if we cannot get them,
1134
1077
{
1135
1078
    size_t offset;
1136
1079
 
1137
 
#   if ( (ID3LIB_MAJOR >= 3) && (ID3LIB_MINOR >= 8) && (ID3LIB_PATCH >= 1) ) // Same test used in Id3tag_Read_File_Tag to use ID3Tag_HasTagType
 
1080
#   if (0) // Link the file with the both tags may cause damage to unicode strings
 
1081
//#   if ( (ID3LIB_MAJOR >= 3) && (ID3LIB_MINOR >= 8) && (ID3LIB_PATCH >= 1) ) // Same test used in Id3tag_Read_File_Tag to use ID3Tag_HasTagType
1138
1082
        /* No problem of priority, so we link the file with the both tags
1139
1083
         * to manage => ID3Tag_HasTagType works correctly */
1140
1084
        offset = ID3Tag_LinkWithFlags(id3tag,filename,ID3TT_ID3V1 | ID3TT_ID3V2);
1221
1165
#            endif
1222
1166
#        else
1223
1167
             // (>= to 3.8.0)
1224
 
             //return ID3Field_GetUNICODE(field,buffer,maxChars);
1225
 
             return ID3Field_GetUNICODEItem(field,buffer,maxChars,itemNum);
 
1168
             return ID3Field_GetUNICODE(field,buffer,maxChars);
 
1169
             // ID3Field_GetUNICODEItem always return 0 with id3lib3.8.3, it is bug in size_t D3_FieldImpl::Get()
 
1170
             //return ID3Field_GetUNICODEItem(field,buffer,maxChars,itemNum);
1226
1171
#        endif
1227
1172
#    else
1228
1173
         // Not tested (< 3.x.x)
1240
1185
 *   encoding description byte. Possible encodings:
1241
1186
 *
1242
1187
 *     $00   ISO-8859-1 [ISO-8859-1]. Terminated with $00.
1243
 
 *     $01   UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All
1244
 
 *           strings in the same frame SHALL have the same byteorder.
1245
 
 *           Terminated with $00 00.
 
1188
 *     $01   UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM ($FF FE
 
1189
 *           or $FE FF). All strings in the same frame SHALL have the same
 
1190
 *           byteorder. Terminated with $00 00.
1246
1191
 *     $02   UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM.
1247
1192
 *           Terminated with $00 00.
1248
1193
 *     $03   UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with $00.
1249
1194
 *
 
1195
 * For example :
 
1196
 *         T  P  E  1  .  .  .  .  .  .  .  ?  ?  J  .  o  .  n  .     .  G  .  i  .  n  .  d  .  i  .  c  .  k  . 
 
1197
 * Hex :   54 50 45 31 00 00 00 19 00 00 01 ff fe 4a 00 6f 00 6e 00 20 00 47 00 69 00 6e 00 64 00 6e 00 63 00 6b 00
 
1198
 *                                       ^
 
1199
 *                                       |___ UTF-16
1250
1200
 */
1251
1201
/*
1252
 
 * Read the Frame and convert the string if needed to the current locale
1253
 
 * id3frameid -> values : ID3FID_TITLE, ...
 
1202
 * Read the content (ID3FN_TEXT, ID3FN_URL, ...) of the id3_field of the
 
1203
 * id3_frame, and convert the string if needed to UTF-8.
1254
1204
 */
1255
 
gchar *Id3tag_Get_Frame_Text (const ID3Tag *id3tag, ID3_FrameID id3frameid)
 
1205
gchar *Id3tag_Get_Field (const ID3Frame *id3_frame, ID3_FieldID id3_fieldid)
1256
1206
{
1257
 
    ID3Frame *id3_frame = NULL;
1258
1207
    ID3Field *id3_field = NULL;
1259
1208
    ID3Field *id3_field_encoding = NULL;
1260
 
    luint num_chars;
 
1209
    size_t num_chars = 0;
1261
1210
    gchar *string = NULL, *string1 = NULL;
1262
 
    unicode_t *unicode_string = NULL;
1263
 
 
1264
 
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3tag,id3frameid)) 
1265
 
    &&   (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
 
1211
 
 
1212
    //g_print("Id3tag_Get_Field - ID3Frame '%s'\n",ID3FrameInfo_ShortName(ID3Frame_GetID(id3_frame)));
 
1213
 
 
1214
    if ( (id3_field = ID3Frame_GetField(id3_frame,id3_fieldid)) )
1266
1215
    {
1267
 
 
 
1216
        ID3_TextEnc enc = ID3TE_NONE;
 
1217
 
 
1218
        // Data of the field must be a TEXT (ID3FTY_TEXTSTRING)
 
1219
        if (ID3Field_GetType(id3_field) != ID3FTY_TEXTSTRING)
 
1220
        {
 
1221
            g_warning("Id3tag_Get_Field() must be used only for fields containing text.\n");
 
1222
            return NULL;
 
1223
        }
 
1224
 
 
1225
        #if (0)
 
1226
 
 
1227
        /*
 
1228
         * In this part we prioritize the encoding specified by the user.
 
1229
         */
1268
1230
        // Get encoding of the field
 
1231
        if (USE_NON_STANDARD_ID3_READING_CHARACTER_SET) // Override with an other character set?
 
1232
        {
 
1233
            // Encoding set by user to ???.
 
1234
            if ( strcmp(ID3_FILE_READING_CHARACTER_SET,"ISO-8859-1") == 0 )
 
1235
            {
 
1236
                enc = ID3TE_ISO8859_1;
 
1237
            }else if ( strcmp(ID3_FILE_READING_CHARACTER_SET,"UTF-16BE") == 0 
 
1238
                  ||   strcmp(ID3_FILE_READING_CHARACTER_SET,"UTF-16LE") == 0 )
 
1239
            {
 
1240
                enc = ID3TE_UTF16;
 
1241
            }else if ( strcmp(ID3_FILE_READING_CHARACTER_SET,"UTF-8") == 0 )
 
1242
            {
 
1243
                enc = ID3TE_UTF8;
 
1244
            }else
 
1245
            {
 
1246
                enc = 9999;
 
1247
            }
 
1248
        }else
 
1249
        {
 
1250
            // No encoding set by user. Get encoding from content of file...
 
1251
            id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
 
1252
            if (id3_field_encoding)
 
1253
                enc = ID3Field_GetINT(id3_field_encoding);
 
1254
            // Else, get encoding from the field
 
1255
            //enc = ID3Field_GetEncoding(id3_field);
 
1256
        }
 
1257
        
 
1258
        #else
 
1259
        
 
1260
        /*
 
1261
         * In this part we prioritize the encoding of the field. If the encoding 
 
1262
         * of the field is ISO-8859-1, it can be read with an other single byte encoding.
 
1263
         */
 
1264
        // Get encoding from content of file...
1269
1265
        id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
1270
 
        switch ( ID3Field_GetINT(id3_field_encoding) )
 
1266
        if (id3_field_encoding)
 
1267
            enc = ID3Field_GetINT(id3_field_encoding);
 
1268
        // Else, get encoding from the field
 
1269
        //enc = ID3Field_GetEncoding(id3_field);
 
1270
        
 
1271
        if (enc != ID3TE_UTF16 && enc != ID3TE_UTF8) // Encoding is ISO-8859-1?
 
1272
        {
 
1273
            if (USE_NON_STANDARD_ID3_READING_CHARACTER_SET) // Override with an other character set?
 
1274
            {
 
1275
                // Encoding set by user to ???.
 
1276
                if ( strcmp(ID3_FILE_READING_CHARACTER_SET,"ISO-8859-1") == 0 )
 
1277
                {
 
1278
                    enc = ID3TE_ISO8859_1;
 
1279
                }else if ( strcmp(ID3_FILE_READING_CHARACTER_SET,"UTF-16BE") == 0 
 
1280
                      ||   strcmp(ID3_FILE_READING_CHARACTER_SET,"UTF-16LE") == 0 )
 
1281
                {
 
1282
                    enc = ID3TE_UTF16;
 
1283
                }else if ( strcmp(ID3_FILE_READING_CHARACTER_SET,"UTF-8") == 0 )
 
1284
                {
 
1285
                    enc = ID3TE_UTF8;
 
1286
                }else
 
1287
                {
 
1288
                    enc = 9999;
 
1289
                }
 
1290
            }
 
1291
        }
 
1292
        #endif
 
1293
 
 
1294
        // Some fields, as URL, aren't encodable, so there were written using ISO characters.
 
1295
        if ( !ID3Field_IsEncodable(id3_field) )
 
1296
        {
 
1297
            enc = ID3TE_ISO8859_1;
 
1298
        }
 
1299
        
 
1300
        // Action according the encoding...
 
1301
        switch ( enc )
1271
1302
        {
1272
1303
            case ID3TE_ISO8859_1:
1273
1304
                string = g_malloc0(sizeof(char)*ID3V2_MAX_STRING_LEN+1);
1274
1305
                num_chars = ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,0);
1275
 
                string1 = convert_from_this_charset(string,"ISO-8859-1");
 
1306
                string1 = convert_string(string,"ISO-8859-1","UTF-8",FALSE);
1276
1307
                break;
1277
1308
 
1278
 
            case ID3TE_UTF8: // Shouldn't work with id3lib 3.8.13....
 
1309
            case ID3TE_UTF8: // Shouldn't work with id3lib 3.8.3 (supports only ID3v2.3, not ID3v2.4)
 
1310
                // For UTF-8, this part do the same thing that enc=9999
1279
1311
                string = g_malloc0(sizeof(char)*ID3V2_MAX_STRING_LEN+1);
1280
1312
                num_chars = ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,0);
1281
 
                string1 = convert_from_this_charset(string,"UTF-8");
 
1313
                //string1 = convert_string(string,"UTF-8","UTF-8",FALSE); // Nothing to do
 
1314
                if (g_utf8_validate(string,-1,NULL))
 
1315
                    string1 = g_strdup(string);
1282
1316
                break;
1283
1317
 
1284
1318
            case ID3TE_UTF16:
1285
 
                string = g_malloc0(sizeof(unicode_t)*ID3V2_MAX_STRING_LEN+1);
1286
 
                //num_chars = ID3Field_GetUNICODE_1(id3_field,(unicode_t *)string,ID3V2_MAX_STRING_LEN,0);
1287
 
                //string1 = convert_from_this_charset(string,"UTF-16LE");
1288
 
                num_chars = ID3Field_GetUNICODE_1(id3_field,unicode_string,ID3V2_MAX_STRING_LEN,0);
1289
 
                string1 = convert_from_this_charset((gchar*)unicode_string,"UTF-16LE");
1290
 
                break;
1291
 
 
 
1319
                // Id3lib (3.8.3 at least) always returns Unicode strings in UTF-16BE.
1292
1320
            case ID3TE_UTF16BE:
1293
1321
                string = g_malloc0(sizeof(unicode_t)*ID3V2_MAX_STRING_LEN+1);
1294
 
                //num_chars = ID3Field_GetUNICODE_1(id3_field,(unicode_t *)string,ID3V2_MAX_STRING_LEN,0);
1295
 
                //string1 = convert_from_this_charset(string,"UTF-16BE");
1296
 
                num_chars = ID3Field_GetUNICODE_1(id3_field,unicode_string,ID3V2_MAX_STRING_LEN,0);
1297
 
                string1 = convert_from_this_charset((gchar*)unicode_string,"UTF-16BE");
 
1322
                num_chars = ID3Field_GetUNICODE_1(id3_field,(unicode_t *)string,ID3V2_MAX_STRING_LEN,0);
 
1323
                // "convert_string_1" as we need to pass length for UTF-16
 
1324
                string1 = convert_string_1(string,num_chars,"UTF-16BE","UTF-8",FALSE);
 
1325
                break;
 
1326
 
 
1327
            case 9999:
 
1328
                string = g_malloc0(sizeof(char)*ID3V2_MAX_STRING_LEN+1);
 
1329
                num_chars = ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,0);
 
1330
                string1 = convert_string(string,ID3_FILE_READING_CHARACTER_SET,"UTF-8",FALSE);
1298
1331
                break;
1299
1332
 
1300
1333
            default:
1301
1334
                string = g_malloc0(sizeof(char)*4*ID3V2_MAX_STRING_LEN+1);
1302
1335
                num_chars = ID3Field_GetASCII_1(id3_field,string,ID3V2_MAX_STRING_LEN,0);
1303
 
                string1 = convert_from_this_charset(string,"UTF-8");
 
1336
                string1 = convert_to_utf8(string);
1304
1337
                break;
1305
 
 
1306
1338
        }
1307
1339
    }
1308
 
    //g_print(">>ID:%d >'%s' (%s) (%d)\n",ID3Field_GetINT(id3_field_encoding),string,string1,num_chars);
 
1340
    //g_print(">>ID:%d >'%s' (string1:'%s') (num_chars:%d)\n",ID3Field_GetINT(id3_field_encoding),string,string1,num_chars);
1309
1341
 
 
1342
    // In case the conversion fails, try 'filename_to_display' character fix...
 
1343
    if (num_chars && !string1)
 
1344
    {
 
1345
        gchar *escaped_str = g_strescape(string, NULL);
 
1346
        g_print("Id3tag_Get_Field: Trying to fix string '%s' ...",escaped_str);
 
1347
        g_free(escaped_str);
 
1348
        
 
1349
        string1 = filename_to_display(string);
 
1350
        
 
1351
        if (string1)
 
1352
            g_print("OK\n");
 
1353
        else
 
1354
            g_print("KO\n");
 
1355
    }
1310
1356
    g_free(string);
1311
1357
 
1312
1358
    return string1;
1313
 
 
1314
 
}
1315
 
 
1316
 
 
1317
 
/*
1318
 
 * This function calculates the CRC-32 value of audio data (It doesn't read
1319
 
 * the ID3v2 and ID3v1 tags).
1320
 
 */
1321
 
/***********
1322
 
#include <sys/types.h>
1323
 
#include <sys/stat.h>
1324
 
#include <fcntl.h>
1325
 
#include "crc32.h"
1326
 
gulong Id3tag_Get_Crc32_Value (gchar *filename)
1327
 
{
1328
 
    gint     fd;
1329
 
    gint     id3v2size = 0;
1330
 
    guchar   tmp_id3v1[128];
1331
 
    guchar   tmp_id3v2[4];
1332
 
    gboolean has_id3v1 = FALSE;
1333
 
    gboolean has_id3v2 = FALSE;
1334
 
    gulong   crc32_value;
1335
 
 
1336
 
 
1337
 
    // Open the file on read/write mode
1338
 
    // Note : the file descriptor is an 'int' instead of 'FILE *' as I doesn't
1339
 
    // know the equivalent of ftruncate()
1340
 
    if ( (fd=open(filename, O_RDWR)) == -1 )
1341
 
        return 0;
1342
 
 
1343
 
    // Go to the beginning for the ID3v2 tag
1344
 
    lseek(fd, 0L, SEEK_SET);
1345
 
    if (read(fd, &tmp_id3v2, 4) != 4)
1346
 
        return 0;
1347
 
    // Calculate ID3v2 length
1348
 
    if (tmp_id3v2[0] == 'I' && tmp_id3v2[1] == 'D' && tmp_id3v2[2] == '3' && tmp_id3v2[3] < 0xFF)
1349
 
    {
1350
 
        has_id3v2 = TRUE;
1351
 
        // id3v2 tag skipeer $49 44 33 yy yy xx zz zz zz zz [zz size]
1352
 
        lseek(fd, 2, SEEK_CUR); // Size is 6-9 position
1353
 
        if (read(fd, &tmp_id3v2, 4) != 4)
1354
 
            return 0;
1355
 
        id3v2size = 10 + ( (long)(tmp_id3v2[3])        | ((long)(tmp_id3v2[2]) << 7)
1356
 
                           | ((long)(tmp_id3v2[1]) << 14) | ((long)(tmp_id3v2[0]) << 21) );
1357
 
    }
1358
 
 
1359
 
 
1360
 
    // Now we remove the ID3v1 tag temporarly
1361
 
    // Skip data of ID3v1.x tag
1362
 
    lseek(fd, -128, SEEK_END);
1363
 
    if (read(fd, &tmp_id3v1, 128) != 128)
1364
 
        return 0;
1365
 
    if (tmp_id3v1[0] == 'T' && tmp_id3v1[1] == 'A' && tmp_id3v1[2] == 'G')
1366
 
    {
1367
 
        int len;
1368
 
 
1369
 
           has_id3v1 = TRUE;
1370
 
        len = lseek(fd, -128, SEEK_END);
1371
 
        // Remove the tag
1372
 
        if (ftruncate(fd, len)!=0)
1373
 
        {        
1374
 
            g_print(_("Warning the CRC32 value may be wrong (Can't remove ID3v1 tag of '%s') (%s).\n"),filename,g_strerror(errno));
1375
 
        }
1376
 
    }
1377
 
 
1378
 
    // We return at the beginning of the file, after the id3v2 tag before calculating CRC-32
1379
 
    if (has_id3v2 == TRUE)
1380
 
        lseek(fd, id3v2size, SEEK_SET);
1381
 
    else
1382
 
        lseek(fd, 0L, SEEK_SET);
1383
 
 
1384
 
    // Calculate the CRC-32 value
1385
 
    if (crc32_easytag(fd, &crc32_value))
1386
 
        g_print(_("Error while calculating CRC value on file: '%s' (%s).\n\a"),filename,g_strerror(errno));
1387
 
    //g_print("CRC-32: %.8lx\n",crc32_value);
1388
 
 
1389
 
    // Write again the ID3v1 tag
1390
 
    if (has_id3v1 == TRUE)
1391
 
    {
1392
 
        lseek(fd, 0, SEEK_END);
1393
 
        write(fd, &tmp_id3v1, sizeof(tmp_id3v1));
1394
 
    }
1395
 
 
1396
 
    close(fd);
1397
 
 
1398
 
    return crc32_value;
1399
 
}
1400
 
***********/
 
1359
}
 
1360
 
 
1361
 
 
1362
/*
 
1363
 * Set the content (ID3FN_TEXT, ID3FN_URL, ...) of the id3_field of the
 
1364
 * id3_frame. Check also if the string must be written from UTF-8 (gtk2) in the
 
1365
 * ISO-8859-1 encoding or UTF-16.
 
1366
 *
 
1367
 * Return the encoding used as if UTF-16 was used, we musn't write the ID3v1 tag.
 
1368
 *
 
1369
 * Known problem with id3lib
 
1370
 * - [ 1016290 ] Unicode16 writing bug
 
1371
 *               http://sourceforge.net/tracker/index.php?func=detail&aid=1016290&group_id=979&atid=300979
 
1372
 *               For example with Latin-1 characters (like éöäüß) not saved correctly
 
1373
 *               in Unicode, due to id3lib (for "é" it will write "E9 FF" instead of "EF 00")
 
1374
 */
 
1375
/*
 
1376
 * OLD NOTE : PROBLEM with ID3LIB
 
1377
 * - [ 1074169 ] Writing ID3v1 tag breaks Unicode string in v2 tags
 
1378
 *               http://sourceforge.net/tracker/index.php?func=detail&aid=1074169&group_id=979&atid=100979
 
1379
 *      => don't write id3v1 tag if Unicode is used, up to patch applied
 
1380
 * - [ 1073951 ] Added missing Field Encoding functions to C wrapper
 
1381
 *               http://sourceforge.net/tracker/index.php?func=detail&aid=1073951&group_id=979&atid=300979
 
1382
 */
 
1383
ID3_TextEnc Id3tag_Set_Field (const ID3Frame *id3_frame, ID3_FieldID id3_fieldid, gchar *string)
 
1384
{
 
1385
    ID3Field *id3_field = NULL;
 
1386
    ID3Field *id3_field_encoding = NULL;
 
1387
    gchar *string_converted = NULL;
 
1388
 
 
1389
    if ( (id3_field = ID3Frame_GetField(id3_frame,id3_fieldid)) )
 
1390
    {
 
1391
        ID3_TextEnc enc = ID3TE_NONE;
 
1392
 
 
1393
        // Data of the field must be a TEXT (ID3FTY_TEXTSTRING)
 
1394
        if (ID3Field_GetType(id3_field) != ID3FTY_TEXTSTRING)
 
1395
        {
 
1396
            g_print("Id3tag_Set_Field() must be used only for fields containing text.\n");
 
1397
            return ID3TE_NONE;
 
1398
        }
 
1399
 
 
1400
        #if (0)
 
1401
 
 
1402
        /*
 
1403
         * In this part we prioritize the encoding specified by the user.
 
1404
         */
 
1405
        // Determine encoding to use for the field
 
1406
        if (USE_NON_STANDARD_ID3_WRITING_CHARACTER_SET) // Override with an other character set?
 
1407
        {
 
1408
            // Encoding set by user to ???.
 
1409
            if ( strcmp(ID3_FILE_WRITING_CHARACTER_SET,"ISO-8859-1") == 0 )
 
1410
            {
 
1411
                enc = ID3TE_ISO8859_1;
 
1412
            }else if ( strcmp(ID3_FILE_WRITING_CHARACTER_SET,"UTF-16BE") == 0 
 
1413
                  ||   strcmp(ID3_FILE_WRITING_CHARACTER_SET,"UTF-16LE") == 0 )
 
1414
            {
 
1415
                enc = ID3TE_UTF16;
 
1416
            }else if ( strcmp(ID3_FILE_WRITING_CHARACTER_SET,"UTF-8") == 0 )
 
1417
            {
 
1418
                enc = ID3TE_UTF8;
 
1419
            }else
 
1420
            {
 
1421
                enc = 9999;
 
1422
            }
 
1423
        }else if (USE_ID3_ISO_8859_1_CHARACTER_SET)
 
1424
        {
 
1425
            enc = ID3TE_ISO8859_1;
 
1426
            
 
1427
        }else if (USE_ID3_ISO_8859_1_THEN_UNICODE_CHARACTER_SET)
 
1428
        {
 
1429
            // No encoding set by user. Check if we can write the tag using ISO-8859-1 or UTF-16...
 
1430
            if ( (string_converted = g_convert(string, strlen(string), "ISO-8859-1", 
 
1431
                                               "UTF-8", NULL, NULL ,NULL)) )
 
1432
            {
 
1433
                enc = ID3TE_ISO8859_1;
 
1434
                g_free(string_converted);
 
1435
            }else
 
1436
            {
 
1437
                enc = ID3TE_UTF16;
 
1438
            }
 
1439
        }else if (USE_ID3_UNICODE_CHARACTER_SET)
 
1440
        {
 
1441
            enc = ID3TE_UTF16;
 
1442
        }
 
1443
        
 
1444
        #else
 
1445
        
 
1446
        /*
 
1447
         * In this part we prioritize the rule selected in options. If the encoding 
 
1448
         * of the field is ISO-8859-1, we can write it to an other single byte encoding.
 
1449
         */
 
1450
        if (USE_ID3_ISO_8859_1_CHARACTER_SET)
 
1451
        {
 
1452
            enc = ID3TE_ISO8859_1;
 
1453
            
 
1454
        }else if (USE_ID3_ISO_8859_1_THEN_UNICODE_CHARACTER_SET)
 
1455
        {
 
1456
            // No encoding set by user. Check if we can write the tag using ISO-8859-1 or UTF-16...
 
1457
            if ( (string_converted = g_convert(string, strlen(string), "ISO-8859-1", 
 
1458
                                               "UTF-8", NULL, NULL ,NULL)) )
 
1459
            {
 
1460
                enc = ID3TE_ISO8859_1;
 
1461
                g_free(string_converted);
 
1462
            }else
 
1463
            {
 
1464
                enc = ID3TE_UTF16;
 
1465
            }
 
1466
        }else //if (USE_ID3_UNICODE_CHARACTER_SET)
 
1467
        {
 
1468
            enc = ID3TE_UTF16;
 
1469
        }
 
1470
        
 
1471
        if (enc != ID3TE_UTF16) // Encoding is ISO-8859-1?
 
1472
        {
 
1473
            // Determine encoding to use for the field
 
1474
            if (USE_NON_STANDARD_ID3_WRITING_CHARACTER_SET) // Override with an other character set?
 
1475
            {
 
1476
                // Encoding set by user to ???.
 
1477
                if ( strcmp(ID3_FILE_WRITING_CHARACTER_SET,"ISO-8859-1") == 0 )
 
1478
                {
 
1479
                    enc = ID3TE_ISO8859_1;
 
1480
                }else if ( strcmp(ID3_FILE_WRITING_CHARACTER_SET,"UTF-16BE") == 0 
 
1481
                      ||   strcmp(ID3_FILE_WRITING_CHARACTER_SET,"UTF-16LE") == 0 )
 
1482
                {
 
1483
                    enc = ID3TE_UTF16;
 
1484
                }else if ( strcmp(ID3_FILE_WRITING_CHARACTER_SET,"UTF-8") == 0 )
 
1485
                {
 
1486
                    enc = ID3TE_UTF8;
 
1487
                }else
 
1488
                {
 
1489
                    enc = 9999;
 
1490
                }
 
1491
            }
 
1492
        }
 
1493
        
 
1494
        #endif
 
1495
 
 
1496
        // Some fields, as URL, aren't encodable, so there were written using ISO characters!
 
1497
        if ( !ID3Field_IsEncodable(id3_field) )
 
1498
        {
 
1499
            enc = ID3TE_ISO8859_1;
 
1500
        }
 
1501
        
 
1502
        // Action according the encoding...
 
1503
        switch ( enc )
 
1504
        {
 
1505
            case ID3TE_ISO8859_1:
 
1506
                // Write into ISO-8859-1
 
1507
                //string_converted = convert_string(string,"UTF-8","ISO-8859-1",TRUE);
 
1508
                string_converted = Id3tag_Rules_For_ISO_Fields(string,"UTF-8","ISO-8859-1");
 
1509
                ID3Field_SetEncoding(id3_field,ID3TE_ISO8859_1); // Not necessary for ISO-8859-1, but better to precise if field has an other encoding...
 
1510
                ID3Field_SetASCII(id3_field,string_converted);
 
1511
                g_free(string_converted);
 
1512
                
 
1513
                id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
 
1514
                if (id3_field_encoding)
 
1515
                    ID3Field_SetINT(id3_field_encoding,ID3TE_ISO8859_1);
 
1516
                
 
1517
                return ID3TE_ISO8859_1;
 
1518
                break;
 
1519
 
 
1520
            /*** Commented as it doesn't with id3lib 3.8.3 :
 
1521
             ***  - it writes a strange UTF-8 string (2 bytes per character. Second char is FF) with a BOM
 
1522
             ***  - it set the frame encoded to UTF-8 : "$03" which is OK
 
1523
            case ID3TE_UTF8: // Shouldn't work with id3lib 3.8.3 (supports only ID3v2.3, not ID3v2.4)
 
1524
                ID3Field_SetEncoding(id3_field,ID3TE_UTF8);
 
1525
                ID3Field_SetASCII(id3_field,string);
 
1526
                
 
1527
                id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
 
1528
                if (id3_field_encoding)
 
1529
                    ID3Field_SetINT(id3_field_encoding,ID3TE_UTF8);
 
1530
                
 
1531
                return ID3TE_UTF8;
 
1532
                break;
 
1533
             ***/
 
1534
 
 
1535
            case ID3TE_UTF16:
 
1536
            //case ID3TE_UTF16BE:
 
1537
 
 
1538
                /* See known problem on the top : [ 1016290 ] Unicode16 writing bug */
 
1539
                // Write into UTF-16
 
1540
                string_converted = convert_string_1(string, strlen(string), "UTF-8",
 
1541
                                                    "UTF-16BE", FALSE);
 
1542
 
 
1543
                // id3lib (3.8.3 at least) always takes big-endian input for Unicode
 
1544
                // fields, even if the field is set little-endian.
 
1545
                ID3Field_SetEncoding(id3_field,ID3TE_UTF16);
 
1546
                ID3Field_SetUNICODE(id3_field,(const unicode_t*)string_converted);
 
1547
                g_free(string_converted);
 
1548
 
 
1549
                id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
 
1550
                if (id3_field_encoding)
 
1551
                    ID3Field_SetINT(id3_field_encoding,ID3TE_UTF16);
 
1552
 
 
1553
                return ID3TE_UTF16;
 
1554
                break;
 
1555
 
 
1556
            case 9999:
 
1557
                //string_converted = convert_string(string,"UTF-8",ID3_FILE_WRITING_CHARACTER_SET,TRUE);
 
1558
                string_converted = Id3tag_Rules_For_ISO_Fields(string,"UTF-8",ID3_FILE_WRITING_CHARACTER_SET);
 
1559
                ID3Field_SetEncoding(id3_field,ID3TE_ISO8859_1);
 
1560
                ID3Field_SetASCII(id3_field,string_converted);
 
1561
                g_free(string_converted);
 
1562
                
 
1563
                id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
 
1564
                if (id3_field_encoding)
 
1565
                    ID3Field_SetINT(id3_field_encoding,ID3TE_ISO8859_1);
 
1566
                
 
1567
                return ID3TE_NONE;
 
1568
                break;
 
1569
 
 
1570
            default:
 
1571
                string_converted = convert_from_utf8(string);
 
1572
                ID3Field_SetEncoding(id3_field,ID3TE_ISO8859_1);
 
1573
                ID3Field_SetASCII(id3_field,string_converted);
 
1574
                g_free(string_converted);
 
1575
                
 
1576
                id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
 
1577
                if (id3_field_encoding)
 
1578
                    ID3Field_SetINT(id3_field_encoding,ID3TE_ISO8859_1);
 
1579
                
 
1580
                return ID3TE_NONE;
 
1581
                break;
 
1582
        }
 
1583
    }
 
1584
    
 
1585
    return ID3TE_NONE;
 
1586
}
 
1587
 
 
1588
 
 
1589
/*
 
1590
 * By default id3lib converts id3tag to ISO-8859-1 (single byte character set)
 
1591
 * If USE_NON_STANDARD_ID3_WRITING_CHARACTER_SET is activated, the character set
 
1592
 * in ID3_FILE_WRITING_CHARACTER_SET will be used, but must be also a single
 
1593
 * byte character set.
 
1594
 * Note : converting UTF-16 string (two bytes character set) to ISO-8859-1
 
1595
 *        remove only the second byte => a strange string appears...
 
1596
 */
 
1597
void Id3tag_Prepare_ID3v1 (ID3Tag *id3_tag)
 
1598
{
 
1599
    ID3Frame *frame;
 
1600
    ID3Field *id3_field_encoding;
 
1601
    ID3Field *id3_field_text;
 
1602
    
 
1603
    if ( id3_tag != NULL )
 
1604
    {
 
1605
        ID3TagIterator *id3_tag_iterator;
 
1606
        size_t num_chars = 0;
 
1607
        gchar *string, *string1, *string_converted;
 
1608
        
 
1609
        id3_tag_iterator = ID3Tag_CreateIterator(id3_tag);
 
1610
        while ( NULL != (frame = ID3TagIterator_GetNext(id3_tag_iterator)) )
 
1611
        {
 
1612
            ID3_TextEnc enc = ID3TE_ISO8859_1;
 
1613
            ID3_FrameID frameid;
 
1614
            
 
1615
            frameid = ID3Frame_GetID(frame);
 
1616
            
 
1617
            if (frameid != ID3FID_TITLE
 
1618
            &&  frameid != ID3FID_LEADARTIST
 
1619
            &&  frameid != ID3FID_ALBUM
 
1620
            &&  frameid != ID3FID_YEAR
 
1621
            &&  frameid != ID3FID_TRACKNUM
 
1622
            &&  frameid != ID3FID_CONTENTTYPE
 
1623
            &&  frameid != ID3FID_COMMENT)
 
1624
                continue;
 
1625
            
 
1626
            id3_field_encoding = ID3Frame_GetField(frame, ID3FN_TEXTENC);
 
1627
            if (id3_field_encoding != NULL)
 
1628
                enc = ID3Field_GetINT(id3_field_encoding);
 
1629
            id3_field_text = ID3Frame_GetField(frame, ID3FN_TEXT);
 
1630
            
 
1631
            /* The frames in ID3TE_ISO8859_1 are already converted to the selected
 
1632
             * single-byte character set if used. So we treat only Unicode frames */
 
1633
            if ( (id3_field_text != NULL)
 
1634
            &&   (enc != ID3TE_ISO8859_1) )
 
1635
            {
 
1636
                // Read UTF-16 frame
 
1637
                string = g_malloc0(sizeof(unicode_t)*ID3V2_MAX_STRING_LEN+1);
 
1638
                num_chars = ID3Field_GetUNICODE_1(id3_field_text,(unicode_t *)string,ID3V2_MAX_STRING_LEN,0);
 
1639
                // "convert_string_1" as we need to pass length for UTF-16
 
1640
                string1 = convert_string_1(string,num_chars,"UTF-16BE","UTF-8",FALSE);
 
1641
                
 
1642
                // Write frame to the selected single byte character set.
 
1643
                if (USE_NON_STANDARD_ID3_WRITING_CHARACTER_SET)
 
1644
                {
 
1645
                    //string_converted = convert_string(string1,"UTF-8",ID3_FILE_WRITING_CHARACTER_SET,TRUE);
 
1646
                    string_converted = Id3tag_Rules_For_ISO_Fields(string1,"UTF-8",ID3_FILE_WRITING_CHARACTER_SET);
 
1647
                }else
 
1648
                {
 
1649
                    //string_converted = convert_string(string1,"UTF-8","ISO-8859-1",TRUE);
 
1650
                    string_converted = Id3tag_Rules_For_ISO_Fields(string1,"UTF-8","ISO-8859-1");
 
1651
                }
 
1652
                
 
1653
                if (string_converted)
 
1654
                {
 
1655
                    ID3Field_SetEncoding(id3_field_text,ID3TE_ISO8859_1); // Not necessary for ISO-8859-1
 
1656
                    ID3Field_SetASCII(id3_field_text,string_converted);
 
1657
                    ID3Field_SetINT(id3_field_encoding,ID3TE_ISO8859_1);
 
1658
                    g_free(string_converted);
 
1659
                }
 
1660
                g_free(string);
 
1661
                g_free(string1);
 
1662
            }
 
1663
        }
 
1664
        ID3TagIterator_Delete(id3_tag_iterator);
 
1665
    }
 
1666
}
 
1667
 
 
1668
/*
 
1669
 * This function must be used for tag fields containing ISO data.
 
1670
 * We use specials functionalities of iconv : //TRANSLIT and //IGNORE (the last 
 
1671
 * one doesn't work on my system) to force conversion to the target encoding.
 
1672
 */
 
1673
gchar *Id3tag_Rules_For_ISO_Fields (const gchar *string, const gchar *from_codeset, const gchar *to_codeset)
 
1674
{
 
1675
    gchar *string_converted = NULL;
 
1676
    
 
1677
    if (!string || !from_codeset || !to_codeset)
 
1678
        return NULL;
 
1679
    
 
1680
    if (FILE_WRITING_CHARACTER_SET_OTHER)
 
1681
    {
 
1682
        string_converted = convert_string(string,from_codeset,to_codeset,TRUE);
 
1683
        
 
1684
    }else if (FILE_WRITING_CHARACTER_SET_APPROXIMATE)
 
1685
    {
 
1686
        // iconv_open (3):
 
1687
        // When the string "//TRANSLIT" is appended to tocode, transliteration
 
1688
        // is activated. This means that when a character cannot be represented
 
1689
        // in the target character set, it can be approximated through one or
 
1690
        // several similarly looking characters.
 
1691
        gchar *to_enc = g_strconcat(to_codeset, "//TRANSLIT", NULL);
 
1692
        string_converted = convert_string(string,from_codeset,to_enc,TRUE);
 
1693
        g_free(to_enc);
 
1694
        
 
1695
    }else if (FILE_WRITING_CHARACTER_SET_DISCARD)
 
1696
    {
 
1697
        // iconv_open (3):
 
1698
        // When the string "//IGNORE" is appended to tocode, characters that
 
1699
        // cannot be represented in the target character set will be silently
 
1700
        // discarded.
 
1701
        gchar *to_enc = g_strconcat(to_codeset, "//IGNORE", NULL);
 
1702
        string_converted = convert_string(string,from_codeset,to_enc,TRUE);
 
1703
        g_free(to_enc);
 
1704
    }
 
1705
    
 
1706
    return string_converted;
 
1707
}
 
1708
 
 
1709
/*
 
1710
 * Some files which contains only zeroes create an infinite loop in id3lib...
 
1711
 * To generate a file with zeroes : dd if=/dev/zero bs=1M count=6 of=test-corrupted-mp3-zero-contend.mp3
 
1712
 */
 
1713
gboolean Id3tag_Check_If_File_Is_Corrupted (gchar *filename)
 
1714
{
 
1715
    FILE *file;
 
1716
    unsigned char tmp[256];
 
1717
    unsigned char tmp0[256];
 
1718
    gint bytes_read;
 
1719
    gboolean result = TRUE;
 
1720
    gint cmp;
 
1721
    
 
1722
    if (!filename)
 
1723
        return FALSE;
 
1724
    
 
1725
    if ( (file=fopen(filename,"rb"))==NULL )
 
1726
    {
 
1727
        gchar *filename_utf8 = filename_to_display(filename);
 
1728
        g_print(_("ERROR while opening file: '%s' (%s).\n\a"),filename_utf8,g_strerror(errno));
 
1729
        g_free(filename_utf8);
 
1730
        return FALSE;
 
1731
    }
 
1732
    
 
1733
    memset(&tmp0,0,256);
 
1734
    while (!feof(file))
 
1735
    {
 
1736
        bytes_read = fread(tmp, 1, 256, file);
 
1737
        if ( (cmp=memcmp(tmp,tmp0,bytes_read)) != 0)
 
1738
        {
 
1739
            result = FALSE;
 
1740
            break;
 
1741
        }
 
1742
    }
 
1743
    fclose(file);
 
1744
    
 
1745
    if (result)
 
1746
    {
 
1747
        GtkWidget *msgbox = NULL;
 
1748
        gchar *msg;
 
1749
        gchar *basename;
 
1750
        gchar *basename_utf8;
 
1751
        
 
1752
        basename = g_path_get_basename(filename);
 
1753
        basename_utf8 = filename_to_display(basename);
 
1754
 
 
1755
        msg = g_strdup_printf(_("As the following corrupted file: '%s'\nwill cause "
 
1756
            "an error in id3lib, it will not be processed by the program."),basename_utf8);
 
1757
        msgbox = msg_box_new (_("Corrupted file..."),msg,GTK_STOCK_DIALOG_ERROR,BUTTON_CLOSE,0);
 
1758
        msg_box_hide_check_button(MSG_BOX(msgbox));
 
1759
        msg_box_run(MSG_BOX(msgbox));
 
1760
        gtk_widget_destroy(msgbox);
 
1761
        g_free(msg);
 
1762
        g_free(basename);
 
1763
        g_free(basename_utf8);
 
1764
    }
 
1765
    
 
1766
    return result;
 
1767
}
 
1768
 
 
1769
 
 
1770
/*
 
1771
 * Function to detect if id3lib isn't bugged when writting to Unicode
 
1772
 * Returns TRUE if bugged, else FALSE
 
1773
 */
 
1774
gboolean Id3tag_Check_If_Id3lib_Is_Bugged (void)
 
1775
{
 
1776
    FILE *file;
 
1777
    unsigned char tmp[16] = {0xFF, 0xFB, 0x00, 0x00, 0x00, 0x00, 
 
1778
                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 
1779
                             0x00, 0x00, 0x00, 0x00};
 
1780
    ID3Tag *id3_tag = NULL;
 
1781
    gchar *filename;
 
1782
    gchar *result = NULL;
 
1783
    ID3Frame *id3_frame;
 
1784
    gboolean use_iso, use_iso_then_unicode, use_unicode;
 
1785
 
 
1786
 
 
1787
    if (!HOME_VARIABLE)
 
1788
        return FALSE;
 
1789
        
 
1790
    // Create a temporary file
 
1791
    filename = g_strconcat(HOME_VARIABLE,
 
1792
                           HOME_VARIABLE[strlen(HOME_VARIABLE)-1]!=G_DIR_SEPARATOR?G_DIR_SEPARATOR_S:"",
 
1793
                           ".easytag"G_DIR_SEPARATOR_S"test_easytag.mp3",
 
1794
                           NULL);
 
1795
    if ( (file=fopen(filename,"w+"))==NULL )
 
1796
    {
 
1797
        gchar *filename_utf8 = filename_to_display(filename);
 
1798
        g_print(_("ERROR while opening file: '%s' (%s).\n\a"),filename_utf8,g_strerror(errno));
 
1799
        g_free(filename_utf8);
 
1800
        return FALSE;
 
1801
    }
 
1802
    // Set data in the file
 
1803
    fwrite(&tmp,16,1,file);
 
1804
    fclose(file);
 
1805
 
 
1806
    // Save state of switches as we must force to Unicode before writting
 
1807
    use_iso              = USE_ID3_ISO_8859_1_CHARACTER_SET;
 
1808
    use_iso_then_unicode = USE_ID3_ISO_8859_1_THEN_UNICODE_CHARACTER_SET;
 
1809
    use_unicode          = USE_ID3_UNICODE_CHARACTER_SET;
 
1810
    USE_ID3_ISO_8859_1_CHARACTER_SET              = FALSE;
 
1811
    USE_ID3_ISO_8859_1_THEN_UNICODE_CHARACTER_SET = FALSE;
 
1812
    USE_ID3_UNICODE_CHARACTER_SET                 = TRUE;
 
1813
 
 
1814
    id3_tag = ID3Tag_New();
 
1815
    ID3Tag_Link_1(id3_tag,filename);
 
1816
 
 
1817
    // Create a new 'title' field for testing
 
1818
    id3_frame = ID3Frame_NewID(ID3FID_TITLE);
 
1819
    ID3Tag_AttachFrame(id3_tag,id3_frame);
 
1820
    Id3tag_Set_Field(id3_frame, ID3FN_TEXT, "é"); // This latin-1 character is written in Unicode as 'E9 FF' instead of 'E9 00' if bugged
 
1821
 
 
1822
    // Update the tag
 
1823
    ID3Tag_UpdateByTagType(id3_tag,ID3TT_ID3V2);
 
1824
    ID3Tag_Delete(id3_tag);
 
1825
 
 
1826
    USE_ID3_ISO_8859_1_CHARACTER_SET              = use_iso;
 
1827
    USE_ID3_ISO_8859_1_THEN_UNICODE_CHARACTER_SET = use_iso_then_unicode;
 
1828
    USE_ID3_UNICODE_CHARACTER_SET                 = use_unicode;
 
1829
 
 
1830
 
 
1831
    id3_tag = ID3Tag_New();
 
1832
    ID3Tag_Link_1(id3_tag,filename);
 
1833
    // Read the written field
 
1834
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_TITLE)) )
 
1835
    {
 
1836
        result = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
 
1837
    }
 
1838
 
 
1839
    ID3Tag_Delete(id3_tag);
 
1840
    remove(filename);
 
1841
 
 
1842
    // Same string found? if yes => not bugged
 
1843
    if ( result && strcmp(result,"é")!=0 )
 
1844
    {
 
1845
        return TRUE;
 
1846
    }
 
1847
 
 
1848
    return FALSE;
 
1849
}
 
1850
 
 
1851
 
 
1852
#endif /* ENABLE_MP3 */
 
1853
 
 
1854
 
 
1855
 
 
1856
// Placed out #ifdef ENABLE_MP3 as not dependant of id3lib, and used in CDDB
 
1857
/*
 
1858
 * Returns the corresponding genre value of the input string (for ID3v1.x),
 
1859
 * else returns 0xFF (unknown genre, but not invalid).
 
1860
 */
 
1861
guchar Id3tag_String_To_Genre (gchar *genre)
 
1862
{
 
1863
    guint i;
 
1864
 
 
1865
    if (genre != NULL)
 
1866
    {
 
1867
        for (i=0; i<=GENRE_MAX; i++)
 
1868
            if (strcasecmp(genre,id3_genres[i])==0)
 
1869
                return (guchar)i;
 
1870
    }
 
1871
    return (guchar)0xFF;
 
1872
}
 
1873
 
 
1874
 
 
1875
/*
 
1876
 * Returns the name of a genre code if found
 
1877
 * Three states for genre code :
 
1878
 *    - defined (0 to GENRE_MAX)
 
1879
 *    - undefined/unknown (GENRE_MAX+1 to ID3_INVALID_GENRE-1)
 
1880
 *    - invalid (>ID3_INVALID_GENRE)
 
1881
 */
 
1882
gchar *Id3tag_Genre_To_String (unsigned char genre_code)
 
1883
{
 
1884
    if (genre_code>=ID3_INVALID_GENRE)    /* empty */
 
1885
        return "";
 
1886
    else if (genre_code>GENRE_MAX)        /* unknown tag */
 
1887
        return "Unknown";
 
1888
    else                                  /* known tag */
 
1889
        return id3_genres[genre_code];
 
1890
}