Beispiel #1
0
/* 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;
}
Beispiel #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;
}
Beispiel #3
0
static PyObject *
flac_MetadataSimpleIterator__get_block (flac_MetadataSimpleIteratorObject *self)
{
	FLAC__StreamMetadata *block;

	if ((block = FLAC__metadata_simple_iterator_get_block(self->iterator)))
		return PyFLAC_StreamMetadata_FromClass(block);

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

	return PyErr_NoMemory();
}
Beispiel #4
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);
	}
}
Beispiel #5
0
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;
}
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;
}
Beispiel #7
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;
}
Beispiel #8
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;
}