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

📄 id3.c

📁 在linux环境下的MP3播放软件
💻 C
📖 第 1 页 / 共 2 页
字号:
												size_t comsize = realsize-1-(strlen((char*)realdata+pos)+1);												if(param.verbose > 1) fprintf(stderr, "ID3v2: evaluating %s data for RVA\n", realdata+pos);												if((comstr = (char*) malloc(comsize+1)) != NULL)												{													memcpy(comstr,realdata+realsize-comsize, comsize);													comstr[comsize] = 0;													if(is_peak)													{														rva_peak[rva_mode] = atof(comstr);														if(param.verbose > 1) fprintf(stderr, "ID3v2: RVA peak %fdB\n", rva_peak[rva_mode]);													}													else													{														rva_gain[rva_mode] = atof(comstr);														if(param.verbose > 1) fprintf(stderr, "ID3v2: RVA gain %fdB\n", rva_gain[rva_mode]);													}													rva_level[rva_mode] = tt+1;													free(comstr);												}												else error("could not allocate memory for rva comment interpretation");											}										}									}									break;									case rva2: /* "the" RVA tag */									{										#ifdef HAVE_INTTYPES_H										/* starts with null-terminated identification */										if(param.verbose > 1) fprintf(stderr, "ID3v2: 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(rva_level[rva_mode] <= tt+1)										{											pos += strlen((char*) realdata) + 1;											if(realdata[pos] == 1)											{												++pos;												/* only handle master channel */												if(param.verbose > 1) fprintf(stderr, "ID3v2: it is for the master channel\n");												/* two bytes adjustment, one byte for bits representing peak - n bytes for peak */												/* 16 bit signed integer = dB * 512 */												rva_gain[rva_mode] = (float) ((((int16_t) realdata[pos]) << 8) | ((int16_t) realdata[pos+1])) / 512;												pos += 2;												if(param.verbose > 1) fprintf(stderr, "ID3v2: RVA value %fdB\n", rva_gain[rva_mode]);												/* heh, the peak value is represented by a number of bits - but in what manner? Skipping that part */												rva_peak[rva_mode] = 0;												rva_level[rva_mode] = tt+1;											}										}										#else										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 artist:										debug("ID3v2: parsing artist info");										store_id3_text(&id3.artist, (char*) realdata, realsize);									break;									case album:										debug("ID3v2: parsing album info");										store_id3_text(&id3.album, (char*) realdata, realsize);									break;									case title:										debug("ID3v2: parsing title info");										store_id3_text(&id3.title, (char*) realdata, realsize);									break;									case year:										debug("ID3v2: parsing year info");										store_id3_text(&id3.year, (char*) realdata, realsize);									break;									case genre:										debug("ID3v2: parsing genre info");										store_id3_text(&id3.genre, (char*) realdata, realsize);									break;									default: 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			{				error("ID3v2: Duh, not able to read ID3v2 tag data.");				ret = 0;			}			free(tagdata);		}		else		{			error1("ID3v2Arrg! Unable to allocate %lu bytes for interpreting ID3v2 data - trying to skip instead.", length);			if(!rds->skip_bytes(rds,length)) /* will not store data in backbuff! */			ret = 0;		}	}	/* skip footer if present */	if((flags & FOOTER_FLAG) && (!rds->skip_bytes(rds,length))) ret = 0;	return ret;	#undef UNSYNC_FLAG	#undef EXTHEAD_FLAG	#undef EXP_FLAG	#undef FOOTER_FLAG	#undef UNKOWN_FLAGS}void print_id3_tag(unsigned char *id3v1buf){	char genre_from_v1 = 0;	if(id3v1buf != NULL)	{		/* fill gaps in id3v2 info with id3v1 info */		struct id3tag {			char tag[3];			char title[30];			char artist[30];			char album[30];			char year[4];			char comment[30];			unsigned char genre;		};		struct id3tag *tag = (struct id3tag *) id3v1buf;		/* I _could_ skip the recalculation of fill ... */		if(!id3.title.fill)		{			if(id3.title.size >= 31 || resize_stringbuf(&id3.title, 31))			{				strncpy(id3.title.p,tag->title,30);				id3.title.p[30] = 0;				id3.title.fill = strlen(id3.title.p) + 1;			}		}		if(!id3.artist.fill)		{			if(id3.artist.size >= 31 || resize_stringbuf(&id3.artist,31))			{				strncpy(id3.artist.p,tag->artist,30);				id3.artist.p[30] = 0;				id3.artist.fill = strlen(id3.artist.p) + 1;			}		}		if(!id3.album.fill)		{			if(id3.album.size >= 31 || resize_stringbuf(&id3.album,31))			{				strncpy(id3.album.p,tag->album,30);				id3.album.p[30] = 0;				id3.album.fill = strlen(id3.album.p) + 1;			}		}		if(!id3.comment.fill)		{			if(id3.comment.size >= 31 || resize_stringbuf(&id3.comment,31))			{				strncpy(id3.comment.p,tag->comment,30);				id3.comment.p[30] = 0;				id3.comment.fill = strlen(id3.comment.p) + 1;			}		}		if(!id3.year.fill)		{			if(id3.year.size >= 5 || resize_stringbuf(&id3.year,5))			{				strncpy(id3.year.p,tag->year,4);				id3.year.p[4] = 0;				id3.year.fill = strlen(id3.year.p) + 1;			}		}		/*			genre is special... tag->genre holds an index, id3v2 genre may contain indices in textual form and raw textual genres...		*/		if(!id3.genre.fill)		{			if(id3.genre.size >= 31 || resize_stringbuf(&id3.genre,31))			{				if (tag->genre <= genre_count)				{					strncpy(id3.genre.p, genre_table[tag->genre], 30);				}				else				{					strncpy(id3.genre.p,"Unknown",30);				}				id3.genre.p[30] = 0;				id3.genre.fill = strlen(id3.genre.p) + 1;				genre_from_v1 = 1;			}		}	}		if(id3.genre.fill && !genre_from_v1)	{		/*			id3v2.3 says (id)(id)blabla and in case you want ot have (blabla) write ((blabla)			also, there is			(RX) Remix			(CR) Cover			id3v2.4 says			"one or several of the ID3v1 types as numerical strings"			or define your own (write strings), RX and CR 			Now I am very sure that I'll encounter hellishly mixed up id3v2 frames, so try to parse both at once.	 */		struct stringbuf tmp;		init_stringbuf(&tmp);		debug1("interpreting genre: %s\n", id3.genre.p);		if(copy_stringbuf(&id3.genre, &tmp))		{			size_t num = 0;			size_t nonum = 0;			size_t i;			enum { nothing, number, outtahere } state = nothing;			id3.genre.fill = 0; /* going to be refilled */			/* number\n -> id3v1 genre */			/* (number) -> id3v1 genre */			/* (( -> ( */			for(i = 0; i < tmp.fill; ++i)			{				debug1("i=%lu", (unsigned long) i);				switch(state)				{					case nothing:						nonum = i;						if(tmp.p[i] == '(')						{							num = i+1; /* number starting as next? */							state = number;							debug1("( before number at %lu?", (unsigned long) num);						}						/* you know an encoding where this doesn't work? */						else if(tmp.p[i] >= '0' && tmp.p[i] <= '9')						{							num = i;							state = number;							debug1("direct number at %lu", (unsigned long) num);						}						else state = outtahere;					break;					case number:						/* fake number alert: (( -> ( */						if(tmp.p[i] == '(')						{							nonum = i;							state = outtahere;							debug("no, it was ((");						}						else if(tmp.p[i] == ')' || tmp.p[i] == '\n' || tmp.p[i] == 0)						{							if(i-num > 0)							{								/* we really have a number */								int gid;								char* genre = "Unknown";								tmp.p[i] = 0;								gid = atoi(tmp.p+num);								/* get that genre */								if (gid >= 0 && gid <= genre_count) genre = genre_table[gid];								debug1("found genre: %s", genre);								if(id3.genre.fill) add_to_stringbuf(&id3.genre, ", ");								add_to_stringbuf(&id3.genre, genre);								nonum = i+1; /* next possible stuff */								state = nothing;								debug1("had a number: %i", gid);							}							else							{								/* wasn't a number, nonum is set */								state = outtahere;								debug("no (num) thing...");							}						}						else if(!(tmp.p[i] >= '0' && tmp.p[i] <= '9'))						{							/* no number at last... */							state = outtahere;							debug("nothing numeric here");						}						else						{							debug("still number...");						}					break;					default: break;				}				if(state == outtahere) break;			}			if(nonum < tmp.fill-1)			{				if(id3.genre.fill) add_to_stringbuf(&id3.genre, ", ");				add_to_stringbuf(&id3.genre, tmp.p+nonum);			}		}		free_stringbuf(&tmp);	}	if(id3.version > 1)	{		fprintf(stderr,"\n");		/* print id3v2 */		/* dammed, I use pointers as bool again! It's so convenient... */		fprintf(stderr,"\tTitle:   %s\n", id3.title.fill ? id3.title.p : "");		fprintf(stderr,"\tArtist:  %s\n", id3.artist.fill ? id3.artist.p : "");		fprintf(stderr,"\tAlbum:   %s\n", id3.album.fill ? id3.album.p : "");		fprintf(stderr,"\tYear:    %s\n", id3.year.fill ? id3.year.p : "");		fprintf(stderr,"\tGenre:   %s\n", id3.genre.fill ? id3.genre.p : "");		fprintf(stderr,"\tComment: %s\n", id3.comment.fill ? id3.comment.p : "");		fprintf(stderr,"\n");	}	else if(id3v1buf != NULL)	{		fprintf(stderr,"Title  : %-30s  Artist: %s\n",id3.title.p,id3.artist.p);		fprintf(stderr,"Album  : %-30s  Year  : %4s\n",id3.album.p,id3.year.p);		fprintf(stderr,"Comment: %-30s  Genre : %s\n",id3.comment.p,id3.genre.p);	}}

⌨️ 快捷键说明

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