1240
1185
* encoding description byte. Possible encodings:
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.
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
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.
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)
1257
ID3Frame *id3_frame = NULL;
1258
1207
ID3Field *id3_field = NULL;
1259
1208
ID3Field *id3_field_encoding = NULL;
1209
size_t num_chars = 0;
1261
1210
gchar *string = NULL, *string1 = NULL;
1262
unicode_t *unicode_string = NULL;
1264
if ( (id3_frame = ID3Tag_FindFrameWithID(id3tag,id3frameid))
1265
&& (id3_field = ID3Frame_GetField(id3_frame,ID3FN_TEXT)) )
1212
//g_print("Id3tag_Get_Field - ID3Frame '%s'\n",ID3FrameInfo_ShortName(ID3Frame_GetID(id3_frame)));
1214
if ( (id3_field = ID3Frame_GetField(id3_frame,id3_fieldid)) )
1216
ID3_TextEnc enc = ID3TE_NONE;
1218
// Data of the field must be a TEXT (ID3FTY_TEXTSTRING)
1219
if (ID3Field_GetType(id3_field) != ID3FTY_TEXTSTRING)
1221
g_warning("Id3tag_Get_Field() must be used only for fields containing text.\n");
1228
* In this part we prioritize the encoding specified by the user.
1268
1230
// Get encoding of the field
1231
if (USE_NON_STANDARD_ID3_READING_CHARACTER_SET) // Override with an other character set?
1233
// Encoding set by user to ???.
1234
if ( strcmp(ID3_FILE_READING_CHARACTER_SET,"ISO-8859-1") == 0 )
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 )
1241
}else if ( strcmp(ID3_FILE_READING_CHARACTER_SET,"UTF-8") == 0 )
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);
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.
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);
1271
if (enc != ID3TE_UTF16 && enc != ID3TE_UTF8) // Encoding is ISO-8859-1?
1273
if (USE_NON_STANDARD_ID3_READING_CHARACTER_SET) // Override with an other character set?
1275
// Encoding set by user to ???.
1276
if ( strcmp(ID3_FILE_READING_CHARACTER_SET,"ISO-8859-1") == 0 )
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 )
1283
}else if ( strcmp(ID3_FILE_READING_CHARACTER_SET,"UTF-8") == 0 )
1294
// Some fields, as URL, aren't encodable, so there were written using ISO characters.
1295
if ( !ID3Field_IsEncodable(id3_field) )
1297
enc = ID3TE_ISO8859_1;
1300
// Action according the encoding...
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);
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);
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");
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);
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);
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);
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);
1342
// In case the conversion fails, try 'filename_to_display' character fix...
1343
if (num_chars && !string1)
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);
1349
string1 = filename_to_display(string);
1310
1356
g_free(string);
1312
1358
return string1;
1318
* This function calculates the CRC-32 value of audio data (It doesn't read
1319
* the ID3v2 and ID3v1 tags).
1322
#include <sys/types.h>
1323
#include <sys/stat.h>
1326
gulong Id3tag_Get_Crc32_Value (gchar *filename)
1330
guchar tmp_id3v1[128];
1331
guchar tmp_id3v2[4];
1332
gboolean has_id3v1 = FALSE;
1333
gboolean has_id3v2 = FALSE;
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 )
1343
// Go to the beginning for the ID3v2 tag
1344
lseek(fd, 0L, SEEK_SET);
1345
if (read(fd, &tmp_id3v2, 4) != 4)
1347
// Calculate ID3v2 length
1348
if (tmp_id3v2[0] == 'I' && tmp_id3v2[1] == 'D' && tmp_id3v2[2] == '3' && tmp_id3v2[3] < 0xFF)
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)
1355
id3v2size = 10 + ( (long)(tmp_id3v2[3]) | ((long)(tmp_id3v2[2]) << 7)
1356
| ((long)(tmp_id3v2[1]) << 14) | ((long)(tmp_id3v2[0]) << 21) );
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)
1365
if (tmp_id3v1[0] == 'T' && tmp_id3v1[1] == 'A' && tmp_id3v1[2] == 'G')
1370
len = lseek(fd, -128, SEEK_END);
1372
if (ftruncate(fd, len)!=0)
1374
g_print(_("Warning the CRC32 value may be wrong (Can't remove ID3v1 tag of '%s') (%s).\n"),filename,g_strerror(errno));
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);
1382
lseek(fd, 0L, SEEK_SET);
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);
1389
// Write again the ID3v1 tag
1390
if (has_id3v1 == TRUE)
1392
lseek(fd, 0, SEEK_END);
1393
write(fd, &tmp_id3v1, sizeof(tmp_id3v1));
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.
1367
* Return the encoding used as if UTF-16 was used, we musn't write the ID3v1 tag.
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")
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
1383
ID3_TextEnc Id3tag_Set_Field (const ID3Frame *id3_frame, ID3_FieldID id3_fieldid, gchar *string)
1385
ID3Field *id3_field = NULL;
1386
ID3Field *id3_field_encoding = NULL;
1387
gchar *string_converted = NULL;
1389
if ( (id3_field = ID3Frame_GetField(id3_frame,id3_fieldid)) )
1391
ID3_TextEnc enc = ID3TE_NONE;
1393
// Data of the field must be a TEXT (ID3FTY_TEXTSTRING)
1394
if (ID3Field_GetType(id3_field) != ID3FTY_TEXTSTRING)
1396
g_print("Id3tag_Set_Field() must be used only for fields containing text.\n");
1403
* In this part we prioritize the encoding specified by the user.
1405
// Determine encoding to use for the field
1406
if (USE_NON_STANDARD_ID3_WRITING_CHARACTER_SET) // Override with an other character set?
1408
// Encoding set by user to ???.
1409
if ( strcmp(ID3_FILE_WRITING_CHARACTER_SET,"ISO-8859-1") == 0 )
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 )
1416
}else if ( strcmp(ID3_FILE_WRITING_CHARACTER_SET,"UTF-8") == 0 )
1423
}else if (USE_ID3_ISO_8859_1_CHARACTER_SET)
1425
enc = ID3TE_ISO8859_1;
1427
}else if (USE_ID3_ISO_8859_1_THEN_UNICODE_CHARACTER_SET)
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)) )
1433
enc = ID3TE_ISO8859_1;
1434
g_free(string_converted);
1439
}else if (USE_ID3_UNICODE_CHARACTER_SET)
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.
1450
if (USE_ID3_ISO_8859_1_CHARACTER_SET)
1452
enc = ID3TE_ISO8859_1;
1454
}else if (USE_ID3_ISO_8859_1_THEN_UNICODE_CHARACTER_SET)
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)) )
1460
enc = ID3TE_ISO8859_1;
1461
g_free(string_converted);
1466
}else //if (USE_ID3_UNICODE_CHARACTER_SET)
1471
if (enc != ID3TE_UTF16) // Encoding is ISO-8859-1?
1473
// Determine encoding to use for the field
1474
if (USE_NON_STANDARD_ID3_WRITING_CHARACTER_SET) // Override with an other character set?
1476
// Encoding set by user to ???.
1477
if ( strcmp(ID3_FILE_WRITING_CHARACTER_SET,"ISO-8859-1") == 0 )
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 )
1484
}else if ( strcmp(ID3_FILE_WRITING_CHARACTER_SET,"UTF-8") == 0 )
1496
// Some fields, as URL, aren't encodable, so there were written using ISO characters!
1497
if ( !ID3Field_IsEncodable(id3_field) )
1499
enc = ID3TE_ISO8859_1;
1502
// Action according the encoding...
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);
1513
id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
1514
if (id3_field_encoding)
1515
ID3Field_SetINT(id3_field_encoding,ID3TE_ISO8859_1);
1517
return ID3TE_ISO8859_1;
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);
1527
id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
1528
if (id3_field_encoding)
1529
ID3Field_SetINT(id3_field_encoding,ID3TE_UTF8);
1536
//case ID3TE_UTF16BE:
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",
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);
1549
id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
1550
if (id3_field_encoding)
1551
ID3Field_SetINT(id3_field_encoding,ID3TE_UTF16);
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);
1563
id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
1564
if (id3_field_encoding)
1565
ID3Field_SetINT(id3_field_encoding,ID3TE_ISO8859_1);
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);
1576
id3_field_encoding = ID3Frame_GetField(id3_frame,ID3FN_TEXTENC);
1577
if (id3_field_encoding)
1578
ID3Field_SetINT(id3_field_encoding,ID3TE_ISO8859_1);
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...
1597
void Id3tag_Prepare_ID3v1 (ID3Tag *id3_tag)
1600
ID3Field *id3_field_encoding;
1601
ID3Field *id3_field_text;
1603
if ( id3_tag != NULL )
1605
ID3TagIterator *id3_tag_iterator;
1606
size_t num_chars = 0;
1607
gchar *string, *string1, *string_converted;
1609
id3_tag_iterator = ID3Tag_CreateIterator(id3_tag);
1610
while ( NULL != (frame = ID3TagIterator_GetNext(id3_tag_iterator)) )
1612
ID3_TextEnc enc = ID3TE_ISO8859_1;
1613
ID3_FrameID frameid;
1615
frameid = ID3Frame_GetID(frame);
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)
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);
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) )
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);
1642
// Write frame to the selected single byte character set.
1643
if (USE_NON_STANDARD_ID3_WRITING_CHARACTER_SET)
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);
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");
1653
if (string_converted)
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);
1664
ID3TagIterator_Delete(id3_tag_iterator);
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.
1673
gchar *Id3tag_Rules_For_ISO_Fields (const gchar *string, const gchar *from_codeset, const gchar *to_codeset)
1675
gchar *string_converted = NULL;
1677
if (!string || !from_codeset || !to_codeset)
1680
if (FILE_WRITING_CHARACTER_SET_OTHER)
1682
string_converted = convert_string(string,from_codeset,to_codeset,TRUE);
1684
}else if (FILE_WRITING_CHARACTER_SET_APPROXIMATE)
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);
1695
}else if (FILE_WRITING_CHARACTER_SET_DISCARD)
1698
// When the string "//IGNORE" is appended to tocode, characters that
1699
// cannot be represented in the target character set will be silently
1701
gchar *to_enc = g_strconcat(to_codeset, "//IGNORE", NULL);
1702
string_converted = convert_string(string,from_codeset,to_enc,TRUE);
1706
return string_converted;
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
1713
gboolean Id3tag_Check_If_File_Is_Corrupted (gchar *filename)
1716
unsigned char tmp[256];
1717
unsigned char tmp0[256];
1719
gboolean result = TRUE;
1725
if ( (file=fopen(filename,"rb"))==NULL )
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);
1733
memset(&tmp0,0,256);
1736
bytes_read = fread(tmp, 1, 256, file);
1737
if ( (cmp=memcmp(tmp,tmp0,bytes_read)) != 0)
1747
GtkWidget *msgbox = NULL;
1750
gchar *basename_utf8;
1752
basename = g_path_get_basename(filename);
1753
basename_utf8 = filename_to_display(basename);
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);
1763
g_free(basename_utf8);
1771
* Function to detect if id3lib isn't bugged when writting to Unicode
1772
* Returns TRUE if bugged, else FALSE
1774
gboolean Id3tag_Check_If_Id3lib_Is_Bugged (void)
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;
1782
gchar *result = NULL;
1783
ID3Frame *id3_frame;
1784
gboolean use_iso, use_iso_then_unicode, use_unicode;
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",
1795
if ( (file=fopen(filename,"w+"))==NULL )
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);
1802
// Set data in the file
1803
fwrite(&tmp,16,1,file);
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;
1814
id3_tag = ID3Tag_New();
1815
ID3Tag_Link_1(id3_tag,filename);
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
1823
ID3Tag_UpdateByTagType(id3_tag,ID3TT_ID3V2);
1824
ID3Tag_Delete(id3_tag);
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;
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)) )
1836
result = Id3tag_Get_Field(id3_frame,ID3FN_TEXT);
1839
ID3Tag_Delete(id3_tag);
1842
// Same string found? if yes => not bugged
1843
if ( result && strcmp(result,"é")!=0 )
1852
#endif /* ENABLE_MP3 */
1856
// Placed out #ifdef ENABLE_MP3 as not dependant of id3lib, and used in CDDB
1858
* Returns the corresponding genre value of the input string (for ID3v1.x),
1859
* else returns 0xFF (unknown genre, but not invalid).
1861
guchar Id3tag_String_To_Genre (gchar *genre)
1867
for (i=0; i<=GENRE_MAX; i++)
1868
if (strcasecmp(genre,id3_genres[i])==0)
1871
return (guchar)0xFF;
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)
1882
gchar *Id3tag_Genre_To_String (unsigned char genre_code)
1884
if (genre_code>=ID3_INVALID_GENRE) /* empty */
1886
else if (genre_code>GENRE_MAX) /* unknown tag */
1888
else /* known tag */
1889
return id3_genres[genre_code];