www.pudn.com > EXT.rar > id3tag.c


/*
 * madplay - MPEG audio decoder and player
 * Copyright (C) 2000-2003 Robert Leslie
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * $Id: id3tag.c,v 1.7 2003/06/05 03:56:04 rob Exp $
 */

#  include "config.h"

#include "myhead.h"
# include "global.h"
# include "id3tag.h"
# include "gettext.h"

static void show_id3(struct id3_tag const *tag)
{
	unsigned int i;
	struct id3_frame const *frame;
	id3_ucs4_t const *ucs4;
	id3_latin1_t *latin1;
	char const spaces[] = "          ";

	static struct {
		char const *id;
		char const *name;
	} const info[] = {
		{ ID3_FRAME_TITLE,  N_("Title")     },
		{ "TIT3",           0               },  /* Subtitle */
		{ "TCOP",           0               },  /* Copyright */
		{ "TPRO",           0               },  /* Produced */
		{ "TCOM",           N_("Composer")  },
		{ ID3_FRAME_ARTIST, N_("Artist")    },
		{ "TPE2",           N_("Orchestra") },
		{ "TPE3",           N_("Conductor") },
		{ "TEXT",           N_("Lyricist")  },
		{ ID3_FRAME_ALBUM,  N_("Album")     },
		{ ID3_FRAME_TRACK,  N_("Track")     },
		{ ID3_FRAME_YEAR,   N_("Year")      },
		{ "TPUB",           N_("Publisher") },
		{ ID3_FRAME_GENRE,  N_("Genre")     },
		{ "TRSN",           N_("Station")   },
		{ "TENC",           N_("Encoder")   }
	};

	/* text information */

	for (i = 0; i < sizeof(info) / sizeof(info[0]); ++i) {
		union id3_field const *field;
		unsigned int nstrings, namelen, j;
		char const *name;

		frame = id3_tag_findframe(tag, info[i].id, 0);
		if (frame == 0)
			continue;

		field    = id3_frame_field(frame, 1);
		nstrings = id3_field_getnstrings(field);

		name = info[i].name;
		if (name)
			name = gettext(name);

		namelen = name ? strlen(name) : 0;
		assert(namelen < sizeof(spaces));

		for (j = 0; j < nstrings; ++j) {
			ucs4 = id3_field_getstrings(field, j);
			assert(ucs4);

			if (strcmp(info[i].id, ID3_FRAME_GENRE) == 0)
				ucs4 = id3_genre_name(ucs4);

			latin1 = id3_ucs4_latin1duplicate(ucs4);
			if (latin1 == 0)
				goto fail;

			if (j == 0 && name)
				printf("%s%s: %s\n", &spaces[namelen], name, latin1);
			else {
				if (strcmp(info[i].id, "TCOP") == 0 ||
						strcmp(info[i].id, "TPRO") == 0) {
					printf("%s  %s %s\n", spaces, (info[i].id[1] == 'C') ?
							_("Copyright (C)") : _("Produced (P)"), latin1);
				}
				else
					printf("%s  %s\n", spaces, latin1);
			}

			free(latin1);
		}
	}

	/* comments */

	i = 0;
	while ((frame = id3_tag_findframe(tag, ID3_FRAME_COMMENT, i++))) {
		id3_latin1_t *ptr, *newline;
		int first = 1;

		ucs4 = id3_field_getstring(id3_frame_field(frame, 2));
		assert(ucs4);

		if (*ucs4)
			continue;

		ucs4 = id3_field_getfullstring(id3_frame_field(frame, 3));
		assert(ucs4);

		latin1 = id3_ucs4_latin1duplicate(ucs4);
		if (latin1 == 0)
			goto fail;

		ptr = latin1;
		while (*ptr) {
			newline = strchr(ptr, '\n');
			if (newline)
				*newline = 0;

			if (strlen(ptr) > 66) {
				id3_latin1_t *linebreak;

				linebreak = ptr + 66;

				while (linebreak > ptr && *linebreak != ' ')
					--linebreak;

				if (*linebreak == ' ') {
					if (newline)
						*newline = '\n';

					newline = linebreak;
					*newline = 0;
				}
			}

			if (first) {
				char const *name;
				unsigned int namelen;

				name    = _("Comment");
				namelen = strlen(name);
				assert(namelen < sizeof(spaces));

				printf("%s%s: %s\n", &spaces[namelen], name, ptr);
				first = 0;
			}
			else 
				printf("%s  %s\n", spaces, ptr);

			ptr += strlen(ptr) + (newline ? 1 : 0);
		}

		free(latin1);
		break;
	}

	if (0) {
fail:
		fprintf(stderr, "id3, not enough memory to display tag");
	}
}
/*
 * NAME:	process_id3()
 * DESCRIPTION:	display and process ID3 tag information
 */
static
void process_id3(struct id3_tag const *tag)
{
	struct id3_frame const *frame;

	/* display the tag */

	show_id3(tag);

	/*
	 * The following is based on information from the
	 * ID3 tag version 2.4.0 Native Frames informal standard.
	 */

	/* length information */

	frame = id3_tag_findframe(tag, "TLEN", 0);
	if (frame) {
		union id3_field const *field;
		unsigned int nstrings;

		field    = id3_frame_field(frame, 1);
		nstrings = id3_field_getnstrings(field);

		if (nstrings > 0) {
			id3_latin1_t *latin1;

			latin1 = id3_ucs4_latin1duplicate(id3_field_getstrings(field, 0));
			if (latin1) {
				signed long ms;

				/*
				 * "The 'Length' frame contains the length of the audio file
				 * in milliseconds, represented as a numeric string."
				 */

				ms = atol(latin1);
				if (ms > 0)
					//FIXME: mp3play can use this field as song time?
					//mad_timer_set(&player->stats.total_time, 0, ms, 1000);

					free(latin1);
			}
		}
	}
}

int show_id3tagv2_from_file(char* filename)
{
	/* try reading ID3 tag information now (else read later from stream) */
	{
		int fd;
		struct id3_file *file;

		fd = open(filename, O_RDONLY);
		file = id3_file_fdopen(fd, ID3_FILE_MODE_READONLY);
		if (file == 0) {
			close(fd);
		}
		else {
			process_id3(id3_file_tag(file));
			id3_file_close(file);
		}
	}
}