示例#1
0
static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error)
{
	FLAC__byte buffer[4];
	const unsigned ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
	size_t block_num = 0;
	FLAC__ASSERT(sizeof(buffer) >= ID_LEN);
	while(block_num < fm->num_blocks) {
		/* find next matching padding block */
		do {
			/* even on the first chunk's loop there will be a skippable STREAMINFO block, on subsequent loops we are first moving past the PADDING we just used */
			if(!FLAC__metadata_simple_iterator_next(it)) {
				if(error) *error = "no matching PADDING block found (004)";
				return false;
			}
		} while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING);
		if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) {
			if(error) *error = "PADDING block with wrong size found (005)";
			return false;
		}
		/* transfer chunk into APPLICATION block */
		/* first set up the file pointers */
		if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) {
			if(error) *error = "seek failed in WAVE/AIFF file (006)";
			return false;
		}
		if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) {
			if(error) *error = "seek failed in FLAC file (007)";
			return false;
		}
		/* update the type */
		buffer[0] = FLAC__METADATA_TYPE_APPLICATION;
		if(FLAC__metadata_simple_iterator_is_last(it))
			buffer[0] |= 0x80; /*MAGIC number*/
		if(fwrite(buffer, 1, 1, fout) < 1) {
			if(error) *error = "write failed in FLAC file (008)";
			return false;
		}
		/* length stays the same so skip over it */
		if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) {
			if(error) *error = "seek failed in FLAC file (009)";
			return false;
		}
		/* write the APPLICATION ID */
		memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN);
		if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) {
			if(error) *error = "write failed in FLAC file (010)";
			return false;
		}
		/* transfer the foreign metadata */
		if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)"))
			return false;
		block_num++;
	}
	return true;
}
示例#2
0
int flac_write( const char* filename, const char *predicate, const char* uri )
{
	if (strcmp(predicate, LL_LICENSE) != 0) {
		return -LL_E_MODULE_WRITE_FAIL; /* We only know License */
	}
	int ret = 1;

	FLAC__Metadata_SimpleIterator *iter = FLAC__metadata_simple_iterator_new();
	if (FLAC__metadata_simple_iterator_init(iter,filename,false,false) && FLAC__metadata_simple_iterator_is_writable(iter)) {
		FLAC__bool found_vc = false;
		do {
			if (FLAC__metadata_simple_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
				FLAC__StreamMetadata *vc;

				found_vc = true;
				vc = FLAC__metadata_simple_iterator_get_block(iter);

				if (uri) {
					FLAC__StreamMetadata_VorbisComment_Entry entry;
					FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "LICENSE", uri);
					FLAC__metadata_object_vorbiscomment_replace_comment(vc,entry,true,false);
				} else {
					int i = FLAC__metadata_object_vorbiscomment_find_entry_from(vc,0,"LICENSE");
					if (i != -1) {
						FLAC__metadata_object_vorbiscomment_delete_comment(vc,i);
					}
				}

				ret = FLAC__metadata_simple_iterator_set_block(iter, vc, true);
				FLAC__metadata_object_delete(vc);
				break;
			}
		} while (FLAC__metadata_simple_iterator_next(iter));

		if (!found_vc && uri) {
			FLAC__StreamMetadata *vc = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);

			FLAC__StreamMetadata_VorbisComment_Entry entry;
			FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "LICENSE", uri);
			FLAC__metadata_object_vorbiscomment_append_comment(vc,entry,false);

			ret = FLAC__metadata_simple_iterator_insert_block_after(iter,vc,true);
			FLAC__metadata_object_delete(vc);
		}
	} else {
		ret = 0;
	}

	FLAC__metadata_simple_iterator_delete(iter);

	return ret;
}
示例#3
0
文件: id3.c 项目: tedkulp/bossogg
/* FLAC implementation. notice, it uses the ogg functions
   when the FLAC comment is extracted */
static text_tag_s *get_flac_text_tag (const char *filename)
{
  text_tag_s *text_tag = new_text_tag ();
  char buf[256];
  FLAC__StreamMetadata *metadata = malloc (sizeof (FLAC__StreamMetadata));
  FLAC__Metadata_SimpleIterator *iter = FLAC__metadata_simple_iterator_new ();
  if (FLAC__metadata_simple_iterator_init (iter, filename, true, false) != true) {
	snprintf (buf, 256, "Problem reading file \'%s\'", filename);
	log_msg (buf, FL, FN, LN);
	free (metadata);
	FLAC__metadata_simple_iterator_delete (iter);
	free_text_tag (text_tag);
	return NULL;
  }

  do {
	int i = 0;
	
	switch (FLAC__metadata_simple_iterator_get_block_type (iter)) {
	case FLAC__METADATA_TYPE_STREAMINFO:
	  metadata = FLAC__metadata_simple_iterator_get_block (iter);
	  
	  text_tag->frequency = metadata->data.stream_info.sample_rate;
	  text_tag->songlength = metadata->data.stream_info.total_samples /
		metadata->data.stream_info.sample_rate;
	  text_tag->bitrate = (int)((metadata->data.stream_info.total_samples *
								 metadata->data.stream_info.bits_per_sample) / text_tag->songlength);
	  break;
	case FLAC__METADATA_TYPE_VORBIS_COMMENT:
	  metadata = FLAC__metadata_simple_iterator_get_block (iter);

	  for (i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
		int type = get_ogg_type (metadata->data.vorbis_comment.comments[i].entry);
		parse_ogg_content (metadata->data.vorbis_comment.comments[i].entry, metadata->data.vorbis_comment.comments[i].length, &text_tag, type);
	  }
	  
	  break;
	default:
	  //printf ("Unhandled metadata type\n");
	  break;
	}
  } while (FLAC__metadata_simple_iterator_next (iter) == true);

  fill_null_text_tag (text_tag);
  
  FLAC__metadata_simple_iterator_delete (iter);
  free (metadata);
		   
  return text_tag;
}
示例#4
0
static PyObject *
flac_MetadataSimpleIterator_next (flac_MetadataSimpleIteratorObject *self)
{
	PyFLAC_CHECK_initialized(self);

	self->next = true;

	if (FLAC__metadata_simple_iterator_next(self->iterator))
		Py_RETURN_TRUE;

	if (flac_MetadataSimpleIterator_PyErr_FromIteratorStatus(self) < 0)
		return NULL;

	Py_RETURN_FALSE;
}
示例#5
0
static PyObject *
flac_MetadataSimpleIterator_get_next_block (flac_MetadataSimpleIteratorObject *self)
{
#ifndef __PyFLAC3__
	self = ((flac_MetadataSimpleIteratorIterObject *) self)->parent;
#endif // __PyFLAC3__

	PyFLAC_CHECK_initialized(self);

	if (self->next && !FLAC__metadata_simple_iterator_next(self->iterator))
	{
		flac_MetadataSimpleIterator_PyErr_FromIteratorStatus(self);
		return NULL;
	}

	self->next = true;
	return flac_MetadataSimpleIterator__get_block(self);
}
示例#6
0
void FLAC_plugin__vorbiscomment_get(const char *filename, FLAC_Plugin__CanonicalTag *tag)
{
	FLAC__Metadata_SimpleIterator *iterator = FLAC__metadata_simple_iterator_new();
	if(0 != iterator) {
		if(FLAC__metadata_simple_iterator_init(iterator, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) {
			FLAC__bool got_vorbis_comments = false;
			do {
				if(FLAC__metadata_simple_iterator_get_block_type(iterator) == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
					FLAC__StreamMetadata *block = FLAC__metadata_simple_iterator_get_block(iterator);
					if(0 != block) {
						unsigned i;
						const FLAC__StreamMetadata_VorbisComment *vc = &block->data.vorbis_comment;
						for(i = 0; i < vc->num_comments; i++) {
							if(local__vcentry_matches("artist", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->composer);
							else if(local__vcentry_matches("performer", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->performer);
							else if(local__vcentry_matches("album", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->album);
							else if(local__vcentry_matches("title", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->title);
							else if(local__vcentry_matches("tracknumber", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->track_number);
							else if(local__vcentry_matches("genre", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->genre);
							else if(local__vcentry_matches("description", &vc->comments[i]))
								local__vcentry_parse_value(&vc->comments[i], &tag->comment);
						}
						FLAC__metadata_object_delete(block);
						got_vorbis_comments = true;
					}
				}
			} while (!got_vorbis_comments && FLAC__metadata_simple_iterator_next(iterator));
		}
		FLAC__metadata_simple_iterator_delete(iterator);
	}
}
示例#7
0
文件: replaygain.c 项目: ACUVE/flac
FLAC__bool FLAC_plugin__replaygain_get_from_file(const char *filename,
                                                 double *reference, FLAC__bool *reference_set,
                                                 double *track_gain, FLAC__bool *track_gain_set,
                                                 double *album_gain, FLAC__bool *album_gain_set,
                                                 double *track_peak, FLAC__bool *track_peak_set,
                                                 double *album_peak, FLAC__bool *album_peak_set)
{
	FLAC__Metadata_SimpleIterator *iterator = FLAC__metadata_simple_iterator_new();
	FLAC__bool ret = false;

	*track_gain_set = *album_gain_set = *track_peak_set = *album_peak_set = false;

	if(0 != iterator) {
		if(FLAC__metadata_simple_iterator_init(iterator, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) {
			FLAC__bool got_vorbis_comments = false;
			ret = true;
			do {
				if(FLAC__metadata_simple_iterator_get_block_type(iterator) == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
					FLAC__StreamMetadata *block = FLAC__metadata_simple_iterator_get_block(iterator);
					if(0 != block) {
						if(grabbag__replaygain_load_from_vorbiscomment(block, /*album_mode=*/false, /*strict=*/true, reference, track_gain, track_peak)) {
							*reference_set = *track_gain_set = *track_peak_set = true;
						}
						if(grabbag__replaygain_load_from_vorbiscomment(block, /*album_mode=*/true, /*strict=*/true, reference, album_gain, album_peak)) {
							*reference_set = *album_gain_set = *album_peak_set = true;
						}
						FLAC__metadata_object_delete(block);
						got_vorbis_comments = true;
					}
				}
			} while (!got_vorbis_comments && FLAC__metadata_simple_iterator_next(iterator));
		}
		FLAC__metadata_simple_iterator_delete(iterator);
	}
	return ret;
}
示例#8
0
static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error)
{
	FLAC__byte id[4], buffer[12];
	FLAC__off_t offset;
	FLAC__bool type_found = false, ds64_found = false;

	FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8);

	while(FLAC__metadata_simple_iterator_next(it)) {
		if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION)
			continue;
		if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) {
			if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (002)";
			return false;
		}
		if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id)))
			continue;
		offset = FLAC__metadata_simple_iterator_get_block_offset(it);
		/* skip over header and app ID */
		offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
		offset += sizeof(id);
		/* look for format or audio blocks */
		if(fseeko(f, offset, SEEK_SET) < 0) {
			if(error) *error = "seek error (003)";
			return false;
		}
		if(fread(buffer, 1, 4, f) != 4) {
			if(error) *error = "read error (004)";
			return false;
		}
		if(fm->num_blocks == 0) { /* first block? */
			fm->is_rf64 = 0 == memcmp(buffer, "RF64", 4);
			if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && (0 == memcmp(buffer, "RIFF", 4) || fm->is_rf64))
				type_found = true;
			else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64 && 0 == memcmp(buffer, "riff", 4)) /* use first 4 bytes instead of whole GUID */
				type_found = true;
			else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4))
				type_found = true;
			else {
				if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)";
				return false;
			}
		}
		else if(!type_found) {
			FLAC__ASSERT(0);
			/* double protection: */
			if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)";
			return false;
		}
		else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) {
			if(!memcmp(buffer, "fmt ", 4)) {
				if(fm->format_block) {
					if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)";
					return false;
				}
				if(fm->audio_block) {
					if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)";
					return false;
				}
				fm->format_block = fm->num_blocks;
			}
			else if(!memcmp(buffer, "data", 4)) {
				if(fm->audio_block) {
					if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)";
					return false;
				}
				if(!fm->format_block) {
					if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)";
					return false;
				}
				fm->audio_block = fm->num_blocks;
			}
			else if(fm->is_rf64 && fm->num_blocks == 1) {
				if(memcmp(buffer, "ds64", 4)) {
					if(error) *error = "invalid RF64 metadata: second chunk is not \"ds64\" (011)";
					return false;
				}
				ds64_found = true;
			}
		}
		else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64) {
			if(!memcmp(buffer, "fmt ", 4)) { /* use first 4 bytes instead of whole GUID */
				if(fm->format_block) {
					if(error) *error = "invalid Wave64 metadata: multiple \"fmt \" chunks (012)";
					return false;
				}
				if(fm->audio_block) {
					if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (013)";
					return false;
				}
				fm->format_block = fm->num_blocks;
			}
			else if(!memcmp(buffer, "data", 4)) { /* use first 4 bytes instead of whole GUID */
				if(fm->audio_block) {
					if(error) *error = "invalid Wave64 metadata: multiple \"data\" chunks (014)";
					return false;
				}
				if(!fm->format_block) {
					if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (015)";
					return false;
				}
				fm->audio_block = fm->num_blocks;
			}
		}
		else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) {
			if(!memcmp(buffer, "COMM", 4)) {
				if(fm->format_block) {
					if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (016)";
					return false;
				}
				if(fm->audio_block) {
					if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (017)";
					return false;
				}
				fm->format_block = fm->num_blocks;
			}
			else if(!memcmp(buffer, "SSND", 4)) {
				if(fm->audio_block) {
					if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (018)";
					return false;
				}
				if(!fm->format_block) {
					if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (019)";
					return false;
				}
				fm->audio_block = fm->num_blocks;
				/* read SSND offset size */
				if(fread(buffer+4, 1, 8, f) != 8) {
					if(error) *error = "read error (020)";
					return false;
				}
				fm->ssnd_offset_size = unpack32be_(buffer+8);
			}
		}
		else {
			FLAC__ASSERT(0);
			/* double protection: */
			if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (021)";
			return false;
		}
		if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error))
			return false;
	}
	if(!type_found) {
		if(error) *error = "no foreign metadata found (022)";
		return false;
	}
	if(fm->is_rf64 && !ds64_found) {
		if(error) *error = "invalid RF64 file: second chunk is not \"ds64\" (023)";
		return false;
	}
	if(!fm->format_block) {
		if(error)
			*error =
				fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (024)" :
				fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"fmt \" chunk (025)" :
				"invalid AIFF file: missing \"COMM\" chunk (026)";
		return false;
	}
	if(!fm->audio_block) {
		if(error)
			*error =
				fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (027)" :
				fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"data\" chunk (028)" :
				"invalid AIFF file: missing \"SSND\" chunk (029)";
		return false;
	}
	return true;
}
示例#9
0
static int
_get_flctags(char *filename, struct song_metadata *psong)
{
	FLAC__Metadata_SimpleIterator *iterator = 0;
	FLAC__StreamMetadata *block;
	int block_number;
	unsigned int sec, ms;
	int i;
	int err = 0;

	if(!(iterator = FLAC__metadata_simple_iterator_new()))
	{
		DPRINTF(E_FATAL, L_SCANNER, "Out of memory while FLAC__metadata_simple_iterator_new()\n");
		return -1;
	}

	block_number = 0;
	if(!FLAC__metadata_simple_iterator_init(iterator, filename, true, true))
	{
		DPRINTF(E_ERROR, L_SCANNER, "Cannot extract tag from %s\n", filename);
		return -1;
	}

	do {
		if(!(block = FLAC__metadata_simple_iterator_get_block(iterator)))
		{
			DPRINTF(E_ERROR, L_SCANNER, "Cannot extract tag from %s\n", filename);
			err = -1;
			goto _exit;
		}

		switch(block->type)
		{
		case FLAC__METADATA_TYPE_STREAMINFO:
			sec = (unsigned int)(block->data.stream_info.total_samples /
			                     block->data.stream_info.sample_rate);
			ms = (unsigned int)(((block->data.stream_info.total_samples %
			                      block->data.stream_info.sample_rate) * 1000) /
			                      block->data.stream_info.sample_rate);
			if ((sec == 0) && (ms == 0))
				break; /* Info is crap, escape div-by-zero. */
			psong->song_length = (sec * 1000) + ms;
			psong->bitrate = (((uint64_t)(psong->file_size) * 1000) / (psong->song_length / 8));
			psong->samplerate = block->data.stream_info.sample_rate;
			psong->channels = block->data.stream_info.channels;
			break;

		case FLAC__METADATA_TYPE_VORBIS_COMMENT:
			for(i = 0; i < block->data.vorbis_comment.num_comments; i++)
			{
				vc_scan(psong,
					(char*)block->data.vorbis_comment.comments[i].entry,
					block->data.vorbis_comment.comments[i].length);
			}
			break;
#if FLAC_API_VERSION_CURRENT >= 10
		case FLAC__METADATA_TYPE_PICTURE:
			psong->image_size = block->data.picture.data_length;
			if((psong->image = malloc(psong->image_size)))
				memcpy(psong->image, block->data.picture.data, psong->image_size);
			else
				DPRINTF(E_ERROR, L_SCANNER, "Out of memory [%s]\n", filename);
			break;
#endif
		default:
			break;
		}
		FLAC__metadata_object_delete(block);
	}
	while(FLAC__metadata_simple_iterator_next(iterator));

 _exit:
	if(iterator)
		FLAC__metadata_simple_iterator_delete(iterator);

	return err;
}
示例#10
0
/*
 * Read tag data from a FLAC file using the level 1 flac interface,
 * Note:
 *  - if field is found but contains no info (strlen(str)==0), we don't read it
 */
gboolean Flac_Tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
{
    FLAC__Metadata_SimpleIterator *iter;
    gchar *string = NULL;
    gchar *filename_utf8 = filename_to_display(filename);
    guint i;
#ifndef LEGACY_FLAC // For FLAC >= 1.1.3
    Picture *prev_pic = NULL;
#endif
    //gint j = 1;


    if (!filename || !FileTag)
        return FALSE;

    flac_error_msg = NULL;

    // Initialize the iterator for the blocks
    iter = FLAC__metadata_simple_iterator_new();
    if ( iter == NULL || !FLAC__metadata_simple_iterator_init(iter, filename, true, false) )
    {
        if ( iter == NULL )
        {
            // Error with "FLAC__metadata_simple_iterator_new"
            flac_error_msg = FLAC__Metadata_SimpleIteratorStatusString[FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR];
        } else
        {
            // Error with "FLAC__metadata_simple_iterator_init"
            FLAC__Metadata_SimpleIteratorStatus status = FLAC__metadata_simple_iterator_status(iter);
            flac_error_msg = FLAC__Metadata_SimpleIteratorStatusString[status];

            FLAC__metadata_simple_iterator_delete(iter);
        }

        Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' as FLAC (%s)."),filename_utf8,flac_error_msg);
        g_free(filename_utf8);
        return FALSE;
    }


    /* libFLAC is able to detect (and skip) ID3v2 tags by itself */

    while (FLAC__metadata_simple_iterator_next(iter))
    {
        // Get block data
        FLAC__StreamMetadata *block = FLAC__metadata_simple_iterator_get_block(iter);
        //g_print("Read: %d %s -> block type: %d\n",j++,g_path_get_basename(filename),FLAC__metadata_simple_iterator_get_block_type(iter));

        // Action to do according the type
        switch ( FLAC__metadata_simple_iterator_get_block_type(iter) )
        {
        //
        // Read the VORBIS_COMMENT block (only one should exist)
        //
        case FLAC__METADATA_TYPE_VORBIS_COMMENT:
        {
            FLAC__StreamMetadata_VorbisComment       *vc;
            FLAC__StreamMetadata_VorbisComment_Entry *field;
            gint   field_num;
            gint   field_len;
            gchar *field_value;
            gchar *field_value_tmp;

            // Get comments from block
            vc = &block->data.vorbis_comment;

            /*********
             * Title *
             *********/
            field_num = 0;
            while ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"TITLE")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num++];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (FileTag->title==NULL)
                            FileTag->title = g_strdup(field_value);
                        else
                            FileTag->title = g_strconcat(FileTag->title,MULTIFIELD_SEPARATOR,field_value,NULL);
                        g_free(field_value);
                    }
                }
            }

            /**********
             * Artist *
             **********/
            field_num = 0;
            while ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"ARTIST")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num++];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (FileTag->artist==NULL)
                            FileTag->artist = g_strdup(field_value);
                        else
                            FileTag->artist = g_strconcat(FileTag->artist,MULTIFIELD_SEPARATOR,field_value,NULL);
                        g_free(field_value);
                    }
                }
            }

            /*********
             * Album *
             *********/
            field_num = 0;
            while ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"ALBUM")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num++];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (FileTag->album==NULL)
                            FileTag->album = g_strdup(field_value);
                        else
                            FileTag->album = g_strconcat(FileTag->album,MULTIFIELD_SEPARATOR,field_value,NULL);
                        g_free(field_value);
                    }
                }
            }

            /***************
             * Disc Number *
             ***************/
            if ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"DISCNUMBER")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        FileTag->disc_number = field_value;
                    }
                }
            }

            /********
             * Year *
             ********/
            if ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"DATE")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        FileTag->year = field_value;
                        if (g_utf8_strlen(FileTag->year, -1) > 4)
                            Log_Print(LOG_WARNING,_("The year value '%s' seems to be invalid in file '%s'. The information will be lost while saving tag."),FileTag->year,filename_utf8);
                    }
                }
            }

            /*************************
             * Track and Total Track *
             *************************/
            if ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"TRACKTOTAL")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (NUMBER_TRACK_FORMATED)
                        {
                            FileTag->track_total = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(field_value));
                        } else
                        {
                            FileTag->track_total = g_strdup(field_value);
                        }
                        g_free(field_value);
                    }
                }
                // Below is also filled track_total if not done here
            }

            if ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,0,"TRACKNUMBER")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        string = g_utf8_strchr(field_value, -1, '/');
                        if (NUMBER_TRACK_FORMATED)
                        {
                            // If track_total not filled before, try now...
                            if (string && !FileTag->track_total)
                            {
                                FileTag->track_total = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string+1));
                                *string = '\0';
                            }
                            FileTag->track = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(field_value));
                        } else
                        {
                            if (string && !FileTag->track_total)
                            {
                                FileTag->track_total = g_strdup(string+1);
                                *string = '\0';
                            }
                            FileTag->track = g_strdup(field_value);
                        }
                        g_free(field_value);
                    }
                }
            }

            /*********
             * Genre *
             *********/
            field_num = 0;
            while ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"GENRE")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num++];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (FileTag->genre==NULL)
                            FileTag->genre = g_strdup(field_value);
                        else
                            FileTag->genre = g_strconcat(FileTag->genre,MULTIFIELD_SEPARATOR,field_value,NULL);
                        g_free(field_value);
                    }
                }
            }

            /***********
             * Comment *
             ***********/
            field_num = 0;
            while ( 1 )
            {
                gint field_num1, field_num2;

                // The comment field can take two forms...
                field_num1 = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"DESCRIPTION");
                field_num2 = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"COMMENT");

                if (field_num1 >= 0 && field_num2 >= 0)
                    // Note : We set field_num to the last "comment" field to avoid to concatenate
                    // the DESCRIPTION and COMMENT field if there are both present (EasyTAG writes the both...)
                    if (field_num1 < field_num2)
                        field_num = field_num2;
                    else
                        field_num = field_num1;
                else if (field_num1 >= 0)
                    field_num = field_num1;
                else if (field_num2 >= 0)
                    field_num = field_num2;
                else
                    break;

                /* Extract field value */
                field = &vc->comments[field_num++];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (FileTag->comment==NULL)
                            FileTag->comment = g_strdup(field_value);
                        else
                            FileTag->comment = g_strconcat(FileTag->comment,MULTIFIELD_SEPARATOR,field_value,NULL);
                        g_free(field_value);
                    }
                }
            }

            /************
             * Composer *
             ************/
            field_num = 0;
            while ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"COMPOSER")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num++];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (FileTag->composer==NULL)
                            FileTag->composer = g_strdup(field_value);
                        else
                            FileTag->composer = g_strconcat(FileTag->composer,MULTIFIELD_SEPARATOR,field_value,NULL);
                        g_free(field_value);
                    }
                }
            }

            /*******************
             * Original artist *
             *******************/
            field_num = 0;
            while ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"PERFORMER")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num++];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (FileTag->orig_artist==NULL)
                            FileTag->orig_artist = g_strdup(field_value);
                        else
                            FileTag->orig_artist = g_strconcat(FileTag->orig_artist,MULTIFIELD_SEPARATOR,field_value,NULL);
                        g_free(field_value);
                    }
                }
            }

            /*************
             * Copyright *
             *************/
            field_num = 0;
            while ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"COPYRIGHT")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num++];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (FileTag->copyright==NULL)
                            FileTag->copyright = g_strdup(field_value);
                        else
                            FileTag->copyright = g_strconcat(FileTag->copyright,MULTIFIELD_SEPARATOR,field_value,NULL);
                        g_free(field_value);
                    }
                }
            }

            /*******
             * URL *
             *******/
            field_num = 0;
            while ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"LICENSE")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num++];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (FileTag->url==NULL)
                            FileTag->url = g_strdup(field_value);
                        else
                            FileTag->url = g_strconcat(FileTag->url,MULTIFIELD_SEPARATOR,field_value,NULL);
                        g_free(field_value);
                    }
                }
            }

            /**************
             * Encoded by *
             **************/
            field_num = 0;
            while ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(block,field_num,"ENCODED-BY")) >= 0 )
            {
                /* Extract field value */
                field = &vc->comments[field_num++];
                field_value = memchr(field->entry, '=', field->length);

                if (field_value)
                {
                    field_value++;
                    if ( field_value && g_utf8_strlen(field_value, -1) > 0 )
                    {
                        field_len = field->length - (field_value - (gchar*) field->entry);
                        field_value_tmp = g_strndup(field_value, field_len);
                        field_value = Try_To_Validate_Utf8_String(field_value_tmp);
                        g_free(field_value_tmp);
                        if (FileTag->encoded_by==NULL)
                            FileTag->encoded_by = g_strdup(field_value);
                        else
                            FileTag->encoded_by = g_strconcat(FileTag->encoded_by,MULTIFIELD_SEPARATOR,field_value,NULL);
                        g_free(field_value);
                    }
                }
            }

            /***************************
             * Save unsupported fields *
             ***************************/
            for (i=0; i<(guint)vc->num_comments; i++)
            {
                field = &vc->comments[i];
                if ( strncasecmp((gchar *)field->entry,"TITLE=",       MIN(6,  field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"ARTIST=",      MIN(7,  field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"ALBUM=",       MIN(6,  field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"DISCNUMBER=",  MIN(11, field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"DATE=",        MIN(5,  field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"TRACKNUMBER=", MIN(12, field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"TRACKTOTAL=",  MIN(11, field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"GENRE=",       MIN(6,  field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"DESCRIPTION=", MIN(12, field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"COMMENT=",     MIN(8,  field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"COMPOSER=",    MIN(9,  field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"PERFORMER=",   MIN(10, field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"COPYRIGHT=",   MIN(10, field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"LICENSE=",     MIN(8,  field->length)) != 0
                        && strncasecmp((gchar *)field->entry,"ENCODED-BY=",  MIN(11, field->length)) != 0 )
                {
                    //g_print("custom %*s\n", field->length, field->entry);
                    FileTag->other = g_list_append(FileTag->other,g_strndup((const gchar *)field->entry, field->length));
                }
            }

            break;
        }


            //
            // Read the PICTURE block (severals can exist)
            //
#ifndef LEGACY_FLAC // For FLAC >= 1.1.3
        case FLAC__METADATA_TYPE_PICTURE:
        {

            /***********
             * Picture *
             ***********/
            FLAC__StreamMetadata_Picture *p;
            Picture *pic;

            // Get picture data from block
            p = &block->data.picture;

            pic = Picture_Allocate();
            if (!prev_pic)
                FileTag->picture = pic;
            else
                prev_pic->next = pic;
            prev_pic = pic;

            pic->size = p->data_length;
            pic->data = g_memdup(p->data,pic->size);
            pic->type = p->type;
            pic->description = g_strdup((gchar *)p->description);
            // Not necessary: will be calculated later
            //pic->height = p->height;
            //pic->width  = p->width;

            //g_print("Picture type : %s\n",FLAC__StreamMetadata_Picture_TypeString[p->type]);
            //g_print("Mime    type : %s\n",p->mime_type);

            break;
        }
#endif

        default:
            break;
        }

        // Free block data
        //FLAC__metadata_object_delete(block);
    }

    // Free iter
    FLAC__metadata_simple_iterator_delete(iter);


#ifdef ENABLE_MP3
    /* If no FLAC vorbis tag found : we try to get the ID3 tag if it exists
     * (but it will be deleted when rewriting the tag) */
    if ( FileTag->title       == NULL
            && FileTag->artist      == NULL
            && FileTag->album       == NULL
            && FileTag->disc_number == NULL
            && FileTag->year        == NULL
            && FileTag->track       == NULL
            && FileTag->track_total == NULL
            && FileTag->genre       == NULL
            && FileTag->comment     == NULL
            && FileTag->composer    == NULL
            && FileTag->orig_artist == NULL
            && FileTag->copyright   == NULL
            && FileTag->url         == NULL
            && FileTag->encoded_by  == NULL
            && FileTag->picture     == NULL)
    {
        gint rc = Id3tag_Read_File_Tag(filename,FileTag);

        // If an ID3 tag has been found (and no FLAC tag), we mark the file as
        // unsaved to rewrite a flac tag.
        if ( FileTag->title       != NULL
                || FileTag->artist      != NULL
                || FileTag->album       != NULL
                || FileTag->disc_number != NULL
                || FileTag->year        != NULL
                || FileTag->track       != NULL
                || FileTag->track_total != NULL
                || FileTag->genre       != NULL
                || FileTag->comment     != NULL
                || FileTag->composer    != NULL
                || FileTag->orig_artist != NULL
                || FileTag->copyright   != NULL
                || FileTag->url         != NULL
                || FileTag->encoded_by  != NULL
                || FileTag->picture     != NULL)
        {
            FileTag->saved = FALSE;
        }

        g_free(filename_utf8);
        return rc;
    }

    /* Part to get cover artist :
     * If we have read the ID3 tag previously we don't arrive here (and we have
     * the picture if it exists).
     * Else the ID3 tag wasn't read (as there was data in FLAC tag) so we try
     * to read it only to get the picture (not supported by the FLAC tag). */
    /***if (WRITE_ID3_TAGS_IN_FLAC_FILE && FileTag->picture == NULL)
    {
        File_Tag *FileTag_tmp = ET_File_Tag_Item_New();
        gint rc = Id3tag_Read_File_Tag(filename,FileTag_tmp);
        if (rc && FileTag_tmp->picture)
        {
            // Copy picture to FileTag
            FileTag->picture = Picture_Copy(FileTag_tmp->picture);
        }

        ET_Free_File_Tag_Item(FileTag_tmp);

        return rc;
    }***/
#endif

    g_free(filename_utf8);
    return TRUE;
}
示例#11
0
G_MODULE_EXPORT gboolean
tracker_extract_get_metadata (TrackerExtractInfo *info)
{
	FLAC__Metadata_SimpleIterator *iter;
	FLAC__StreamMetadata *stream = NULL, *vorbis, *picture;
	FLAC__bool success;
	FlacData fd = { 0 };
	TrackerSparqlBuilder *preupdate, *metadata;
	gchar *filename, *uri, *artist_uri = NULL, *album_uri = NULL;
	const gchar *creator;
	GFile *file;
	goffset size;
	const gchar *graph;

	graph = tracker_extract_info_get_graph (info);
	preupdate = tracker_extract_info_get_preupdate_builder (info);
	metadata = tracker_extract_info_get_metadata_builder (info);

	file = tracker_extract_info_get_file (info);
	filename = g_file_get_path (file);

	size = tracker_file_get_size (filename);

	if (size < 18) {
		g_free (filename);
		return FALSE;
	}

	iter = FLAC__metadata_simple_iterator_new ();
	success = FLAC__metadata_simple_iterator_init (iter, filename, TRUE, TRUE);
	g_free (filename);

	if (!success) {
		FLAC__metadata_simple_iterator_delete (iter);
		return FALSE;
	}

	uri = g_file_get_uri (file);

	do {
		switch (FLAC__metadata_simple_iterator_get_block_type (iter)) {
		case FLAC__METADATA_TYPE_STREAMINFO:
			stream = FLAC__metadata_simple_iterator_get_block (iter);
			break;

		case FLAC__METADATA_TYPE_VORBIS_COMMENT:
			vorbis = FLAC__metadata_simple_iterator_get_block (iter);
			parse_vorbis_comments (&(vorbis->data.vorbis_comment), &fd);
			FLAC__metadata_object_delete (vorbis);
			break;

		case FLAC__METADATA_TYPE_PICTURE:
			picture = FLAC__metadata_simple_iterator_get_block (iter);
			/* Deal with picture */
			FLAC__metadata_object_delete (picture);
			break;

		default:
			break;
		}
	} while (FLAC__metadata_simple_iterator_next (iter));

	creator = tracker_coalesce_strip (3, fd.artist, fd.albumartist,
	                                  fd.performer);

	if (creator) {
		artist_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", creator);

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, artist_uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nmm:Artist");
		tracker_sparql_builder_predicate (preupdate, "nmm:artistName");
		tracker_sparql_builder_object_unvalidated (preupdate, creator);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

	}

	if (fd.album) {
                if (fd.albumartist) {
                        album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s:%s", fd.album, fd.albumartist);
                } else {
                        album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s", fd.album);
                }
		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, album_uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nmm:MusicAlbum");
		/* FIXME: nmm:albumTitle is now deprecated
		 * tracker_sparql_builder_predicate (preupdate, "nie:title");
		 */
		tracker_sparql_builder_predicate (preupdate, "nmm:albumTitle");
		tracker_sparql_builder_object_unvalidated (preupdate, fd.album);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		if (fd.trackcount) {
			tracker_sparql_builder_delete_open (preupdate, NULL);
			tracker_sparql_builder_subject_iri (preupdate, album_uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_delete_close (preupdate);

			tracker_sparql_builder_where_open (preupdate);
			tracker_sparql_builder_subject_iri (preupdate, album_uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_where_close (preupdate);

			tracker_sparql_builder_insert_open (preupdate, NULL);
			if (graph) {
				tracker_sparql_builder_graph_open (preupdate, graph);
			}

			tracker_sparql_builder_subject_iri (preupdate, album_uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
			tracker_sparql_builder_object_unvalidated (preupdate, fd.trackcount);

			if (graph) {
				tracker_sparql_builder_graph_close (preupdate);
			}
			tracker_sparql_builder_insert_close (preupdate);
		}

		if (fd.albumgain) {
			tracker_sparql_builder_delete_open (preupdate, NULL);
			tracker_sparql_builder_subject_iri (preupdate, album_uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_delete_close (preupdate);
			tracker_sparql_builder_where_open (preupdate);
			tracker_sparql_builder_subject_iri (preupdate, album_uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_where_close (preupdate);

			tracker_sparql_builder_insert_open (preupdate, NULL);
			if (graph) {
				tracker_sparql_builder_graph_open (preupdate, graph);
			}

			tracker_sparql_builder_subject_iri (preupdate, album_uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
			tracker_sparql_builder_object_double (preupdate, atof (fd.albumgain));

			if (graph) {
				tracker_sparql_builder_graph_close (preupdate);
			}
			tracker_sparql_builder_insert_close (preupdate);
		}

		if (fd.albumpeakgain) {
			tracker_sparql_builder_delete_open (preupdate, NULL);
			tracker_sparql_builder_subject_iri (preupdate, album_uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_delete_close (preupdate);
			tracker_sparql_builder_where_open (preupdate);
			tracker_sparql_builder_subject_iri (preupdate, album_uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_where_close (preupdate);

			tracker_sparql_builder_insert_open (preupdate, NULL);
			if (graph) {
				tracker_sparql_builder_graph_open (preupdate, graph);
			}

			tracker_sparql_builder_subject_iri (preupdate, album_uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
			tracker_sparql_builder_object_double (preupdate, atof (fd.albumpeakgain));

			if (graph) {
				tracker_sparql_builder_graph_close (preupdate);
			}
			tracker_sparql_builder_insert_close (preupdate);
		}
	}

	tracker_sparql_builder_predicate (metadata, "a");
	tracker_sparql_builder_object (metadata, "nmm:MusicPiece");
	tracker_sparql_builder_object (metadata, "nfo:Audio");

	add_tuple (metadata, "nmm:performer", artist_uri);
	g_free (artist_uri);

	add_tuple (metadata, "nmm:musicAlbum", album_uri);

	tracker_guarantee_title_from_file (metadata, "nie:title", fd.title, uri, NULL);
	add_tuple (metadata, "nmm:trackNumber", fd.tracknumber);

	if (fd.album && album_uri) {
		gchar *album_disc_uri;
                if (fd.albumartist) {
                        album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:%s:Disc%d",
                                                                           fd.album, fd.albumartist,
                                                                           fd.discno ? atoi(fd.discno) : 1);
                } else {
                        album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d",
                                                                           fd.album,
                                                                           fd.discno ? atoi(fd.discno) : 1);
                }

		tracker_sparql_builder_delete_open (preupdate, NULL);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_delete_close (preupdate);
		tracker_sparql_builder_where_open (preupdate);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_where_close (preupdate);

		tracker_sparql_builder_delete_open (preupdate, NULL);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_delete_close (preupdate);
		tracker_sparql_builder_where_open (preupdate);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_where_close (preupdate);

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nmm:MusicAlbumDisc");
		tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
		tracker_sparql_builder_object_int64 (preupdate, fd.discno ? atoi (fd.discno) : 1);
		tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum");
		tracker_sparql_builder_object_iri (preupdate, album_uri);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		tracker_sparql_builder_predicate (metadata, "nmm:musicAlbumDisc");
		tracker_sparql_builder_object_iri (metadata, album_disc_uri);

		g_free (album_disc_uri);
	}

	g_free (album_uri);

	/* FIXME: Trackgain/Trackpeakgain: commented out in vorbis */

	add_tuple (metadata, "nie:comment", fd.comment);
	add_tuple (metadata, "nie:contentCreated", fd.date);
	add_tuple (metadata, "nfo:genre", fd.genre);
	add_tuple (metadata, "nie:plainTextContent", fd.lyrics);
	add_tuple (metadata, "nie:copyright", fd.copyright);
	add_tuple (metadata, "nie:license", fd.license);

	if (fd.publisher) {
		tracker_sparql_builder_predicate (metadata, "dc:publisher");

		tracker_sparql_builder_object_blank_open (metadata);
		tracker_sparql_builder_predicate (metadata, "a");
		tracker_sparql_builder_object (metadata, "nco:Contact");

		tracker_sparql_builder_predicate (metadata, "nco:fullname");
		tracker_sparql_builder_object_unvalidated (metadata,
		                                           fd.publisher);
		tracker_sparql_builder_object_blank_close (metadata);
	}

	if (stream) {
		tracker_sparql_builder_predicate (metadata, "nfo:sampleRate");
		tracker_sparql_builder_object_int64 (metadata,
		                                     stream->data.stream_info.sample_rate);

		tracker_sparql_builder_predicate (metadata, "nfo:channels");
		tracker_sparql_builder_object_int64 (metadata,
		                                     stream->data.stream_info.channels);

		tracker_sparql_builder_predicate (metadata,
		                                  "nfo:averageBitrate");
		tracker_sparql_builder_object_int64 (metadata,
		                                     stream->data.stream_info.bits_per_sample);

		tracker_sparql_builder_predicate (metadata, "nfo:duration");
		tracker_sparql_builder_object_int64 (metadata,
		                                     stream->data.stream_info.total_samples /
		                                     stream->data.stream_info.sample_rate);
	}

	g_free (fd.artist);
	g_free (fd.album);
	g_free (fd.albumartist);
	g_free (fd.performer);
	g_free (fd.title);
	g_free (fd.trackcount);
	g_free (fd.tracknumber);
	g_free (fd.discno);
	g_free (fd.trackgain);
	g_free (fd.trackpeakgain);
	g_free (fd.albumgain);
	g_free (fd.albumpeakgain);
	g_free (fd.date);
	g_free (fd.comment);
	g_free (fd.genre);
	g_free (fd.mbalbumid);
	g_free (fd.mbartistid);
	g_free (fd.mbalbumartistid);
	g_free (fd.mbtrackid);
	g_free (fd.lyrics);
	g_free (fd.copyright);
	g_free (fd.license);
	g_free (fd.organisation);
	g_free (fd.location);
	g_free (fd.publisher);
	g_free (uri);

	return TRUE;
}