Rob Leslie wrote:
The file API of libid3tag presents a single view of all the tags contained in a file, and does not differentiate between V1 and V2 tags. The idea is that V1 and V2 tags should represent the same information about a file, and if both are present then V2 information is preferred because its field lengths are not constrained as in V1. (When writing tags back to a file, the intent is that the file interface will generate both V1 and V2 tags from the same source, ensuring consistency.)
This is certainly a sensible strategy. To that end, I think it would be useful to allow the application to determine what the V1 equivalent of the V2 information is. Sometimes it is possible to create a better V1 equivalent of a V2 tag by abbreviating certain words or phrases. For example, if the V2 title is something like "While the Earth Sleeps (Pet Shop Boys Remix)", the truncated version is "While the Earth Sleeps (Pet Sh", whereas a more informative alternative is "While the Earth Sleeps (PSB)". Obviously, it's beyond the scope of libid3tag to be able to generate abbreviations for this method. They should be handled by the application. But in order to do that, however, the library would have to allow the application to override what it considers to be the equivalent V1 tag, or to put it more simply, the application would have to be allowed to set the V2 and V1 tags independantly of each other.
Accordingly, it's not possible to access the V1 and V2 information as separate tags with the file interface. If you really want to do this, you can use the tag parsing and rendering routines to maintain separate tag structures and data, but you'll have to read and write the data from the file yourself.
I'm preared to do this if necessary, however it occurs to me that what I'll end up doing is rewriting, almost verbatim, functions that already exist in libid3tag (new_file() and the like). The only reason I couldn't use the library functions is that they aren't exported to the API. This seems like a bit of a waste since I have to link to the library anyway.
Would you be willing to accept a few patches which expose a bit more of the library's internals to the API?
- Cedric
Rob? Anybody?
Rob Leslie wrote:
The file API of libid3tag presents a single view of all the tags contained in a file, and does not differentiate between V1 and V2 tags. The idea is that V1 and V2 tags should represent the same information about a file, and if both are present then V2 information is preferred because its field lengths are not constrained as in V1. (When writing tags back to a file, the intent is that the file interface will generate both V1 and V2 tags from the same source, ensuring consistency.)
This is certainly a sensible strategy. To that end, I think it would be useful to allow the application to determine what the V1 equivalent of the V2 information is. Sometimes it is possible to create a better V1 equivalent of a V2 tag by abbreviating certain words or phrases. For example, if the V2 title is something like "While the Earth Sleeps (Pet Shop Boys Remix)", the truncated version is "While the Earth Sleeps (Pet Sh", whereas a more informative alternative is "While the Earth Sleeps (PSB)". Obviously, it's beyond the scope of libid3tag to be able to generate abbreviations for this method. They should be handled by the application. But in order to do that, however, the library would have to allow the application to override what it considers to be the equivalent V1 tag, or to put it more simply, the application would have to be allowed to set the V2 and V1 tags independantly of each other.
Accordingly, it's not possible to access the V1 and V2 information as separate tags with the file interface. If you really want to do this, you can use the tag parsing and rendering routines to maintain separate tag structures and data, but you'll have to read and write the data from the file yourself.
I'm preared to do this if necessary, however it occurs to me that what I'll end up doing is rewriting, almost verbatim, functions that already exist in libid3tag (new_file() and the like). The only reason I couldn't use the library functions is that they aren't exported to the API. This seems like a bit of a waste since I have to link to the library anyway.
Would you be willing to accept a few patches which expose a bit more of the library's internals to the API?
- Cedric
On Sep 9, 2004, at 8:55 PM, Cedric Tefft wrote:
Accordingly, it's not possible to access the V1 and V2 information as separate tags with the file interface. If you really want to do this, you can use the tag parsing and rendering routines to maintain separate tag structures and data, but you'll have to read and write the data from the file yourself.
I'm preared to do this if necessary, however it occurs to me that what I'll end up doing is rewriting, almost verbatim, functions that already exist in libid3tag (new_file() and the like). The only reason I couldn't use the library functions is that they aren't exported to the API. This seems like a bit of a waste since I have to link to the library anyway.
Would you be willing to accept a few patches which expose a bit more of the library's internals to the API?
I'll consider it, but it seems you should not have to duplicate much functionality. Once you have a tag structure containing the desired V1 data, it is very easy to render and apply to a file.
Simply disable the ID3_TAG_OPTION_ID3V1 option on the file interface's primary tag and the file interface will ensure the V1 tag is absent when the tags are updated. You can then directly append to the file whatever V1 tag data you prefer.
Rob Leslie wrote:
On Sep 9, 2004, at 8:55 PM, Cedric Tefft wrote:
Accordingly, it's not possible to access the V1 and V2 information as separate tags with the file interface. If you really want to do this, you can use the tag parsing and rendering routines to maintain separate tag structures and data, but you'll have to read and write the data from the file yourself.
I'm preared to do this if necessary, however it occurs to me that what I'll end up doing is rewriting, almost verbatim, functions that already exist in libid3tag (new_file() and the like). The only reason I couldn't use the library functions is that they aren't exported to the API. This seems like a bit of a waste since I have to link to the library anyway.
Would you be willing to accept a few patches which expose a bit more of the library's internals to the API?
I'll consider it, but it seems you should not have to duplicate much functionality. Once you have a tag structure containing the desired V1 data, it is very easy to render and apply to a file.
True, but there's no way to read the contents of any *existing* V1 tag (not if there's a V2 tag present, anyway). All you can do is create a new one from scratch and overwrite the old one.
I guess this might make more sense if I explained what I'm doing. I maintain a general-purpose ID3 tagging tool that I'm trying to upgrade to support V2 tags. I believe in the philosophy that the best programs are the ones that allow users to do things the developers never thought of. While I don't personally have a reason to manipulate V1 tags independently of V2 tags, I think a general-purpose tag manipulation tool should be flexible enough to let the user do that if he really wants to
I think your tagging library is wonderful -- and it seems to have all the tag minipulation code I need, I just keep bumping up against a few minor issues where, in order to let the user have complete control over all aspects of tagging, I need access to some things the library doesn't export to the API.
I haven't made any modifications to the library yet, but just off the top of my head I think I'd only need a few additional functions like:
id3_file_numtags(struct id3_file const *) id3_file_specifictag(struct id3_file const *, int tagnumber)
possibly:
id3_file_fpopen(FILE *file_pointer, enum id3_file_mode)
maybe an additional flag and some things that aren't obvious to me at this point. Shouldn't be anything major and certainly nothing that would break backward compatibility.
Anyway, if you like I'll work up the changes and send them over.
Thx,
- Cedric
On Tue, 21 Sep 2004, Cedric Tefft wrote:
I guess this might make more sense if I explained what I'm doing. I maintain a general-purpose ID3 tagging tool that I'm trying to upgrade to support V2 tags.
Just out of curiosity - are you experiencing the same problem as me, that it seems impossible to add a tag to a file which does not have one already using libid3tag, and how have you solved it?
What I am experiencing is:
* If a file has ID3v2 but not ID3v1, only the ID3v2 tag is manipulated, no ID3v1 tag is added.
* If a file has ID3v1 only, vice versa.
* If a file has neither, the file won't have a tag after being processed by libid3tag either.
Same?
Linus Walleij
On Sep 21, 2004, at 6:08 AM, Linus Walleij wrote:
Just out of curiosity - are you experiencing the same problem as me, that it seems impossible to add a tag to a file which does not have one already using libid3tag, and how have you solved it?
What I am experiencing is:
- If a file has ID3v2 but not ID3v1, only the ID3v2 tag is
manipulated, no ID3v1 tag is added.
To add an ID3v1 tag, you must set the ID3_TAG_OPTION_ID3V1 option on the file tag, e.g.:
id3_tag_options(tag, ID3_TAG_OPTION_ID3V1, ~0);
Likewise if you want to remove the ID3v1 tag, unset the option by passing 0 as the third argument. The file interface uses this option to determine whether the file should have an ID3v1 tag.
To determine whether the file currently has an ID3v1 tag, you can test like this (before modifying the option):
id3_tag_options(tag, 0, 0) & ID3_TAG_OPTION_ID3V1
- If a file has ID3v1 only, vice versa.
This is unfortunately because the file interface is incomplete. ID3v2 tag writing in cases where the entire file should ordinarily be rewritten is not yet implemented.
- If a file has neither, the file won't have a tag after being
processed by libid3tag either.
This has the same causes as above.
Until the file interface is completed, I suggest manipulating tags in the file directly yourself. You can render an ID3v2 tag by unsetting the above option and calling id3_tag_render(); likewise render an ID3v1 tag by setting the option. Rewriting a file involves placing the ID3v2 tag at the beginning, the data stream in the middle, and the ID3v1 tag at the end.
It's also possible to place the ID3v2 tag at the end, before the ID3v1 tag. To do this you must set the ID3_TAG_OPTION_APPENDEDTAG option before rendering. The file interface will find and read such tags, but the ubiquity of other tag-reading tools that support such appended tags is unknown.
On Sep 21, 2004, at 2:44 AM, Cedric Tefft wrote:
Would you be willing to accept a few patches which expose a bit more of the library's internals to the API?
I'll consider it, but it seems you should not have to duplicate much functionality. Once you have a tag structure containing the desired V1 data, it is very easy to render and apply to a file.
True, but there's no way to read the contents of any *existing* V1 tag (not if there's a V2 tag present, anyway). All you can do is create a new one from scratch and overwrite the old one.
Actually, all you have to do is read the last 128 bytes of the file and call id3_tag_parse().
I haven't made any modifications to the library yet, but just off the top of my head I think I'd only need a few additional functions like:
id3_file_numtags(struct id3_file const *) id3_file_specifictag(struct id3_file const *, int tagnumber)
I'm afraid these are not really in the spirit of the file interface. Logically, there are at most two "tags" -- except as I have described, the file interface presents a merged view of V1 and V2 tags, reducing this number to one. The possibility of multiple V2 tags in various locations throughout the file (as sanctioned by the ID3v2.4 specification) is supported, but these have special semantics in which later tags may either augment or replace information in earlier ones. Again, the file interface is designed to hide these complications by presenting a single merged view of all the applicable tag data.
This is not to say might oppose a simpler API exposing the V1 tag as an independent entity.
possibly:
id3_file_fpopen(FILE *file_pointer, enum id3_file_mode)
The same effect can probably be achieved with id3_file_fdopen(dup(fileno(file_pointer)), mode).