Hello -
I hate to generate traffic that might be FAQs on such a quiet list, but I can't seem to find my answers in any of the places I know about. I've got two separate questions which I will place in two messages after I make this contribution.
I'm trying to update id3v2.4 tags using libid3tag. I implemented Sam Clegg's modifications until I found the part where he hadn't modified the id3_file_update function, so I wrote one and am enclosing it for your consumption and comment. Instead of using Sam's id3_file_open function, I added an argument to id3_file_update for the new file name. Please adapt as you see fit.
I added a field to the id3_file struct: struct id3_file { ... fpos_t id3v2End; // MDM };
Then in search_tags I added the line:
fgetpos(file->iofile, &file->id3v2End);
After all the tags were located (before the comment that reads "look for a tag at the end of the file (before any ID3v1 tag").
Then I replaced the id3_file_update function. No flames please about the style. Goto is not a bad word in my dictionary if used judiciously. :-) Again, adapt as you see fit.
/* * NAME: file->update() * DESCRIPTION: rewrite tag(s) to a file */ int id3_file_update(struct id3_file *file, const char *newFileName) { id3_length_t size; FILE *f = NULL; fpos_t savePos, fileSize; char *contents = NULL;
if (file->mode != ID3_FILE_MODE_READWRITE) goto Err0;
/* ** Scoop in the whole file */ if (fgetpos(file->iofile, &savePos) == -1) goto Err0;
if (fseek (file->iofile, 0, SEEK_END) == -1) goto Err0;
if (fgetpos(file->iofile, &fileSize) == -1) goto Err0;
if (fseek (file->iofile, 0, SEEK_SET) == -1) goto Err0;
if ((contents = (char *) malloc (fileSize)) == NULL) goto Err0;
if (fread (contents, 1, fileSize, file->iofile) != fileSize) goto Err0;
if (fsetpos (file->iofile, &savePos) == -1) goto Err0;
/* ** Open the new file */ if ((f = fopen (newFileName, "w")) == NULL) goto Err0;
/* ** Now render the v2 tag */ file->primary->options &= ~ID3_TAG_OPTION_ID3V1; file->primary->options &= ~ID3_TAG_OPTION_CRC; // Prevent extended header
if ((size = id3_tag_render(file->primary, 0)) > 0) { unsigned char *id3v2 = NULL;
if ((id3v2 = malloc(size)) == 0) goto Err0;
if ((size = id3_tag_render(file->primary, id3v2)) != 0) fwrite (id3v2, size, 1, f);
free(id3v2); }
/* ** Now write the remainder of the file */ { char *writeBuf; fpos_t writeSize;
writeBuf = contents + file->id3v2End; writeSize = fileSize - file->id3v2End; if (file->options | ID3_FILE_OPTION_ID3V1) writeSize -= 128;
fwrite (writeBuf, writeSize, 1, f); }
/* ** Now render the v1 tag */ if (file->options | ID3_FILE_OPTION_ID3V1) { file->primary->options |= ID3_TAG_OPTION_ID3V1;
if ((size = id3_tag_render(file->primary, 0)) > 0) { unsigned char *id3v1 = NULL;
if ((id3v1 = malloc(size)) == 0) return -1;
if ((size = id3_tag_render(file->primary, id3v1)) != 0) fwrite (id3v1, size, 1, f);
free(id3v1); } }
fclose(f); free (contents); return 0;
Err0: if (f) fclose (f); if (contents) free (contents); return -1; }