⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 id3.c

📁 mips上编译过的mpg 运行正常 环境:AU12
💻 C
📖 第 1 页 / 共 2 页
字号:
	if(VERBOSE3) fprintf(stderr, "Ignoring untranslated ID3v2.2 frame %c%c%c\n", id[0], id[1], id[2]);	return -1;}/*	trying to parse ID3v2.3 and ID3v2.4 tags...	returns:  0: bad or just unparseable tag	          1: good, (possibly) new tag info	         <0: reader error (may need more data feed, try again)*/int parse_new_id3(mpg123_handle *fr, unsigned long first4bytes){	#define UNSYNC_FLAG 128	#define EXTHEAD_FLAG 64	#define EXP_FLAG 32	#define FOOTER_FLAG 16	#define UNKNOWN_FLAGS 15 /* 00001111*/	unsigned char buf[6];	unsigned long length=0;	unsigned char flags = 0;	int ret = 1;	int ret2;	unsigned char* tagdata = NULL;	unsigned char major = first4bytes & 0xff;	debug1("ID3v2: major tag version: %i", major);	if(major == 0xff) return 0; /* Invalid... */	if((ret2 = fr->rd->read_frame_body(fr, buf, 6)) < 0) /* read more header information */	return ret2;	if(buf[0] == 0xff) return 0; /* Revision, will never be 0xff. */	/* second new byte are some nice flags, if these are invalid skip the whole thing */	flags = buf[1];	debug1("ID3v2: flags 0x%08x", flags);	/* use 4 bytes from buf to construct 28bit uint value and return 1; return 0 if bytes are not synchsafe */	#define synchsafe_to_long(buf,res) \	( \		(((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) \	)	/* id3v2.3 does not store synchsafe frame sizes, but synchsafe tag size - doh! */	#define bytes_to_long(buf,res) \	( \		major == 3 ? \		(res =  (((unsigned long) (buf)[0]) << 24) \		     | (((unsigned long) (buf)[1]) << 16) \		     | (((unsigned long) (buf)[2]) << 8) \		     |  ((unsigned long) (buf)[3]) \		,1) : synchsafe_to_long(buf,res) \	)	/* for id3v2.2 only */	#define threebytes_to_long(buf,res) \	( \		res =  (((unsigned long) (buf)[0]) << 16) \		     | (((unsigned long) (buf)[1]) << 8) \		     |  ((unsigned long) (buf)[2]) \		,1 \	)	/* length-10 or length-20 (footer present); 4 synchsafe integers == 28 bit number  */	/* we have already read 10 bytes, so left are length or length+10 bytes belonging to tag */	if(!synchsafe_to_long(buf+2,length))	{		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]);		return 0;	}	debug1("ID3v2: tag data length %lu", length);	if(VERBOSE2) fprintf(stderr,"Note: ID3v2.%i rev %i tag of %lu bytes\n", major, buf[0], length);	/* skip if unknown version/scary flags, parse otherwise */	if((flags & UNKNOWN_FLAGS) || (major > 4) || (major < 2))	{		/* going to skip because there are unknown flags set */		if(NOQUIET) warning2("ID3v2: Won't parse the ID3v2 tag with major version %u and flags 0x%xu - some extra code may be needed", major, flags);		if((ret2 = fr->rd->skip_bytes(fr,length)) < 0) /* will not store data in backbuff! */		ret = ret2;	}	else	{		fr->id3v2.version = major;		/* try to interpret that beast */		if((tagdata = (unsigned char*) malloc(length+1)) != NULL)		{			debug("ID3v2: analysing frames...");			if((ret2 = fr->rd->read_frame_body(fr,tagdata,length)) > 0)			{				unsigned long tagpos = 0;				debug1("ID3v2: have read at all %lu bytes for the tag now", (unsigned long)length+6);				/* going to apply strlen for strings inside frames, make sure that it doesn't overflow! */				tagdata[length] = 0;				if(flags & EXTHEAD_FLAG)				{					debug("ID3v2: skipping extended header");					if(!bytes_to_long(tagdata, tagpos))					{						ret = 0;						if(NOQUIET) error4("Bad (non-synchsafe) tag offset: 0x%02x%02x%02x%02x", tagdata[0], tagdata[1], tagdata[2], tagdata[3]);					}				}				if(ret > 0)				{					char id[5];					unsigned long framesize;					unsigned long fflags; /* need 16 bits, actually */					id[4] = 0;					/* pos now advanced after ext head, now a frame has to follow */					while(tagpos < length-10) /* I want to read at least a full header */					{						int i = 0;						unsigned long pos = tagpos;						int head_part = fr->id3v2.version == 2 ? 3 : 4; /* bytes of frame title and of framesize value */						/* level 1,2,3 - 0 is info from lame/info tag! */						/* rva tags with ascending significance, then general frames */						#define KNOWN_FRAMES 3						const char frame_type[KNOWN_FRAMES][5] = { "COMM", "TXXX", "RVA2" }; /* plus all text frames... */						enum { unknown = -2, text = -1, comment, extra, rva2 } tt = unknown;						/* we may have entered the padding zone or any other strangeness: check if we have valid frame id characters */						for(i=0; i< head_part; ++i)						if( !( ((tagdata[tagpos+i] > 47) && (tagdata[tagpos+i] < 58))						    || ((tagdata[tagpos+i] > 64) && (tagdata[tagpos+i] < 91)) ) )						{							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]);							/* This is no hard error... let's just hope that we got something meaningful already (ret==1 in that case). */							goto tagparse_cleanup; /* Need to escape two loops here. */						}						if(ret > 0)						{							/* 4 or 3 bytes id */							strncpy(id, (char*) tagdata+pos, head_part);							pos += head_part;							tagpos += head_part;							/* size as 32 bits or 28 bits */							if(fr->id3v2.version == 2) threebytes_to_long(tagdata+pos, framesize);							else							if(!bytes_to_long(tagdata+pos, framesize))							{								/* Just assume that up to now there was some good data. */								if(NOQUIET) error1("ID3v2: non-syncsafe size of %s frame, skipping the remainder of tag", id);								break;							}							if(VERBOSE3) fprintf(stderr, "Note: ID3v2 %s frame of size %lu\n", id, framesize);							tagpos += head_part + framesize; /* the important advancement in whole tag */							if(tagpos > length)							{								if(NOQUIET) error("Whoa! ID3v2 frame claims to be larger than the whole rest of the tag.");								break;							}							pos += head_part;							if(fr->id3v2.version > 2)							{								fflags  = (((unsigned long) tagdata[pos]) << 8) | ((unsigned long) tagdata[pos+1]);								pos    += 2;								tagpos += 2;							}							else fflags = 0;							/* for sanity, after full parsing tagpos should be == pos */							/* debug4("ID3v2: found %s frame, size %lu (as bytes: 0x%08lx), flags 0x%016lx", id, framesize, framesize, fflags); */							/* %0abc0000 %0h00kmnp */							#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							if(head_part < 4 && promote_framename(fr, id) != 0) continue;							/* shall not or want not handle these */							if(fflags & (BAD_FFLAGS | COMPR_FFLAG | ENCR_FFLAG))							{								if(NOQUIET) warning("ID3v2: skipping invalid/unsupported frame");								continue;							}														for(i = 0; i < KNOWN_FRAMES; ++i)							if(!strncmp(frame_type[i], id, 4)){ tt = i; break; }							if(id[0] == 'T' && tt != extra) tt = text;							if(tt != unknown)							{								int rva_mode = -1; /* mix / album */								unsigned long realsize = framesize;								unsigned char* realdata = tagdata+pos;								if((flags & UNSYNC_FLAG) || (fflags & UNSYNC_FFLAG))								{									unsigned long ipos = 0;									unsigned long opos = 0;									debug("Id3v2: going to de-unsync the frame data");									/* de-unsync: FF00 -> FF; real FF00 is simply represented as FF0000 ... */									/* damn, that means I have to delete bytes from withing the data block... thus need temporal storage */									/* standard mandates that de-unsync should always be safe if flag is set */									realdata = (unsigned char*) malloc(framesize); /* will need <= bytes */									if(realdata == NULL)									{										if(NOQUIET) error("ID3v2: unable to allocate working buffer for de-unsync");										continue;									}									/* now going byte per byte through the data... */									realdata[0] = tagdata[pos];									opos = 1;									for(ipos = pos+1; ipos < pos+framesize; ++ipos)									{										if(!((tagdata[ipos] == 0) && (tagdata[ipos-1] == 0xff)))										{											realdata[opos++] = tagdata[ipos];										}									}									realsize = opos;									debug2("ID3v2: de-unsync made %lu out of %lu bytes", realsize, framesize);								}								pos = 0; /* now at the beginning again... */								switch(tt)								{									case comment:										process_comment(fr, (char*)realdata, realsize, comment+1, id);									break;									case extra: /* perhaps foobar2000's work */										process_extra(fr, (char*)realdata, realsize, extra+1, id);									break;									case rva2: /* "the" RVA tag */									{										#ifdef HAVE_INTTYPES_H										/* starts with null-terminated identification */										if(VERBOSE3) fprintf(stderr, "Note: RVA2 identification \"%s\"\n", realdata);										/* default: some individual value, mix mode */										rva_mode = 0;										if( !strncasecmp((char*)realdata, "album", 5)										    || !strncasecmp((char*)realdata, "audiophile", 10)										    || !strncasecmp((char*)realdata, "user", 4))										rva_mode = 1;										if(fr->rva.level[rva_mode] <= rva2+1)										{											pos += strlen((char*) realdata) + 1;											if(realdata[pos] == 1)											{												++pos;												/* only handle master channel */												debug("ID3v2: it is for the master channel");												/* two bytes adjustment, one byte for bits representing peak - n bytes for peak */												/* 16 bit signed integer = dB * 512 */												/* we already assume short being 16 bit */												fr->rva.gain[rva_mode] = (float) ((((short) realdata[pos]) << 8) | ((short) realdata[pos+1])) / 512;												pos += 2;												if(VERBOSE3) fprintf(stderr, "Note: RVA value %fdB\n", fr->rva.gain[rva_mode]);												/* heh, the peak value is represented by a number of bits - but in what manner? Skipping that part */												fr->rva.peak[rva_mode] = 0;												fr->rva.level[rva_mode] = rva2+1;											}										}										#else										if(NOQUIET) warning("ID3v2: Cannot parse RVA2 value because I don't have a guaranteed 16 bit signed integer type");										#endif									}									break;									/* non-rva metainfo, simply store... */									case text:										process_text(fr, (char*)realdata, realsize, id);									break;									default: if(NOQUIET) error1("ID3v2: unknown frame type %i", tt);								}								if((flags & UNSYNC_FLAG) || (fflags & UNSYNC_FFLAG)) free(realdata);							}							#undef BAD_FFLAGS							#undef PRES_TAG_FFLAG							#undef PRES_FILE_FFLAG							#undef READ_ONLY_FFLAG							#undef GROUP_FFLAG							#undef COMPR_FFLAG							#undef ENCR_FFLAG							#undef UNSYNC_FFLAG							#undef DATLEN_FFLAG						}						else break;						#undef KNOWN_FRAMES					}				}			}			else			{				if(NOQUIET) error("ID3v2: Duh, not able to read ID3v2 tag data.");				ret = ret2;			}tagparse_cleanup:			free(tagdata);		}		else		{			if(NOQUIET) error1("ID3v2: Arrg! Unable to allocate %lu bytes for interpreting ID3v2 data - trying to skip instead.", length);			if((ret2 = fr->rd->skip_bytes(fr,length)) < 0) ret = ret2; /* will not store data in backbuff! */			else ret = 0;		}	}	/* skip footer if present */	if((ret > 0) && (flags & FOOTER_FLAG) && ((ret2 = fr->rd->skip_bytes(fr,length)) < 0)) ret = ret2;	return ret;	#undef UNSYNC_FLAG	#undef EXTHEAD_FLAG	#undef EXP_FLAG	#undef FOOTER_FLAG	#undef UNKOWN_FLAGS}static void convert_latin1(mpg123_string *sb, unsigned char* s, size_t l){	size_t length = l;	size_t i;	unsigned char *p;	/* determine real length, a latin1 character can at most take 2  in UTF8 */	for(i=0; i<l; ++i)	if(s[i] >= 0x80) ++length;	debug1("UTF-8 length: %lu", (unsigned long)length);	/* one extra zero byte for paranoia */	if(!mpg123_resize_string(sb, length+1)){ mpg123_free_string(sb); return ; }	p = (unsigned char*) sb->p; /* Signedness doesn't matter but it shows I thought about the non-issue */	for(i=0; i<l; ++i)	if(s[i] < 0x80){ *p = s[i]; ++p; }	else /* two-byte encoding */	{		*p     = 0xc0 | (s[i]>>6);		*(p+1) = 0x80 | (s[i] & 0x3f);		p+=2;	}	sb->p[length] = 0;	sb->fill = length+1;}#define FULLPOINT(f,s) ( (((f)&0x3ff)<<10) + ((s)&0x3ff) + 0x10000 )/* Remember: There's a limit at 0x1ffff. */#define UTF8LEN(x) ( (x)<0x80 ? 1 : ((x)<0x800 ? 2 : ((x)<0x10000 ? 3 : 4)))static void convert_utf16(mpg123_string *sb, unsigned char* s, size_t l, int str_be){	size_t i;	unsigned char *p;	size_t length = 0; /* the resulting UTF-8 length */	/* Determine real length... extreme case can be more than utf-16 length. */	size_t high = 0;	size_t low  = 1;	debug1("convert_utf16 with length %lu", (unsigned long)l);	if(!str_be) /* little-endian */	{		high = 1; /* The second byte is the high byte. */		low  = 0; /* The first byte is the low byte. */	}	/* first: get length, check for errors -- stop at first one */	for(i=0; i < l-1; i+=2)	{		unsigned long point = ((unsigned long) s[i+high]<<8) + s[i+low];		if((point & 0xd800) == 0xd800) /* lead surrogate */		{			unsigned short second = (i+3 < l) ? (s[i+2+high]<<8) + s[i+2+low] : 0;			if((second & 0xdc00) == 0xdc00) /* good... */			{				point = FULLPOINT(point,second);				length += UTF8LEN(point); /* possibly 4 bytes */				i+=2; /* We overstepped one word. */			}			else /* if no valid pair, break here */			{				debug1("Invalid UTF16 surrogate pair at %li.", (unsigned long)i);				l = i; /* Forget the half pair, END! */				break;			}		}		else length += UTF8LEN(point); /* 1,2 or 3 bytes */	}	if(l < 1){ mpg123_set_string(sb, ""); return; }	if(!mpg123_resize_string(sb, length+1)){ mpg123_free_string(sb); return ; }	/* Now really convert, skip checks as these have been done just before. */	p = (unsigned char*) sb->p; /* Signedness doesn't matter but it shows I thought about the non-issue */	for(i=0; i < l-1; i+=2)	{		unsigned long codepoint = ((unsigned long) s[i+high]<<8) + s[i+low];		if((codepoint & 0xd800) == 0xd800) /* lead surrogate */		{			unsigned short second = (s[i+2+high]<<8) + s[i+2+low];			codepoint = FULLPOINT(codepoint,second);			i+=2; /* We overstepped one word. */		}		if(codepoint < 0x80) *p++ = (unsigned char) codepoint;		else if(codepoint < 0x800)		{			*p++ = 0xc0 | (codepoint>>6);			*p++ = 0x80 | (codepoint & 0x3f);		}		else if(codepoint < 0x10000)		{			*p++ = 0xe0 | (codepoint>>12);			*p++ = 0x80 | ((codepoint>>6) & 0x3f);			*p++ = 0x80 | (codepoint & 0x3f);		}		else if (codepoint < 0x200000) 		{			*p++ = 0xf0 | codepoint>>18;			*p++ = 0x80 | ((codepoint>>12) & 0x3f);			*p++ = 0x80 | ((codepoint>>6) & 0x3f);			*p++ = 0x80 | (codepoint & 0x3f);		} /* ignore bigger ones (that are not possible here anyway) */	}	sb->p[sb->size-1] = 0; /* paranoia... */	sb->fill = sb->size;}#undef UTF8LEN#undef FULLPOINTstatic void convert_utf16be(mpg123_string *sb, unsigned char* source, size_t len){	convert_utf16(sb, source, len, 1);}static void convert_utf16bom(mpg123_string *sb, unsigned char* source, size_t len){	if(len < 2){ mpg123_free_string(sb); return; }	if(source[0] == 0xff && source[1] == 0xfe) /* Little-endian */	convert_utf16(sb, source + 2, len - 2, 0);	else /* Big-endian */	convert_utf16(sb, source + 2, len - 2, 1);}static void convert_utf8(mpg123_string *sb, unsigned char* source, size_t len){	if(mpg123_resize_string(sb, len+1))	{		memcpy(sb->p, source, len);		sb->p[len] = 0;		sb->fill = len+1;	}	else mpg123_free_string(sb);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -