Serial-ATA / lofty-rs

Audio metadata library
Apache License 2.0
182 stars 34 forks source link

Issues with ID3v2 TRCK count/total separation #417

Closed basharovV closed 1 week ago

basharovV commented 2 weeks ago

Reproducer

I tried this code:

fn write_track_number() {
    let mut tag = lofty::tag::Tag::new(TagType::Id3v2);
    tag.insert(TagItem::new(
        ItemKey::from_key(TagType::Id3v2, "TRCK"),
        ItemValue::Text(String::from("1")),
    ));

    println!("{:?}", tag.track()); // None
    println!("{:?}\n", tag.track_total()); // Some(1)

    tag.insert(TagItem::new(
        ItemKey::from_key(TagType::Id3v2, "TRCK"),
        ItemValue::Text(String::from("1/14")),
    ));

    println!("{:?}", tag.track()); // None
    println!("{:?}\n", tag.track_total()); // None

    tag.save_to_path("src/blank.mp3", WriteOptions::new());

    let mp3_file = read_from_path("src/blank.mp3").unwrap();

    for tag_item in mp3_file.tags() {
        for tag in tag_item.items() {
            println!("Found tag: {:?}", tag); // Value is "0/1/14"?
        }
    }
}

Output:

None
Some(1)

None
None

Found tag: TagItem { lang: [88, 88, 88], description: "", item_key: TrackTotal, item_value: Text("0/1/14") }

Summary

I'm not sure if I'm doing this wrong, but when writing the TRCK tag, I'm seeing some strange behaviour:

Expected behavior

No response

Assets

No response

Serial-ATA commented 2 weeks ago

Hello!

ItemKey::from_key is confusing and really only used internally. I might make it doc(hidden) or at least document it better.

So, ItemKey doesn't retain any format-specific keys. You should be using ItemKey::TrackTotal and ItemKey::TrackNumber individually. They will map appropriately when writing the tag.

basharovV commented 1 week ago

Ah, thank you for the clarification, I expected lofty to handle the separation here. ItemKey::from_key is still useful to me though because I already have a dict of the exact ID3v2/Vorbis tags to write, so I thought I could use this function to map without having to do additional format-specific handling. Or is there a better way to handle my use case?

Serial-ATA commented 1 week ago

Tag is intended to be format-agnostic, so you should never have to worry about any format-specific handling. If you have to read/write items that ItemKey doesn't cover then you should use Id3v2Tag and VorbisComments (and any other concrete format that you have specific keys for). Both can be split (SplitTag) into a Tag and merged back (MergeTag) into their concrete type

basharovV commented 1 week ago

Makes sense! I'll close this issue then. Thanks for this library!