Beispiel #1
0
static gint init_files(vcedit_state *state)
{
	if ((vte.in = fopen(vte.filename, "rb")) == NULL)
		return -1;

	if (vcedit_open(state, vte.in) < 0)
	{
		fclose(vte.in);
		return -1;
	}
	return 0;
}
gboolean vorbis_update_song_tuple (const char * filename, VFSFile * fd, const Tuple * tuple)
{

    vcedit_state *state;
    vorbis_comment *comment;
    gboolean ret;

    if(!tuple || !fd) return FALSE;

    state = vcedit_new_state();

    if(vcedit_open(state, fd) < 0) {
        vcedit_clear(state);
        return FALSE;
    }

    comment = vcedit_comments(state);
    GHashTable * dict = dictionary_from_vorbis_comment (comment);

    insert_str_tuple_field_to_dictionary(tuple, FIELD_TITLE, dict, "title");
    insert_str_tuple_field_to_dictionary(tuple, FIELD_ARTIST, dict, "artist");
    insert_str_tuple_field_to_dictionary(tuple, FIELD_ALBUM, dict, "album");
    insert_str_tuple_field_to_dictionary(tuple, FIELD_COMMENT, dict, "comment");
    insert_str_tuple_field_to_dictionary(tuple, FIELD_GENRE, dict, "genre");

    insert_int_tuple_field_to_dictionary(tuple, FIELD_YEAR, dict, "date");
    insert_int_tuple_field_to_dictionary(tuple, FIELD_TRACK_NUMBER, dict, "tracknumber");

    dictionary_to_vorbis_comment(comment, dict);
    g_hash_table_destroy (dict);

    ret = write_and_pivot_files(state);

    vcedit_clear(state);

    return ret;
}
Beispiel #3
0
int main(int argc, char **argv)
{
	vcedit_state *state;
	vorbis_comment *vc;
	param_t	*param;
	int i;

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	/* initialize the cmdline interface */
	param = new_param();
	parse_options(argc, argv, param);

	/* take care of opening the requested files */
	/* relevent file pointers are returned in the param struct */
	open_files(param);

	/* which mode are we in? */

	if (param->mode == MODE_LIST) {
		
		state = vcedit_new_state();

		if(vcedit_open(state, param->in) < 0)
		{
			fprintf(stderr, _("Failed to open file as vorbis: %s\n"), 
					vcedit_error(state));
            close_files(param);
            free_param(param);
            vcedit_clear(state);
			return 1;
		}

		/* extract and display the comments */
		vc = vcedit_comments(state);
		print_comments(param->com, vc, param->raw);

		/* done */
		vcedit_clear(state);

		close_files(param);
        free_param(param);
		return 0;		
	}

	if (param->mode == MODE_WRITE || param->mode == MODE_APPEND) {

		state = vcedit_new_state();

		if(vcedit_open(state, param->in) < 0)
		{
			fprintf(stderr, _("Failed to open file as vorbis: %s\n"), 
					vcedit_error(state));
            close_files(param);
            free_param(param);
            vcedit_clear(state);
			return 1;
		}

		/* grab and clear the exisiting comments */
		vc = vcedit_comments(state);
		if(param->mode != MODE_APPEND) 
		{
			vorbis_comment_clear(vc);
			vorbis_comment_init(vc);
		}

		for(i=0; i < param->commentcount; i++)
		{
			if(add_comment(param->comments[i], vc, param->raw) < 0)
				fprintf(stderr, _("Bad comment: \"%s\"\n"), param->comments[i]);
		}

		/* build the replacement structure */
		if(param->commentcount==0)
		{
			/* FIXME should use a resizeable buffer! */
			char *buf = (char *)malloc(sizeof(char)*1024);

			while (fgets(buf, 1024, param->com))
				if (add_comment(buf, vc, param->raw) < 0) {
					fprintf(stderr,
						_("bad comment: \"%s\"\n"),
						buf);
				}
			
			free(buf);
		}

		/* write out the modified stream */
		if(vcedit_write(state, param->out) < 0)
		{
			fprintf(stderr, _("Failed to write comments to output file: %s\n"), 
					vcedit_error(state));
            close_files(param);
            free_param(param);
            vcedit_clear(state);
			return 1;
		}

		/* done */
		vcedit_clear(state);
		
		close_files(param);
        free_param(param);
		return 0;
	}

	/* should never reach this point */
	fprintf(stderr, _("no action specified\n"));
    free_param(param);
	return 1;
}
Beispiel #4
0
gboolean Speex_Header_Read_File_Info (gchar *filename, ET_File_Info *ETFileInfo)
{
    vcedit_state *state;
    SpeexHeader  *si;
    gchar *encoder_version = NULL;
    gint channels = 0;
    glong rate = 0;
    glong bitrate = 0;
    gdouble duration = 0;
    gulong filesize;
    gchar *filename_utf8;
    GFile *gfile;
    GError *error = NULL;

    g_return_val_if_fail (filename != NULL && ETFileInfo != NULL, FALSE);

    filename_utf8 = filename_to_display(filename);

    state = vcedit_new_state();    // Allocate memory for 'state'
    gfile = g_file_new_for_path (filename);
    if (!vcedit_open (state, gfile, &error))
    {
        Log_Print (LOG_ERROR,
                   _("Error: Failed to open file: '%s' as Vorbis (%s)."),
                   filename_utf8, error->message);
        g_error_free (error);
        g_object_unref (gfile);
        g_free(filename_utf8);
        vcedit_clear(state);
        return FALSE;
    }

    // Get Speex information
    if ( (si=state->si) != NULL )
    {
        encoder_version = si->speex_version;
        channels        = si->nb_channels;        // Number of channels in bitstream.
        rate            = si->rate;               // (Hz) Sampling rate of the bitstream.
        bitrate         = si->bitrate;            // (b/s) Specifies the bitrate

        duration        = 0;//ov_time_total(&vf,-1); // (s) Total time.

        //g_print("play time: %ld s\n",(long)ov_time_total(&vf,-1));
        //g_print("serialnumber: %ld\n",(long)ov_serialnumber(&vf,-1));
        //g_print("compressed length: %ld bytes\n",(long)(ov_raw_total(&vf,-1)));
    }

    filesize = Get_File_Size(filename);

    ETFileInfo->mpc_version = g_strdup(encoder_version);
    ETFileInfo->bitrate     = bitrate/1000;
    ETFileInfo->samplerate  = rate;
    ETFileInfo->mode        = channels;
    ETFileInfo->size        = filesize;
    //if (bitrate > 0)
    //    ETFileInfo->duration = filesize*8/bitrate/1000; // FIXME : Approximation!! Needs to remove tag size!
    //else
        ETFileInfo->duration   = duration;

    vcedit_clear(state);
    g_object_unref (gfile);
    g_free(filename_utf8);
    return TRUE;
}
Beispiel #5
0
int write_ogg_tag(const string fname, struct fennec_audiotag *wtag)
{
	vcedit_state   *state;
	vorbis_comment *vc;
	param_t	       *param;
	FILE           *tfile;
	FILE           *of;
	string          outname;

	struct fennec_audiotag_item *ct;

	if(!fname || !wtag)return -3;

	setlocale(LC_ALL, "");

	/* initialize the cmdline interface */
	param = new_param();
	
	tfile = _wfsopen(fname, uni("r+b"), _SH_DENYRW);

	if(!tfile)
	{
		MessageBox(0, uni("Access denied, please stop playback and try again (you don't need to close this window)."), uni("Tag Editing"), MB_ICONINFORMATION);
		return -1;
	}

	state = vcedit_new_state();
	
	if(vcedit_open(state, tfile) < 0)
	{
		fclose(tfile);
		free_param(param);
		vcedit_clear(state);
		return -2;
	}
	
	vc = vcedit_comments(state);

	ct = &wtag->tag_title;         if(ct->tsize)local_addcomment(vc, "TITLE",             ct->tdata); else local_addcomment(vc, "TITLE",              uni("") );
	ct = &wtag->tag_album;         if(ct->tsize)local_addcomment(vc, "ALBUM",             ct->tdata); else local_addcomment(vc, "ALBUM",              uni("") );
	ct = &wtag->tag_artist;        if(ct->tsize)local_addcomment(vc, "ARTIST",            ct->tdata); else local_addcomment(vc, "ARTIST",             uni("") );
	ct = &wtag->tag_origartist;    if(ct->tsize)local_addcomment(vc, "ORIGINALARTIST",    ct->tdata); else local_addcomment(vc, "ORIGINALARTIST",     uni("") );
	ct = &wtag->tag_composer;      if(ct->tsize)local_addcomment(vc, "COMPOSER",          ct->tdata); else local_addcomment(vc, "COMPOSER",           uni("") );
	ct = &wtag->tag_lyricist;      if(ct->tsize)local_addcomment(vc, "LYRICIST",          ct->tdata); else local_addcomment(vc, "LYRICIST",           uni("") );
	ct = &wtag->tag_band;          if(ct->tsize)local_addcomment(vc, "BANDNAME",          ct->tdata); else local_addcomment(vc, "BANDNAME",           uni("") );
	ct = &wtag->tag_copyright;     if(ct->tsize)local_addcomment(vc, "COPYRIGHT",         ct->tdata); else local_addcomment(vc, "COPYRIGHT",          uni("") );
	ct = &wtag->tag_publish;       if(ct->tsize)local_addcomment(vc, "PUBLISHER",         ct->tdata); else local_addcomment(vc, "PUBLISHER",          uni("") );
	ct = &wtag->tag_encodedby;     if(ct->tsize)local_addcomment(vc, "ENCODEDBY",         ct->tdata); else local_addcomment(vc, "ENCODEDBY",          uni("") );
	ct = &wtag->tag_genre;         if(ct->tsize)local_addcomment(vc, "GENRE",             ct->tdata); else local_addcomment(vc, "GENRE",              uni("") );
	ct = &wtag->tag_year;          if(ct->tsize)local_addcomment(vc, "YEAR",              ct->tdata); else local_addcomment(vc, "YEAR",               uni("") );
	ct = &wtag->tag_url;           if(ct->tsize)local_addcomment(vc, "URL",               ct->tdata); else local_addcomment(vc, "URL",                uni("") );
	ct = &wtag->tag_offiartisturl; if(ct->tsize)local_addcomment(vc, "OFFICIALARTISTURL", ct->tdata); else local_addcomment(vc, "OFFICIALARTISTURL",  uni("") );
	ct = &wtag->tag_comments;      if(ct->tsize)local_addcomment(vc, "COMMENT",           ct->tdata); else local_addcomment(vc, "COMMENT",            uni("") );
	ct = &wtag->tag_lyric;         if(ct->tsize)local_addcomment(vc, "LYRIC",             ct->tdata); else local_addcomment(vc, "LYRIC",              uni("") );
	ct = &wtag->tag_bpm;           if(ct->tsize)local_addcomment(vc, "BPM",               ct->tdata); else local_addcomment(vc, "BPM",                uni("") );
	ct = &wtag->tag_tracknum;      if(ct->tsize)local_addcomment(vc, "TRACKNUMBER",       ct->tdata); else local_addcomment(vc, "TRACKNUMBER",        uni("") );

	outname = (string) malloc(str_size(fname) + (5 * sizeof(letter)));

	str_cpy(outname, fname);
	str_cat(outname, uni(".tmp"));

	of = _wfopen(outname, uni("wb"));

	if(vcedit_write(state, of) < 0)
	{
		fclose(of);
		fclose(tfile);
		free_param(param);
		vcedit_clear(state);
		free(outname);
		return 1;
	}

	fclose(of);
	
	/* done */

	vcedit_clear(state);
	fclose(tfile);
	free_param(param);


	_wremove(fname);
	sys_sleep(0);
	_wrename(outname, fname);
		
	free(outname);
	return 0;
}
Beispiel #6
0
gboolean Ogg_Tag_Write_File_Tag (ET_File *ETFile)
{
    File_Tag       *FileTag;
    gchar          *filename;
    gchar          *filename_utf8;
    gchar          *basename_utf8;
    FILE           *file_in;
    vcedit_state   *state;
    vorbis_comment *vc;
    gchar          *string;
    GList          *list;
    Picture        *pic;

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

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

    /* Test to know if we can write into the file */
    if ( (file_in=fopen(filename,"rb"))==NULL )
    {
        Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno));
        return FALSE;
    }

    {
    // Skip the id3v2 tag
    guchar tmp_id3[4];
    gulong id3v2size;

    // Check if there is an ID3v2 tag...
    fseek(file_in, 0L, SEEK_SET);
    if (fread(tmp_id3, 1, 4, file_in) == 4)
    {
        // Calculate ID3v2 length
        if (tmp_id3[0] == 'I' && tmp_id3[1] == 'D' && tmp_id3[2] == '3' && tmp_id3[3] < 0xFF)
        {
            // id3v2 tag skipeer $49 44 33 yy yy xx zz zz zz zz [zz size]
            fseek(file_in, 2, SEEK_CUR); // Size is 6-9 position
            if (fread(tmp_id3, 1, 4, file_in) == 4)
            {
                id3v2size = 10 + ( (long)(tmp_id3[3])        | ((long)(tmp_id3[2]) << 7)
                                | ((long)(tmp_id3[1]) << 14) | ((long)(tmp_id3[0]) << 21) );
                fseek(file_in, id3v2size, SEEK_SET);
            }else
            {
                fseek(file_in, 0L, SEEK_SET);
            }
        }else
        {
            fseek(file_in, 0L, SEEK_SET);
        }
    }else
    {
        fseek(file_in, 0L, SEEK_SET);
    }
    }

    state = vcedit_new_state();    // Allocate memory for 'state'
    if ( vcedit_open(state,file_in) < 0 )
    {
        Log_Print(LOG_ERROR,_("ERROR: Failed to open file: '%s' as vorbis (%s)."),filename_utf8,vcedit_error(state));
        ogg_error_msg = vcedit_error(state);
        fclose(file_in);
        vcedit_clear(state);
        return FALSE;
    }

    /* Get data from tag */
    vc = vcedit_comments(state);
    vorbis_comment_clear(vc);
    vorbis_comment_init(vc);

    /*********
     * Title *
     *********/
    Ogg_Set_Tag(vc,"TITLE=",FileTag->title,VORBIS_SPLIT_FIELD_TITLE);

    /**********
     * Artist *
     **********/
    Ogg_Set_Tag(vc,"ARTIST=",FileTag->artist, VORBIS_SPLIT_FIELD_ARTIST);

    /****************
     * Album Artist *
     ****************/
    Ogg_Set_Tag(vc,"ALBUMARTIST=",FileTag->album_artist, VORBIS_SPLIT_FIELD_ARTIST);

    /*********
     * Album *
     *********/
    Ogg_Set_Tag(vc,"ALBUM=",FileTag->album, VORBIS_SPLIT_FIELD_ALBUM);

    /***************
     * Disc Number *
     ***************/
    Ogg_Set_Tag(vc,"DISCNUMBER=",FileTag->disc_number,FALSE);

    /********
     * Year *
     ********/
    Ogg_Set_Tag(vc,"DATE=",FileTag->year,FALSE);

    /*************************
     * Track and Total Track *
     *************************/
    Ogg_Set_Tag(vc,"TRACKNUMBER=",FileTag->track,FALSE);

    Ogg_Set_Tag(vc,"TRACKTOTAL=",FileTag->track_total,FALSE);

    /*********
     * Genre *
     *********/
    Ogg_Set_Tag(vc,"GENRE=",FileTag->genre,VORBIS_SPLIT_FIELD_GENRE);

    /***********
     * Comment *
     ***********/
    // We write the comment using the two formats "DESCRIPTION" and "COMMENT" to be compatible with old versions
    // Format of new specification
    Ogg_Set_Tag(vc,"DESCRIPTION=",FileTag->comment,VORBIS_SPLIT_FIELD_COMMENT);

    // Format used in winamp plugin
    Ogg_Set_Tag(vc,"COMMENT=",FileTag->comment,VORBIS_SPLIT_FIELD_COMMENT);

    if (OGG_TAG_WRITE_XMMS_COMMENT)
    {
        // Format used into xmms-1.2.5
        Ogg_Set_Tag(vc,"=",FileTag->comment,VORBIS_SPLIT_FIELD_COMMENT);
    }


    /************
     * Composer *
     ************/
    Ogg_Set_Tag(vc,"COMPOSER=",FileTag->composer,VORBIS_SPLIT_FIELD_COMPOSER);

    /*******************
     * Original artist *
     *******************/
    Ogg_Set_Tag(vc,"PERFORMER=",FileTag->orig_artist,VORBIS_SPLIT_FIELD_ORIG_ARTIST);

    /*************
     * Copyright *
     *************/
    Ogg_Set_Tag(vc,"COPYRIGHT=",FileTag->copyright,FALSE);

    /*******
     * URL *
     *******/
    Ogg_Set_Tag(vc,"LICENSE=",FileTag->url,FALSE);

    /**************
     * Encoded by *
     **************/
    Ogg_Set_Tag(vc,"ENCODED-BY=",FileTag->encoded_by,FALSE);
    
    
    /***********
     * Picture *
     ***********/
    pic = FileTag->picture;
    while (pic)
    {
        if (pic->data)
        {
            gchar *data_encoded = NULL;
            gint size;
            Picture_Format format = Picture_Format_From_Data(pic);

            string = g_strdup_printf("COVERARTMIME=%s",Picture_Mime_Type_String(format));
            vorbis_comment_add(vc,string);
            g_free(string);
        
            if (pic->type)
            {
                string = g_strdup_printf("COVERARTTYPE=%d",pic->type);
                vorbis_comment_add(vc,string);
                g_free(string);
            }

            if (pic->description)
            {
                string = g_strdup_printf("COVERARTDESCRIPTION=%s",pic->description);
                vorbis_comment_add(vc,string);
                g_free(string);
            }

            size = base64_encode(pic->data, pic->size, &data_encoded);
            string = g_strdup_printf("COVERART=%s",data_encoded);
            vorbis_comment_add(vc,string);
            g_free(data_encoded);
            g_free(string);
        }

        pic = pic->next;
    }

    /**************************
     * Set unsupported fields *
     **************************/
    list = FileTag->other;
    while (list)
    {
        if (list->data)
            vorbis_comment_add(vc,(gchar *)list->data);
        list = list->next;
    }

    /* Write tag, and close also 'file_in' in all cases */
    if ( Ogg_Tag_Write_File(file_in,filename,state) == FALSE )
    {
        ogg_error_msg = vcedit_error(state);
        Log_Print(LOG_ERROR,_("ERROR: Failed to write comments to file '%s' (%s)."),filename_utf8,ogg_error_msg == NULL ? "" : ogg_error_msg);

        vcedit_clear(state);
        return FALSE;
    }else
    {
        basename_utf8 = g_path_get_basename(filename_utf8);
        Log_Print(LOG_OK,_("Written tag of '%s'"),basename_utf8);

        vcedit_clear(state);
    }

    return TRUE;
}
Beispiel #7
0
/*
 * Read tag data into an Ogg Vorbis file.
 * Note:
 *  - if field is found but contains no info (strlen(str)==0), we don't read it
 */
gboolean Ogg_Tag_Read_File_Tag (gchar *filename, File_Tag *FileTag)
{
    FILE           *file;
    vcedit_state   *state;
    vorbis_comment *vc;
    gchar          *string = NULL;
    gchar          *string1 = NULL;
    gchar          *string2 = NULL;
    gchar          *filename_utf8 = filename_to_display(filename);
    guint           field_num, i;
    Picture        *prev_pic = NULL;


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

    ogg_error_msg = NULL;

    if ( (file=fopen(filename,"rb")) == NULL )
    {
        Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno));
        g_free(filename_utf8);
        return FALSE;
    }

    {
    // Skip the id3v2 tag
    guchar tmp_id3[4];
    gulong id3v2size;

    // Check if there is an ID3v2 tag...
    fseek(file, 0L, SEEK_SET);
    if (fread(tmp_id3, 1, 4, file) == 4)
    {
        // Calculate ID3v2 length
        if (tmp_id3[0] == 'I' && tmp_id3[1] == 'D' && tmp_id3[2] == '3' && tmp_id3[3] < 0xFF)
        {
            // id3v2 tag skipeer $49 44 33 yy yy xx zz zz zz zz [zz size]
            fseek(file, 2, SEEK_CUR); // Size is 6-9 position
            if (fread(tmp_id3, 1, 4, file) == 4)
            {
                id3v2size = 10 + ( (long)(tmp_id3[3])        | ((long)(tmp_id3[2]) << 7)
                                | ((long)(tmp_id3[1]) << 14) | ((long)(tmp_id3[0]) << 21) );
                fseek(file, id3v2size, SEEK_SET);
                Log_Print(LOG_ERROR,_("Warning : The Ogg Vorbis file '%s' contains an ID3v2 tag."),filename_utf8);
            }else
            {
                fseek(file, 0L, SEEK_SET);
            }
        }else
        {
            fseek(file, 0L, SEEK_SET);
        }
    }else
    {
        fseek(file, 0L, SEEK_SET);
    }
    }

    state = vcedit_new_state();    // Allocate memory for 'state'
    if ( vcedit_open(state,file) < 0 )
    {
        Log_Print(LOG_ERROR,_("ERROR: Failed to open file: '%s' as vorbis (%s)."),filename_utf8,vcedit_error(state));
        ogg_error_msg = vcedit_error(state);
        fclose(file);
        g_free(filename_utf8);
        vcedit_clear(state);
        return FALSE;
    }


    /* Get data from tag */
    vc = vcedit_comments(state);
    /*{
        gint i; 
        for (i=0;i<vc->comments;i++) 
            g_print("%s -> Ogg vc:'%s'\n",g_path_get_basename(filename),vc->user_comments[i]);
    }*/

    /*********
     * Title *
     *********/
    /* Note : don't forget to add any new field to 'Save unsupported fields' */
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"TITLE",field_num++)) != NULL )
    {
        string = Try_To_Validate_Utf8_String(string);

        if ( g_utf8_strlen(string, -1) > 0 )
        {
            if (FileTag->title==NULL)
                FileTag->title = g_strdup(string);
            else
                FileTag->title = g_strconcat(FileTag->title,MULTIFIELD_SEPARATOR,string,NULL);
            // If strlen = 0, then no allocated data!
        }

        g_free(string);
    }

    /**********
     * Artist *
     **********/
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"ARTIST",field_num++)) != NULL )
    {
        string = Try_To_Validate_Utf8_String(string);

        if ( g_utf8_strlen(string, -1) > 0 )
        {
            if (FileTag->artist==NULL)
                FileTag->artist = g_strdup(string);
            else
                FileTag->artist = g_strconcat(FileTag->artist,MULTIFIELD_SEPARATOR,string,NULL);
        }

        g_free(string);
    }

    /****************
     * Album Artist *
     ****************/
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"ALBUMARTIST",field_num++)) != NULL )
    {
        string = Try_To_Validate_Utf8_String(string);

        if ( g_utf8_strlen(string, -1) > 0 )
        {
            if (FileTag->album_artist==NULL)
                FileTag->album_artist = g_strdup(string);
            else
                FileTag->album_artist = g_strconcat(FileTag->album_artist,MULTIFIELD_SEPARATOR,string,NULL);
        }

        g_free(string);
    }

    /*********
     * Album *
     *********/
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"ALBUM",field_num++)) != NULL )
    {
        string = Try_To_Validate_Utf8_String(string);

        if ( g_utf8_strlen(string, -1) > 0 )
        {
            if (FileTag->album==NULL)
                FileTag->album = g_strdup(string);
            else
                FileTag->album = g_strconcat(FileTag->album,MULTIFIELD_SEPARATOR,string,NULL);
        }

        g_free(string);
    }

    /*******************************
     * Disc Number (Part of a Set) *
     *******************************/
    if ( (string = vorbis_comment_query(vc,"DISCNUMBER",0)) != NULL && g_utf8_strlen(string, -1) > 0 )
    {
        FileTag->disc_number = g_strdup(string);
    }

    /********
     * Year *
     ********/
    if ( (string = vorbis_comment_query(vc,"DATE",0)) != NULL && g_utf8_strlen(string, -1) > 0 )
    {
        FileTag->year = g_strdup(string);
        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 ( (string = vorbis_comment_query(vc,"TRACKNUMBER",0)) != NULL && g_utf8_strlen(string, -1) > 0 )
    {
        if (NUMBER_TRACK_FORMATED)
        {
            // Ckeck if TRACKTOTAL used, else takes it in TRACKNUMBER
            if ( (string1 = vorbis_comment_query(vc,"TRACKTOTAL",0)) != NULL && g_utf8_strlen(string1, -1) > 0 )
            {
                FileTag->track_total = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string1));
            }else
            if ( (string1 = g_utf8_strchr(string, -1, '/')) )
            {
                FileTag->track_total = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string1+1));
                *string1 = '\0';
            }
            FileTag->track = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string));
        }else
        {
            // Ckeck if TRACKTOTAL used, else takes it in TRACKNUMBER
            if ( (string1 = vorbis_comment_query(vc,"TRACKTOTAL",0)) != NULL && g_utf8_strlen(string1, -1) > 0 )
            {
                FileTag->track_total = g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,atoi(string1));
            }else
            if ( (string1 = g_utf8_strchr(string, -1, '/')) )
            {
                FileTag->track_total = g_strdup(string1+1);
                *string1 = '\0';
            }
            FileTag->track = g_strdup(string);
        }
    }

    /*********
     * Genre *
     *********/
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"GENRE",field_num++)) != NULL )
    {
        string = Try_To_Validate_Utf8_String(string);

        if ( g_utf8_strlen(string, -1) > 0 )
        {
            if (FileTag->genre==NULL)
                FileTag->genre = g_strdup(string);
            else
                FileTag->genre = g_strconcat(FileTag->genre,MULTIFIELD_SEPARATOR,string,NULL);
        }

        g_free(string);
    }

    /***********
     * Comment *
     ***********/
    field_num = 0;
    string1 = NULL; // Cause it may be not updated into the 'while' condition
    while ( ((string2 = vorbis_comment_query(vc,"DESCRIPTION",field_num)) != NULL )   // New specifications
         || ((string  = vorbis_comment_query(vc,"COMMENT",    field_num)) != NULL )   // Old : Winamp format (for EasyTAG 1.99.11 and older)
         || ((string1 = vorbis_comment_query(vc,"",           field_num)) != NULL ) ) // Old : Xmms format   (for EasyTAG 1.99.11 and older)
    {
        string  = Try_To_Validate_Utf8_String(string);
        string1 = Try_To_Validate_Utf8_String(string1);
        string2 = Try_To_Validate_Utf8_String(string2);

        if ( string2 && g_utf8_strlen(string2, -1) > 0 ) // Contains comment to new specifications format and we prefer this format (field name defined)
        {
            if (FileTag->comment==NULL)
                FileTag->comment = g_strdup(string2);
            else
                FileTag->comment = g_strconcat(FileTag->comment,MULTIFIELD_SEPARATOR,string2,NULL);

            // Frees allocated data
            if (string && g_utf8_strlen(string, -1) > 0)
                g_free(string);
            if (string1 && g_utf8_strlen(string1, -1) > 0)
                g_free(string1);
        }else if ( string && g_utf8_strlen(string, -1) > 0 ) // Contains comment to Winamp format and we prefer this format (field name defined)
        {
            if (FileTag->comment==NULL)
                FileTag->comment = g_strdup(string);
            else
                FileTag->comment = g_strconcat(FileTag->comment,MULTIFIELD_SEPARATOR,string,NULL);

            // Frees allocated data
            if (string1 && g_utf8_strlen(string1, -1) > 0)
                g_free(string1);
        }else if ( string1 && g_utf8_strlen(string1, -1) > 0 ) // Contains comment to Xmms format only
        {
            if (FileTag->comment==NULL)
                FileTag->comment = g_strdup(string1);
            else
                FileTag->comment = g_strconcat(FileTag->comment,MULTIFIELD_SEPARATOR,string1,NULL);
        }

        g_free(string);
        g_free(string1);
        g_free(string2);

        string  = NULL;
        string1 = NULL;
        field_num++;
    }

    /************
     * Composer *
     ************/
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"COMPOSER",field_num++)) != NULL )
    {
        string = Try_To_Validate_Utf8_String(string);

        if ( g_utf8_strlen(string, -1) > 0 )
        {
            if (FileTag->composer==NULL)
                FileTag->composer = g_strdup(string);
            else
                FileTag->composer = g_strconcat(FileTag->composer,MULTIFIELD_SEPARATOR,string,NULL);
        }

        g_free(string);
    }

    /*******************
     * Original artist *
     *******************/
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"PERFORMER",field_num++)) != NULL )
    {
        string = Try_To_Validate_Utf8_String(string);

        if ( g_utf8_strlen(string, -1) > 0 )
        {
            if (FileTag->orig_artist==NULL)
                FileTag->orig_artist = g_strdup(string);
            else
                FileTag->orig_artist = g_strconcat(FileTag->orig_artist,MULTIFIELD_SEPARATOR,string,NULL);
        }

        g_free(string);
    }

    /*************
     * Copyright *
     *************/
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"COPYRIGHT",field_num++)) != NULL )
    {
        string = Try_To_Validate_Utf8_String(string);

        if ( g_utf8_strlen(string, -1) > 0 )
        {
            if (FileTag->copyright==NULL)
                FileTag->copyright = g_strdup(string);
            else
                FileTag->copyright = g_strconcat(FileTag->copyright,MULTIFIELD_SEPARATOR,string,NULL);
        }

        g_free(string);
    }

    /*******
     * URL *
     *******/
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"LICENSE",field_num++)) != NULL )
    {
        string = Try_To_Validate_Utf8_String(string);

        if ( g_utf8_strlen(string, -1) > 0 )
        {
            if (FileTag->url==NULL)
                FileTag->url = g_strdup(string);
            else
                FileTag->url = g_strconcat(FileTag->url,MULTIFIELD_SEPARATOR,string,NULL);
        }

        g_free(string);
    }

    /**************
     * Encoded by *
     **************/
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"ENCODED-BY",field_num++)) != NULL )
    {
        string = Try_To_Validate_Utf8_String(string);

        if ( g_utf8_strlen(string, -1) > 0 )
        {
            if (FileTag->encoded_by==NULL)
                FileTag->encoded_by = g_strdup(string);
            else
                FileTag->encoded_by = g_strconcat(FileTag->encoded_by,MULTIFIELD_SEPARATOR,string,NULL);
        }

        g_free(string);
    }


    /**************
     * Picture    *
     **************/
    /* Non officials tags used for picture information:
     *  - COVERART            : contains the picture data
     *  - COVERARTTYPE        : cover front, ...
     *  - COVERARTDESCRIPTION : information set by user
     *  - COVERARTMIME        : image/jpeg or image/png (written only)
     */
    field_num = 0;
    while ( (string = vorbis_comment_query(vc,"COVERART",field_num++)) != NULL )
    {
        gchar *data;
        gint size;
        Picture *pic;
            
        pic = Picture_Allocate();
        if (!prev_pic)
            FileTag->picture = pic;
        else
            prev_pic->next = pic;
        prev_pic = pic;

        pic->data = NULL;
        
        // Decode picture data
        data = g_strdup(string);
        size = base64_decode(string, data);
        if ( data && (pic->data = g_memdup(data, size)) )
            pic->size = size;
        g_free(data);

        if ( (string = vorbis_comment_query(vc,"COVERARTTYPE",field_num-1)) != NULL )
        {
            pic->type = atoi(string);
        }

        if ( (string = vorbis_comment_query(vc,"COVERARTDESCRIPTION",field_num-1)) != NULL )
        {
            pic->description = g_strdup(string);
        }

        //if ((string = vorbis_comment_query(vc,"COVERTARTMIME",field_num-1)) != NULL )
        //{
        //    pic->description = g_strdup(string);
        //}

    }


    /***************************
     * Save unsupported fields *
     ***************************/
    for (i=0;i<(guint)vc->comments;i++)
    {
        if ( strncasecmp(vc->user_comments[i],"TITLE=",            6) != 0
          && strncasecmp(vc->user_comments[i],"ARTIST=",           7) != 0
          && strncasecmp(vc->user_comments[i],"ALBUMARTIST=",     12) != 0
          && strncasecmp(vc->user_comments[i],"ALBUM=",            6) != 0
          && strncasecmp(vc->user_comments[i],"DISCNUMBER=",      11) != 0
          && strncasecmp(vc->user_comments[i],"DATE=",             5) != 0
          && strncasecmp(vc->user_comments[i],"TRACKNUMBER=",     12) != 0
          && strncasecmp(vc->user_comments[i],"TRACKTOTAL=",      11) != 0
          && strncasecmp(vc->user_comments[i],"GENRE=",            6) != 0
          && strncasecmp(vc->user_comments[i],"DESCRIPTION=",     12) != 0
          && strncasecmp(vc->user_comments[i],"COMMENT=",          8) != 0
          && strncasecmp(vc->user_comments[i],"=",                 1) != 0
          && strncasecmp(vc->user_comments[i],"COMPOSER=",         9) != 0
          && strncasecmp(vc->user_comments[i],"PERFORMER=",       10) != 0
          && strncasecmp(vc->user_comments[i],"COPYRIGHT=",       10) != 0
          && strncasecmp(vc->user_comments[i],"LICENSE=",          8) != 0
          && strncasecmp(vc->user_comments[i],"ENCODED-BY=",      11) != 0
          && strncasecmp(vc->user_comments[i],"COVERART=",         9) != 0
          && strncasecmp(vc->user_comments[i],"COVERARTTYPE=",       13) != 0
          && strncasecmp(vc->user_comments[i],"COVERARTMIME=",       13) != 0
          && strncasecmp(vc->user_comments[i],"COVERARTDESCRIPTION=",20) != 0
           )
        {
            FileTag->other = g_list_append(FileTag->other,
                                           Try_To_Validate_Utf8_String(vc->user_comments[i]));
        }
    }

    vcedit_clear(state);
    fclose(file);
    g_free(filename_utf8);

    return TRUE;
}