Logo Search packages:      
Sourcecode: easytag version File versions  Download package

flac_tag.c

/* flac_tag.c - 2003/12/27 */
/*
 *  EasyTAG - Tag editor for MP3 and Ogg Vorbis files
 *  Copyright (C) 2001-2003  Jerome Couderc <easytag@gmail.com>
 *  Copyright (C) 2003       Pavel Minayev <thalion@front.ru>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <config.h>

#ifdef ENABLE_FLAC

#include <gtk/gtk.h>
#include <glib/gi18n-lib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <FLAC/metadata.h>
#include <unistd.h>

#include "easytag.h"
#include "flac_tag.h"
#include "vcedit.h"
#include "et_core.h"
#include "id3_tag.h"
#include "misc.h"
#include "setting.h"
#include "picture.h"
#include "charset.h"


/***************
 * Declaration *
 ***************/

#define MULTIFIELD_SEPARATOR " - "

/* FLAC uses Ogg Vorbis comments
 * Ogg Vorbis fields names :
 *  - TITLE        : Track name
 *  - VERSION      : The version field may be used to differentiate multiple version of the same track title in a single collection. (e.g. remix info)
 *  - ALBUM        : The collection name to which this track belongs
 *  - TRACKNUMBER  : The track number of this piece if part of a specific larger collection or album
 *  - TRACKTOTAL   : 
 *  - ARTIST       : Track performer
 *  - ORGANIZATION : Name of the organization producing the track (i.e. the 'record label')
 *  - DESCRIPTION  : A short text description of the contents
 *  - GENRE        : A short text indication of music genre
 *  - DATE         : Date the track was recorded
 *  - LOCATION     : Location where track was recorded
 *  - COPYRIGHT    : Copyright information
 *  - ISRC         : ISRC number for the track; see the ISRC intro page for more information on ISRC numbers.
 *
 * Field names should not be 'internationalized'; this is a concession to simplicity
 * not an attempt to exclude the majority of the world that doesn't speak English.
 * Field *contents*, however, are represented in UTF-8 to allow easy representation
 * of any language.
 */



/**************
 * Prototypes *
 **************/
gboolean Flac_Tag_Write_File (FILE *file_in, gchar *filename_in, vcedit_state *state);
gchar   *Flac_Tag_Validate_Utf8_Field (gchar *string);


/*************
 * Functions *
 *************/

/*
 * Read tag data from a FLAC file.
 * 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;
    FLAC__StreamMetadata                        *vc_block;
    FLAC__StreamMetadata_VorbisComment          *vc;
    FLAC__StreamMetadata_VorbisComment_Entry    *field;
    gchar                                       *field_value;
    gchar                                       *field_value_tmp;
    gchar                                       *string = NULL;
    gint                                        field_num;
    gint                                        field_len;
    guint                                       i;


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

    flac_error_msg = NULL;

    iter = FLAC__metadata_simple_iterator_new();
    if ( iter == NULL || !FLAC__metadata_simple_iterator_init(iter, filename, true, false) )
    {
        gchar *filename_utf8 = filename_to_display(filename);
        if ( iter == NULL )
        {
#ifdef WIN32
            const char ** const iter = FLAC__Metadata_SimpleIteratorStatusString; /* this is for win32 auto-import of this external symbol works */
            flac_error_msg = iter[FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR];
#else
            flac_error_msg = FLAC__Metadata_SimpleIteratorStatusString[FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR];
#endif
        }else
        {
            flac_error_msg = FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iter)];
            FLAC__metadata_simple_iterator_delete(iter);
        }

        g_print(_("ERROR while opening file: '%s' as FLAC (%s).\n\a"),filename_utf8,flac_error_msg);
        g_free(filename_utf8);
        return FALSE;
    }

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

    /* Find the VORBIS_COMMENT block */
    while ( FLAC__metadata_simple_iterator_get_block_type(iter) != FLAC__METADATA_TYPE_VORBIS_COMMENT )
    {
        if ( !FLAC__metadata_simple_iterator_next(iter) )
        {
            /* End of metadata: comment block not found, nothing to read */
            FLAC__metadata_simple_iterator_delete(iter);
            return TRUE;
        }
    }

    /* Get comments from block */
    vc_block = FLAC__metadata_simple_iterator_get_block(iter);
    vc = &vc_block->data.vorbis_comment;

    /* Get vendor string */
    /*{
        FLAC__StreamMetadata_VorbisComment_Entry vce;
        vce = vc->vendor_string;
        g_print("File %s : \n",filename);
        g_print(" - FLAC File vendor string : '%s'\n",g_strndup(vce.entry,vce.length));
        g_print(" - FLAC Lib vendor string  : '%s'\n",FLAC__VENDOR_STRING);
    }*/


    /*********
     * Title *
     *********/
    field_num = 0;
    while ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(vc_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 = Flac_Tag_Validate_Utf8_Field(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(vc_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 = Flac_Tag_Validate_Utf8_Field(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(vc_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 = Flac_Tag_Validate_Utf8_Field(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(vc_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 = Flac_Tag_Validate_Utf8_Field(field_value_tmp);
                g_free(field_value_tmp);
                FileTag->year = field_value;
            }
        }
    }

    /********
     * Year *
     ********/
    if ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(vc_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 = Flac_Tag_Validate_Utf8_Field(field_value_tmp);
                g_free(field_value_tmp);
                FileTag->year = field_value;
            }
        }
    }

    /*************************
     * Track and Total Track *
     *************************/
    if ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(vc_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 = Flac_Tag_Validate_Utf8_Field(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(vc_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 = Flac_Tag_Validate_Utf8_Field(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(vc_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 = Flac_Tag_Validate_Utf8_Field(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 ( (field_num = FLAC__metadata_object_vorbiscomment_find_entry_from(vc_block,field_num,"DESCRIPTION")) >= 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 = Flac_Tag_Validate_Utf8_Field(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(vc_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 = Flac_Tag_Validate_Utf8_Field(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(vc_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 = Flac_Tag_Validate_Utf8_Field(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(vc_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 = Flac_Tag_Validate_Utf8_Field(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(vc_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 = Flac_Tag_Validate_Utf8_Field(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(vc_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 = Flac_Tag_Validate_Utf8_Field(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,"COMPOSER=",    MIN(6,  field->length)) != 0
          && strncasecmp((gchar *)field->entry,"PERFORMER=",   MIN(6,  field->length)) != 0
          && strncasecmp((gchar *)field->entry,"COPYRIGHT=",   MIN(6,  field->length)) != 0
          && strncasecmp((gchar *)field->entry,"LICENSE=",     MIN(6,  field->length)) != 0
          && strncasecmp((gchar *)field->entry,"ENCODED-BY=",  MIN(6,  field->length)) != 0 )
        {
            //g_print("custom %*s\n", field->length, field->entry);
            FileTag->other = g_list_append(FileTag->other,g_strndup(field->entry, field->length));
        }
    }

    FLAC__metadata_object_delete(vc_block);
    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
     * (will be deleted when writing 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)
    {
        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->saved = FALSE;
        }

        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

    return TRUE;
}


gboolean Flac_Tag_Write_File_Tag (ET_File *ETFile)
{
    File_Tag                                 *FileTag;
    gchar                                    *filename_utf8, *filename;
    gchar                                    *basename_utf8;
    FLAC__Metadata_SimpleIterator            *iter;
    FLAC__StreamMetadata                     *vc_block;
    FLAC__StreamMetadata_VorbisComment_Entry field;
    FLAC__bool                               write_ok;
    gchar                                    *string;
    GList                                    *list;
    // To get original vendor string
    FLAC__StreamMetadata                     *vc_block_svg = NULL;
    FLAC__StreamMetadata_VorbisComment       *vc_svg;
    FLAC__StreamMetadata_VorbisComment_Entry field_svg;
    gboolean                                 vc_found_svg = TRUE;


    if (!ETFile || !ETFile->FileTag)
        return FALSE;

    FileTag  = (File_Tag *)ETFile->FileTag->data;
    filename = ((File_Name *)ETFile->FileNameCur->data)->value;
    filename_utf8 = filename_to_display(filename);
    flac_error_msg = NULL;

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

    iter = FLAC__metadata_simple_iterator_new();
    if ( iter == NULL || !FLAC__metadata_simple_iterator_init(iter,filename,false,false) )
    {
        if ( iter == NULL )
        {
#ifdef WIN32
            const char **iter = FLAC__Metadata_SimpleIteratorStatusString;  /* this is for win32 auto-import of this external symbol works */
            flac_error_msg = iter[FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR];
#else
            flac_error_msg = FLAC__Metadata_SimpleIteratorStatusString[FLAC__METADATA_SIMPLE_ITERATOR_STATUS_MEMORY_ALLOCATION_ERROR];
#endif
        }else
        {
            flac_error_msg = FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iter)];
            FLAC__metadata_simple_iterator_delete(iter);
        }

        g_print(_("ERROR while opening file: '%s' as FLAC (%s).\n\a"),filename_utf8,flac_error_msg);
        g_free(filename_utf8);
        return FALSE;
    }

    /* Find the VORBIS_COMMENT block to get original vendor string */
    while ( FLAC__metadata_simple_iterator_get_block_type(iter) != FLAC__METADATA_TYPE_VORBIS_COMMENT )
    {
        if ( !FLAC__metadata_simple_iterator_next(iter) )
        {
            /* End of metadata: comment block not found, nothing to read */
            vc_found_svg = FALSE;
            break;
        }
    }
    if (vc_found_svg)
    {
        /* Get comments from block */
        vc_block_svg = FLAC__metadata_simple_iterator_get_block(iter);
        vc_svg = &vc_block_svg->data.vorbis_comment;
        /* Get original vendor string */
        field_svg = vc_svg->vendor_string;
    }


    vc_block = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT);
    
    /* Set the original vendor string else it is version of library */
    if (vc_found_svg)
        FLAC__metadata_object_vorbiscomment_set_vendor_string(vc_block, field_svg, true);
    
    
    /*********
     * Title *
     *********/
    if ( FileTag->title )
    {
        string  = g_strconcat("TITLE=",FileTag->title,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string); // Warning : g_utf8_strlen doesn't count the multibyte characters. Here we need the allocated size.
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /**********
     * Artist *
     **********/
    if ( FileTag->artist )
    {
        string  = g_strconcat("ARTIST=",FileTag->artist,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /*********
     * Album *
     *********/
    if ( FileTag->album )
    {
        string  = g_strconcat("ALBUM=",FileTag->album,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /***************
     * Disc Number *
     ***************/
    if ( FileTag->disc_number )
    {
        string  = g_strconcat("DISCNUMBER=",FileTag->disc_number,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /********
     * Year *
     ********/
    if ( FileTag->year )
    {
        string  = g_strconcat("DATE=",FileTag->year,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /*************************
     * Track and Total Track *
     *************************/
    if ( FileTag->track )
    {
        string = g_strconcat("TRACKNUMBER=",FileTag->track,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }
    if ( FileTag->track_total /*&& strlen(FileTag->track_total)>0*/ )
    {
        string = g_strconcat("TRACKTOTAL=",FileTag->track_total,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /*********
     * Genre *
     *********/
    if ( FileTag->genre )
    {
        string  = g_strconcat("GENRE=",FileTag->genre,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /***********
     * Comment *
     ***********/
    // We write the comment using the "both" format
    if ( FileTag->comment )
    {
        string = g_strconcat("DESCRIPTION=",FileTag->comment,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /************
     * Composer *
     ************/
    if ( FileTag->composer )
    {
        string  = g_strconcat("COMPOSER=",FileTag->composer,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /*******************
     * Original artist *
     *******************/
    if ( FileTag->orig_artist )
    {
        string  = g_strconcat("PERFORMER=",FileTag->orig_artist,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /*************
     * Copyright *
     *************/
    if ( FileTag->copyright )
    {
        string  = g_strconcat("COPYRIGHT=",FileTag->copyright,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /*******
     * URL *
     *******/
    if ( FileTag->url )
    {
        string  = g_strconcat("LICENSE=",FileTag->url,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }

    /**************
     * Encoded by *
     **************/
    if ( FileTag->encoded_by )
    {
        string  = g_strconcat("ENCODED-BY=",FileTag->encoded_by,NULL);
        field.entry = (FLAC__byte *)string;
        field.length = strlen(string);
        FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        g_free(string);
    }


    /**************************
     * Set unsupported fields *
     **************************/
    list = FileTag->other;
    while (list)
    {
        if (list->data)
        {
            string = (gchar*)list->data;
            field.entry = (FLAC__byte *)string;
            field.length = strlen(string);
            FLAC__metadata_object_vorbiscomment_insert_comment(vc_block,vc_block->data.vorbis_comment.num_comments,field,true);
        }            
        list = list->next;
    }

    /* Find the VORBIS_COMMENT block */
    while ( FLAC__metadata_simple_iterator_get_block_type(iter) != FLAC__METADATA_TYPE_VORBIS_COMMENT )
    {
        if ( !FLAC__metadata_simple_iterator_next(iter) )
            break;
    }


    /*
     * Write FLAC tag (as Vorbis comment)
     */
    if ( FLAC__metadata_simple_iterator_get_block_type(iter) != FLAC__METADATA_TYPE_VORBIS_COMMENT )
    {
        /* End of metadata: no comment block, so insert one */
        write_ok = FLAC__metadata_simple_iterator_insert_block_after(iter,vc_block,true);
    }else
    {
        write_ok = FLAC__metadata_simple_iterator_set_block(iter,vc_block,true);
    }        

    if ( !write_ok )
    {
        flac_error_msg = FLAC__Metadata_SimpleIteratorStatusString[FLAC__metadata_simple_iterator_status(iter)];
        g_print(_("ERROR: Failed to write comments to file '%s' (%s).\n"),filename_utf8,flac_error_msg);
        FLAC__metadata_simple_iterator_delete(iter);
        FLAC__metadata_object_delete(vc_block);
        g_free(filename_utf8);
        return FALSE;
    }else
    {
        basename_utf8 = g_path_get_basename(filename_utf8);
        g_print(_("Written tag of '%s'\n"),basename_utf8);
        g_free(basename_utf8);
    }

    FLAC__metadata_simple_iterator_delete(iter);
    FLAC__metadata_object_delete(vc_block);
    if (vc_found_svg)
        FLAC__metadata_object_delete(vc_block_svg);

#ifdef ENABLE_MP3
    /*
     * Write also the ID3 tags (ID3v1 and/or ID3v2) if wanted (as needed by some players)
     */
    if (WRITE_ID3_TAGS_IN_FLAC_FILE)
    {
        Id3tag_Write_File_Tag(ETFile);
    }else
    {
        // Delete the ID3 tags (create a dummy ETFile for the Id3tag_... function)
        ET_File   *ETFile_tmp    = ET_File_Item_New();
        File_Name *FileName_tmp  = ET_File_Name_Item_New();
        File_Tag  *FileTag_tmp   = ET_File_Tag_Item_New();
        // Same file...
        FileName_tmp->value      = g_strdup(filename_utf8);
        ETFile_tmp->FileNameList = g_list_append(NULL,FileName_tmp);
        ETFile_tmp->FileNameCur  = ETFile_tmp->FileNameList;
        // With empty tag...
        ETFile_tmp->FileTagList  = g_list_append(NULL,FileTag_tmp);
        ETFile_tmp->FileTag      = ETFile_tmp->FileTagList;
        Id3tag_Write_File_Tag(ETFile_tmp);
        ET_Free_File_List_Item(ETFile_tmp);
    }
#endif

    g_free(filename_utf8);
    return TRUE;
}


/*
 * Check if passed a valid UTF-8 string in parameter.
 * Else, the tag was probably encoded to ISO-8859-15 (by using for example
 * "metaflac --no-utf8-convert ...") so we convert it from ISO-8859-1 to UTF-8.
 */
gchar *Flac_Tag_Validate_Utf8_Field (gchar *string)
{
    if ( !g_utf8_validate(string, -1, NULL) )
    {
        // Returns a native ISO-8859-15 string to UTF-8
        return convert_string(string, "ISO-8859-1", "UTF-8",TRUE);
    }else
    {
        // Returns a native UTF-8 string
        return g_strdup(string);
    }
    
}


#endif /* ENABLE_FLAC */

Generated by  Doxygen 1.6.0   Back to index