ReactOS 0.4.16-dev-319-g6cf4263
id3.c File Reference
#include "mpg123lib_intern.h"
#include "id3.h"
#include "debug.h"
Include dependency graph for id3.c:

Go to the source code of this file.

Macros

#define KNOWN_FRAMES   5
 
#define free_comment(mh)   free_id3_text(&((mh)->id3v2.comment_list), &((mh)->id3v2.comments))
 
#define free_text(mh)   free_id3_text(&((mh)->id3v2.text), &((mh)->id3v2.texts))
 
#define free_extra(mh)   free_id3_text(&((mh)->id3v2.extra), &((mh)->id3v2.extras))
 
#define free_picture(mh)   free_id3_picture(&((mh)->id3v2.picture), &((mh)->id3v2.pictures))
 
#define add_comment(mh, l, d)   add_id3_text(&((mh)->id3v2.comment_list), &((mh)->id3v2.comments), NULL, l, d)
 
#define add_text(mh, id)   add_id3_text(&((mh)->id3v2.text), &((mh)->id3v2.texts), id, NULL, NULL)
 
#define add_uslt(mh, l, d)   add_id3_text(&((mh)->id3v2.text), &((mh)->id3v2.texts), id, l, d)
 
#define add_extra(mh, d)   add_id3_text(&((mh)->id3v2.extra), &((mh)->id3v2.extras), NULL, NULL, d)
 
#define add_picture(mh, t, d)   add_id3_picture(&((mh)->id3v2.picture), &((mh)->id3v2.pictures), t, d)
 
#define UNSYNC_FLAG   128
 
#define EXTHEAD_FLAG   64 /* ID3v2.3+ */
 
#define COMPRESS_FLAG   64 /* ID3v2.2 */
 
#define EXP_FLAG   32
 
#define FOOTER_FLAG   16
 
#define EXT_UPDATE_FLAG   64 /* ID3v2.4 only: extended header update flag */
 
#define UNKNOWN_FLAGS   15 /* 00001111*/
 
#define synchsafe_to_long(buf, res)
 
#define bytes_to_long(buf, res)
 
#define threebytes_to_long(buf, res)
 
#define BAD_FFLAGS   (unsigned long) 36784
 
#define PRES_TAG_FFLAG   16384
 
#define PRES_FILE_FFLAG   8192
 
#define READ_ONLY_FFLAG   4096
 
#define GROUP_FFLAG   64
 
#define COMPR_FFLAG   8
 
#define ENCR_FFLAG   4
 
#define UNSYNC_FFLAG   2
 
#define DATLEN_FFLAG   1
 
#define FULLPOINT(f, s)   ( (((f)&0x3ff)<<10) + ((s)&0x3ff) + 0x10000 )
 
#define UTF8LEN(x)   ( (x)<0x80 ? 1 : ((x)<0x800 ? 2 : ((x)<0x10000 ? 3 : 4)))
 

Typedefs

typedef void(* text_converter) (mpg123_string *sb, const unsigned char *source, size_t len, const int noquiet)
 

Enumerations

enum  frame_types {
  unknown = -2 , text = -1 , comment , extra ,
  rva2 , uslt , picture
}
 

Functions

static void convert_latin1 (mpg123_string *sb, const unsigned char *source, size_t len, const int noquiet)
 
static void convert_utf16bom (mpg123_string *sb, const unsigned char *source, size_t len, const int noquiet)
 
static void convert_utf8 (mpg123_string *sb, const unsigned char *source, size_t len, const int noquiet)
 
static void null_id3_links (mpg123_handle *fr)
 
void init_id3 (mpg123_handle *fr)
 
static void init_mpg123_text (mpg123_text *txt)
 
static void init_mpg123_picture (mpg123_picture *pic)
 
static void free_mpg123_text (mpg123_text *txt)
 
static void free_mpg123_picture (mpg123_picture *pic)
 
static void free_id3_text (mpg123_text **list, size_t *size)
 
static void free_id3_picture (mpg123_picture **list, size_t *size)
 
static mpg123_textadd_id3_text (mpg123_text **list, size_t *size, char id[4], char lang[3], mpg123_string *description)
 
static mpg123_pictureadd_id3_picture (mpg123_picture **list, size_t *size, char type, mpg123_string *description)
 
void exit_id3 (mpg123_handle *fr)
 
void reset_id3 (mpg123_handle *fr)
 
void id3_link (mpg123_handle *fr)
 
static void store_id3_text (mpg123_string *sb, unsigned char *source, size_t source_size, const int noquiet, const int notranslate)
 
void id3_to_utf8 (mpg123_string *sb, unsigned char encoding, const unsigned char *source, size_t source_size, int noquiet)
 
static unsigned charnext_text (unsigned char *prev, unsigned char encoding, size_t limit)
 
static const charenc_name (unsigned char enc)
 
static void process_text (mpg123_handle *fr, unsigned char *realdata, size_t realsize, char *id)
 
static void process_picture (mpg123_handle *fr, unsigned char *realdata, size_t realsize)
 
static void process_comment (mpg123_handle *fr, enum frame_types tt, unsigned char *realdata, size_t realsize, int rva_level, char *id)
 
static void process_extra (mpg123_handle *fr, unsigned char *realdata, size_t realsize, int rva_level, char *id)
 
static int promote_framename (mpg123_handle *fr, char *id)
 
int store_id3v2 (mpg123_handle *fr, unsigned long first4bytes, unsigned char buf[6], unsigned long length)
 
int parse_new_id3 (mpg123_handle *fr, unsigned long first4bytes)
 
static int check_bom (const unsigned char **source, size_t *len)
 

Variables

static const char frame_type [KNOWN_FRAMES][5] = { "COMM", "TXXX", "RVA2", "USLT", "APIC" }
 
static const text_converter text_converters [4]
 
static const unsigned int encoding_widths [4] = { 1, 2, 2, 1 }
 

Macro Definition Documentation

◆ add_comment

#define add_comment (   mh,
  l,
  d 
)    add_id3_text(&((mh)->id3v2.comment_list), &((mh)->id3v2.comments), NULL, l, d)

Definition at line 209 of file id3.c.

◆ add_extra

#define add_extra (   mh,
  d 
)    add_id3_text(&((mh)->id3v2.extra), &((mh)->id3v2.extras), NULL, NULL, d)

Definition at line 212 of file id3.c.

◆ add_picture

#define add_picture (   mh,
  t,
  d 
)    add_id3_picture(&((mh)->id3v2.picture), &((mh)->id3v2.pictures), t, d)

Definition at line 213 of file id3.c.

◆ add_text

#define add_text (   mh,
  id 
)    add_id3_text(&((mh)->id3v2.text), &((mh)->id3v2.texts), id, NULL, NULL)

Definition at line 210 of file id3.c.

◆ add_uslt

#define add_uslt (   mh,
  l,
  d 
)    add_id3_text(&((mh)->id3v2.text), &((mh)->id3v2.texts), id, l, d)

Definition at line 211 of file id3.c.

◆ BAD_FFLAGS

#define BAD_FFLAGS   (unsigned long) 36784

◆ bytes_to_long

#define bytes_to_long (   buf,
  res 
)
Value:
( \
major == 3 ? \
(res = (((unsigned long) (buf)[0]) << 24) \
| (((unsigned long) (buf)[1]) << 16) \
| (((unsigned long) (buf)[2]) << 8) \
| ((unsigned long) (buf)[3]) \
)
GLuint res
Definition: glext.h:9613
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define synchsafe_to_long(buf, res)
#define long
Definition: qsort.c:33
#define major(rdev)
Definition: propsheet.cpp:928

◆ COMPR_FFLAG

#define COMPR_FFLAG   8

◆ COMPRESS_FLAG

#define COMPRESS_FLAG   64 /* ID3v2.2 */

◆ DATLEN_FFLAG

#define DATLEN_FFLAG   1

◆ ENCR_FFLAG

#define ENCR_FFLAG   4

◆ EXP_FLAG

#define EXP_FLAG   32

◆ EXT_UPDATE_FLAG

#define EXT_UPDATE_FLAG   64 /* ID3v2.4 only: extended header update flag */

◆ EXTHEAD_FLAG

#define EXTHEAD_FLAG   64 /* ID3v2.3+ */

◆ FOOTER_FLAG

#define FOOTER_FLAG   16

◆ free_comment

#define free_comment (   mh)    free_id3_text(&((mh)->id3v2.comment_list), &((mh)->id3v2.comments))

Definition at line 184 of file id3.c.

◆ free_extra

#define free_extra (   mh)    free_id3_text(&((mh)->id3v2.extra), &((mh)->id3v2.extras))

Definition at line 186 of file id3.c.

◆ free_picture

#define free_picture (   mh)    free_id3_picture(&((mh)->id3v2.picture), &((mh)->id3v2.pictures))

Definition at line 187 of file id3.c.

◆ free_text

#define free_text (   mh)    free_id3_text(&((mh)->id3v2.text), &((mh)->id3v2.texts))

Definition at line 185 of file id3.c.

◆ FULLPOINT

#define FULLPOINT (   f,
  s 
)    ( (((f)&0x3ff)<<10) + ((s)&0x3ff) + 0x10000 )

Definition at line 1330 of file id3.c.

◆ GROUP_FFLAG

#define GROUP_FFLAG   64

◆ KNOWN_FRAMES

#define KNOWN_FRAMES   5

Definition at line 93 of file id3.c.

◆ PRES_FILE_FFLAG

#define PRES_FILE_FFLAG   8192

◆ PRES_TAG_FFLAG

#define PRES_TAG_FFLAG   16384

◆ READ_ONLY_FFLAG

#define READ_ONLY_FFLAG   4096

◆ synchsafe_to_long

#define synchsafe_to_long (   buf,
  res 
)
Value:
( \
(((buf)[0]|(buf)[1]|(buf)[2]|(buf)[3]) & 0x80) ? 0 : \
(res = (((unsigned long) (buf)[0]) << 21) \
| (((unsigned long) (buf)[1]) << 14) \
| (((unsigned long) (buf)[2]) << 7) \
| ((unsigned long) (buf)[3]) \
,1) \
)

◆ threebytes_to_long

#define threebytes_to_long (   buf,
  res 
)
Value:
( \
res = (((unsigned long) (buf)[0]) << 16) \
| (((unsigned long) (buf)[1]) << 8) \
| ((unsigned long) (buf)[2]) \
)

◆ UNKNOWN_FLAGS

#define UNKNOWN_FLAGS   15 /* 00001111*/

◆ UNSYNC_FFLAG

#define UNSYNC_FFLAG   2

◆ UNSYNC_FLAG

#define UNSYNC_FLAG   128

◆ UTF8LEN

#define UTF8LEN (   x)    ( (x)<0x80 ? 1 : ((x)<0x800 ? 2 : ((x)<0x10000 ? 3 : 4)))

Definition at line 1332 of file id3.c.

Typedef Documentation

◆ text_converter

typedef void(* text_converter) (mpg123_string *sb, const unsigned char *source, size_t len, const int noquiet)

Definition at line 99 of file id3.c.

Enumeration Type Documentation

◆ frame_types

Enumerator
unknown 
text 
comment 
extra 
rva2 
uslt 
picture 

Definition at line 95 of file id3.c.

95{ unknown = -2, text = -1, comment, extra, rva2, uslt, picture };
@ text
Definition: id3.c:95
@ unknown
Definition: id3.c:95
@ extra
Definition: id3.c:95
@ uslt
Definition: id3.c:95
@ comment
Definition: id3.c:95
@ rva2
Definition: id3.c:95
@ picture
Definition: id3.c:95

Function Documentation

◆ add_id3_picture()

static mpg123_picture * add_id3_picture ( mpg123_picture **  list,
size_t size,
char  type,
mpg123_string description 
)
static

Definition at line 255 of file id3.c.

256{
257 if(!description)
258 return NULL;
259
260 // Return entry to overwrite, if appropriate.
261 for(size_t i=0; i<*size; ++i)
262 {
264 if( type == entry->type
265 && ( type == 1 || type == 2 ||
266 mpg123_same_string(&entry->description, description)
267 )
268 )
269 return entry;
270 }
271 // Append a new one.
273 if(x == NULL) return NULL; /* bad */
274
275 *list = x;
276 *size += 1;
277 init_mpg123_picture(&((*list)[*size-1]));
278
279 return &((*list)[*size-1]); /* Return pointer to the added picture. */
280}
Definition: list.h:37
#define NULL
Definition: types.h:112
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
MPG123_EXPORT int mpg123_same_string(mpg123_string *a, mpg123_string *b)
Definition: stringbuf.c:241
static void init_mpg123_picture(mpg123_picture *pic)
Definition: id3.c:159
#define safe_realloc
Definition: intsym.h:10
uint32_t entry
Definition: isohybrid.c:63
const char * description
Definition: directx.c:2497

◆ add_id3_text()

static mpg123_text * add_id3_text ( mpg123_text **  list,
size_t size,
char  id[4],
char  lang[3],
mpg123_string description 
)
static

Definition at line 214 of file id3.c.

216{
217 mdebug( "add_id3_text id=%s lang=%s, desc=%s"
218 , id ? (char[5]) { id[0], id[1], id[2], id[3], 0 } : "(nil)"
219 , lang ? (char[4]) { lang[0], lang[1], lang[2], 0 } : "(nil)"
220 , description ? (description->fill ? description->p : "(empty)") : "(nil)" );
221 if(lang && !description)
222 return NULL; // no lone language intended
223 if(id || description)
224 {
225 // Look through list of existing texts and return an existing entry
226 // if it should be overwritten.
227 for(size_t i=0; i<*size; ++i)
228 {
230 if(description)
231 { // Overwrite entry with same description and same ID and language.
232 if( (!id || !memcmp(id, entry->id, 4))
233 && (!lang || !memcmp(entry->lang, lang, 3))
234 && mpg123_same_string(&(entry->description), description)
235 )
236 return entry;
237 } else if(id && !memcmp(id, entry->id, 4))
238 return entry; // Just ovewrite because of same ID.
239 mdebug("add_id3_text: entry %zu was no match", i);
240 }
241 }
242 mdebug("add_id3_text: append to list of %zu", *size);
243 // Nothing found, add new one.
244 mpg123_text *x = safe_realloc(*list, sizeof(mpg123_text)*(*size+1));
245 if(x == NULL) return NULL; /* bad */
246
247 *list = x;
248 *size += 1;
249 init_mpg123_text(&((*list)[*size-1]));
250
251 return &((*list)[*size-1]); /* Return pointer to the added text. */
252}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
static void init_mpg123_text(mpg123_text *txt)
Definition: id3.c:146
#define mdebug(s,...)
Definition: debug.h:58
static const WCHAR lang[]
Definition: wbemdisp.c:287

◆ check_bom()

static int check_bom ( const unsigned char **  source,
size_t len 
)
static

Definition at line 1304 of file id3.c.

1305{
1306 int this_bom = 0;
1307 int further_bom = 0;
1308
1309 if(*len < 2) return 0;
1310
1311 if((*source)[0] == 0xff && (*source)[1] == 0xfe)
1312 this_bom = -1;
1313
1314 if((*source)[0] == 0xfe && (*source)[1] == 0xff)
1315 this_bom = 1;
1316
1317 /* Skip the detected BOM. */
1318 if(this_bom != 0)
1319 {
1320 *source += 2;
1321 *len -= 2;
1322 /* Check for following BOMs. The last one wins! */
1323 further_bom = check_bom(source, len);
1324 if(further_bom == 0) return this_bom; /* End of the recursion. */
1325 else return further_bom;
1326 }
1327 else return 0;
1328}
GLenum GLsizei len
Definition: glext.h:6722
static int check_bom(const unsigned char **source, size_t *len)
Definition: id3.c:1304

Referenced by check_bom(), and convert_utf16bom().

◆ convert_latin1()

static void convert_latin1 ( mpg123_string sb,
const unsigned char source,
size_t  len,
const int  noquiet 
)
static

Definition at line 1265 of file id3.c.

1266{
1267 size_t length = l;
1268 size_t i;
1269 unsigned char *p;
1270 /* determine real length, a latin1 character can at most take 2 in UTF8 */
1271 for(i=0; i<l; ++i)
1272 if(s[i] >= 0x80) ++length;
1273
1274 debug1("UTF-8 length: %lu", (unsigned long)length);
1275 /* one extra zero byte for paranoia */
1277 return;
1278
1279 p = (unsigned char*) sb->p; /* Signedness doesn't matter but it shows I thought about the non-issue */
1280 for(i=0; i<l; ++i)
1281 if(s[i] < 0x80){ *p = s[i]; ++p; }
1282 else /* two-byte encoding */
1283 {
1284 *p = 0xc0 | (s[i]>>6);
1285 *(p+1) = 0x80 | (s[i] & 0x3f);
1286 p+=2;
1287 }
1288
1289 sb->p[length] = 0;
1290 sb->fill = length+1;
1291}
r l[0]
Definition: byte_order.h:168
superblock * sb
Definition: btrfs.c:4261
GLdouble s
Definition: gl.h:2039
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
MPG123_EXPORT int mpg123_grow_string(mpg123_string *sb, size_t news)
Definition: stringbuf.c:51
#define debug1(s, a)
Definition: debug.h:61

◆ convert_utf16bom()

static void convert_utf16bom ( mpg123_string sb,
const unsigned char source,
size_t  len,
const int  noquiet 
)
static

Definition at line 1333 of file id3.c.

1334{
1335 size_t i;
1336 size_t n; /* number bytes that make up full pairs */
1337 unsigned char *p;
1338 size_t length = 0; /* the resulting UTF-8 length */
1339 /* Determine real length... extreme case can be more than utf-16 length. */
1340 size_t high = 0;
1341 size_t low = 1;
1342 int bom_endian;
1343
1344 debug1("convert_utf16 with length %lu", (unsigned long)l);
1345
1346 bom_endian = check_bom(&s, &l);
1347 debug1("UTF16 endianness check: %i", bom_endian);
1348
1349 if(bom_endian == -1) /* little-endian */
1350 {
1351 high = 1; /* The second byte is the high byte. */
1352 low = 0; /* The first byte is the low byte. */
1353 }
1354
1355 n = (l/2)*2; /* number bytes that make up full pairs */
1356
1357 /* first: get length, check for errors -- stop at first one */
1358 for(i=0; i < n; i+=2)
1359 {
1360 unsigned long point = ((unsigned long) s[i+high]<<8) + s[i+low];
1361 if((point & 0xfc00) == 0xd800) /* lead surrogate */
1362 {
1363 unsigned short second = (i+3 < l) ? (s[i+2+high]<<8) + s[i+2+low] : 0;
1364 if((second & 0xfc00) == 0xdc00) /* good... */
1365 {
1366 point = FULLPOINT(point,second);
1367 length += UTF8LEN(point); /* possibly 4 bytes */
1368 i+=2; /* We overstepped one word. */
1369 }
1370 else /* if no valid pair, break here */
1371 {
1372 if(noquiet) error2("Invalid UTF16 surrogate pair at %li (0x%04lx).", (unsigned long)i, point);
1373 n = i; /* Forget the half pair, END! */
1374 break;
1375 }
1376 }
1377 else length += UTF8LEN(point); /* 1,2 or 3 bytes */
1378 }
1379
1381 return;
1382
1383 /* Now really convert, skip checks as these have been done just before. */
1384 p = (unsigned char*) sb->p; /* Signedness doesn't matter but it shows I thought about the non-issue */
1385 for(i=0; i < n; i+=2)
1386 {
1387 unsigned long codepoint = ((unsigned long) s[i+high]<<8) + s[i+low];
1388 if((codepoint & 0xfc00) == 0xd800) /* lead surrogate */
1389 {
1390 unsigned short second = (s[i+2+high]<<8) + s[i+2+low];
1391 codepoint = FULLPOINT(codepoint,second);
1392 i+=2; /* We overstepped one word. */
1393 }
1394 if(codepoint < 0x80) *p++ = (unsigned char) codepoint;
1395 else if(codepoint < 0x800)
1396 {
1397 *p++ = (unsigned char) (0xc0 | (codepoint>>6));
1398 *p++ = (unsigned char) (0x80 | (codepoint & 0x3f));
1399 }
1400 else if(codepoint < 0x10000)
1401 {
1402 *p++ = (unsigned char) (0xe0 | (codepoint>>12));
1403 *p++ = 0x80 | ((codepoint>>6) & 0x3f);
1404 *p++ = 0x80 | (codepoint & 0x3f);
1405 }
1406 else if (codepoint < 0x200000)
1407 {
1408 *p++ = (unsigned char) (0xf0 | codepoint>>18);
1409 *p++ = (unsigned char) (0x80 | ((codepoint>>12) & 0x3f));
1410 *p++ = (unsigned char) (0x80 | ((codepoint>>6) & 0x3f));
1411 *p++ = (unsigned char) (0x80 | (codepoint & 0x3f));
1412 } /* ignore bigger ones (that are not possible here anyway) */
1413 }
1414 sb->p[sb->size-1] = 0; /* paranoia... */
1415 sb->fill = sb->size;
1416}
unsigned char
Definition: typeof.h:29
POINTL point
Definition: edittest.c:50
GLdouble n
Definition: glext.h:7729
#define FULLPOINT(f, s)
Definition: id3.c:1330
#define UTF8LEN(x)
Definition: id3.c:1332
#define error2(s, a, b)
Definition: debug.h:126

◆ convert_utf8()

static void convert_utf8 ( mpg123_string sb,
const unsigned char source,
size_t  len,
const int  noquiet 
)
static

Definition at line 1420 of file id3.c.

1421{
1422 if(mpg123_grow_string(sb, len+1))
1423 {
1424 memcpy(sb->p, source, len);
1425 sb->p[len] = 0;
1426 sb->fill = len+1;
1427 }
1428}
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878

◆ enc_name()

static const char * enc_name ( unsigned char  enc)
static

Definition at line 433 of file id3.c.

434{
435 switch(enc)
436 {
437 case 0: return "Latin 1";
438 case 1: return "UTF-16 BOM";
439 case 2: return "UTF-16 BE";
440 case 3: return "UTF-8";
441 default: return "unknown!";
442 }
443}

Referenced by process_comment(), process_extra(), and process_text().

◆ exit_id3()

void exit_id3 ( mpg123_handle fr)

Definition at line 284 of file id3.c.

285{
286 free_picture(fr);
287 free_comment(fr);
288 free_extra(fr);
289 free_text(fr);
290}
#define free_extra(mh)
Definition: id3.c:186
#define free_text(mh)
Definition: id3.c:185
#define free_comment(mh)
Definition: id3.c:184
#define free_picture(mh)
Definition: id3.c:187

◆ free_id3_picture()

static void free_id3_picture ( mpg123_picture **  list,
size_t size 
)
static

Definition at line 197 of file id3.c.

198{
199 size_t i;
200 for(i=0; i<*size; ++i) free_mpg123_picture(&((*list)[i]));
201
202 free(*list);
203 *list = NULL;
204 *size = 0;
205}
#define free
Definition: debug_ros.c:5
static void free_mpg123_picture(mpg123_picture *pic)
Definition: id3.c:175

◆ free_id3_text()

static void free_id3_text ( mpg123_text **  list,
size_t size 
)
static

Definition at line 188 of file id3.c.

189{
190 size_t i;
191 for(i=0; i<*size; ++i) free_mpg123_text(&((*list)[i]));
192
193 free(*list);
194 *list = NULL;
195 *size = 0;
196}
static void free_mpg123_text(mpg123_text *txt)
Definition: id3.c:169

◆ free_mpg123_picture()

static void free_mpg123_picture ( mpg123_picture pic)
static

Definition at line 175 of file id3.c.

176{
179 if (pic->data != NULL)
180 free(pic->data);
181}
mpg123_string description
Definition: mpg123.h:1416
unsigned char * data
Definition: mpg123.h:1419
mpg123_string mime_type
Definition: mpg123.h:1417
MPG123_EXPORT void mpg123_free_string(mpg123_string *sb)
Definition: stringbuf.c:43

Referenced by free_id3_picture(), and process_picture().

◆ free_mpg123_text()

static void free_mpg123_text ( mpg123_text txt)
static

Definition at line 169 of file id3.c.

170{
173}
mpg123_string text
Definition: mpg123.h:1380
mpg123_string description
Definition: mpg123.h:1379

Referenced by free_id3_text(), process_comment(), and process_extra().

◆ id3_link()

void id3_link ( mpg123_handle fr)

Definition at line 299 of file id3.c.

300{
301 size_t i;
302 mpg123_id3v2 *v2 = &fr->id3v2;
303 debug("linking ID3v2");
304 null_id3_links(fr);
305 for(i=0; i<v2->texts; ++i)
306 {
307 mpg123_text *entry = &v2->text[i];
308 if (!strncmp("TIT2", entry->id, 4)) v2->title = &entry->text;
309 else if(!strncmp("TALB", entry->id, 4)) v2->album = &entry->text;
310 else if(!strncmp("TPE1", entry->id, 4)) v2->artist = &entry->text;
311 else if(!strncmp("TYER", entry->id, 4)) v2->year = &entry->text;
312 else if(!strncmp("TCON", entry->id, 4)) v2->genre = &entry->text;
313 }
314 for(i=0; i<v2->comments; ++i)
315 {
316 mpg123_text *entry = &v2->comment_list[i];
317 if(entry->description.fill == 0 || entry->description.p[0] == 0)
318 v2->comment = &entry->text;
319 }
320 /* When no generic comment found, use the last non-generic one. */
321 if(v2->comment == NULL && v2->comments > 0)
322 v2->comment = &v2->comment_list[v2->comments-1].text;
323}
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
GLfloat GLfloat GLfloat v2
Definition: glext.h:6063
static void null_id3_links(mpg123_handle *fr)
Definition: id3.c:119
#define debug(msg)
Definition: key_call.c:71
mpg123_id3v2 id3v2
Definition: frame.h:298

◆ id3_to_utf8()

void id3_to_utf8 ( mpg123_string sb,
unsigned char  encoding,
const unsigned char source,
size_t  source_size,
int  noquiet 
)

Definition at line 374 of file id3.c.

375{
376 unsigned int bwidth;
377 if(sb)
378 sb->fill = 0;
379 debug1("encoding: %u", encoding);
380 /* A note: ID3v2.3 uses UCS-2 non-variable 16bit encoding, v2.4 uses UTF16.
381 UTF-16 uses a reserved/private range in UCS-2 to add the magic, so we just always treat it as UTF. */
382 bwidth = encoding_widths[encoding];
383 /* Hack! I've seen a stray zero byte before BOM. Is that supposed to happen? */
384 if(encoding != mpg123_id3_utf16be) /* UTF16be _can_ beging with a null byte! */
385 while(source_size > bwidth && source[0] == 0)
386 {
387 --source_size;
388 ++source;
389 debug("skipped leading zero");
390 }
391 if(source_size % bwidth)
392 {
393 /* When we need two bytes for a character, it's strange to have an uneven bytestream length. */
394 if(noquiet) warning2("Weird tag size %d for encoding %u - I will probably trim too early or something but I think the MP3 is broken.", (int)source_size, encoding);
395 source_size -= source_size % bwidth;
396 }
397 text_converters[encoding](sb, source, source_size, noquiet);
398}
@ mpg123_id3_utf16be
Definition: mpg123.h:1346
static const text_converter text_converters[4]
Definition: id3.c:105
static const unsigned int encoding_widths[4]
Definition: id3.c:115
#define warning2(s, a, b)
Definition: debug.h:85
static char * encoding
Definition: xmllint.c:155

◆ init_id3()

void init_id3 ( mpg123_handle fr)

Definition at line 129 of file id3.c.

130{
131 fr->id3v2.version = 0; /* nothing there */
132 null_id3_links(fr);
133 fr->id3v2.comments = 0;
134 fr->id3v2.comment_list = NULL;
135 fr->id3v2.texts = 0;
136 fr->id3v2.text = NULL;
137 fr->id3v2.extras = 0;
138 fr->id3v2.extra = NULL;
139 fr->id3v2.pictures = 0;
140 fr->id3v2.picture = NULL;
141}
size_t texts
Definition: mpg123.h:1441
mpg123_text * text
Definition: mpg123.h:1440
size_t comments
Definition: mpg123.h:1439
unsigned char version
Definition: mpg123.h:1429
mpg123_text * comment_list
Definition: mpg123.h:1438
size_t pictures
Definition: mpg123.h:1446
mpg123_picture * picture
Definition: mpg123.h:1444
mpg123_text * extra
Definition: mpg123.h:1442
size_t extras
Definition: mpg123.h:1443

◆ init_mpg123_picture()

static void init_mpg123_picture ( mpg123_picture pic)
static

Definition at line 159 of file id3.c.

160{
163 pic->type = 0;
164 pic->size = 0;
165 pic->data = NULL;
166}
size_t size
Definition: mpg123.h:1418
MPG123_EXPORT void mpg123_init_string(mpg123_string *sb)
Definition: stringbuf.c:35

Referenced by add_id3_picture().

◆ init_mpg123_text()

static void init_mpg123_text ( mpg123_text txt)
static

Definition at line 146 of file id3.c.

147{
150 txt->id[0] = 0;
151 txt->id[1] = 0;
152 txt->id[2] = 0;
153 txt->id[3] = 0;
154 txt->lang[0] = 0;
155 txt->lang[1] = 0;
156 txt->lang[2] = 0;
157}
char lang[3]
Definition: mpg123.h:1377
char id[4]
Definition: mpg123.h:1378

Referenced by add_id3_text(), process_comment(), and process_extra().

◆ next_text()

static unsigned char * next_text ( unsigned char prev,
unsigned char  encoding,
size_t  limit 
)
static

Definition at line 401 of file id3.c.

402{
403 unsigned char *text = prev;
405
406 /* So I go lengths to find zero or double zero...
407 Remember bug 2834636: Only check for aligned NULLs! */
408 while(text-prev < (ssize_t)limit)
409 {
410 if(text[0] == 0)
411 {
412 if(width <= limit-(text-prev))
413 {
414 size_t i = 1;
415 for(; i<width; ++i) if(text[i] != 0) break;
416
417 if(i == width) /* found a null wide enough! */
418 {
419 text += width;
420 break;
421 }
422 }
423 else return NULL; /* No full character left? This text is broken */
424 }
425
426 text += width;
427 }
428 if((size_t)(text-prev) >= limit) text = NULL;
429
430 return text;
431}
GLint GLint GLsizei width
Definition: gl.h:1546
GLint limit
Definition: glext.h:10326
int ssize_t
Definition: rosdhcp.h:48

Referenced by process_comment(), process_extra(), and process_picture().

◆ null_id3_links()

static void null_id3_links ( mpg123_handle fr)
static

Definition at line 119 of file id3.c.

120{
121 fr->id3v2.title = NULL;
122 fr->id3v2.artist = NULL;
123 fr->id3v2.album = NULL;
124 fr->id3v2.year = NULL;
125 fr->id3v2.genre = NULL;
126 fr->id3v2.comment = NULL;
127}
mpg123_string * genre
Definition: mpg123.h:1434
mpg123_string * title
Definition: mpg123.h:1430
mpg123_string * comment
Definition: mpg123.h:1435
mpg123_string * artist
Definition: mpg123.h:1431
mpg123_string * year
Definition: mpg123.h:1433
mpg123_string * album
Definition: mpg123.h:1432

Referenced by id3_link(), and init_id3().

◆ parse_new_id3()

int parse_new_id3 ( mpg123_handle fr,
unsigned long  first4bytes 
)

Definition at line 845 of file id3.c.

846{
847 #define UNSYNC_FLAG 128
848 #define EXTHEAD_FLAG 64 /* ID3v2.3+ */
849 #define COMPRESS_FLAG 64 /* ID3v2.2 */
850 #define EXP_FLAG 32
851 #define FOOTER_FLAG 16
852 #define EXT_UPDATE_FLAG 64 /* ID3v2.4 only: extended header update flag */
853 #define UNKNOWN_FLAGS 15 /* 00001111*/
854 unsigned char buf[6];
855 unsigned long length=0;
856 unsigned char flags = 0;
857 int ret = 1;
858 off_t ret2;
859 int storetag = 0;
860 unsigned int footlen = 0;
861#ifndef NO_ID3V2
862 int skiptag = 0;
863#endif
864 unsigned char major = first4bytes & 0xff;
865 debug1("ID3v2: major tag version: %i", major);
866
867 if(major == 0xff) return 0; /* Invalid... */
868 if((ret2 = fr->rd->read_frame_body(fr, buf, 6)) < 0) /* read more header information */
869 return ret2;
870
871 if(buf[0] == 0xff) return 0; /* Revision, will never be 0xff. */
872
873 if(fr->p.flags & MPG123_STORE_RAW_ID3)
874 storetag = 1;
875 /* second new byte are some nice flags, if these are invalid skip the whole thing */
876 flags = buf[1];
877 debug1("ID3v2: flags 0x%08x", flags);
878 /* use 4 bytes from buf to construct 28bit uint value and return 1; return 0 if bytes are not synchsafe */
879 #define synchsafe_to_long(buf,res) \
880 ( \
881 (((buf)[0]|(buf)[1]|(buf)[2]|(buf)[3]) & 0x80) ? 0 : \
882 (res = (((unsigned long) (buf)[0]) << 21) \
883 | (((unsigned long) (buf)[1]) << 14) \
884 | (((unsigned long) (buf)[2]) << 7) \
885 | ((unsigned long) (buf)[3]) \
886 ,1) \
887 )
888 /* id3v2.3 does not store synchsafe frame sizes, but synchsafe tag size - doh! */
889 /* Remember: bytes_to_long() can yield ULONG_MAX on 32 bit platforms! */
890 #define bytes_to_long(buf,res) \
891 ( \
892 major == 3 ? \
893 (res = (((unsigned long) (buf)[0]) << 24) \
894 | (((unsigned long) (buf)[1]) << 16) \
895 | (((unsigned long) (buf)[2]) << 8) \
896 | ((unsigned long) (buf)[3]) \
897 ,1) : synchsafe_to_long(buf,res) \
898 )
899 /* for id3v2.2 only */
900 #define threebytes_to_long(buf,res) \
901 ( \
902 res = (((unsigned long) (buf)[0]) << 16) \
903 | (((unsigned long) (buf)[1]) << 8) \
904 | ((unsigned long) (buf)[2]) \
905 )
906
907 /* length-10 or length-20 (footer present); 4 synchsafe integers == 28 bit number */
908 /* we have already read 10 bytes, so left are length or length+10 bytes belonging to tag */
909 /* Note: This is an 28 bit value in 32 bit storage, plenty of space for */
910 /* length+x for reasonable x. */
912 {
913 if(NOQUIET) error4("Bad tag length (not synchsafe): 0x%02x%02x%02x%02x; You got a bad ID3 tag here.", buf[2],buf[3],buf[4],buf[5]);
914 return 0;
915 }
916 if(flags & FOOTER_FLAG)
917 footlen = 10;
918 debug1("ID3v2: tag data length %lu", length);
919#ifndef NO_ID3V2
920 if(VERBOSE2) fprintf(stderr,"Note: ID3v2.%i rev %i tag of %lu bytes\n", major, buf[0], length);
921 /* skip if unknown version/scary flags, parse otherwise */
922 if(fr->p.flags & MPG123_SKIP_ID3V2)
923 {
924 if(VERBOSE3)
925 fprintf(stderr, "Note: Skipping ID3v2 tag per user request.\n");
926 skiptag = 1;
927 }
928 if((flags & UNKNOWN_FLAGS) || (major > 4) || (major < 2))
929 {
930 if(NOQUIET)
931 warning2( "ID3v2: Won't parse the ID3v2 tag with major version"
932 " %u and flags 0x%xu - some extra code may be needed"
933 , major, flags );
934 skiptag = 1;
935 }
936 // Standard says that compressed tags should be ignored as there isn't an agreed
937 // compressoion scheme.
938 if(major == 2 && flags & COMPRESS_FLAG)
939 {
940 if(NOQUIET)
941 warning("ID3v2: ignoring compressed ID3v2.2 tag");
942 skiptag = 1;
943 }
944 if(length < 10)
945 {
946 if(NOQUIET)
947 warning1("ID3v2: unrealistic small tag lengh %lu, skipping", length);
948 skiptag = 1;
949 }
950 if(!skiptag)
951 storetag = 1;
952#endif
953 if(storetag)
954 {
955 /* Stores whole tag with footer and an additonal trailing zero. */
956 if((ret2 = store_id3v2(fr, first4bytes, buf, length+footlen)) <= 0)
957 return ret2;
958 }
959#ifndef NO_ID3V2
960 if(skiptag)
961 {
962 if(VERBOSE3)
963 fprintf(stderr, "Note: skipped tag clearing possibly existing ID3v2 data");
964 reset_id3(fr); // Old data is invalid.
965#endif
966 if(!storetag && (ret2=fr->rd->skip_bytes(fr,length+footlen))<0)
967 ret=ret2;
968#ifndef NO_ID3V2
969 }
970 else
971 {
972 unsigned char* tagdata = fr->id3v2_raw+10;
973 /* try to interpret that beast */
974 debug("ID3v2: analysing frames...");
975 if(length > 0)
976 {
977 unsigned char extflags = 0;
978 unsigned long tagpos = 0;
979 /* bytes of frame title and of framesize value */
980 unsigned int head_part = major > 2 ? 4 : 3;
981 unsigned int flag_part = major > 2 ? 2 : 0;
982 /* The amount of bytes that are unconditionally read for each frame: */
983 /* ID, size, flags. */
984 unsigned int framebegin = head_part+head_part+flag_part;
985 debug1("ID3v2: have read at all %lu bytes for the tag now", (unsigned long)length+6);
986 if(flags & EXTHEAD_FLAG)
987 {
988 debug("ID3v2: extended header");
989 if(!bytes_to_long(tagdata, tagpos) || tagpos >= length)
990 {
991 ret = 0;
992 if(NOQUIET)
993 error4( "Bad (non-synchsafe/too large) tag offset from extended header:"
994 "0x%02x%02x%02x%02x"
995 , tagdata[0], tagdata[1], tagdata[2], tagdata[3] );
996 } else if(tagpos < 6)
997 {
998 ret = 0;
999 if(NOQUIET)
1000 merror("Extended header too small (%lu).", tagpos);
1001 }
1002 if(major == 3)
1003 {
1004 tagpos += 4; // The size itself is not included.
1005 if(tagpos >= length)
1006 {
1007 ret = 0;
1008 if(NOQUIET)
1009 error("Too much extended v2.3 header.");
1010 }
1011 } else if(ret) // v2.4 and at least got my 6 bytes of ext header
1012 {
1013 // Only v4 knows update frames, check for that.
1014 // Need to step back. Header is 4 bytes length, one byte flag size,
1015 // one byte flags. Flag size has to be 1!
1016 if(tagdata[4] == 1 && tagdata[5] & EXT_UPDATE_FLAG)
1017 {
1018 if(VERBOSE3)
1019 fprintf(stderr, "Note: ID3v2.4 update tag\n");
1020 extflags |= EXT_UPDATE_FLAG;
1021 }
1022 }
1023 }
1024 if(!(extflags & EXT_UPDATE_FLAG))
1025 {
1026 if(VERBOSE3)
1027 fprintf(stderr, "Note: non-update tag replacing existing ID3v2 data\n");
1028 reset_id3(fr);
1029 }
1030 if(ret > 0)
1031 {
1032 char id[5];
1033 unsigned long framesize;
1034 unsigned long fflags; /* need 16 bits, actually */
1035 id[4] = 0;
1036 fr->id3v2.version = major;
1037 /* Pos now advanced after ext head, now a frame has to follow. */
1038 /* Note: tagpos <= length, which is 28 bit integer, so both */
1039 /* far away from overflow for adding known small values. */
1040 /* I want to read at least one full header now. */
1041 while(length >= tagpos+framebegin)
1042 {
1043 int i = 0;
1044 unsigned long pos = tagpos;
1045 /* level 1,2,3 - 0 is info from lame/info tag! */
1046 /* rva tags with ascending significance, then general frames */
1047 enum frame_types tt = unknown;
1048 /* we may have entered the padding zone or any other strangeness: check if we have valid frame id characters */
1049 for(i=0; i< head_part; ++i)
1050 if( !( ((tagdata[tagpos+i] > 47) && (tagdata[tagpos+i] < 58))
1051 || ((tagdata[tagpos+i] > 64) && (tagdata[tagpos+i] < 91)) ) )
1052 {
1053 debug5("ID3v2: real tag data apparently ended after %lu bytes with 0x%02x%02x%02x%02x", tagpos, tagdata[tagpos], tagdata[tagpos+1], tagdata[tagpos+2], tagdata[tagpos+3]);
1054 /* This is no hard error... let's just hope that we got something meaningful already (ret==1 in that case). */
1055 goto tagparse_cleanup; /* Need to escape two loops here. */
1056 }
1057 if(ret > 0)
1058 {
1059 /* 4 or 3 bytes id */
1060 strncpy(id, (char*) tagdata+pos, head_part);
1061 id[head_part] = 0; /* terminate for 3 or 4 bytes */
1062 pos += head_part;
1063 tagpos += head_part;
1064 /* size as 32 bits or 28 bits */
1065 if(fr->id3v2.version == 2) threebytes_to_long(tagdata+pos, framesize);
1066 else
1067 if(!bytes_to_long(tagdata+pos, framesize))
1068 {
1069 /* Just assume that up to now there was some good data. */
1070 if(NOQUIET) error1("ID3v2: non-syncsafe size of %s frame, skipping the remainder of tag", id);
1071 break;
1072 }
1073 if(VERBOSE3) fprintf(stderr, "Note: ID3v2 %s frame of size %lu\n", id, framesize);
1074 tagpos += head_part;
1075 pos += head_part;
1076 if(fr->id3v2.version > 2)
1077 {
1078 fflags = (((unsigned long) tagdata[pos]) << 8) | ((unsigned long) tagdata[pos+1]);
1079 pos += 2;
1080 tagpos += 2;
1081 }
1082 else fflags = 0;
1083
1084 if(length - tagpos < framesize)
1085 {
1086 if(NOQUIET) error("Whoa! ID3v2 frame claims to be larger than the whole rest of the tag.");
1087 break;
1088 }
1089 tagpos += framesize; /* the important advancement in whole tag */
1090 /* for sanity, after full parsing tagpos should be == pos */
1091 /* debug4("ID3v2: found %s frame, size %lu (as bytes: 0x%08lx), flags 0x%016lx", id, framesize, framesize, fflags); */
1092 /* %0abc0000 %0h00kmnp */
1093 #define BAD_FFLAGS (unsigned long) 36784
1094 #define PRES_TAG_FFLAG 16384
1095 #define PRES_FILE_FFLAG 8192
1096 #define READ_ONLY_FFLAG 4096
1097 #define GROUP_FFLAG 64
1098 #define COMPR_FFLAG 8
1099 #define ENCR_FFLAG 4
1100 #define UNSYNC_FFLAG 2
1101 #define DATLEN_FFLAG 1
1102 if(head_part < 4 && promote_framename(fr, id) != 0) continue;
1103
1104 /* shall not or want not handle these */
1105 if(fflags & (BAD_FFLAGS | COMPR_FFLAG | ENCR_FFLAG))
1106 {
1107 if(NOQUIET) warning("ID3v2: skipping invalid/unsupported frame");
1108 continue;
1109 }
1110
1111 for(i = 0; i < KNOWN_FRAMES; ++i)
1112 if(!strncmp(frame_type[i], id, 4)){ tt = i; break; }
1113
1114 if(id[0] == 'T' && tt != extra) tt = text;
1115
1116 if(tt != unknown)
1117 {
1118 int rva_mode = -1; /* mix / album */
1119 unsigned long realsize = framesize;
1120 unsigned char* realdata = tagdata+pos;
1121 unsigned char* unsyncbuffer = NULL;
1122 if(((flags & UNSYNC_FLAG) || (fflags & UNSYNC_FFLAG)) && framesize > 0)
1123 {
1124 unsigned long ipos = 0;
1125 unsigned long opos = 0;
1126 debug("Id3v2: going to de-unsync the frame data");
1127 /* de-unsync: FF00 -> FF; real FF00 is simply represented as FF0000 ... */
1128 /* damn, that means I have to delete bytes from withing the data block... thus need temporal storage */
1129 /* standard mandates that de-unsync should always be safe if flag is set */
1130 realdata = unsyncbuffer = malloc(framesize+1); /* will need <= bytes, plus a safety zero */
1131 if(realdata == NULL)
1132 {
1133 if(NOQUIET) error("ID3v2: unable to allocate working buffer for de-unsync");
1134 continue;
1135 }
1136 /* now going byte per byte through the data... */
1137 realdata[0] = tagdata[pos];
1138 opos = 1;
1139 for(ipos = pos+1; ipos < pos+framesize; ++ipos)
1140 {
1141 if(!((tagdata[ipos] == 0) && (tagdata[ipos-1] == 0xff)))
1142 {
1143 realdata[opos++] = tagdata[ipos];
1144 }
1145 }
1146 realsize = opos;
1147 /* Append a zero to keep strlen() safe. */
1148 realdata[realsize] = 0;
1149 debug2("ID3v2: de-unsync made %lu out of %lu bytes", realsize, framesize);
1150 }
1151 pos = 0; /* now at the beginning again... */
1152 /* Avoid reading over boundary, even if there is a */
1153 /* zero byte of padding for safety. */
1154 if(realsize) switch(tt)
1155 {
1156 case comment:
1157 case uslt:
1158 process_comment(fr, tt, realdata, realsize, comment+1, id);
1159 break;
1160 case extra: /* perhaps foobar2000's work */
1161 process_extra(fr, realdata, realsize, extra+1, id);
1162 break;
1163 case rva2: /* "the" RVA tag */
1164 {
1165 /* starts with null-terminated identification */
1166 if(VERBOSE3) fprintf(stderr, "Note: RVA2 identification \"%s\"\n", realdata);
1167 /* default: some individual value, mix mode */
1168 rva_mode = 0;
1169 if( !strncasecmp((char*)realdata, "album", 5)
1170 || !strncasecmp((char*)realdata, "audiophile", 10)
1171 || !strncasecmp((char*)realdata, "user", 4))
1172 rva_mode = 1;
1173 if(fr->rva.level[rva_mode] <= rva2+1)
1174 {
1175 pos += strlen((char*) realdata) + 1;
1176 debug2("got my pos: %zu - %zu", realsize, pos);
1177 // channel and two bytes for RVA value
1178 // pos possibly just past the safety zero, so one more than realsize
1179 if(pos > realsize || realsize-pos < 3)
1180 {
1181 if(NOQUIET)
1182 error("bad RVA2 tag (truncated?)");
1183 }
1184 else if(realdata[pos] == 1)
1185 {
1186 ++pos;
1187 /* only handle master channel */
1188 debug("ID3v2: it is for the master channel");
1189 /* two bytes adjustment, one byte for bits representing peak - n bytes, eh bits, for peak */
1190 /* 16 bit signed integer = dB * 512. Do not shift signed integers! Multiply instead.
1191 Also no implementation-defined casting. Reinterpret the pointer to signed char, then do
1192 proper casting. */
1193 fr->rva.gain[rva_mode] = (float) (
1194 ((short)((signed char*)realdata)[pos]) * 256 + (short)realdata[pos+1] ) / 512;
1195 pos += 2;
1196 if(VERBOSE3) fprintf(stderr, "Note: RVA value %fdB\n", fr->rva.gain[rva_mode]);
1197 /* heh, the peak value is represented by a number of bits - but in what manner? Skipping that part */
1198 fr->rva.peak[rva_mode] = 0;
1199 fr->rva.level[rva_mode] = rva2+1;
1200 }
1201 }
1202 }
1203 break;
1204 /* non-rva metainfo, simply store... */
1205 case text:
1206 process_text(fr, realdata, realsize, id);
1207 break;
1208 case picture:
1209 if (fr->p.flags & MPG123_PICTURE)
1210 process_picture(fr, realdata, realsize);
1211
1212 break;
1213 default: if(NOQUIET) error1("ID3v2: unknown frame type %i", tt);
1214 }
1215 if(unsyncbuffer)
1216 free(unsyncbuffer);
1217 }
1218 #undef BAD_FFLAGS
1219 #undef PRES_TAG_FFLAG
1220 #undef PRES_FILE_FFLAG
1221 #undef READ_ONLY_FFLAG
1222 #undef GROUP_FFLAG
1223 #undef COMPR_FFLAG
1224 #undef ENCR_FFLAG
1225 #undef UNSYNC_FFLAG
1226 #undef DATLEN_FFLAG
1227 }
1228 else break;
1229 #undef KNOWN_FRAMES
1230 }
1231 } else
1232 {
1233 if(VERBOSE3)
1234 fprintf(stderr, "Note: faulty ID3v2 tag still clearing old data\n");
1235 reset_id3(fr);
1236 }
1237 } else // No new data, but still there was a tag that invalidates old data.
1238 {
1239 if(VERBOSE3)
1240 fprintf(stderr, "Note: empty ID3v2 clearing old data\n");
1241 reset_id3(fr);
1242 }
1243tagparse_cleanup:
1244 /* Get rid of stored raw data that should not be kept. */
1245 if(!(fr->p.flags & MPG123_STORE_RAW_ID3))
1246 {
1247 free(fr->id3v2_raw);
1248 fr->id3v2_raw = NULL;
1249 fr->id3v2_size = 0;
1250 }
1251 }
1252#endif /* NO_ID3V2 */
1253 return ret;
1254 #undef UNSYNC_FLAG
1255 #undef EXTHEAD_FLAG
1256 #undef COMPRESS_FLAG
1257 #undef EXP_FLAG
1258 #undef FOOTER_FLAG
1259 #undef EXT_UPDATE_FLAG
1260 #undef UNKOWN_FLAGS
1261}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
#define malloc
Definition: debug_ros.c:4
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
__kernel_off_t off_t
Definition: linux.h:201
#define strncasecmp
Definition: fake.h:10
GLbitfield flags
Definition: glext.h:7161
@ MPG123_PICTURE
Definition: mpg123.h:230
@ MPG123_STORE_RAW_ID3
Definition: mpg123.h:238
@ MPG123_SKIP_ID3V2
Definition: mpg123.h:227
static void process_text(mpg123_handle *fr, unsigned char *realdata, size_t realsize, char *id)
Definition: id3.c:445
#define BAD_FFLAGS
#define EXT_UPDATE_FLAG
static void process_extra(mpg123_handle *fr, unsigned char *realdata, size_t realsize, int rva_level, char *id)
Definition: id3.c:655
#define COMPRESS_FLAG
#define threebytes_to_long(buf, res)
frame_types
Definition: id3.c:95
#define KNOWN_FRAMES
Definition: id3.c:93
#define UNSYNC_FFLAG
static void process_picture(mpg123_handle *fr, unsigned char *realdata, size_t realsize)
Definition: id3.c:465
static const char frame_type[KNOWN_FRAMES][5]
Definition: id3.c:94
#define COMPR_FFLAG
#define ENCR_FFLAG
#define bytes_to_long(buf, res)
static int promote_framename(mpg123_handle *fr, char *id)
Definition: id3.c:762
#define EXTHEAD_FLAG
#define UNSYNC_FLAG
static void process_comment(mpg123_handle *fr, enum frame_types tt, unsigned char *realdata, size_t realsize, int rva_level, char *id)
Definition: id3.c:551
#define FOOTER_FLAG
int store_id3v2(mpg123_handle *fr, unsigned long first4bytes, unsigned char buf[6], unsigned long length)
Definition: id3.c:794
#define UNKNOWN_FLAGS
#define stderr
Definition: stdio.h:100
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
#define reset_id3
Definition: intsym.h:213
#define error(str)
Definition: mkdosfs.c:1605
static float(__cdecl *square_half_float)(float x
#define VERBOSE2
#define NOQUIET
#define VERBOSE3
#define warning(s)
Definition: debug.h:83
#define debug2(s, a, b)
Definition: debug.h:62
#define debug5(s, a, b, c, d, e)
Definition: debug.h:65
#define warning1(s, a)
Definition: debug.h:84
#define error1(s, a)
Definition: debug.h:125
#define error4(s, a, b, c, d)
Definition: debug.h:128
#define merror(s,...)
Definition: debug.h:122
struct mpg123_pars_struct p
Definition: frame.h:289
unsigned char * id3v2_raw
Definition: frame.h:300
size_t id3v2_size
Definition: frame.h:301
struct reader * rd
Definition: frame.h:287
struct mpg123_handle_struct::@3460 rva
int ret

◆ process_comment()

static void process_comment ( mpg123_handle fr,
enum frame_types  tt,
unsigned char realdata,
size_t  realsize,
int  rva_level,
char id 
)
static

Definition at line 551 of file id3.c.

552{
553 /* Text encoding $xx */
554 /* Language $xx xx xx */
555 /* Short description (encoded!) <text> $00 (00) */
556 /* Then the comment text (encoded) ... */
557 unsigned char encoding = realdata[0];
558 char lang[3]; // realdata + 1
559 unsigned char *descr = realdata+4;
560 unsigned char *text = NULL;
561 mpg123_text *xcom = NULL;
562 mpg123_text localcom; // UTF-8 variant for local processing, remember to clean up!
563 init_mpg123_text(&localcom);
564
565 if(realsize < (size_t)(descr-realdata))
566 {
567 if(NOQUIET) error1("Invalid frame size of %"SIZE_P" (too small for anything).", (size_p)realsize);
568 return;
569 }
571 {
572 if(NOQUIET)
573 error1("Unknown text encoding %u, I take no chances, sorry!", encoding);
574 return;
575 }
576 memcpy(lang, realdata+1, 3);
577 /* Now I can abuse a byte from lang for the encoding. */
578 descr[-1] = encoding;
579 /* Be careful with finding the end of description, I have to honor encoding here. */
580 text = next_text(descr, encoding, realsize-(descr-realdata));
581 if(text == NULL)
582 {
583 if(NOQUIET)
584 error("No comment text / valid description?");
585 return;
586 }
587 { // just vor variable scope
590 // Store the text, with desired encoding, but for comments always a local copy in UTF-8.
592 , NOQUIET, fr->p.flags & MPG123_PLAIN_ID3TEXT );
593 if(tt == comment)
594 store_id3_text( &localcom.description, descr-1, text-descr+1
595 , NOQUIET, 0 );
596 if(VERBOSE4)
597 fprintf( stderr, "Note: Storing comment from %s encoding\n"
598 , enc_name(realdata[0]) );
599 xcom = tt == uslt
600 ? add_uslt(fr, lang, &description)
602 if(xcom == NULL)
603 {
604 if(NOQUIET)
605 error("Unable to attach new comment!");
607 free_mpg123_text(&localcom);
608 return;
609 }
610 memcpy(xcom->id, id, 4);
611 memcpy(xcom->lang, lang, 3);
612 // That takes over the description allocation.
614 }
615
616 text[-1] = encoding; /* Byte abusal for encoding... */
617 store_id3_text(&xcom->text, text-1, realsize+1-(text-realdata), NOQUIET, fr->p.flags & MPG123_PLAIN_ID3TEXT);
618 /* Remember: I will probably decode the above (again) for rva comment checking. So no messing around, please. */
619
620 if(VERBOSE4) /* Do _not_ print the verbatim text: The encoding might be funny! */
621 {
622 fprintf(stderr, "Note: ID3 comm/uslt desc of length %"SIZE_P".\n", (size_p)xcom->description.fill);
623 fprintf(stderr, "Note: ID3 comm/uslt text of length %"SIZE_P".\n", (size_p)xcom->text.fill);
624 }
625 /* Look out for RVA info only when we really deal with a straight comment. */
626 if(tt == comment && localcom.description.fill > 0)
627 {
628 int rva_mode = -1; /* mix / album */
629 if( !strcasecmp(localcom.description.p, "rva")
630 || !strcasecmp(localcom.description.p, "rva_mix")
631 || !strcasecmp(localcom.description.p, "rva_track")
632 || !strcasecmp(localcom.description.p, "rva_radio") )
633 rva_mode = 0;
634 else if( !strcasecmp(localcom.description.p, "rva_album")
635 || !strcasecmp(localcom.description.p, "rva_audiophile")
636 || !strcasecmp(localcom.description.p, "rva_user") )
637 rva_mode = 1;
638 if((rva_mode > -1) && (fr->rva.level[rva_mode] <= rva_level))
639 {
640 /* Only translate the contents in here where we really need them. */
641 store_id3_text(&localcom.text, text-1, realsize+1-(text-realdata), NOQUIET, 0);
642 if(localcom.text.fill > 0)
643 {
644 fr->rva.gain[rva_mode] = (float) atof(localcom.text.p);
645 if(VERBOSE3) fprintf(stderr, "Note: RVA value %fdB\n", fr->rva.gain[rva_mode]);
646 fr->rva.peak[rva_mode] = 0;
647 fr->rva.level[rva_mode] = rva_level;
648 }
649 }
650 }
651 /* Make sure to free the local memory... */
652 free_mpg123_text(&localcom);
653}
#define strcasecmp
Definition: fake.h:9
@ MPG123_PLAIN_ID3TEXT
Definition: mpg123.h:225
char * p
Definition: mpg123.h:1193
size_t fill
Definition: mpg123.h:1195
MPG123_EXPORT int mpg123_move_string(mpg123_string *from, mpg123_string *to)
Definition: stringbuf.c:122
@ mpg123_id3_enc_max
Definition: mpg123.h:1348
#define add_comment(mh, l, d)
Definition: id3.c:209
static const char * enc_name(unsigned char enc)
Definition: id3.c:433
#define add_uslt(mh, l, d)
Definition: id3.c:211
static unsigned char * next_text(unsigned char *prev, unsigned char encoding, size_t limit)
Definition: id3.c:401
static void store_id3_text(mpg123_string *sb, unsigned char *source, size_t source_size, const int noquiet, const int notranslate)
Definition: id3.c:333
#define VERBOSE4
#define SIZE_P
Definition: compat.h:139
unsigned long size_p
Definition: compat.h:140
const char * descr
Definition: boot.c:45
double atof()

Referenced by parse_new_id3().

◆ process_extra()

static void process_extra ( mpg123_handle fr,
unsigned char realdata,
size_t  realsize,
int  rva_level,
char id 
)
static

Definition at line 655 of file id3.c.

656{
657 /* Text encoding $xx */
658 /* Description ... $00 (00) */
659 /* Text ... */
660 unsigned char encoding = realdata[0];
661 unsigned char *descr = realdata+1; /* remember, the encoding is descr[-1] */
662 unsigned char *text;
663 mpg123_text *xex;
664 mpg123_text localex;
665
666 if((int)realsize < descr-realdata)
667 {
668 if(NOQUIET) error1("Invalid frame size of %lu (too small for anything).", (unsigned long)realsize);
669 return;
670 }
672 {
673 if(NOQUIET)
674 error1("Unknown text encoding %u, I take no chances, sorry!", encoding);
675 return;
676 }
677 text = next_text(descr, encoding, realsize-(descr-realdata));
678 if(VERBOSE4) fprintf(stderr, "Note: Storing extra from %s encoding\n", enc_name(realdata[0]));
679 if(text == NULL)
680 {
681 if(NOQUIET) error("No extra frame text / valid description?");
682 return;
683 }
684 { // just vor variable scope
687 /* The outside storage gets reencoded to UTF-8 only if not requested otherwise.
688 Remember that we really need the -1 here to hand in the encoding byte!*/
690 , NOQUIET, fr->p.flags & MPG123_PLAIN_ID3TEXT );
691 xex = add_extra(fr, &description);
692 if(xex)
694 else
696 }
697 if(xex == NULL)
698 {
699 if(NOQUIET) error("Unable to attach new extra text!");
700 return;
701 }
702 memcpy(xex->id, id, 4);
703 init_mpg123_text(&localex); /* For our local copy. */
704
705 /* Our local copy is always stored in UTF-8! */
706 store_id3_text(&localex.description, descr-1, text-descr+1, NOQUIET, 0);
707 /* At first, only store the outside copy of the payload. We may not need the local copy. */
708 text[-1] = encoding;
709 store_id3_text(&xex->text, text-1, realsize-(text-realdata)+1, NOQUIET, fr->p.flags & MPG123_PLAIN_ID3TEXT);
710
711 /* Now check if we would like to interpret this extra info for RVA. */
712 if(localex.description.fill > 0)
713 {
714 int is_peak = 0;
715 int rva_mode = -1; /* mix / album */
716
717 if(!strncasecmp(localex.description.p, "replaygain_track_",17))
718 {
719 if(VERBOSE3) fprintf(stderr, "Note: RVA ReplayGain track gain/peak\n");
720
721 rva_mode = 0;
722 if(!strcasecmp(localex.description.p, "replaygain_track_peak")) is_peak = 1;
723 else if(strcasecmp(localex.description.p, "replaygain_track_gain")) rva_mode = -1;
724 }
725 else
726 if(!strncasecmp(localex.description.p, "replaygain_album_",17))
727 {
728 if(VERBOSE3) fprintf(stderr, "Note: RVA ReplayGain album gain/peak\n");
729
730 rva_mode = 1;
731 if(!strcasecmp(localex.description.p, "replaygain_album_peak")) is_peak = 1;
732 else if(strcasecmp(localex.description.p, "replaygain_album_gain")) rva_mode = -1;
733 }
734 if((rva_mode > -1) && (fr->rva.level[rva_mode] <= rva_level))
735 {
736 /* Now we need the translated copy of the data. */
737 store_id3_text(&localex.text, text-1, realsize-(text-realdata)+1, NOQUIET, 0);
738 if(localex.text.fill > 0)
739 {
740 if(is_peak)
741 {
742 fr->rva.peak[rva_mode] = (float) atof(localex.text.p);
743 if(VERBOSE3) fprintf(stderr, "Note: RVA peak %f\n", fr->rva.peak[rva_mode]);
744 }
745 else
746 {
747 fr->rva.gain[rva_mode] = (float) atof(localex.text.p);
748 if(VERBOSE3) fprintf(stderr, "Note: RVA gain %fdB\n", fr->rva.gain[rva_mode]);
749 }
750 fr->rva.level[rva_mode] = rva_level;
751 }
752 }
753 }
754
755 free_mpg123_text(&localex);
756}
#define add_extra(mh, d)
Definition: id3.c:212

Referenced by parse_new_id3().

◆ process_picture()

static void process_picture ( mpg123_handle fr,
unsigned char realdata,
size_t  realsize 
)
static

Definition at line 465 of file id3.c.

466{
467 unsigned char encoding;
469 unsigned char* workpoint = NULL;
471 unsigned char image_type = 0;
473 unsigned char *image_data = NULL;
474 if(realsize < 1)
475 {
476 debug("Empty id3 data!");
477 return;
478 }
479 encoding = realdata[0];
480 realdata++; realsize--;
482 {
483 if(NOQUIET)
484 error1("Unknown text encoding %u, I take no chances, sorry!", encoding);
485 return;
486 }
487 if(VERBOSE4) fprintf(stderr, "Note: Storing picture from APIC frame.\n");
488
489 /* get mime type (encoding is always latin-1) */
490 workpoint = next_text(realdata, 0, realsize);
491 if(!workpoint)
492 {
493 if(NOQUIET)
494 error("Unable to get mime type for picture; skipping picture.");
495 return;
496 }
497 id3_to_utf8(&mime, 0, realdata, workpoint - realdata, NOQUIET);
498 realsize -= workpoint - realdata;
499 realdata = workpoint;
500 /* get picture type */
501 image_type = realdata[0];
502 realdata++; realsize--;
503 /* get description (encoding is encoding) */
504 workpoint = next_text(realdata, encoding, realsize);
505 if(!workpoint)
506 {
507 if(NOQUIET)
508 error("Unable to get description for picture; skipping picture.");
510 return;
511 }
512 id3_to_utf8(&description, encoding, realdata, workpoint - realdata, NOQUIET);
513 realsize -= workpoint - realdata;
514 if(realsize)
515 image_data = (unsigned char*)malloc(realsize);
516 if(!realsize || !image_data) {
517 if(NOQUIET)
518 error("No picture data or malloc failure; skipping picture.");
521 return;
522 }
523 memcpy(image_data, workpoint, realsize);
524
525 // All data ready now, append to/replace in list.
526 i = add_picture(fr, image_type, &description);
527 if(!i)
528 {
529 if(NOQUIET)
530 error("Unable to attach new picture!");
531 free(image_data);
534 return;
535 }
536
537 // Either this is a fresh image, or one to be replaced.
538 // We hand over memory, so old storage needs to be freed.
540 i->type = image_type;
541 i->size = realsize;
542 i->data = image_data;
543 mpg123_move_string(&mime, &i->mime_type);
544 mpg123_move_string(&description, &i->description);
545 if(VERBOSE4)
546 fprintf(stderr, "Note: ID3v2 APIC picture frame of type: %d\n", i->type);
547}
#define add_picture(mh, t, d)
Definition: id3.c:213
#define id3_to_utf8
Definition: intsym.h:216
const WCHAR * mime
Definition: mimefilter.c:512

Referenced by parse_new_id3().

◆ process_text()

static void process_text ( mpg123_handle fr,
unsigned char realdata,
size_t  realsize,
char id 
)
static

Definition at line 445 of file id3.c.

446{
447 /* Text encoding $xx */
448 /* The text (encoded) ... */
449 mpg123_text *t = add_text(fr, id);
450 if(VERBOSE4) fprintf(stderr, "Note: Storing text from %s encoding\n", enc_name(realdata[0]));
451 if(t == NULL)
452 {
453 if(NOQUIET) error("Unable to attach new text!");
454 return;
455 }
456 mdebug("process_text: (over)writing entry with ID %s", t->id
457 ? (char[5]) { t->id[0], t->id[1], t->id[2], t->id[3], 0 }
458 : "(nil)" );
459 memcpy(t->id, id, 4);
460 store_id3_text(&t->text, realdata, realsize, NOQUIET, fr->p.flags & MPG123_PLAIN_ID3TEXT);
461 if(VERBOSE4) // Do not print unsanitized text to terminals!
462 fprintf(stderr, "Note: ID3v2 %c%c%c%c text frame stored\n", id[0], id[1], id[2], id[3]);
463}
GLdouble GLdouble t
Definition: gl.h:2047
#define add_text(mh, id)
Definition: id3.c:210

Referenced by parse_new_id3().

◆ promote_framename()

static int promote_framename ( mpg123_handle fr,
char id 
)
static

Definition at line 762 of file id3.c.

763{
764 size_t i;
765 char *old[] =
766 {
767 "COM", "TAL", "TBP", "TCM", "TCO", "TCR", "TDA", "TDY", "TEN", "TFT",
768 "TIM", "TKE", "TLA", "TLE", "TMT", "TOA", "TOF", "TOL", "TOR", "TOT",
769 "TP1", "TP2", "TP3", "TP4", "TPA", "TPB", "TRC", "TDA", "TRK", "TSI",
770 "TSS", "TT1", "TT2", "TT3", "TXT", "TXX", "TYE"
771 };
772 char *new[] =
773 {
774 "COMM", "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDAT", "TDLY", "TENC", "TFLT",
775 "TIME", "TKEY", "TLAN", "TLEN", "TMED", "TOPE", "TOFN", "TOLY", "TORY", "TOAL",
776 "TPE1", "TPE2", "TPE3", "TPE4", "TPOS", "TPUB", "TSRC", "TRDA", "TRCK", "TSIZ",
777 "TSSE", "TIT1", "TIT2", "TIT3", "TEXT", "TXXX", "TYER"
778 };
779 for(i=0; i<sizeof(old)/sizeof(char*); ++i)
780 {
781 if(!strncmp(id, old[i], 3))
782 {
783 memcpy(id, new[i], 4);
784 if(VERBOSE3) fprintf(stderr, "Translated ID3v2.2 frame %s to %s\n", old[i], new[i]);
785 return 0;
786 }
787 }
788 if(VERBOSE3) fprintf(stderr, "Ignoring untranslated ID3v2.2 frame %c%c%c\n", id[0], id[1], id[2]);
789 return -1;
790}

Referenced by parse_new_id3().

◆ reset_id3()

void reset_id3 ( mpg123_handle fr)

Definition at line 292 of file id3.c.

293{
294 exit_id3(fr);
295 init_id3(fr);
296}
#define exit_id3
Definition: intsym.h:212
#define init_id3
Definition: intsym.h:211

◆ store_id3_text()

static void store_id3_text ( mpg123_string sb,
unsigned char source,
size_t  source_size,
const int  noquiet,
const int  notranslate 
)
static

Definition at line 333 of file id3.c.

334{
335 unsigned char encoding;
336 if(sb) // Always overwrite, even with nothing.
337 sb->fill = 0;
338 if(!source_size)
339 {
340 debug("Empty id3 data!");
341 return;
342 }
343
344 /* We shall just copy the data. Client wants to decode itself. */
345 if(notranslate)
346 {
347 /* Future: Add a path for ID3 errors. */
348 if(!mpg123_grow_string(sb, source_size))
349 {
350 if(noquiet) error("Cannot resize target string, out of memory?");
351 return;
352 }
353 memcpy(sb->p, source, source_size);
354 sb->fill = source_size;
355 debug1("stored undecoded ID3 text of size %"SIZE_P, (size_p)source_size);
356 return;
357 }
358
359 encoding = source[0];
361 {
362 if(noquiet)
363 error1("Unknown text encoding %u, I take no chances, sorry!", encoding);
364 return;
365 }
366 id3_to_utf8(sb, encoding, source+1, source_size-1, noquiet);
367
368 if(sb->fill) debug1("UTF-8 string (the first one): %s", sb->p);
369 else if(noquiet) error("unable to convert string to UTF-8 (out of memory, junk input?)!");
370}

Referenced by process_comment(), process_extra(), and process_text().

◆ store_id3v2()

int store_id3v2 ( mpg123_handle fr,
unsigned long  first4bytes,
unsigned char  buf[6],
unsigned long  length 
)

Definition at line 794 of file id3.c.

796{
797 int ret = 1;
798 off_t ret2;
799 unsigned long fullen = 10+length;
800 if(fr->id3v2_raw)
801 free(fr->id3v2_raw);
802 fr->id3v2_size = 0;
803 /* Allocate one byte more for a closing zero as safety catch for strlen(). */
804 fr->id3v2_raw = malloc(fullen+1);
805 if(!fr->id3v2_raw)
806 {
808 if(NOQUIET)
809 error1("ID3v2: Arrg! Unable to allocate %lu bytes"
810 " for ID3v2 data - trying to skip instead.", length+1);
811 if((ret2=fr->rd->skip_bytes(fr,length)) < 0)
812 ret = ret2;
813 else
814 ret = 0;
815 }
816 else
817 {
818 fr->id3v2_raw[0] = (first4bytes>>24) & 0xff;
819 fr->id3v2_raw[1] = (first4bytes>>16) & 0xff;
820 fr->id3v2_raw[2] = (first4bytes>>8) & 0xff;
821 fr->id3v2_raw[3] = first4bytes & 0xff;
822 memcpy(fr->id3v2_raw+4, buf, 6);
823 if((ret2=fr->rd->read_frame_body(fr, fr->id3v2_raw+10, length)) < 0)
824 {
825 ret=ret2;
826 free(fr->id3v2_raw);
827 fr->id3v2_raw = NULL;
828 }
829 else
830 { /* Closing with a zero for paranoia. */
831 fr->id3v2_raw[fullen] = 0;
832 fr->id3v2_size = fullen;
833 }
834 }
835 return ret;
836}
@ MPG123_OUT_OF_MEM
Definition: mpg123.h:390

Referenced by parse_new_id3().

Variable Documentation

◆ encoding_widths

const unsigned int encoding_widths[4] = { 1, 2, 2, 1 }
static

Definition at line 115 of file id3.c.

Referenced by id3_to_utf8(), and next_text().

◆ frame_type

const char frame_type[KNOWN_FRAMES][5] = { "COMM", "TXXX", "RVA2", "USLT", "APIC" }
static

Definition at line 94 of file id3.c.

Referenced by parse_new_id3().

◆ text_converters

const text_converter text_converters[4]
static
Initial value:
=
{
}
static void convert_utf8(mpg123_string *sb, const unsigned char *source, size_t len, const int noquiet)
Definition: id3.c:1420
static void convert_utf16bom(mpg123_string *sb, const unsigned char *source, size_t len, const int noquiet)
Definition: id3.c:1333
static void convert_latin1(mpg123_string *sb, const unsigned char *source, size_t len, const int noquiet)
Definition: id3.c:1265

Definition at line 105 of file id3.c.

Referenced by id3_to_utf8().