gboolean Mac_Header_Read_File_Info(gchar *filename, ET_File_Info *ETFileInfo) { StreamInfoMac Info; if (info_mac_read(filename, &Info)) { gchar *filename_utf8 = filename_to_display(filename); fprintf(stderr,"MAC header not found for file '%s'\n", filename_utf8); g_free(filename_utf8); return FALSE; } ETFileInfo->mpc_profile = g_strdup(Info.CompresionName); ETFileInfo->version = Info.Version; ETFileInfo->bitrate = Info.Bitrate/1000.0; ETFileInfo->samplerate = Info.SampleFreq; ETFileInfo->mode = Info.Channels; ETFileInfo->size = Info.FileSize; ETFileInfo->duration = Info.Duration/1000; return TRUE; }
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; }
gboolean Ogg_Header_Read_File_Info (const gchar *filename, ET_File_Info *ETFileInfo) { OggVorbis_File vf; vorbis_info *vi; gint encoder_version = 0; gint channels = 0; glong rate = 0; glong bitrate_nominal = 0; gdouble duration = 0; gulong filesize; gint res; ov_callbacks callbacks = { et_ogg_read_func, et_ogg_seek_func, et_ogg_close_func, et_ogg_tell_func }; EtOggState state; gchar *filename_utf8; g_return_val_if_fail (filename != NULL && ETFileInfo != NULL, FALSE); state.file = g_file_new_for_path (filename); state.error = NULL; state.istream = G_INPUT_STREAM (g_file_read (state.file, NULL, &state.error)); filename_utf8 = filename_to_display (filename); if (!state.istream) { /* FIXME: Pass error back to calling function. */ Log_Print (LOG_ERROR, _("Error while opening file: '%s' (%s)"), filename_utf8, state.error->message); g_free (filename_utf8); return FALSE; } if ((res = ov_open_callbacks (&state, &vf, NULL, 0, callbacks)) == 0) { if ( (vi=ov_info(&vf,0)) != NULL ) { encoder_version = vi->version; // Vorbis encoder version used to create this bitstream. channels = vi->channels; // Number of channels in bitstream. rate = vi->rate; // (Hz) Sampling rate of the bitstream. bitrate_nominal = vi->bitrate_nominal; // (b/s) Specifies the average bitrate for a VBR bitstream. }else { Log_Print(LOG_ERROR,_("Ogg Vorbis: The specified bitstream does not exist or the " "file has been initialized improperly (file: '%s')."),filename_utf8); } duration = 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))); /***{ // Test for displaying comments vorbis_comment *vc = ov_comment(&vf,-1); Log_Print(LOG_OK,">>> %s",filename_utf8); Log_Print(LOG_OK,"Nbr comments : %d",vc->comments); Log_Print(LOG_OK,"Vendor : %s",vc->vendor); char **ptr = vc->user_comments; while(*ptr){ Log_Print(LOG_OK,"> %s",*ptr); ++ptr; } }***/ ov_clear(&vf); // This close also the file }else { /* On error. */ if (state.error) { g_debug ("Ogg Vorbis: error reading header information (%s)", state.error->message); } et_ogg_close_func (&state); switch (res) { case OV_EREAD: Log_Print(LOG_ERROR,_("Ogg Vorbis: Read from media returned an error (file: '%s')."),filename_utf8); break; case OV_ENOTVORBIS: Log_Print(LOG_ERROR,_("Ogg Vorbis: Bitstream is not Vorbis data (file: '%s')."),filename_utf8); break; case OV_EVERSION: Log_Print(LOG_ERROR,_("Ogg Vorbis: Vorbis version mismatch (file: '%s')."),filename_utf8); break; case OV_EBADHEADER: Log_Print(LOG_ERROR,_("Ogg Vorbis: Invalid Vorbis bitstream header (file: '%s')."),filename_utf8); break; case OV_EFAULT: Log_Print(LOG_ERROR,_("Ogg Vorbis: Internal logic fault, indicates a bug or heap/stack corruption (file: '%s')."),filename_utf8); break; default: break; } } filesize = Get_File_Size(filename); ETFileInfo->version = encoder_version; ETFileInfo->bitrate = bitrate_nominal/1000; ETFileInfo->samplerate = rate; ETFileInfo->mode = channels; ETFileInfo->size = filesize; ETFileInfo->duration = duration; g_free(filename_utf8); return TRUE; }
/* * 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; }
/* * 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; }
/* * Read infos into header of first frame */ gboolean Mpeg_Header_Read_File_Info (gchar *filename, ET_File_Info *ETFileInfo) { #if (!USE_ID3LIB_4_HEADER) FILE *file; gulong filesize; if (!filename || !ETFileInfo) return FALSE; /* Get size of file */ filesize = Get_File_Size(filename); ETFileInfo->size = filesize; /* * This part was taken from XMMS */ if ((file = fopen(filename, "rb")) != NULL) { guint32 head; unsigned char tmp[4]; struct frame frm; gboolean id3_found = FALSE; if (fread(tmp, 1, 4, file) != 4) { fclose(file); return FALSE; } // Skip data of the ID3v2.x tag (It may contain data similar to mpeg frame // as, for example, in the id3 APIC frame) (patch from Artur Polaczynski) if (tmp[0] == 'I' && tmp[1] == 'D' && tmp[2] == '3' && tmp[3] < 0xFF) { // ID3v2 tag skipeer $49 44 33 yy yy xx zz zz zz zz [zz size] long id3v2size; fseek(file, 2, SEEK_CUR); // Size is 6-9 position if (fread(tmp, 1, 4, file) != 4) // Read bytes of tag size { fclose(file); return FALSE; } id3v2size = 10 + ( (long)(tmp[3]) | ((long)(tmp[2]) << 7) | ((long)(tmp[1]) << 14) | ((long)(tmp[0]) << 21) ); fseek(file, id3v2size, SEEK_SET); if (fread(tmp, 1, 4, file) != 4) // Read mpeg header { fclose(file); return FALSE; } } head = ((guint32) tmp[0] << 24) | ((guint32) tmp[1] << 16) | ((guint32) tmp[2] << 8) | (guint32) tmp[3]; while (!mpg123_head_check(head)) { head <<= 8; if (fread(tmp, 1, 1, file) != 1) { fclose(file); return FALSE; } head |= tmp[0]; } if (mpg123_decode_header(&frm, head)) { guchar *buf; gdouble tpf; gint pos; XHEADDATA xing_header; guint32 num_frames; buf = g_malloc(frm.framesize + 4); fseek(file, -4, SEEK_CUR); fread(buf, 1, frm.framesize + 4, file); xing_header.toc = NULL; tpf = mpg123_compute_tpf(&frm); // MPEG and Layer version ETFileInfo->mpeg25 = frm.mpeg25; if (!ETFileInfo->mpeg25) ETFileInfo->version = frm.lsf+1; ETFileInfo->layer = frm.lay; //if (ETFileInfo->mpeg25) g_print("mpeg_level: MPEG 2.5, layer %d\n",ETFileInfo->layer); //else g_print("mpeg_level: MPEG %d, layer %d\n",ETFileInfo->version,ETFileInfo->layer); pos = ftell(file); fseek(file, 0, SEEK_END); // Variable bitrate? + bitrate if ( (ETFileInfo->variable_bitrate=mpg123_get_xing_header(&xing_header,buf)) ) { num_frames = xing_header.frames; ETFileInfo->bitrate = (gint) ((xing_header.bytes * 8) / (tpf * xing_header.frames * 1000)); //g_print("Bitrate: Variable,\navg. bitrate: %d kb/s\n",ETFileInfo->bitrate); } else { num_frames = ((ftell(file) - pos - (id3_found ? 128 : 0)) / mpg123_compute_bpf(&frm)) + 1; ETFileInfo->bitrate = tabsel_123[frm.lsf][frm.lay - 1][frm.bitrate_index]; //g_print("Bitrate: %d kb/s\n",ETFileInfo->bitrate); } // Samplerate ETFileInfo->samplerate = mpg123_freqs[frm.sampling_frequency]; // Mode ETFileInfo->mode = frm.mode; //g_print("Samplerate: %ld Hz\n", mpg123_freqs[frm.sampling_frequency]); //g_print("%s\nError protection: %s\nCopyright: %s\nOriginal: %s\nEmphasis: %s\n", channel_mode_name(frm.mode), bool_label[frm.error_protection], bool_label[frm.copyright], bool_label[frm.original], emphasis[frm.emphasis]); //g_print("%d frames\nFilesize: %lu B\n", num_frames, ftell(file)); g_free(buf); } // Duration ETFileInfo->duration = mpg123_get_song_time(file)/1000; //g_print("time %s\n",Convert_Duration(ETFileInfo->duration)); fclose(file); }else { gchar *filename_utf8 = filename_to_display(filename); Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno)); g_free(filename_utf8); return FALSE; } #else // Needs to uncomment some #include at the beginning /* * With id3lib, the header frame couldn't be read if the file contains an ID3v2 tag with an APIC frame */ gulong filesize; ID3Tag *id3_tag = NULL; /* Tag defined by the id3lib */ const Mp3_Headerinfo* headerInfo = NULL; if (!filename || !ETFileInfo) return FALSE; /* Get size of file */ filesize = Get_File_Size(filename); ETFileInfo->size = filesize; /* Get data from tag */ if ( (id3_tag = ID3Tag_New()) == NULL ) return FALSE; /* Link the file to the tag (uses ID3TT_ID3V2 to get header if APIC is present in Tag) */ ID3Tag_LinkWithFlags(id3_tag,filename,ID3TT_ID3V2); /*ID3_STRUCT(Mp3_Headerinfo) { Mpeg_Layers layer; Mpeg_Version version; MP3_BitRates bitrate; Mp3_ChannelMode channelmode; Mp3_ModeExt modeext; Mp3_Emphasis emphasis; Mp3_Crc crc; uint32 vbr_bitrate; // avg bitrate from xing header uint32 frequency; // samplerate uint32 framesize; uint32 frames; // nr of frames uint32 time; // nr of seconds in song bool privatebit; bool copyrighted; bool original; };*/ if ( (headerInfo = ID3Tag_GetMp3HeaderInfo(id3_tag)) ) { switch (headerInfo->version) { case MPEGVERSION_1: ETFileInfo->version = 1; ETFileInfo->mpeg25 = FALSE; break; case MPEGVERSION_2: ETFileInfo->version = 2; ETFileInfo->mpeg25 = FALSE; break; case MPEGVERSION_2_5: ETFileInfo->mpeg25 = TRUE; ETFileInfo->mpeg25 = FALSE; break; default: break; } switch (headerInfo->layer) { case MPEGLAYER_I: ETFileInfo->layer = 1; break; case MPEGLAYER_II: ETFileInfo->layer = 2; break; case MPEGLAYER_III: ETFileInfo->layer = 3; break; default: break; } // Samplerate ETFileInfo->samplerate = headerInfo->frequency; // Mode -> Seems to be detected but incorrect?! switch (headerInfo->modeext) { case MP3CHANNELMODE_STEREO: ETFileInfo->mode = 0; break; case MP3CHANNELMODE_JOINT_STEREO: ETFileInfo->mode = 1; break; case MP3CHANNELMODE_DUAL_CHANNEL: ETFileInfo->mode = 2; break; case MP3CHANNELMODE_SINGLE_CHANNEL: ETFileInfo->mode = 3; break; default: break; } // Bitrate if (headerInfo->vbr_bitrate <= 0) { ETFileInfo->variable_bitrate = FALSE; ETFileInfo->bitrate = headerInfo->bitrate/1000; }else { ETFileInfo->variable_bitrate = TRUE; ETFileInfo->bitrate = headerInfo->vbr_bitrate/1000; } // Duration ETFileInfo->duration = headerInfo->time; } /* Free allocated data */ ID3Tag_Delete(id3_tag); #endif return TRUE; }
/* * Mp4_Tag_Read_File_Tag: * * Read tag data into an Mp4 file. * * Note: * - for string fields, //if field is found but contains no info (strlen(str)==0), we don't read it * - for track numbers, if they are zero, then we don't read it */ gboolean Mp4tag_Read_File_Tag (gchar *filename, File_Tag *FileTag) { FILE *file; TagLib_File *mp4file; TagLib_Tag *tag; guint track; if (!filename || !FileTag) return FALSE; if ( (file=fopen(filename,"r"))==NULL ) { gchar *filename_utf8 = filename_to_display(filename); Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno)); g_free(filename_utf8); return FALSE; } fclose(file); // We close it cause mp4 opens/closes file itself /* Get data from tag */ mp4file = taglib_file_new_type(filename,TagLib_File_MP4); if (mp4file == NULL) { gchar *filename_utf8 = filename_to_display(filename); Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,_("MP4 format invalid")); g_free(filename_utf8); return FALSE; } /* TODO Add error detection */ tag = taglib_file_tag(mp4file); /********* * Title * *********/ FileTag->title = g_strdup(taglib_tag_title(tag)); /********** * Artist * **********/ FileTag->artist = g_strdup(taglib_tag_artist(tag)); /********* * Album * *********/ FileTag->album = g_strdup(taglib_tag_album(tag)); /**************** * Album Artist * ****************/ /* TODO: No album artist or disc number support in the TagLib C API! */ /******** * Year * ********/ FileTag->year = g_strdup_printf("%u", taglib_tag_year(tag)); /************************* * Track and Total Track * *************************/ track = taglib_tag_track(tag); if (track != 0) FileTag->track = NUMBER_TRACK_FORMATED ? g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,(gint)track) : g_strdup_printf("%d",(gint)track); /* TODO: No total track support in the TagLib C API! */ /********* * Genre * *********/ FileTag->genre = g_strdup(taglib_tag_genre(tag)); /*********** * Comment * ***********/ FileTag->comment = g_strdup(taglib_tag_comment(tag)); /********************** * Composer or Writer * **********************/ /* TODO: No composer support in the TagLib C API! */ /***************** * Encoding Tool * *****************/ /* TODO: No encode_by support in the TagLib C API! */ /*********** * Picture * ***********/ /* TODO: No encode_by support in the TagLib C API! */ /* Free allocated data */ taglib_tag_free_strings(); taglib_file_free(mp4file); return TRUE; }