lofty-rs
lofty-rs copied to clipboard
Support writing ID3v2 version 3.
Currently all ID3v2 tags are upgraded to version 4, but this is not always desired.
Hm, not sure how to best go about this. Maybe ID3v2Tag::set_version?
Maybe create something like ID3v2Tag::upgrade for 3 -> 4 and ID3v2Tag::downgrade for 4 -> 3 and on reading instead of force upgrading all to version 4 something like:
2 -> 3
3 -> 3
4 -> 4
Allowing two different versions of the tag would complicate things quite a bit, even TagLib upgrades all tags to 2.4. TagLib lets you change the version with overloading, so maybe a new trait is the way to go, maybe ID3v2Writable?
If I understand correctly this would meant that Lofty would store ID3v2.4 internally and than decide what version to use on saving? ID3v2.3 file would then on reading be upgraded (as it is now) to ID3v2.4 and on writing be downgraded back to ID3v2.3. Is transforming ID3v2.3 to version 4 lossless or lossy? Looking at Wikipedia it loos like more or less lossless with only few fields having some difficult mappings.
The conversion isn't completely lossless, some frames have a 1:1 mapping and others have expanded in 2.4. The discarded frames aren't that important though IMO, I doubt most apps even look at them.
I really would like for this to be implemented. Sadly the support for id3v2.4 is pretty bad and so I need to use v2.3. Lofty is a genius library, the only one that allows writing many different tag formats so easily so I would really like to use it.
The only blocker here is how to best expose the option to downgrade the tag.
I may just end up going with the suggestion above:
Maybe create something like
ID3v2Tag::upgradefor 3 -> 4 andID3v2Tag::downgradefor 4 -> 3 and on reading instead of force upgrading all to version 4 something like: 2 -> 3 3 -> 3 4 -> 4
Yeah I think that's a good solution
I've been looking into this and I think it'd introduce way more complexity than needed. The current behavior of upgrading to version 4 will stay so there aren't a bunch of unnecessary version checks.
The best solution would probably be through a setting in WriteOptions once that gets implemented (#228). Probably use_id3v23.
There can be an almost entirely lossless v3 -> v4 conversion (with the exception of the RVAD and EQUA (?) frames). The couple of frames that can't be upgraded can be stored with FrameId::Outdated, and ignored on write unless allowed through WriteOptions::use_id3v23.
There's a list of ID3v2.4 frames that can be discarded when writing ID3v2.3:
ASPI Audio seek point index [F:4.30]
EQU2 Equalisation (2) [F:4.12]
RVA2 Relative volume adjustment (2) [F:4.11]
SEEK Seek frame [F:4.29]
SIGN Signature frame [F:4.28]
TDEN Encoding time [F:4.2.5]
TDOR Original release time [F:4.2.5]
TDRC Recording time [F:4.2.5]
TDRL Release time [F:4.2.5]
TDTG Tagging time [F:4.2.5]
TIPL Involved people list [F:4.2.2]
TMCL Musician credits list [F:4.2.2]
TMOO Mood [F:4.2.3]
TPRO Produced notice [F:4.2.4]
TSOA Album sort order [F:4.2.5]
TSOP Performer sort order [F:4.2.5]
TSOT Title sort order [F:4.2.5]
TSST Set subtitle [F:4.2.1]
Writing an ID3v2.4 tag as ID3v2.3 would be as "simple" as:
- Filtering out the above IDs
- Splitting dates into multiple frames (Will be much easier after #233)
TDORhas its year split intoTORY(Original release year)TDRCis split into three components: Year, month/day, and hour/minute, going intoTYER(yyyy),TDAT(DDMM), andTIME(HHMM) respectively.
TCONneeds to be split and any number (<= 255) or the strings "RX" or "CR" need to be wrapped in parentheses. (Trivial after #286)- All frames encoded
TextEncoding::{UTF8, UTF16BE}need to be changed toTextEncoding::UTF16 FrameFlagsneed to be written with their ID3v2.3 mappings: https://github.com/Serial-ATA/lofty-rs/blob/cc338a3bc5298ff6af6c377ca8cce500f068962d/src/id3/v2/frame/header.rs#L100-L128
Everything's in place for this to be worked on now. I'll probably work on this after the next release.