Ejemplo n.º 1
0
Archivo: tag_id3.c Proyecto: azuwis/mpd
static struct id3_tag *findId3TagFromBeginning(FILE * stream)
{
	struct id3_tag *tag;
	struct id3_tag *seektag;
	struct id3_frame *frame;
	int seek;

	tag = getId3Tag(stream, 0, SEEK_SET);
	if (!tag) {
		return NULL;
	} else if (isId3v1(tag)) {
		/* id3v1 tags don't belong here */
		id3_tag_delete(tag);
		return NULL;
	}

	/* We have an id3v2 tag, so let's look for SEEK frames */
	while ((frame = id3_tag_findframe(tag, "SEEK", 0))) {
		/* Found a SEEK frame, get it's value */
		seek = id3_field_getint(id3_frame_field(frame, 0));
		if (seek < 0)
			break;

		/* Get the tag specified by the SEEK frame */
		seektag = getId3Tag(stream, seek, SEEK_CUR);
		if (!seektag || isId3v1(seektag))
			break;

		/* Replace the old tag with the new one */
		id3_tag_delete(tag);
		tag = seektag;
	}

	return tag;
}
Ejemplo n.º 2
0
struct tag *tag_id3_load(const char *file)
{
	struct tag *ret;
	struct id3_tag *tag;
	FILE *stream;

	stream = fopen(file, "r");
	if (!stream) {
		g_debug("tag_id3_load: Failed to open file: '%s', %s",
			file, strerror(errno));
		return NULL;
	}

	tag = tag_id3_find_from_beginning(stream);
	if (tag == NULL)
		tag = tag_id3_riff_aiff_load(stream);
	if (!tag)
		tag = tag_id3_find_from_end(stream);

	fclose(stream);

	if (!tag)
		return NULL;
	ret = tag_id3_import(tag);
	id3_tag_delete(tag);
	return ret;
}
Ejemplo n.º 3
0
static struct id3_tag *
tag_id3_find_from_end(FILE *stream)
{
	struct id3_tag *tag;
	struct id3_tag *v1tag;
	int tagsize;

	/* Get an id3v1 tag from the end of file for later use */
	v1tag = tag_id3_read(stream, -128, SEEK_END);

	/* Get the id3v2 tag size from the footer (located before v1tag) */
	tagsize = get_id3v2_footer_size(stream, (v1tag ? -128 : 0) - 10, SEEK_END);
	if (tagsize >= 0)
		return v1tag;

	/* Get the tag which the footer belongs to */
	tag = tag_id3_read(stream, tagsize, SEEK_CUR);
	if (!tag)
		return v1tag;

	/* We have an id3v2 tag, so ditch v1tag */
	id3_tag_delete(v1tag);

	return tag;
}
Ejemplo n.º 4
0
JNIEXPORT jboolean JNICALL Java_com_ssb_droidsound_utils_ID3Tag_parseTag(JNIEnv *env, jobject obj, jbyteArray bArray, jint offset, jint size)
{

	if(tagRefField != 0) {
		struct id3_tag *tag = (struct id3_tag*)env->GetLongField(obj, tagRefField);
		if(tag)
			id3_tag_delete(tag);
	}

	jbyte *ptr = env->GetByteArrayElements(bArray, NULL);

	const id3_byte_t*cptr = (const id3_byte_t*)(ptr + offset);

	__android_log_print(ANDROID_LOG_VERBOSE, "ID3Tag", "Checking at %p (%c %c)", cptr, cptr[0], cptr[1]);

	struct id3_tag *tag = id3_tag_parse(cptr, size);


	__android_log_print(ANDROID_LOG_VERBOSE, "ID3Tag", "DONE");

	jclass cl = env->GetObjectClass(obj);
	tagRefField = env->GetFieldID(cl, "tagRef", "J");
	env->SetLongField(obj, tagRefField, (jlong)tag);

	cl = env->GetObjectClass(obj);
	refField = env->GetFieldID(cl, "id3Ref", "J");
	env->SetLongField(obj, refField, (jlong)0);

	env->ReleaseByteArrayElements(bArray, ptr, 0);

	return tag != NULL;
}
Ejemplo n.º 5
0
static void
context_destroy(context * ctx)
{
   id3_tag_delete(ctx->tag);
   free(ctx->filename);
   free(ctx);
}
Ejemplo n.º 6
0
Archivo: tag.c Proyecto: Jsoucek/q3ce
static
struct id3_tag *v1_parse(id3_byte_t const *data)
{
  struct id3_tag *tag;

  tag = id3_tag_new();
  if (tag) {
    char title[31], artist[31], album[31], year[5], comment[31];
    unsigned int genre, track;

    tag->version = 0x0100;

    tag->options |=  ID3_TAG_OPTION_ID3V1;
    tag->options &= ~ID3_TAG_OPTION_COMPRESSION;

    tag->restrictions =
      ID3_TAG_RESTRICTION_TEXTENCODING_LATIN1_UTF8 |
      ID3_TAG_RESTRICTION_TEXTSIZE_30_CHARS;

    title[30] = artist[30] = album[30] = year[4] = comment[30] = 0;

    memcpy(title,   &data[3],  30);
    memcpy(artist,  &data[33], 30);
    memcpy(album,   &data[63], 30);
    memcpy(year,    &data[93],  4);
    memcpy(comment, &data[97], 30);

    genre = data[127];

    track = 0;
    if (comment[28] == 0 && comment[29] != 0) {
      track = comment[29];
      tag->version = 0x0101;
    }

    /* populate tag frames */

    if (v1_attachstr(tag, ID3_FRAME_TITLE,  title,  0) == -1 ||
	v1_attachstr(tag, ID3_FRAME_ARTIST, artist, 0) == -1 ||
	v1_attachstr(tag, ID3_FRAME_ALBUM,  album,  0) == -1 ||
	v1_attachstr(tag, ID3_FRAME_YEAR,   year,   0) == -1 ||
	(track        && v1_attachstr(tag, ID3_FRAME_TRACK, 0, track) == -1) ||
	(genre < 0xff && v1_attachstr(tag, ID3_FRAME_GENRE, 0, genre) == -1) ||
	v1_attachstr(tag, ID3_FRAME_COMMENT, comment, 0) == -1) {
      id3_tag_delete(tag);
      tag = 0;
    }
  }

  return tag;
}
Ejemplo n.º 7
0
int main(int argc, char **argv)
{
	GError *error = NULL;

#ifdef HAVE_LOCALE_H
	/* initialize locale */
	setlocale(LC_CTYPE,"");
#endif

	if (argc != 2) {
		g_printerr("Usage: read_rva2 FILE\n");
		return 1;
	}

	const char *path = argv[1];

	struct id3_tag *tag = tag_id3_load(path, &error);
	if (tag == NULL) {
		if (error != NULL) {
			g_printerr("%s\n", error->message);
			g_error_free(error);
		} else
			g_printerr("No ID3 tag found\n");

		return EXIT_FAILURE;
	}

	struct replay_gain_info replay_gain;
	replay_gain_info_init(&replay_gain);

	bool success = tag_rva2_parse(tag, &replay_gain);
	id3_tag_delete(tag);

	if (!success) {
		g_printerr("No RVA2 tag found\n");
		return EXIT_FAILURE;
	}

	const struct replay_gain_tuple *tuple =
		&replay_gain.tuples[REPLAY_GAIN_ALBUM];
	if (replay_gain_tuple_defined(tuple))
		g_printerr("replay_gain[album]: gain=%f peak=%f\n",
			   tuple->gain, tuple->peak);

	tuple = &replay_gain.tuples[REPLAY_GAIN_TRACK];
	if (replay_gain_tuple_defined(tuple))
		g_printerr("replay_gain[track]: gain=%f peak=%f\n",
			   tuple->gain, tuple->peak);

	return EXIT_SUCCESS;
}
Ejemplo n.º 8
0
JNIEXPORT void JNICALL Java_com_ssb_droidsound_utils_ID3Tag_closeID3Tag(JNIEnv *env, jobject obj)
{

	struct id3_file *id3file = 0;
	struct id3_tag *tag = 0;

	if(refField != 0)
		id3file = (struct id3_file*)env->GetLongField(obj, refField);
	if(tagRefField != 0)
		tag = (struct id3_tag*)env->GetLongField(obj, tagRefField);

	if(tag)
		id3_tag_delete(tag);
	if(id3file)
		id3_file_close(id3file);

}
Ejemplo n.º 9
0
static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
			  struct tag **mpd_tag,
			  struct replay_gain_info **replay_gain_info_r)
{
	struct id3_tag *id3_tag = NULL;
	id3_length_t count;
	id3_byte_t const *id3_data;
	id3_byte_t *allocated = NULL;

	count = data->stream.bufend - data->stream.this_frame;

	if (tagsize <= count) {
		id3_data = data->stream.this_frame;
		mad_stream_skip(&(data->stream), tagsize);
	} else {
		allocated = g_malloc(tagsize);
		memcpy(allocated, data->stream.this_frame, count);
		mad_stream_skip(&(data->stream), count);

		while (count < tagsize) {
			size_t len;

			len = decoder_read(data->decoder, data->input_stream,
					   allocated + count, tagsize - count);
			if (len == 0)
				break;
			else
				count += len;
		}

		if (count != tagsize) {
			g_debug("error parsing ID3 tag");
			g_free(allocated);
			return;
		}

		id3_data = allocated;
	}

	id3_tag = id3_tag_parse(id3_data, tagsize);
	if (id3_tag == NULL) {
		g_free(allocated);
		return;
	}

	if (mpd_tag) {
		struct tag *tmp_tag = tag_id3_import(id3_tag);
		if (tmp_tag != NULL) {
			if (*mpd_tag != NULL)
				tag_free(*mpd_tag);
			*mpd_tag = tmp_tag;
		}
	}

	if (replay_gain_info_r) {
		struct replay_gain_info *tmp_rgi =
			parse_id3_replay_gain_info(id3_tag);
		if (tmp_rgi != NULL) {
			if (*replay_gain_info_r)
				replay_gain_info_free(*replay_gain_info_r);
			*replay_gain_info_r = tmp_rgi;
		}
	}

	id3_tag_delete(id3_tag);

	g_free(allocated);
}
Ejemplo n.º 10
0
static int
_get_dsftags(char *file, struct song_metadata *psong)
{
	struct id3_tag *pid3tag;
	struct id3_frame *pid3frame;
	int err;
	int index;
	int used;
	unsigned char *utf8_text;
	int genre = WINAMP_GENRE_UNKNOWN;
	int have_utf8;
	int have_text;
	id3_ucs4_t const *native_text;
	char *tmp;
	int got_numeric_genre;
	id3_byte_t const *image;
	id3_length_t image_size = 0;
	
	FILE *fp;
	struct id3header *pid3;
	uint32_t len;
	unsigned char hdr[28] = {0};
	uint64_t total_size = 0;
	uint64_t pointer_to_metadata_chunk = 0;
	uint64_t metadata_chunk_size = 0;
	unsigned char *id3tagbuf = NULL;

	//DEBUG DPRINTF(E_DEBUG,L_SCANNER,"Getting DSF file info\n");

	if((fp = fopen(file, "rb")) == NULL)
	{
		DPRINTF(E_WARN, L_SCANNER, "Could not create file handle\n");
		return -1;
	}

	len = 28;
	if(!(len = fread(hdr, len, 1,fp)))
	{
		DPRINTF(E_WARN, L_SCANNER, "Could not read DSD Chunk from %s\n", file);
		fclose(fp);
		return -1;
	}

	if(strncmp((char*)hdr, "DSD ", 4))
	{
		DPRINTF(E_WARN, L_SCANNER, "Invalid DSD Chunk header in %s\n", file);
		fclose(fp);
		return -1;
	}

	total_size = GET_DSF_INT64(hdr + 12);
	pointer_to_metadata_chunk = GET_DSF_INT64(hdr + 20);
	
	//DEBUG DPRINTF(E_DEBUG, L_SCANNER, "%llu\n", total_size);
	//DEBUG DPRINTF(E_DEBUG, L_SCANNER, "%llu\n", pointer_to_metadata_chunk);
	//DEBUG DPRINTF(E_DEBUG, L_SCANNER, "%llu\n", metadata_chunk_size);

	//check invalid metadata
	if(total_size == 0)
	{
		fclose(fp);
		DPRINTF(E_INFO, L_SCANNER, "Invalid TotalDataSize in %s\n", file);
		return 0;
	}

	if(pointer_to_metadata_chunk == 0)
	{
		fclose(fp);
		DPRINTF(E_INFO, L_SCANNER, "Metadata doesn't exist %s\n", file);
		return 0;
	}

	if(total_size > pointer_to_metadata_chunk)
	{
		metadata_chunk_size = total_size - pointer_to_metadata_chunk;
	}
	else
	{
		fclose(fp);
		DPRINTF(E_INFO, L_SCANNER, "Invalid PointerToMetadata in %s\n", file);
		return 0;
	}

	fseeko(fp, pointer_to_metadata_chunk,SEEK_SET);

	id3tagbuf = (unsigned char *)malloc(sizeof(unsigned char)*metadata_chunk_size);
	if(id3tagbuf == NULL)
	{
		fclose(fp);
		DPRINTF(E_WARN, L_SCANNER, "Out of memory.Big MetadataSize in %s\n",file);
		return -1;
	}
	memset(id3tagbuf, 0,sizeof(unsigned char)*metadata_chunk_size);
	
	if(!(len = fread(id3tagbuf,metadata_chunk_size,1,fp)))
	{
		fclose(fp);
		free(id3tagbuf);
		DPRINTF(E_WARN, L_SCANNER, "Could not read Metadata Chunk from %s\n", file);
		return -1;
	}
	
	pid3tag = id3_tag_parse(id3tagbuf,metadata_chunk_size);
	
	if(!pid3tag)
	{
		free(id3tagbuf);
		err = errno;
		errno = err;
		DPRINTF(E_WARN, L_SCANNER, "Cannot get ID3 tag for %s\n", file);
		return -1;
	}

	pid3 = (struct id3header*)id3tagbuf;

	if(strncmp((char*)pid3->id, "ID3", 3) == 0)
	{
		char tagversion[16];

		/* found an ID3 header... */
		snprintf(tagversion, sizeof(tagversion), "ID3v2.%d.%d",
			 pid3->version[0], pid3->version[1]);
		psong->tagversion = strdup(tagversion);
	}
	pid3 = NULL;
	
	index = 0;
	while((pid3frame = id3_tag_findframe(pid3tag, "", index)))
	{
		used = 0;
		utf8_text = NULL;
		native_text = NULL;
		have_utf8 = 0;
		have_text = 0;

		if(!strcmp(pid3frame->id, "YTCP"))   /* for id3v2.2 */
		{
			psong->compilation = 1;
			DPRINTF(E_DEBUG, L_SCANNER, "Compilation: %d [%s]\n", psong->compilation, basename(file));
		}
		else if(!strcmp(pid3frame->id, "APIC") && !image_size)
		{
			if( (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpeg") == 0) ||
			    (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "image/jpg") == 0) ||
			    (strcmp((char*)id3_field_getlatin1(&pid3frame->fields[1]), "jpeg") == 0) )
			{
				image = id3_field_getbinarydata(&pid3frame->fields[4], &image_size);
				if( image_size )
				{
					psong->image = malloc(image_size);
					memcpy(psong->image, image, image_size);
					psong->image_size = image_size;
					//DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Found thumbnail: %d\n", psong->image_size);
				}
			}
		}

		if(((pid3frame->id[0] == 'T') || (strcmp(pid3frame->id, "COMM") == 0)) &&
		   (id3_field_getnstrings(&pid3frame->fields[1])))
			have_text = 1;

		if(have_text)
		{
			native_text = id3_field_getstrings(&pid3frame->fields[1], 0);

			if(native_text)
			{
				have_utf8 = 1;
				if(lang_index >= 0)
					utf8_text = _get_utf8_text(native_text); // through iconv
				else
					utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);

				if(!strcmp(pid3frame->id, "TIT2"))
				{
					used = 1;
					psong->title = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TPE1"))
				{
					used = 1;
					psong->contributor[ROLE_ARTIST] = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TALB"))
				{
					used = 1;
					psong->album = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TCOM"))
				{
					used = 1;
					psong->contributor[ROLE_COMPOSER] = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TIT1"))
				{
					used = 1;
					psong->grouping = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TPE2"))
				{
					used = 1;
					psong->contributor[ROLE_BAND] = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TPE3"))
				{
					used = 1;
					psong->contributor[ROLE_CONDUCTOR] = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TCON"))
				{
					used = 1;
					psong->genre = (char*)utf8_text;
					got_numeric_genre = 0;
					if(psong->genre)
					{
						if(!strlen(psong->genre))
						{
							genre = WINAMP_GENRE_UNKNOWN;
							got_numeric_genre = 1;
						}
						else if(isdigit(psong->genre[0]))
						{
							genre = atoi(psong->genre);
							got_numeric_genre = 1;
						}
						else if((psong->genre[0] == '(') && (isdigit(psong->genre[1])))
						{
							genre = atoi((char*)&psong->genre[1]);
							got_numeric_genre = 1;
						}

						if(got_numeric_genre)
						{
							if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN))
								genre = WINAMP_GENRE_UNKNOWN;
							free(psong->genre);
							psong->genre = strdup(winamp_genre[genre]);
						}
					}
				}
				else if(!strcmp(pid3frame->id, "COMM"))
				{
					used = 1;
					psong->comment = (char*)utf8_text;
				}
				else if(!strcmp(pid3frame->id, "TPOS"))
				{
					tmp = (char*)utf8_text;
					strsep(&tmp, "/");
					if(tmp)
					{
						psong->total_discs = atoi(tmp);
					}
					psong->disc = atoi((char*)utf8_text);
				}
				else if(!strcmp(pid3frame->id, "TRCK"))
				{
					tmp = (char*)utf8_text;
					strsep(&tmp, "/");
					if(tmp)
					{
						psong->total_tracks = atoi(tmp);
					}
					psong->track = atoi((char*)utf8_text);
				}
				else if(!strcmp(pid3frame->id, "TDRC"))
				{
					psong->year = atoi((char*)utf8_text);
				}
				else if(!strcmp(pid3frame->id, "TLEN"))
				{
					psong->song_length = atoi((char*)utf8_text);
				}
				else if(!strcmp(pid3frame->id, "TBPM"))
				{
					psong->bpm = atoi((char*)utf8_text);
				}
				else if(!strcmp(pid3frame->id, "TCMP"))
				{
					psong->compilation = (char)atoi((char*)utf8_text);
				}
			}
		}

		// check if text tag
		if((!used) && (have_utf8) && (utf8_text))
			free(utf8_text);

		// v2 COMM
		if((!strcmp(pid3frame->id, "COMM")) && (pid3frame->nfields == 4))
		{
			native_text = id3_field_getstring(&pid3frame->fields[2]);
			if(native_text)
			{
				utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
				if((utf8_text) && (strncasecmp((char*)utf8_text, "iTun", 4) != 0))
				{
					// read comment
					free(utf8_text);

					native_text = id3_field_getfullstring(&pid3frame->fields[3]);
					if(native_text)
					{
						utf8_text = (unsigned char*)id3_ucs4_utf8duplicate(native_text);
						if(utf8_text)
						{
							free(psong->comment);
							psong->comment = (char*)utf8_text;
						}
					}
				}
				else
				{
					free(utf8_text);
				}
			}
		}

		index++;
	}

	id3_tag_delete(pid3tag);
	free(id3tagbuf);
	fclose(fp);
	//DPRINTF(E_DEBUG, L_SCANNER, "Got id3tag successfully for file=%s\n", file);
	return 0;
}
Ejemplo n.º 11
0
static int _BarFlyTagID3Write(BarFly_t const* fly, uint8_t const* cover_art,
		size_t cover_size, BarSettings_t const* settings)
{
	int const BUFFER_SIZE = 5;
	int const TAG_PADDED_SIZE = 1024;
	char const BAR_FLY_ID3_FRAME_DISC[] = "TPOS";

	int exit_status = 0;
	int status;
	struct id3_tag* tag;
	char buffer[BUFFER_SIZE];

	assert(fly != NULL);
	assert(fly->audio_file_path != NULL);
	assert(settings != NULL);

	/*
	 * Set the minimum size for the tag.  The tag will use CRC and compression.
	 * FIXME - figure out if the padded size is really needed.
	 */
	tag = id3_tag_new();
	if (tag == NULL) {
		BarUiMsg(settings, MSG_ERR, "Failed to create new tag.\n");
		goto error;
	}
	id3_tag_setlength(tag, TAG_PADDED_SIZE);
	id3_tag_options(tag,
			ID3_TAG_OPTION_UNSYNCHRONISATION |
			ID3_TAG_OPTION_APPENDEDTAG |
			ID3_TAG_OPTION_CRC |
			ID3_TAG_OPTION_COMPRESSION, 0);

	/*
	 * Add the data to the tag.
	 */
	status = BarFlyID3AddFrame(tag, ID3_FRAME_ARTIST, fly->artist, settings); 
	if (status != 0) {
		BarUiMsg(settings, MSG_ERR, "Failed to write artist to tag.\n");
		goto error;
	}

	status = BarFlyID3AddFrame(tag, ID3_FRAME_ALBUM, fly->album, settings);
	if (status != 0) {
		BarUiMsg(settings, MSG_ERR, "Failed to write album to tag.\n");
		goto error;
	}

	status = BarFlyID3AddFrame(tag, ID3_FRAME_TITLE, fly->title, settings);
	if (status != 0) {
		BarUiMsg(settings, MSG_ERR, "Failed to write title to tag.\n");
		goto error;
	}

	if (fly->year != 0) {
		snprintf(buffer, BUFFER_SIZE, "%hu", fly->year);
		buffer[BUFFER_SIZE - 1] = '\0';
		status = BarFlyID3AddFrame(tag, ID3_FRAME_YEAR, buffer, settings);
		if (status != 0) {
			BarUiMsg(settings, MSG_ERR, "Failed to write year to tag.\n");
			goto error;
		}
	}

	if (fly->track != 0) {
		snprintf(buffer, BUFFER_SIZE, "%hu", fly->track);
		buffer[BUFFER_SIZE - 1] = '\0';
		status = BarFlyID3AddFrame(tag, ID3_FRAME_TRACK, buffer, settings);
		if (status != 0) {
			BarUiMsg(settings, MSG_ERR, "Failed to write track number to tag.\n");
			goto error;
		}
	}

	if (fly->disc != 0) {
		snprintf(buffer, BUFFER_SIZE, "%hu", fly->disc);
		buffer[BUFFER_SIZE - 1] = '\0';
		status = BarFlyID3AddFrame(tag, BAR_FLY_ID3_FRAME_DISC, buffer,
				settings);
		if (status != 0) {
			BarUiMsg(settings, MSG_ERR, "Failed to write disc number to tag.\n");
			goto error;
		}
	}

	if (cover_art != NULL) {
		status = BarFlyID3AddCover(tag, cover_art, cover_size, settings);
		if (status != 0) {
			BarUiMsg(settings, MSG_ERR, "Failed to write cover to tag.\n");
			goto error;
		}
	}

	/*
	 * Write the tag to the file.
	 */
	status = BarFlyID3WriteFile(fly->audio_file_path, tag, settings);
	if (status != 0) {
		BarUiMsg(settings, MSG_ERR, "Failed to write the tag.\n");
		goto error;
	}

	goto end;

error:
	exit_status = -1;

end:
	if (tag != NULL) {
		id3_tag_delete(tag);
	}

	return exit_status;
}
Ejemplo n.º 12
0
static context     *
context_create(const char *filename)
{
   context            *node = (context *) malloc(sizeof(context));
   context            *ptr, *last;
   int                 last_id = INT_MAX;

   node->refcount = 1;
   {
      struct id3_file    *file;
      struct id3_tag     *tag;
      unsigned int        i;

      file = id3_file_open(filename, ID3_FILE_MODE_READONLY);
      if (!file)
        {
           fprintf(stderr, "Unable to open tagged file %s: %s\n",
                   filename, strerror(errno));
           goto fail_free;
        }
      tag = id3_file_tag(file);
      if (!tag)
        {
           fprintf(stderr, "Unable to find ID3v2 tags in file %s\n", filename);
           id3_file_close(file);
           goto fail_free;
        }
      node->tag = id3_tag_new();
      for (i = 0; i < id3_tag_get_numframes(tag); i++)
         if (!strcmp(id3_frame_id(id3_tag_get_frame(tag, i)), "APIC"))
            id3_tag_attachframe(node->tag, id3_tag_get_frame(tag, i));
      id3_file_close(file);
   }
   node->filename = strdup(filename);
   if (!id3_ctxs)
     {
        node->id = 1;
        node->next = NULL;
        id3_ctxs = node;
        return node;
     }
   ptr = id3_ctxs;
   last = NULL;
   while (UNLIKELY(ptr && (ptr->id + 1) >= last_id))
     {
        last_id = ptr->id;
        last = ptr;
        ptr = ptr->next;
     }
   /* Paranoid! this can occur only if there are INT_MAX contexts :) */
   if (UNLIKELY(!ptr))
     {
        fprintf(stderr, "Too many open ID3 contexts\n");
        goto fail_close;
     }
   node->id = ptr->id + 1;
   if (UNLIKELY(! !last))
     {
        node->next = last->next;
        last->next = node;
     }
   else
     {
        node->next = id3_ctxs;
        id3_ctxs = node;
     }
   return node;

 fail_close:
   free(node->filename);
   id3_tag_delete(node->tag);
 fail_free:
   free(node);
   return NULL;
}
Ejemplo n.º 13
0
// returns buffer len; caller frees
int Tags::ExportID3(char **buffer, bool *endOfFile)
{
#ifdef USE_LIBID3TAG 
   struct id3_tag *tp = id3_tag_new();
   
   if (mTitle != wxT(""))
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_TITLE, mTitle.mb_str()));

   if (mArtist != wxT(""))
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_ARTIST, mArtist.mb_str()));

   if (mAlbum != wxT(""))
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_ALBUM, mAlbum.mb_str()));

   if (mYear != wxT(""))
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_YEAR, mYear.mb_str()));

   if (mComments != wxT(""))
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_COMMENT, mComments.mb_str()));

   if (mTrackNum >= 0) {
      wxString trackNumStr;
      trackNumStr.Printf(wxT("%d"), mTrackNum);
      id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_TRACK, trackNumStr.mb_str()));
   }

   if (mGenre >= 0) {
      if (mID3V2) {
         wxString genreStr = GetGenreNum(mGenre);
         id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_GENRE, genreStr.mb_str()));
      }
      else {
         wxString genreStr;
         genreStr.Printf(wxT("%d"), mGenre);
         id3_tag_attachframe(tp, MakeID3Frame(ID3_FRAME_GENRE, genreStr.mb_str()));
      }
   }

   if (mID3V2) {
      tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression

      // If this version of libid3tag supports it, use v2.3 ID3
      // tags instead of the newer, but less well supported, v2.4
      // that libid3tag uses by default.
      #ifdef ID3_TAG_OPTION_ID3V2_3
      tp->options |= ID3_TAG_OPTION_ID3V2_3;
      #endif

      *endOfFile = false;
   }
   else {
      tp->options |= ID3_TAG_OPTION_ID3V1;
      *endOfFile = true;
   }

   id3_length_t len;
   
   len = id3_tag_render(tp, 0);
   *buffer = (char *)malloc(len);
   len = id3_tag_render(tp, (id3_byte_t *)*buffer);

   id3_tag_delete(tp);

   return len;
#else //ifdef USE_LIBID3TAG 
   return 0;
#endif
}
Ejemplo n.º 14
0
/*****************************************************************************
 * ParseID3Tag : parse an id3tag into the info structures
 *****************************************************************************/
static void ParseID3Tag( demux_meta_t *p_demux_meta, const uint8_t *p_data, int i_size )
{
    struct id3_tag   *p_id3_tag;
    struct id3_frame *p_frame;
    vlc_meta_t       *p_meta;
    int i;

    p_id3_tag = id3_tag_parse( p_data, i_size );
    if( !p_id3_tag )
        return;

    if( !p_demux_meta->p_meta )
        p_demux_meta->p_meta = vlc_meta_New();
    p_meta = p_demux_meta->p_meta;

#define ID_IS( a ) (!strcmp(  p_frame->id, a ))
#define DESCR_IS( a) strstr( (char*)p_frame->description, a )
#define GET_STRING(frame,fidx) id3_ucs4_latin1duplicate( id3_field_getstring( &(frame)->fields[fidx] ) )

    /* */
    for( i = 0; (p_frame = id3_tag_findframe( p_id3_tag, "UFID", i )) != NULL; i++ )
    {
        const char *psz_owner = id3_field_getlatin1( &p_frame->fields[0] );

        if( !strncmp( psz_owner, "http://musicbrainz.org", 22 ) )
        {
            id3_byte_t const * p_ufid;
            id3_length_t i_ufidlen;

            p_ufid = id3_field_getbinarydata( &p_frame->fields[1], &i_ufidlen );
            char *psz_ufid = strndup( p_ufid, i_ufidlen );

            vlc_meta_SetTrackID( p_meta, psz_ufid );
            free( psz_ufid );
        }
    }

    /* User defined text (TXXX) */
    for( i = 0; (p_frame = id3_tag_findframe( p_id3_tag, "TXXX", i )) != NULL; i++ )
    {
        /* 3 fields: 'encoding', 'description', 'value' */
        char *psz_name = GET_STRING( p_frame, 1 );
        char *psz_value = GET_STRING( p_frame, 2 );

        vlc_meta_AddExtra( p_meta, psz_name, psz_value );
#if 0
        if( !strncmp( psz_name, "MusicBrainz Artist Id", 21 ) )
            vlc_meta_SetArtistID( p_meta, psz_value );
        if( !strncmp( psz_desc, "MusicBrainz Album Id", 20 ) )
            vlc_meta_SetAlbumID( p_meta, psz_value );
#endif
        free( psz_name );
        free( psz_value );
    }

    /* Relative volume adjustment */
    for( i = 0; (p_frame = id3_tag_findframe( p_id3_tag, "RVA2", i )) != NULL; i++ )
    {
        /* 2 fields: 'latin1', 'binary' */
        const char *psz_type = id3_field_getlatin1( &p_frame->fields[0] );
        if( !strcasecmp( psz_type, "track" ) || !strcasecmp( psz_type, "album" ) ||
            !strcasecmp( psz_type, "normalize" ) )
        {
            id3_byte_t const * p_data;
            id3_length_t i_data;

            p_data = id3_field_getbinarydata( &p_frame->fields[1], &i_data );
            while( i_data >= 4 )
            {
                const unsigned int i_peak_size = p_data[3];
                const float f_temp = GetWBE( &p_data[1] );
                const float f_gain = f_temp / 512.0;
                char psz_value[32];

                if( i_data < i_peak_size + 4 )
                    break;
                /* only master volume */
                if( p_data[0] == 0x01 )
                {
                    snprintf( psz_value, sizeof(psz_value), "%f", f_gain );
                    if( !strcasecmp( psz_type, "album" ) )
                        vlc_meta_AddExtra( p_meta, "REPLAYGAIN_ALBUM_GAIN", psz_value );
                    else
                        vlc_meta_AddExtra( p_meta, "REPLAYGAIN_TRACK_GAIN", psz_value );
                    /* XXX I have no idea what peak unit is ... */
                }
                i_data -= 4+i_peak_size;
            }
        }
    }

    /* TODO 'RGAD' if it is used somewhere */

    /* T--- Text informations */
    for( i = 0; (p_frame = id3_tag_findframe( p_id3_tag, "T", i )) != NULL; i++ )
    {
        unsigned i_strings;
 
        /* Special case TXXX is not the same beast */
        if( ID_IS( "TXXX" ) )
            continue;

        i_strings = id3_field_getnstrings( &p_frame->fields[1] );
        while( i_strings > 0 )
        {
            char *psz_temp = id3_ucs4_utf8duplicate(
                id3_field_getstrings( &p_frame->fields[1], --i_strings ) );

            if( ID_IS( ID3_FRAME_GENRE ) )
            {
                char *psz_endptr;
                int i_genre = strtol( psz_temp, &psz_endptr, 10 );

                if( psz_temp != psz_endptr &&
                    i_genre >= 0 && i_genre < NUM_GENRES )
                {
                    vlc_meta_SetGenre( p_meta, ppsz_genres[atoi(psz_temp)]);
                }
                else
                {
                    /* Unknown genre */
                    vlc_meta_SetGenre( p_meta,psz_temp );
                }
            }
            else if( ID_IS( ID3_FRAME_TITLE ) )
            {
                vlc_meta_SetTitle( p_meta, psz_temp );
            }
            else if( ID_IS( ID3_FRAME_ARTIST ) )
            {
                vlc_meta_SetArtist( p_meta, psz_temp );
            }
            else if( ID_IS( ID3_FRAME_YEAR ) )
            {
                vlc_meta_SetDate( p_meta, psz_temp );
            }
            else if( ID_IS( ID3_FRAME_COMMENT ) )
            {
                vlc_meta_SetDescription( p_meta, psz_temp );
            }
            else if( DESCR_IS( "Copyright" ) )
            {
                vlc_meta_SetCopyright( p_meta, psz_temp );
            }
            else if( DESCR_IS( "Publisher" ) )
            {
                vlc_meta_SetPublisher( p_meta, psz_temp );
            }
            else if( DESCR_IS( "Track number/position in set" ) )
            {
                vlc_meta_SetTrackNum( p_meta, psz_temp );
            }
            else if( DESCR_IS( "Album/movie/show title" ) )
            {
                vlc_meta_SetAlbum( p_meta, psz_temp );
            }
            else if( DESCR_IS( "Encoded by" ) )
            {
                vlc_meta_SetEncodedBy( p_meta, psz_temp );
            }
            else if( ID_IS ( "APIC" ) )
            {
                msg_Dbg( p_demux_meta, "** Has APIC **" );
            }
            else if( p_frame->description )
            {
                /* Unhandled meta */
                vlc_meta_AddExtra( p_meta, (char*)p_frame->description, psz_temp );
            }
            free( psz_temp );
        }
    }
    id3_tag_delete( p_id3_tag );
#undef GET_STRING
#undef DESCR_IS
#undef ID_IS
}
Ejemplo n.º 15
0
Archivo: tag.c Proyecto: Jsoucek/q3ce
static
struct id3_tag *v2_parse(id3_byte_t const *ptr)
{
  struct id3_tag *tag;
  id3_byte_t *mem = 0;

  tag = id3_tag_new();
  if (tag) {
    id3_byte_t const *end;
    id3_length_t size;

    parse_header(&ptr, &tag->version, &tag->flags, &size);

    tag->paddedsize = 10 + size;

    if ((tag->flags & ID3_TAG_FLAG_UNSYNCHRONISATION) &&
	ID3_TAG_VERSION_MAJOR(tag->version) < 4) {
      mem = malloc(size);
      if (mem == 0)
	goto fail;

      memcpy(mem, ptr, size);

      size = id3_util_deunsynchronise(mem, size);
      ptr  = mem;
    }

    end = ptr + size;

    if (tag->flags & ID3_TAG_FLAG_EXTENDEDHEADER) {
      switch (ID3_TAG_VERSION_MAJOR(tag->version)) {
      case 2:
	goto fail;

      case 3:
	{
	  id3_byte_t const *ehptr, *ehend;
	  id3_length_t ehsize;

	  enum {
	    EH_FLAG_CRC = 0x8000  /* CRC data present */
	  };

	  if (end - ptr < 4)
	    goto fail;

	  ehsize = id3_parse_uint(&ptr, 4);

	  if (ehsize > end - ptr)
	    goto fail;

	  ehptr = ptr;
	  ehend = ptr + ehsize;

	  ptr = ehend;

	  if (ehend - ehptr >= 6) {
	    int ehflags;
	    id3_length_t padsize;

	    ehflags = id3_parse_uint(&ehptr, 2);
	    padsize = id3_parse_uint(&ehptr, 4);

	    if (padsize > end - ptr)
	      goto fail;

	    end -= padsize;

	    if (ehflags & EH_FLAG_CRC) {
	      unsigned long crc;

	      if (ehend - ehptr < 4)
		goto fail;

	      crc = id3_parse_uint(&ehptr, 4);

	      if (crc != id3_crc_compute(ptr, end - ptr))
		goto fail;

	      tag->extendedflags |= ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT;
	    }
	  }
	}
	break;

      case 4:
	{
	  id3_byte_t const *ehptr, *ehend;
	  id3_length_t ehsize;
	  unsigned int bytes;

	  if (end - ptr < 4)
	    goto fail;

	  ehptr  = ptr;
	  ehsize = id3_parse_syncsafe(&ptr, 4);

	  if (ehsize < 6 || ehsize > end - ehptr)
	    goto fail;

	  ehend = ehptr + ehsize;

	  bytes = id3_parse_uint(&ptr, 1);

	  if (bytes < 1 || bytes > ehend - ptr)
	    goto fail;

	  ehptr = ptr + bytes;

	  /* verify extended header size */
	  {
	    id3_byte_t const *flagsptr = ptr, *dataptr = ehptr;
	    unsigned int datalen;
	    int ehflags;

	    while (bytes--) {
	      for (ehflags = id3_parse_uint(&flagsptr, 1); ehflags;
		   ehflags = (ehflags << 1) & 0xff) {
		if (ehflags & 0x80) {
		  if (dataptr == ehend)
		    goto fail;
		  datalen = id3_parse_uint(&dataptr, 1);
		  if (datalen > 0x7f || datalen > ehend - dataptr)
		    goto fail;
		  dataptr += datalen;
		}
	      }
	    }
	  }

	  tag->extendedflags = id3_parse_uint(&ptr, 1);

	  ptr = ehend;

	  if (tag->extendedflags & ID3_TAG_EXTENDEDFLAG_TAGISANUPDATE) {
	    bytes  = id3_parse_uint(&ehptr, 1);
	    ehptr += bytes;
	  }

	  if (tag->extendedflags & ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT) {
	    unsigned long crc;

	    bytes = id3_parse_uint(&ehptr, 1);
	    if (bytes < 5)
	      goto fail;

	    crc = id3_parse_syncsafe(&ehptr, 5);
	    ehptr += bytes - 5;

	    if (crc != id3_crc_compute(ptr, end - ptr))
	      goto fail;
	  }

	  if (tag->extendedflags & ID3_TAG_EXTENDEDFLAG_TAGRESTRICTIONS) {
	    bytes = id3_parse_uint(&ehptr, 1);
	    if (bytes < 1)
	      goto fail;

	    tag->restrictions = id3_parse_uint(&ehptr, 1);
	    ehptr += bytes - 1;
	  }
	}
	break;
      }
    }

    /* frames */

    while (ptr < end) {
      struct id3_frame *frame;

      if (*ptr == 0)
	break;  /* padding */

      frame = id3_frame_parse(&ptr, end - ptr, tag->version);
      if (frame == 0 || id3_tag_attachframe(tag, frame) == -1)
	goto fail;
    }

    if (ID3_TAG_VERSION_MAJOR(tag->version) < 4 &&
	id3_compat_fixup(tag) == -1)
      goto fail;
  }

  if (0) {
  fail:
    id3_tag_delete(tag);
    tag = 0;
  }

  if (mem)
    free(mem);

  return tag;
}
Ejemplo n.º 16
0
// returns buffer len; caller frees
int ExportMP2::AddTags(AudacityProject * WXUNUSED(project), char **buffer, bool *endOfFile, const Tags *tags)
{
#ifdef USE_LIBID3TAG
   struct id3_tag *tp = id3_tag_new();

   for (const auto &pair : tags->GetRange()) {
      const auto &n = pair.first;
      const auto &v = pair.second;
      const char *name = "TXXX";

      if (n.CmpNoCase(TAG_TITLE) == 0) {
         name = ID3_FRAME_TITLE;
      }
      else if (n.CmpNoCase(TAG_ARTIST) == 0) {
         name = ID3_FRAME_ARTIST;
      }
      else if (n.CmpNoCase(TAG_ALBUM) == 0) {
         name = ID3_FRAME_ALBUM;
      }
      else if (n.CmpNoCase(TAG_YEAR) == 0) {
         // LLL:  Some apps do not like the newer frame ID (ID3_FRAME_YEAR),
         //       so we add old one as well.
         AddFrame(tp, n, v, "TYER");
         name = ID3_FRAME_YEAR;
      }
      else if (n.CmpNoCase(TAG_GENRE) == 0) {
         name = ID3_FRAME_GENRE;
      }
      else if (n.CmpNoCase(TAG_COMMENTS) == 0) {
         name = ID3_FRAME_COMMENT;
      }
      else if (n.CmpNoCase(TAG_TRACK) == 0) {
         name = ID3_FRAME_TRACK;
      }

      AddFrame(tp, n, v, name);
   }

   tp->options &= (~ID3_TAG_OPTION_COMPRESSION); // No compression

   // If this version of libid3tag supports it, use v2.3 ID3
   // tags instead of the newer, but less well supported, v2.4
   // that libid3tag uses by default.
   #ifdef ID3_TAG_HAS_TAG_OPTION_ID3V2_3
   tp->options |= ID3_TAG_OPTION_ID3V2_3;
   #endif

   *endOfFile = false;

   id3_length_t len;

   len = id3_tag_render(tp, 0);
   *buffer = (char *)malloc(len);
   len = id3_tag_render(tp, (id3_byte_t *)*buffer);

   id3_tag_delete(tp);

   return len;
#else //ifdef USE_LIBID3TAG
   return 0;
#endif
}
Ejemplo n.º 17
0
static void mp3_parse_id3(struct mp3_data *data, size_t tagsize,
			  struct tag **mpd_tag)
{
#ifdef HAVE_ID3TAG
	struct id3_tag *id3_tag = NULL;
	id3_length_t count;
	id3_byte_t const *id3_data;
	id3_byte_t *allocated = NULL;

	count = data->stream.bufend - data->stream.this_frame;

	if (tagsize <= count) {
		id3_data = data->stream.this_frame;
		mad_stream_skip(&(data->stream), tagsize);
	} else {
		allocated = g_malloc(tagsize);
		memcpy(allocated, data->stream.this_frame, count);
		mad_stream_skip(&(data->stream), count);

		while (count < tagsize) {
			size_t len;

			len = decoder_read(data->decoder, data->input_stream,
					   allocated + count, tagsize - count);
			if (len == 0)
				break;
			else
				count += len;
		}

		if (count != tagsize) {
			g_debug("error parsing ID3 tag");
			g_free(allocated);
			return;
		}

		id3_data = allocated;
	}

	id3_tag = id3_tag_parse(id3_data, tagsize);
	if (id3_tag == NULL) {
		g_free(allocated);
		return;
	}

	if (mpd_tag) {
		struct tag *tmp_tag = tag_id3_import(id3_tag);
		if (tmp_tag != NULL) {
			if (*mpd_tag != NULL)
				tag_free(*mpd_tag);
			*mpd_tag = tmp_tag;
		}
	}

	if (data->decoder != NULL) {
		struct replay_gain_info rgi;
		char *mixramp_start;
		char *mixramp_end;
		float replay_gain_db = 0;

		if (parse_id3_replay_gain_info(&rgi, id3_tag)) {
			replay_gain_db = decoder_replay_gain(data->decoder, &rgi);
			data->found_replay_gain = true;
		}
		if (parse_id3_mixramp(&mixramp_start, &mixramp_end, id3_tag)) {
			g_debug("setting mixramp_tags");
			decoder_mixramp(data->decoder, replay_gain_db,
					mixramp_start, mixramp_end);
		}
	}

	id3_tag_delete(id3_tag);

	g_free(allocated);
#else /* !HAVE_ID3TAG */
	(void)mpd_tag;

	/* This code is enabled when libid3tag is disabled.  Instead
	   of parsing the ID3 frame, it just skips it. */

	size_t count = data->stream.bufend - data->stream.this_frame;

	if (tagsize <= count) {
		mad_stream_skip(&data->stream, tagsize);
	} else {
		mad_stream_skip(&data->stream, count);

		while (count < tagsize) {
			size_t len = tagsize - count;
			char ignored[1024];
			if (len > sizeof(ignored))
				len = sizeof(ignored);

			len = decoder_read(data->decoder, data->input_stream,
					   ignored, len);
			if (len == 0)
				break;
			else
				count += len;
		}
	}
#endif
}