~ubuntu-branches/ubuntu/wily/easytag/wily

« back to all changes in this revision

Viewing changes to src/id3_tag.c

  • Committer: Package Import Robot
  • Author(s): Alessio Treglia
  • Date: 2013-10-11 17:07:47 UTC
  • mto: (8.1.4 sid)
  • mto: This revision was merged to the branch mainline in revision 14.
  • Revision ID: package-import@ubuntu.com-20131011170747-uqvgtx7uyd046j7z
Tags: upstream-2.1.8
Import upstream version 2.1.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
#include "log.h"
39
39
#include "misc.h"
40
40
#include "et_core.h"
41
 
#include "msgbox.h"
42
41
#include "charset.h"
43
42
 
44
43
#ifdef ENABLE_MP3
60
59
/**************
61
60
 * Prototypes *
62
61
 **************/
63
 
gchar *Id3tag_Get_Error_Message (ID3_Err error);
64
 
void   Id3tag_Prepare_ID3v1     (ID3Tag *id3_tag);
65
 
gchar *Id3tag_Rules_For_ISO_Fields (const gchar *string, const gchar *from_codeset, const gchar *to_codeset);
66
 
gchar *Id3tag_Get_Field         (const ID3Frame *id3_frame, ID3_FieldID id3_fieldid);
67
 
ID3_TextEnc Id3tag_Set_Field    (const ID3Frame *id3_frame, ID3_FieldID id3_fieldid, gchar *string);
 
62
static gchar *Id3tag_Get_Error_Message (ID3_Err error);
 
63
static void Id3tag_Prepare_ID3v1 (ID3Tag *id3_tag);
 
64
static gchar *Id3tag_Rules_For_ISO_Fields (const gchar *string,
 
65
                                           const gchar *from_codeset,
 
66
                                           const gchar *to_codeset);
 
67
static gchar *Id3tag_Get_Field (const ID3Frame *id3_frame,
 
68
                                ID3_FieldID id3_fieldid);
 
69
static ID3_TextEnc Id3tag_Set_Field (const ID3Frame *id3_frame,
 
70
                                     ID3_FieldID id3_fieldid, gchar *string);
68
71
 
69
72
ID3_C_EXPORT size_t ID3Tag_Link_1         (ID3Tag *id3tag, const char *filename);
70
73
ID3_C_EXPORT size_t ID3Field_GetASCII_1   (const ID3Field *field, char *buffer,      size_t maxChars, size_t itemNum);
71
74
ID3_C_EXPORT size_t ID3Field_GetUNICODE_1 (const ID3Field *field, unicode_t *buffer, size_t maxChars, size_t itemNum);
72
75
 
73
 
gboolean Id3tag_Check_If_File_Is_Corrupted (gchar *filename);
 
76
static gboolean Id3tag_Check_If_File_Is_Corrupted (const gchar *filename);
74
77
 
75
 
gboolean Id3tag_Check_If_Id3lib_Is_Bugged (void);
 
78
static gboolean Id3tag_Check_If_Id3lib_Is_Bugged (void);
76
79
 
77
80
 
78
81
 
83
86
/*
84
87
 * Write the ID3 tags to the file. Returns TRUE on success, else 0.
85
88
 */
86
 
gboolean Id3tag_Write_File_v23Tag (ET_File *ETFile)
 
89
static gboolean
 
90
Id3tag_Write_File_v23Tag (ET_File *ETFile)
87
91
{
88
92
    File_Tag *FileTag;
89
93
    gchar    *filename;
143
147
    /* Test to know if we can write into the file */
144
148
    if ( (file=fopen(filename,"r+"))==NULL )
145
149
    {
146
 
        Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno));
 
150
        Log_Print(LOG_ERROR,_("Error while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno));
147
151
        return FALSE;
148
152
    }
149
153
    fclose(file);
542
546
                    if (Id3tag_Read_File_Tag(filename,FileTag_tmp) == TRUE
543
547
                    &&  ET_Detect_Changes_Of_File_Tag(FileTag,FileTag_tmp) == TRUE)
544
548
                    {
545
 
                        GtkWidget *msgbox = NULL;
546
 
                        gchar *msg;
 
549
                        GtkWidget *msgdialog;
547
550
 
548
 
                        msg = g_strdup_printf(_("You have tried to save this tag to Unicode "
549
 
                            "but it was detected that your version of id3lib is bugged.\n"
550
 
                            "If you reload this file, some characters in the tag may be not "
551
 
                            "displayed correctly...\nPlease, apply to id3lib the patch "
552
 
                            "src/id3lib/patch_id3lib_3.8.3_UTF16_writing_bug.diff\n"
553
 
                            "available in EasyTAG package sources.\n"
554
 
                            "Note that this message will appear only one time.\n\n"
555
 
                            "File : %s"),filename_utf8);
556
551
                        //Log_Print(LOG_ERROR,msg);
557
552
 
558
 
                        msgbox = msg_box_new(_("Error..."),
559
 
                                             GTK_WINDOW(MainWindow),
560
 
                                             NULL,
561
 
                                             GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
562
 
                                             msg,
563
 
                                             GTK_STOCK_DIALOG_ERROR,
564
 
                                             GTK_STOCK_OK, GTK_RESPONSE_OK,
565
 
                                             NULL);
566
 
                        gtk_dialog_run(GTK_DIALOG(msgbox));
567
 
                        gtk_widget_destroy(msgbox);
568
 
                        g_free(msg);
 
553
                        msgdialog = gtk_message_dialog_new(GTK_WINDOW(MainWindow),
 
554
                                                           GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
 
555
                                                           GTK_MESSAGE_ERROR,
 
556
                                                           GTK_BUTTONS_CLOSE,
 
557
                                                           "%s",
 
558
                                                           _("You have tried to save this tag to Unicode but it was detected that your version of id3lib is buggy"));
 
559
                        gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(msgdialog),
 
560
                                                                 _("If you reload this file, some characters in the tag may not be displayed "
 
561
                                                                 "correctly. Please, apply the patch "
 
562
                                                                 "src/id3lib/patch_id3lib_3.8.3_UTF16_writing_bug.diff to id3lib, which is "
 
563
                                                                 "available in the EasyTAG package sources.\nNote that this message will "
 
564
                                                                 "appear only once.\n\nFile: %s"),
 
565
                                                                  filename_utf8);
 
566
 
 
567
                        gtk_window_set_title(GTK_WINDOW(msgdialog),_("Buggy id3lib"));
 
568
                        gtk_dialog_run(GTK_DIALOG(msgdialog));
 
569
                        gtk_widget_destroy(msgdialog);
569
570
                        flag_id3lib_bugged = FALSE; // To display the message only one time
570
571
                    }
571
572
                    ET_Free_File_Tag_Item(FileTag_tmp);
658
659
        case ID3E_zlibError:
659
660
            return _("Error in compression/uncompression");
660
661
        default:
661
 
            return _("Unknown error message!");
 
662
            return _("Unknown error message");
662
663
    }
663
664
 
664
665
}
823
824
 
824
825
        /*
825
826
         * We prioritize the encoding of the field. If the encoding of the field
826
 
         * is ISO-8859-1, it can be read with an other single byte encoding.
 
827
         * is ISO-8859-1, it can be read with another single byte encoding.
827
828
         */
828
829
        // Get encoding from content of file...
829
830
        id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
834
835
 
835
836
        if (enc != ID3TE_UTF16 && enc != ID3TE_UTF8) // Encoding is ISO-8859-1?
836
837
        {
837
 
            if (USE_NON_STANDARD_ID3_READING_CHARACTER_SET) // Override with an other character set?
 
838
            if (USE_NON_STANDARD_ID3_READING_CHARACTER_SET) // Override with another character set?
838
839
            {
839
840
                // Encoding set by user to ???.
840
841
                if ( strcmp(FILE_READING_ID3V1V2_CHARACTER_SET,"ISO-8859-1") == 0 )
906
907
    if (num_chars && !string1)
907
908
    {
908
909
        gchar *escaped_str = g_strescape(string, NULL);
909
 
        Log_Print(LOG_OK,"Id3tag_Get_Field: Trying to fix string '%s' ...",escaped_str);
 
910
        Log_Print(LOG_OK,"Id3tag_Get_Field: Trying to fix string '%s'…",escaped_str);
910
911
        g_free(escaped_str);
911
912
 
912
913
        string1 = filename_to_display(string);
962
963
 
963
964
        /*
964
965
         * We prioritize the rule selected in options. If the encoding of the
965
 
         * field is ISO-8859-1, we can write it to an other single byte encoding.
 
966
         * field is ISO-8859-1, we can write it to another single byte encoding.
966
967
         */
967
968
        if (FILE_WRITING_ID3V2_USE_UNICODE_CHARACTER_SET)
968
969
        {
1010
1011
                // Write into ISO-8859-1
1011
1012
                //string_converted = convert_string(string,"UTF-8","ISO-8859-1",TRUE);
1012
1013
                string_converted = Id3tag_Rules_For_ISO_Fields(string,"UTF-8","ISO-8859-1");
1013
 
                ID3Field_SetEncoding(id3_field,ID3TE_ISO8859_1); // Not necessary for ISO-8859-1, but better to precise if field has an other encoding...
 
1014
                ID3Field_SetEncoding(id3_field,ID3TE_ISO8859_1); // Not necessary for ISO-8859-1, but better to precise if field has another encoding...
1014
1015
                ID3Field_SetASCII(id3_field,string_converted);
1015
1016
                g_free(string_converted);
1016
1017
 
1191
1192
 * Some files which contains only zeroes create an infinite loop in id3lib...
1192
1193
 * To generate a file with zeroes : dd if=/dev/zero bs=1M count=6 of=test-corrupted-mp3-zero-contend.mp3
1193
1194
 */
1194
 
gboolean Id3tag_Check_If_File_Is_Corrupted (gchar *filename)
 
1195
gboolean Id3tag_Check_If_File_Is_Corrupted (const gchar *filename)
1195
1196
{
1196
1197
    FILE *file;
1197
1198
    unsigned char tmp[256];
1206
1207
    if ( (file=fopen(filename,"rb"))==NULL )
1207
1208
    {
1208
1209
        gchar *filename_utf8 = filename_to_display(filename);
1209
 
        Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno));
 
1210
        Log_Print(LOG_ERROR,_("Error while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno));
1210
1211
        g_free(filename_utf8);
1211
1212
        return FALSE;
1212
1213
    }
1225
1226
 
1226
1227
    if (result)
1227
1228
    {
1228
 
        GtkWidget *msgbox = NULL;
1229
 
        gchar *msg;
 
1229
        GtkWidget *msgdialog;
1230
1230
        gchar *basename;
1231
1231
        gchar *basename_utf8;
1232
1232
 
1233
1233
        basename = g_path_get_basename(filename);
1234
1234
        basename_utf8 = filename_to_display(basename);
1235
1235
 
1236
 
        msg = g_strdup_printf(_("As the following corrupted file: '%s'\nwill cause "
1237
 
            "an error in id3lib, it will not be processed by the program."),basename_utf8);
1238
 
        msgbox = msg_box_new(_("Corrupted file..."),
1239
 
                             GTK_WINDOW(MainWindow),
1240
 
                             NULL,
1241
 
                             GTK_DIALOG_MODAL  | GTK_DIALOG_DESTROY_WITH_PARENT,
1242
 
                             msg,
1243
 
                             GTK_STOCK_DIALOG_ERROR,
1244
 
                             GTK_STOCK_OK, GTK_RESPONSE_OK,
1245
 
                             NULL);
1246
 
        gtk_dialog_run(GTK_DIALOG(msgbox));
1247
 
        gtk_widget_destroy(msgbox);
1248
 
        g_free(msg);
 
1236
        msgdialog = gtk_message_dialog_new(GTK_WINDOW(MainWindow),
 
1237
                                           GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
 
1238
                                           GTK_MESSAGE_ERROR,
 
1239
                                           GTK_BUTTONS_CLOSE,
 
1240
                                           _("As the following corrupted file '%s' will cause an error in id3lib, it will not be processed"),
 
1241
                                           basename_utf8);
 
1242
        gtk_window_set_title(GTK_WINDOW(msgdialog),_("Corrupted file"));
 
1243
 
 
1244
        gtk_dialog_run(GTK_DIALOG(msgdialog));
 
1245
        gtk_widget_destroy(msgdialog);
1249
1246
        g_free(basename);
1250
1247
        g_free(basename_utf8);
1251
1248
    }
1260
1257
 */
1261
1258
gboolean Id3tag_Check_If_Id3lib_Is_Bugged (void)
1262
1259
{
1263
 
    FILE *file;
1264
 
    unsigned char tmp[16] = {0xFF, 0xFB, 0x00, 0x00, 0x00, 0x00,
1265
 
                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1266
 
                             0x00, 0x00, 0x00, 0x00};
 
1260
    GFile *file;
 
1261
    GFileIOStream *iostream = NULL;
 
1262
    GOutputStream *ostream = NULL;
 
1263
    GError *error = NULL;
 
1264
    guchar tmp[16] = {0xFF, 0xFB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
1265
                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1267
1266
    ID3Tag *id3_tag = NULL;
1268
 
    gchar *filename;
1269
 
    gchar *filename_tmp;
 
1267
    gchar *path;
1270
1268
    gchar *result = NULL;
1271
1269
    ID3Frame *id3_frame;
1272
1270
    gboolean use_unicode;
1273
 
 
1274
 
 
1275
 
    if (!HOME_VARIABLE)
1276
 
        return FALSE;
1277
 
 
1278
 
    // Create a temporary file
1279
 
    filename = g_strconcat(HOME_VARIABLE,
1280
 
                           HOME_VARIABLE[strlen(HOME_VARIABLE)-1]!=G_DIR_SEPARATOR ? G_DIR_SEPARATOR_S : "",
1281
 
                           ".easytag" G_DIR_SEPARATOR_S "test_easytag.mp3",
1282
 
                           NULL);
1283
 
 
1284
 
    // Must convert to the filesystem encoding (else may cause problem under XP with accounts like "L�o")
1285
 
    filename_tmp = filename;
1286
 
    filename = filename_from_display(filename);
1287
 
    g_free(filename_tmp);
1288
 
 
1289
 
    if ( (file=fopen(filename,"w+"))==NULL )
1290
 
    {
1291
 
        gchar *filename_utf8 = filename_to_display(filename);
1292
 
        Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno));
1293
 
        g_free(filename_utf8);
1294
 
        return FALSE;
1295
 
    }
1296
 
    // Set data in the file
1297
 
    fwrite(&tmp,16,1,file);
1298
 
    fclose(file);
 
1271
    gssize count;
 
1272
 
 
1273
 
 
1274
    /* Create a temporary file. */
 
1275
    file = g_file_new_tmp ("easytagXXXXXX.mp3", &iostream, &error);
 
1276
    if (!file)
 
1277
    {
 
1278
        if (error)
 
1279
        {
 
1280
            Log_Print (LOG_ERROR,
 
1281
                       _("Error while creating temporary file: '%s'"),
 
1282
                       error->message);
 
1283
            g_clear_error (&error);
 
1284
        }
 
1285
        else
 
1286
        {
 
1287
            Log_Print (LOG_ERROR, "%s",
 
1288
                       _("Error while creating temporary file"));
 
1289
        }
 
1290
 
 
1291
        return FALSE;
 
1292
    }
 
1293
 
 
1294
    /* Set data in the file. */
 
1295
    ostream = g_io_stream_get_output_stream (G_IO_STREAM (iostream));
 
1296
    count = g_output_stream_write (G_OUTPUT_STREAM (ostream), tmp,
 
1297
                                   sizeof (tmp), NULL, &error);
 
1298
    if (count != sizeof (tmp))
 
1299
    {
 
1300
        gchar *filename;
 
1301
        gchar *filename_utf8;
 
1302
 
 
1303
        filename = g_file_get_path (file);
 
1304
        filename_utf8 = filename_to_display (filename);
 
1305
        Log_Print (LOG_ERROR, _("Error while writing to file: '%s' (%s)"),
 
1306
                   filename_utf8, error->message);
 
1307
 
 
1308
        g_free (filename);
 
1309
        g_free (filename_utf8);
 
1310
        g_clear_error (&error);
 
1311
        g_object_unref (file);
 
1312
        g_output_stream_close (G_OUTPUT_STREAM (ostream), NULL, NULL);
 
1313
 
 
1314
        return FALSE;
 
1315
    }
 
1316
 
 
1317
    g_output_stream_close (G_OUTPUT_STREAM (ostream), NULL, NULL);
 
1318
    g_object_unref (ostream);
1299
1319
 
1300
1320
    // Save state of switches as we must force to Unicode before writting
1301
1321
    use_unicode = FILE_WRITING_ID3V2_USE_UNICODE_CHARACTER_SET;
1302
1322
    FILE_WRITING_ID3V2_USE_UNICODE_CHARACTER_SET = TRUE;
1303
1323
 
1304
1324
    id3_tag = ID3Tag_New();
1305
 
    ID3Tag_Link_1(id3_tag,filename);
 
1325
    path = g_file_get_path (file);
 
1326
    ID3Tag_Link_1 (id3_tag, path);
1306
1327
 
1307
1328
    // Create a new 'title' field for testing
1308
1329
    id3_frame = ID3Frame_NewID(ID3FID_TITLE);
1309
1330
    ID3Tag_AttachFrame(id3_tag,id3_frame);
1310
1331
    // Use a Chinese character instead of the latin-1 character as in Id3tag_Set_Field()
1311
1332
    // we try to convert the string to ISO-8859-1 even in the Unicode mode.
1312
 
    //Id3tag_Set_Field(id3_frame, ID3FN_TEXT, "é"); // This latin-1 character is written in Unicode as 'E9 FF' instead of 'E9 00' if bugged
1313
 
    Id3tag_Set_Field(id3_frame, ID3FN_TEXT, "�°"); // This Chinese character is written in Unicode as 'FF FE B0 FF' instead of 'FF FE B0 30' if bugged
 
1333
    //Id3tag_Set_Field(id3_frame, ID3FN_TEXT, "\303\251"); // This latin-1 character is written in Unicode as 'E9 FF' instead of 'E9 00' if bugged
 
1334
    Id3tag_Set_Field(id3_frame, ID3FN_TEXT, "\343\302\260"); // This Chinese character is written in Unicode as 'FF FE B0 FF' instead of 'FF FE B0 30' if bugged
1314
1335
 
1315
1336
    // Update the tag
1316
1337
    ID3Tag_UpdateByTagType(id3_tag,ID3TT_ID3V2);
1320
1341
 
1321
1342
 
1322
1343
    id3_tag = ID3Tag_New();
1323
 
    ID3Tag_Link_1(id3_tag,filename);
 
1344
    ID3Tag_Link_1 (id3_tag, path);
1324
1345
    // Read the written field
1325
1346
    if ( (id3_frame = ID3Tag_FindFrameWithID(id3_tag,ID3FID_TITLE)) )
1326
1347
    {
1328
1349
    }
1329
1350
 
1330
1351
    ID3Tag_Delete(id3_tag);
1331
 
    remove(filename);
 
1352
    g_free (path);
 
1353
    g_file_delete (file, NULL, NULL);
 
1354
 
 
1355
    g_object_unref (file);
1332
1356
 
1333
1357
    // Same string found? if yes => not bugged
1334
 
    //if ( result && strcmp(result,"é")!=0 )
1335
 
    if ( result && strcmp(result,"�°")!=0 )
 
1358
    //if ( result && strcmp(result,"\303\251")!=0 )
 
1359
    if ( result && strcmp(result,"\343\302\260")!=0 )
1336
1360
    {
1337
1361
        return TRUE;
1338
1362
    }