Skip to content

Comments

Add support for ID3v2.4 multi-value tags#10799

Merged
rohitjoins merged 11 commits intogoogle:dev-v2from
OxygenCobalt:id3v2-multi-value
Nov 29, 2022
Merged

Add support for ID3v2.4 multi-value tags#10799
rohitjoins merged 11 commits intogoogle:dev-v2from
OxygenCobalt:id3v2-multi-value

Conversation

@OxygenCobalt
Copy link
Contributor

@OxygenCobalt OxygenCobalt commented Nov 21, 2022

The problem

My app uses ExoPlayer's metadata parser to work around issues with MediaStore's metadata handling. However, recent developments have required me to start handling multi-value tags, as many users want my app to support multiple artist/genre entries.

While the vorbis extractor supports multiple instances of the tag, the ID3v2 extractor does not, even though ID3v2.4 specifies that text information frames can have multiple values in them if delimited by a null terminator. This worsens the user experience with multi-value tags.

What this PR does

This PR deprecates the value field in TextInformationFrame and replaces it with a new array field called values. Id3Decoder populates this field with multiple values if it finds multiple tags delimited by null terminators. The now-deprecated value field is populated with the first item in values, to retain compatibility with the old implementation that would parse the first value only.

This new algorithm should be backwards compatible with ID3v2.3 and ID3v2.2, as they only leverage null terminators as an informal shortcut to make serializing to C strings easier.

Further notes

I've modified other parts of the codebase to use the non-deprecated value to the most backwards-compatible extent possible. I have also added tests into Id3Decoder to handle the new functionality.

Add support for multi-value tags based on null terminators.

These are specific to ID3v2.4, but is backwards compatible with
ID3v2.3, so no version checks are needed.
Clarify that null-termianted multi-value separators are specific to
ID3v2.4.
Rename indexOfEos to indexOfTerminator to better reflect how a
terminator != the end of a frame now.
Fix second-order issues stemming from the addition of multi-value tags.
Add tests for ID3v2 multi-value text frames.
@icbaker icbaker self-requested a review November 21, 2022 17:19
@icbaker icbaker self-assigned this Nov 21, 2022
Copy link
Collaborator

@icbaker icbaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! I added some initial thoughts

Rework the interface for ID3v2 text frames by:
- Switching from a mutable array to ImmutableList
- Never leaving the array empty, instead filling it with "" if there
are no values

This makes the surface safer and more in line with the rest of the
module.
Rework the parsing of multi-value text frames to reduce duplication
and increase efficiency.
@OxygenCobalt OxygenCobalt requested a review from icbaker November 21, 2022 18:56
Make the values of TextInformationFrame an abstract list instead of an
explicit ImmutableList.
Fix a constructor usage that tried to use an array instead of a list.
Instead of the ID3v2 text frame falling back to a singleton list of an
empty string when the given values are empty, make that case throw
an exception within the text frame, and move that fallback behavior
into the ID3v2 decoder.
@OxygenCobalt OxygenCobalt requested a review from icbaker November 22, 2022 16:31
@icbaker
Copy link
Collaborator

icbaker commented Nov 23, 2022

Looks good, thanks for all the changes! I'll get this merged.

@rohitjoins rohitjoins merged commit c827e46 into google:dev-v2 Nov 29, 2022
@google google locked and limited conversation to collaborators Jan 29, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants