static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error) { FLAC__byte buffer[4]; const unsigned ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8; size_t block_num = 0; FLAC__ASSERT(sizeof(buffer) >= ID_LEN); while(block_num < fm->num_blocks) { /* find next matching padding block */ do { /* even on the first chunk's loop there will be a skippable STREAMINFO block, on subsequent loops we are first moving past the PADDING we just used */ if(!FLAC__metadata_simple_iterator_next(it)) { if(error) *error = "no matching PADDING block found (004)"; return false; } } while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING); if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) { if(error) *error = "PADDING block with wrong size found (005)"; return false; } /* transfer chunk into APPLICATION block */ /* first set up the file pointers */ if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) { if(error) *error = "seek failed in WAVE/AIFF file (006)"; return false; } if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) { if(error) *error = "seek failed in FLAC file (007)"; return false; } /* update the type */ buffer[0] = FLAC__METADATA_TYPE_APPLICATION; if(FLAC__metadata_simple_iterator_is_last(it)) buffer[0] |= 0x80; /*MAGIC number*/ if(fwrite(buffer, 1, 1, fout) < 1) { if(error) *error = "write failed in FLAC file (008)"; return false; } /* length stays the same so skip over it */ if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) { if(error) *error = "seek failed in FLAC file (009)"; return false; } /* write the APPLICATION ID */ memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN); if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) { if(error) *error = "write failed in FLAC file (010)"; return false; } /* transfer the foreign metadata */ if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)")) return false; block_num++; } return true; }
int flac_write( const char* filename, const char *predicate, const char* uri ) { if (strcmp(predicate, LL_LICENSE) != 0) { return -LL_E_MODULE_WRITE_FAIL; /* We only know License */ } int ret = 1; FLAC__Metadata_SimpleIterator *iter = FLAC__metadata_simple_iterator_new(); if (FLAC__metadata_simple_iterator_init(iter,filename,false,false) && FLAC__metadata_simple_iterator_is_writable(iter)) { FLAC__bool found_vc = false; do { if (FLAC__metadata_simple_iterator_get_block_type(iter) == FLAC__METADATA_TYPE_VORBIS_COMMENT) { FLAC__StreamMetadata *vc; found_vc = true; vc = FLAC__metadata_simple_iterator_get_block(iter); if (uri) { FLAC__StreamMetadata_VorbisComment_Entry entry; FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "LICENSE", uri); FLAC__metadata_object_vorbiscomment_replace_comment(vc,entry,true,false); } else { int i = FLAC__metadata_object_vorbiscomment_find_entry_from(vc,0,"LICENSE"); if (i != -1) { FLAC__metadata_object_vorbiscomment_delete_comment(vc,i); } } ret = FLAC__metadata_simple_iterator_set_block(iter, vc, true); FLAC__metadata_object_delete(vc); break; } } while (FLAC__metadata_simple_iterator_next(iter)); if (!found_vc && uri) { FLAC__StreamMetadata *vc = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT); FLAC__StreamMetadata_VorbisComment_Entry entry; FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "LICENSE", uri); FLAC__metadata_object_vorbiscomment_append_comment(vc,entry,false); ret = FLAC__metadata_simple_iterator_insert_block_after(iter,vc,true); FLAC__metadata_object_delete(vc); } } else { ret = 0; } FLAC__metadata_simple_iterator_delete(iter); return ret; }
/* FLAC implementation. notice, it uses the ogg functions when the FLAC comment is extracted */ static text_tag_s *get_flac_text_tag (const char *filename) { text_tag_s *text_tag = new_text_tag (); char buf[256]; FLAC__StreamMetadata *metadata = malloc (sizeof (FLAC__StreamMetadata)); FLAC__Metadata_SimpleIterator *iter = FLAC__metadata_simple_iterator_new (); if (FLAC__metadata_simple_iterator_init (iter, filename, true, false) != true) { snprintf (buf, 256, "Problem reading file \'%s\'", filename); log_msg (buf, FL, FN, LN); free (metadata); FLAC__metadata_simple_iterator_delete (iter); free_text_tag (text_tag); return NULL; } do { int i = 0; switch (FLAC__metadata_simple_iterator_get_block_type (iter)) { case FLAC__METADATA_TYPE_STREAMINFO: metadata = FLAC__metadata_simple_iterator_get_block (iter); text_tag->frequency = metadata->data.stream_info.sample_rate; text_tag->songlength = metadata->data.stream_info.total_samples / metadata->data.stream_info.sample_rate; text_tag->bitrate = (int)((metadata->data.stream_info.total_samples * metadata->data.stream_info.bits_per_sample) / text_tag->songlength); break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: metadata = FLAC__metadata_simple_iterator_get_block (iter); for (i = 0; i < metadata->data.vorbis_comment.num_comments; i++) { int type = get_ogg_type (metadata->data.vorbis_comment.comments[i].entry); parse_ogg_content (metadata->data.vorbis_comment.comments[i].entry, metadata->data.vorbis_comment.comments[i].length, &text_tag, type); } break; default: //printf ("Unhandled metadata type\n"); break; } } while (FLAC__metadata_simple_iterator_next (iter) == true); fill_null_text_tag (text_tag); FLAC__metadata_simple_iterator_delete (iter); free (metadata); return text_tag; }
static PyObject * flac_MetadataSimpleIterator_next (flac_MetadataSimpleIteratorObject *self) { PyFLAC_CHECK_initialized(self); self->next = true; if (FLAC__metadata_simple_iterator_next(self->iterator)) Py_RETURN_TRUE; if (flac_MetadataSimpleIterator_PyErr_FromIteratorStatus(self) < 0) return NULL; Py_RETURN_FALSE; }
static PyObject * flac_MetadataSimpleIterator_get_next_block (flac_MetadataSimpleIteratorObject *self) { #ifndef __PyFLAC3__ self = ((flac_MetadataSimpleIteratorIterObject *) self)->parent; #endif // __PyFLAC3__ PyFLAC_CHECK_initialized(self); if (self->next && !FLAC__metadata_simple_iterator_next(self->iterator)) { flac_MetadataSimpleIterator_PyErr_FromIteratorStatus(self); return NULL; } self->next = true; return flac_MetadataSimpleIterator__get_block(self); }
void FLAC_plugin__vorbiscomment_get(const char *filename, FLAC_Plugin__CanonicalTag *tag) { FLAC__Metadata_SimpleIterator *iterator = FLAC__metadata_simple_iterator_new(); if(0 != iterator) { if(FLAC__metadata_simple_iterator_init(iterator, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) { FLAC__bool got_vorbis_comments = false; do { if(FLAC__metadata_simple_iterator_get_block_type(iterator) == FLAC__METADATA_TYPE_VORBIS_COMMENT) { FLAC__StreamMetadata *block = FLAC__metadata_simple_iterator_get_block(iterator); if(0 != block) { unsigned i; const FLAC__StreamMetadata_VorbisComment *vc = &block->data.vorbis_comment; for(i = 0; i < vc->num_comments; i++) { if(local__vcentry_matches("artist", &vc->comments[i])) local__vcentry_parse_value(&vc->comments[i], &tag->composer); else if(local__vcentry_matches("performer", &vc->comments[i])) local__vcentry_parse_value(&vc->comments[i], &tag->performer); else if(local__vcentry_matches("album", &vc->comments[i])) local__vcentry_parse_value(&vc->comments[i], &tag->album); else if(local__vcentry_matches("title", &vc->comments[i])) local__vcentry_parse_value(&vc->comments[i], &tag->title); else if(local__vcentry_matches("tracknumber", &vc->comments[i])) local__vcentry_parse_value(&vc->comments[i], &tag->track_number); else if(local__vcentry_matches("genre", &vc->comments[i])) local__vcentry_parse_value(&vc->comments[i], &tag->genre); else if(local__vcentry_matches("description", &vc->comments[i])) local__vcentry_parse_value(&vc->comments[i], &tag->comment); } FLAC__metadata_object_delete(block); got_vorbis_comments = true; } } } while (!got_vorbis_comments && FLAC__metadata_simple_iterator_next(iterator)); } FLAC__metadata_simple_iterator_delete(iterator); } }
FLAC__bool FLAC_plugin__replaygain_get_from_file(const char *filename, double *reference, FLAC__bool *reference_set, double *track_gain, FLAC__bool *track_gain_set, double *album_gain, FLAC__bool *album_gain_set, double *track_peak, FLAC__bool *track_peak_set, double *album_peak, FLAC__bool *album_peak_set) { FLAC__Metadata_SimpleIterator *iterator = FLAC__metadata_simple_iterator_new(); FLAC__bool ret = false; *track_gain_set = *album_gain_set = *track_peak_set = *album_peak_set = false; if(0 != iterator) { if(FLAC__metadata_simple_iterator_init(iterator, filename, /*read_only=*/true, /*preserve_file_stats=*/true)) { FLAC__bool got_vorbis_comments = false; ret = true; do { if(FLAC__metadata_simple_iterator_get_block_type(iterator) == FLAC__METADATA_TYPE_VORBIS_COMMENT) { FLAC__StreamMetadata *block = FLAC__metadata_simple_iterator_get_block(iterator); if(0 != block) { if(grabbag__replaygain_load_from_vorbiscomment(block, /*album_mode=*/false, /*strict=*/true, reference, track_gain, track_peak)) { *reference_set = *track_gain_set = *track_peak_set = true; } if(grabbag__replaygain_load_from_vorbiscomment(block, /*album_mode=*/true, /*strict=*/true, reference, album_gain, album_peak)) { *reference_set = *album_gain_set = *album_peak_set = true; } FLAC__metadata_object_delete(block); got_vorbis_comments = true; } } } while (!got_vorbis_comments && FLAC__metadata_simple_iterator_next(iterator)); } FLAC__metadata_simple_iterator_delete(iterator); } return ret; }
static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error) { FLAC__byte id[4], buffer[12]; FLAC__off_t offset; FLAC__bool type_found = false, ds64_found = false; FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8); while(FLAC__metadata_simple_iterator_next(it)) { if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION) continue; if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) { if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (002)"; return false; } if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id))) continue; offset = FLAC__metadata_simple_iterator_get_block_offset(it); /* skip over header and app ID */ offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8; offset += sizeof(id); /* look for format or audio blocks */ if(fseeko(f, offset, SEEK_SET) < 0) { if(error) *error = "seek error (003)"; return false; } if(fread(buffer, 1, 4, f) != 4) { if(error) *error = "read error (004)"; return false; } if(fm->num_blocks == 0) { /* first block? */ fm->is_rf64 = 0 == memcmp(buffer, "RF64", 4); if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && (0 == memcmp(buffer, "RIFF", 4) || fm->is_rf64)) type_found = true; else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64 && 0 == memcmp(buffer, "riff", 4)) /* use first 4 bytes instead of whole GUID */ type_found = true; else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4)) type_found = true; else { if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)"; return false; } } else if(!type_found) { FLAC__ASSERT(0); /* double protection: */ if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)"; return false; } else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) { if(!memcmp(buffer, "fmt ", 4)) { if(fm->format_block) { if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)"; return false; } if(fm->audio_block) { if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)"; return false; } fm->format_block = fm->num_blocks; } else if(!memcmp(buffer, "data", 4)) { if(fm->audio_block) { if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)"; return false; } if(!fm->format_block) { if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)"; return false; } fm->audio_block = fm->num_blocks; } else if(fm->is_rf64 && fm->num_blocks == 1) { if(memcmp(buffer, "ds64", 4)) { if(error) *error = "invalid RF64 metadata: second chunk is not \"ds64\" (011)"; return false; } ds64_found = true; } } else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64) { if(!memcmp(buffer, "fmt ", 4)) { /* use first 4 bytes instead of whole GUID */ if(fm->format_block) { if(error) *error = "invalid Wave64 metadata: multiple \"fmt \" chunks (012)"; return false; } if(fm->audio_block) { if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (013)"; return false; } fm->format_block = fm->num_blocks; } else if(!memcmp(buffer, "data", 4)) { /* use first 4 bytes instead of whole GUID */ if(fm->audio_block) { if(error) *error = "invalid Wave64 metadata: multiple \"data\" chunks (014)"; return false; } if(!fm->format_block) { if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (015)"; return false; } fm->audio_block = fm->num_blocks; } } else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) { if(!memcmp(buffer, "COMM", 4)) { if(fm->format_block) { if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (016)"; return false; } if(fm->audio_block) { if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (017)"; return false; } fm->format_block = fm->num_blocks; } else if(!memcmp(buffer, "SSND", 4)) { if(fm->audio_block) { if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (018)"; return false; } if(!fm->format_block) { if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (019)"; return false; } fm->audio_block = fm->num_blocks; /* read SSND offset size */ if(fread(buffer+4, 1, 8, f) != 8) { if(error) *error = "read error (020)"; return false; } fm->ssnd_offset_size = unpack32be_(buffer+8); } } else { FLAC__ASSERT(0); /* double protection: */ if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (021)"; return false; } if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error)) return false; } if(!type_found) { if(error) *error = "no foreign metadata found (022)"; return false; } if(fm->is_rf64 && !ds64_found) { if(error) *error = "invalid RF64 file: second chunk is not \"ds64\" (023)"; return false; } if(!fm->format_block) { if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (024)" : fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"fmt \" chunk (025)" : "invalid AIFF file: missing \"COMM\" chunk (026)"; return false; } if(!fm->audio_block) { if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (027)" : fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"data\" chunk (028)" : "invalid AIFF file: missing \"SSND\" chunk (029)"; return false; } return true; }
static int _get_flctags(char *filename, struct song_metadata *psong) { FLAC__Metadata_SimpleIterator *iterator = 0; FLAC__StreamMetadata *block; int block_number; unsigned int sec, ms; int i; int err = 0; if(!(iterator = FLAC__metadata_simple_iterator_new())) { DPRINTF(E_FATAL, L_SCANNER, "Out of memory while FLAC__metadata_simple_iterator_new()\n"); return -1; } block_number = 0; if(!FLAC__metadata_simple_iterator_init(iterator, filename, true, true)) { DPRINTF(E_ERROR, L_SCANNER, "Cannot extract tag from %s\n", filename); return -1; } do { if(!(block = FLAC__metadata_simple_iterator_get_block(iterator))) { DPRINTF(E_ERROR, L_SCANNER, "Cannot extract tag from %s\n", filename); err = -1; goto _exit; } switch(block->type) { case FLAC__METADATA_TYPE_STREAMINFO: sec = (unsigned int)(block->data.stream_info.total_samples / block->data.stream_info.sample_rate); ms = (unsigned int)(((block->data.stream_info.total_samples % block->data.stream_info.sample_rate) * 1000) / block->data.stream_info.sample_rate); if ((sec == 0) && (ms == 0)) break; /* Info is crap, escape div-by-zero. */ psong->song_length = (sec * 1000) + ms; psong->bitrate = (((uint64_t)(psong->file_size) * 1000) / (psong->song_length / 8)); psong->samplerate = block->data.stream_info.sample_rate; psong->channels = block->data.stream_info.channels; break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: for(i = 0; i < block->data.vorbis_comment.num_comments; i++) { vc_scan(psong, (char*)block->data.vorbis_comment.comments[i].entry, block->data.vorbis_comment.comments[i].length); } break; #if FLAC_API_VERSION_CURRENT >= 10 case FLAC__METADATA_TYPE_PICTURE: psong->image_size = block->data.picture.data_length; if((psong->image = malloc(psong->image_size))) memcpy(psong->image, block->data.picture.data, psong->image_size); else DPRINTF(E_ERROR, L_SCANNER, "Out of memory [%s]\n", filename); break; #endif default: break; } FLAC__metadata_object_delete(block); } while(FLAC__metadata_simple_iterator_next(iterator)); _exit: if(iterator) FLAC__metadata_simple_iterator_delete(iterator); return err; }
/* * 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; }
G_MODULE_EXPORT gboolean tracker_extract_get_metadata (TrackerExtractInfo *info) { FLAC__Metadata_SimpleIterator *iter; FLAC__StreamMetadata *stream = NULL, *vorbis, *picture; FLAC__bool success; FlacData fd = { 0 }; TrackerSparqlBuilder *preupdate, *metadata; gchar *filename, *uri, *artist_uri = NULL, *album_uri = NULL; const gchar *creator; GFile *file; goffset size; const gchar *graph; graph = tracker_extract_info_get_graph (info); preupdate = tracker_extract_info_get_preupdate_builder (info); metadata = tracker_extract_info_get_metadata_builder (info); file = tracker_extract_info_get_file (info); filename = g_file_get_path (file); size = tracker_file_get_size (filename); if (size < 18) { g_free (filename); return FALSE; } iter = FLAC__metadata_simple_iterator_new (); success = FLAC__metadata_simple_iterator_init (iter, filename, TRUE, TRUE); g_free (filename); if (!success) { FLAC__metadata_simple_iterator_delete (iter); return FALSE; } uri = g_file_get_uri (file); do { switch (FLAC__metadata_simple_iterator_get_block_type (iter)) { case FLAC__METADATA_TYPE_STREAMINFO: stream = FLAC__metadata_simple_iterator_get_block (iter); break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: vorbis = FLAC__metadata_simple_iterator_get_block (iter); parse_vorbis_comments (&(vorbis->data.vorbis_comment), &fd); FLAC__metadata_object_delete (vorbis); break; case FLAC__METADATA_TYPE_PICTURE: picture = FLAC__metadata_simple_iterator_get_block (iter); /* Deal with picture */ FLAC__metadata_object_delete (picture); break; default: break; } } while (FLAC__metadata_simple_iterator_next (iter)); creator = tracker_coalesce_strip (3, fd.artist, fd.albumartist, fd.performer); if (creator) { artist_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", creator); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, artist_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nmm:Artist"); tracker_sparql_builder_predicate (preupdate, "nmm:artistName"); tracker_sparql_builder_object_unvalidated (preupdate, creator); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (fd.album) { if (fd.albumartist) { album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s:%s", fd.album, fd.albumartist); } else { album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s", fd.album); } tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nmm:MusicAlbum"); /* FIXME: nmm:albumTitle is now deprecated * tracker_sparql_builder_predicate (preupdate, "nie:title"); */ tracker_sparql_builder_predicate (preupdate, "nmm:albumTitle"); tracker_sparql_builder_object_unvalidated (preupdate, fd.album); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); if (fd.trackcount) { tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount"); tracker_sparql_builder_object_unvalidated (preupdate, fd.trackcount); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (fd.albumgain) { tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumGain"); tracker_sparql_builder_object_double (preupdate, atof (fd.albumgain)); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } if (fd.albumpeakgain) { tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain"); tracker_sparql_builder_object_double (preupdate, atof (fd.albumpeakgain)); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); } } tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nmm:MusicPiece"); tracker_sparql_builder_object (metadata, "nfo:Audio"); add_tuple (metadata, "nmm:performer", artist_uri); g_free (artist_uri); add_tuple (metadata, "nmm:musicAlbum", album_uri); tracker_guarantee_title_from_file (metadata, "nie:title", fd.title, uri, NULL); add_tuple (metadata, "nmm:trackNumber", fd.tracknumber); if (fd.album && album_uri) { gchar *album_disc_uri; if (fd.albumartist) { album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:%s:Disc%d", fd.album, fd.albumartist, fd.discno ? atoi(fd.discno) : 1); } else { album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d", fd.album, fd.discno ? atoi(fd.discno) : 1); } tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_delete_open (preupdate, NULL); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_delete_close (preupdate); tracker_sparql_builder_where_open (preupdate); tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); tracker_sparql_builder_object_variable (preupdate, "unknown"); tracker_sparql_builder_where_close (preupdate); tracker_sparql_builder_insert_open (preupdate, NULL); if (graph) { tracker_sparql_builder_graph_open (preupdate, graph); } tracker_sparql_builder_subject_iri (preupdate, album_disc_uri); tracker_sparql_builder_predicate (preupdate, "a"); tracker_sparql_builder_object (preupdate, "nmm:MusicAlbumDisc"); tracker_sparql_builder_predicate (preupdate, "nmm:setNumber"); tracker_sparql_builder_object_int64 (preupdate, fd.discno ? atoi (fd.discno) : 1); tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum"); tracker_sparql_builder_object_iri (preupdate, album_uri); if (graph) { tracker_sparql_builder_graph_close (preupdate); } tracker_sparql_builder_insert_close (preupdate); tracker_sparql_builder_predicate (metadata, "nmm:musicAlbumDisc"); tracker_sparql_builder_object_iri (metadata, album_disc_uri); g_free (album_disc_uri); } g_free (album_uri); /* FIXME: Trackgain/Trackpeakgain: commented out in vorbis */ add_tuple (metadata, "nie:comment", fd.comment); add_tuple (metadata, "nie:contentCreated", fd.date); add_tuple (metadata, "nfo:genre", fd.genre); add_tuple (metadata, "nie:plainTextContent", fd.lyrics); add_tuple (metadata, "nie:copyright", fd.copyright); add_tuple (metadata, "nie:license", fd.license); if (fd.publisher) { tracker_sparql_builder_predicate (metadata, "dc:publisher"); tracker_sparql_builder_object_blank_open (metadata); tracker_sparql_builder_predicate (metadata, "a"); tracker_sparql_builder_object (metadata, "nco:Contact"); tracker_sparql_builder_predicate (metadata, "nco:fullname"); tracker_sparql_builder_object_unvalidated (metadata, fd.publisher); tracker_sparql_builder_object_blank_close (metadata); } if (stream) { tracker_sparql_builder_predicate (metadata, "nfo:sampleRate"); tracker_sparql_builder_object_int64 (metadata, stream->data.stream_info.sample_rate); tracker_sparql_builder_predicate (metadata, "nfo:channels"); tracker_sparql_builder_object_int64 (metadata, stream->data.stream_info.channels); tracker_sparql_builder_predicate (metadata, "nfo:averageBitrate"); tracker_sparql_builder_object_int64 (metadata, stream->data.stream_info.bits_per_sample); tracker_sparql_builder_predicate (metadata, "nfo:duration"); tracker_sparql_builder_object_int64 (metadata, stream->data.stream_info.total_samples / stream->data.stream_info.sample_rate); } g_free (fd.artist); g_free (fd.album); g_free (fd.albumartist); g_free (fd.performer); g_free (fd.title); g_free (fd.trackcount); g_free (fd.tracknumber); g_free (fd.discno); g_free (fd.trackgain); g_free (fd.trackpeakgain); g_free (fd.albumgain); g_free (fd.albumpeakgain); g_free (fd.date); g_free (fd.comment); g_free (fd.genre); g_free (fd.mbalbumid); g_free (fd.mbartistid); g_free (fd.mbalbumartistid); g_free (fd.mbtrackid); g_free (fd.lyrics); g_free (fd.copyright); g_free (fd.license); g_free (fd.organisation); g_free (fd.location); g_free (fd.publisher); g_free (uri); return TRUE; }