musikr: use uppercase tag names

This reduces the amount of string processing I need to do in
ktaglib.
This commit is contained in:
Alexander Capehart 2024-12-13 16:20:46 -07:00
parent 65151e006f
commit a2498db6e5
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
2 changed files with 87 additions and 88 deletions

View file

@ -27,31 +27,31 @@ import org.oxycblt.musikr.tag.util.parseXiphPositionField
// Song
fun Metadata.musicBrainzId() =
(xiph["musicbrainz_releasetrackid"]
?: xiph["musicbrainz release track id"]
?: id3v2["TXXX:musicbrainz release track id"]
?: id3v2["TXXX:musicbrainz_releasetrackid"])
(xiph["MUSICBRAINZ_RELEASETRACKID"]
?: xiph["MUSICBRAINZ RELEASE TRACK ID"]
?: id3v2["TXXX:MUSICBRAINZ RELEASE TRACK ID"]
?: id3v2["TXXX:MUSICBRAINZ_RELEASETRACKID"])
?.first()
fun Metadata.name() = (xiph["title"] ?: id3v2["TIT2"])?.first()
fun Metadata.name() = (xiph["TITLE"] ?: id3v2["TIT2"])?.first()
fun Metadata.sortName() = (xiph["titlesort"] ?: id3v2["TSOT"])?.first()
fun Metadata.sortName() = (xiph["TITLESORT"] ?: id3v2["TSOT"])?.first()
// Track.
fun Metadata.track() =
(parseXiphPositionField(
xiph["tracknumber"]?.first(),
(xiph["totaltracks"] ?: xiph["tracktotal"] ?: xiph["trackc"])?.first())
xiph["TRACKNUMBER"]?.first(),
(xiph["TOTALTRACKS"] ?: xiph["TRACKTOTAL"] ?: xiph["TRACKC"])?.first())
?: id3v2["TRCK"]?.run { first().parseId3v2PositionField() })
// Disc and it's subtitle name.
fun Metadata.disc() =
(parseXiphPositionField(
xiph["discnumber"]?.first(),
(xiph["totaldiscs"] ?: xiph["disctotal"] ?: xiph["discc"])?.run { first() })
xiph["DISCNUMBER"]?.first(),
(xiph["TOTALDISCS"] ?: xiph["DISCTOTAL"] ?: xiph["DISCC"])?.run { first() })
?: id3v2["TPOS"]?.run { first().parseId3v2PositionField() })
fun Metadata.subtitle() = (xiph["discsubtitle"] ?: id3v2["TSST"])?.first()
fun Metadata.subtitle() = (xiph["DISCSUBTITLE"] ?: id3v2["TSST"])?.first()
// Dates are somewhat complicated, as not only did their semantics change from a flat year
// value in ID3v2.3 to a full ISO-8601 date in ID3v2.4, but there are also a variety of
@ -66,9 +66,9 @@ fun Metadata.subtitle() = (xiph["discsubtitle"] ?: id3v2["TSST"])?.first()
// TODO: Handle dates that are in "January" because the actual specific release date
// isn't known?
fun Metadata.date() =
(xiph["originaldate"]?.run { Date.from(first()) }
?: xiph["date"]?.run { Date.from(first()) }
?: xiph["year"]?.run { Date.from(first()) }
(xiph["ORIGINALDATE"]?.run { Date.from(first()) }
?: xiph["DATE"]?.run { Date.from(first()) }
?: xiph["YEAR"]?.run { Date.from(first()) }
?:
// xiph dates are less complicated, but there are still several types
@ -84,95 +84,95 @@ fun Metadata.date() =
// Album
fun Metadata.albumMusicBrainzId() =
(xiph["musicbrainz_albumid"]
?: xiph["musicbrainz album id"]
?: id3v2["TXXX:musicbrainz album id"]
?: id3v2["TXXX:musicbrainz_albumid"])
(xiph["MUSICBRAINZ_ALBUMID"]
?: xiph["MUSICBRAINZ ALBUM ID"]
?: id3v2["TXXX:MUSICBRAINZ ALBUM ID"]
?: id3v2["TXXX:MUSICBRAINZ_ALBUMID"])
?.first()
fun Metadata.albumName() = (xiph["album"] ?: id3v2["TALB"])?.first()
fun Metadata.albumName() = (xiph["ALBUM"] ?: id3v2["TALB"])?.first()
fun Metadata.albumSortName() = (xiph["albumsort"] ?: id3v2["TSOA"])?.first()
fun Metadata.albumSortName() = (xiph["ALBUMSORT"] ?: id3v2["TSOA"])?.first()
fun Metadata.releaseTypes() =
(xiph["releasetype"]
?: xiph["musicbrainz album type"]
?: id3v2["TXXX:musicbrainz album type"]
?: id3v2["TXXX:releasetype"]
(xiph["RELEASETYPE"]
?: xiph["MUSICBRAINZ ALBUM TYPE"]
?: id3v2["TXXX:MUSICBRAINZ ALBUM TYPE"]
?: id3v2["TXXX:RELEASETYPE"]
?:
// This is a non-standard iTunes extension
id3v2["GRP1"])
// Artist
fun Metadata.artistMusicBrainzIds() =
(xiph["musicbrainz_artistid"]
?: xiph["musicbrainz artist id"]
?: id3v2["TXXX:musicbrainz artist id"]
?: id3v2["TXXX:musicbrainz_artistid"])
(xiph["MUSICBRAINZ_ARTISTID"]
?: xiph["MUSICBRAINZ ARTIST ID"]
?: id3v2["TXXX:MUSICBRAINZ ARTIST ID"]
?: id3v2["TXXX:MUSICBRAINZ_ARTISTID"])
fun Metadata.artistNames() =
(xiph["artists"]
?: xiph["artist"]
?: id3v2["TXXX:artists"]
(xiph["ARTISTS"]
?: xiph["ARTIST"]
?: id3v2["TXXX:ARTISTS"]
?: id3v2["TPE1"]
?: id3v2["TXXX:artist"])
?: id3v2["TXXX:ARTIST"])
fun Metadata.artistSortNames() =
(xiph["artistssort"]
?: xiph["artists_sort"]
?: xiph["artists sort"]
?: xiph["artistsort"]
?: xiph["artist sort"]
?: id3v2["TXXX:artistssort"]
?: id3v2["TXXX:artists_sort"]
?: id3v2["TXXX:artists sort"]
(xiph["ARTISTSSORT"]
?: xiph["ARTISTS_SORT"]
?: xiph["ARTISTS SORT"]
?: xiph["ARTISTSORT"]
?: xiph["ARTIST SORT"]
?: id3v2["TXXX:ARTISTSSORT"]
?: id3v2["TXXX:ARTISTS_SORT"]
?: id3v2["TXXX:ARTISTS SORT"]
?: id3v2["TSOP"]
?: id3v2["artistsort"]
?: id3v2["TXXX:artist sort"])
?: id3v2["TXXX:ARTISTSORT"]
?: id3v2["TXXX:ARTIST SORT"])
fun Metadata.albumArtistMusicBrainzIds() =
(xiph["musicbrainz_albumartistid"]
?: xiph["musicbrainz album artist id"]
?: id3v2["TXXX:musicbrainz album artist id"]
?: id3v2["TXXX:musicbrainz_albumartistid"])
(xiph["MUSICBRAINZ_ALBUMARTISTID"]
?: xiph["MUSICBRAINZ ALBUM ARTIST ID"]
?: id3v2["TXXX:MUSICBRAINZ ALBUM ARTIST ID"]
?: id3v2["TXXX:MUSICBRAINZ_ALBUMARTISTID"])
fun Metadata.albumArtistNames() =
(xiph["albumartists"]
?: xiph["album_artists"]
?: xiph["album artists"]
?: xiph["albumartist"]
?: xiph["album artist"]
?: id3v2["TXXX:albumartists"]
?: id3v2["TXXX:album_artists"]
?: id3v2["TXXX:album artists"]
(xiph["ALBUMARTISTS"]
?: xiph["ALBUM_ARTISTS"]
?: xiph["ALBUM ARTISTS"]
?: xiph["ALBUMARTIST"]
?: xiph["ALBUM ARTIST"]
?: id3v2["TXXX:ALBUMARTISTS"]
?: id3v2["TXXX:ALBUM_ARTISTS"]
?: id3v2["TXXX:ALBUM ARTISTS"]
?: id3v2["TPE2"]
?: id3v2["TXXX:albumartist"]
?: id3v2["TXXX:album artist"])
?: id3v2["TXXX:ALBUMARTIST"]
?: id3v2["TXXX:ALBUM ARTIST"])
fun Metadata.albumArtistSortNames() =
(xiph["albumartistssort"]
?: xiph["albumartists_sort"]
?: xiph["albumartists sort"]
?: xiph["albumartistsort"]
?: xiph["album artist sort"]
?: id3v2["TXXX:albumartistssort"]
?: id3v2["TXXX:albumartists_sort"]
?: id3v2["TXXX:albumartists sort"]
?: id3v2["TXXX:albumartistsort"]
(xiph["ALBUMARTISTSSORT"]
?: xiph["ALBUMARTISTS_SORT"]
?: xiph["ALBUMARTISTS SORT"]
?: xiph["ALBUMARTISTSORT"]
?: xiph["ALBUM ARTIST SORT"]
?: id3v2["TXXX:ALBUMARTISTSSORT"]
?: id3v2["TXXX:ALBUMARTISTS_SORT"]
?: id3v2["TXXX:ALBUMARTISTS SORT"]
?: id3v2["TXXX:ALBUMARTISTSORT"]
// This is a non-standard iTunes extension
?: id3v2["TSO2"]
?: id3v2["TXXX:album artist sort"])
?: id3v2["TXXX:ALBUM ARTIST SORT"])
// Genre
fun Metadata.genreNames() = xiph["genre"] ?: id3v2["TCON"]
fun Metadata.genreNames() = xiph["GENRE"] ?: id3v2["TCON"]
// Compilation Flag
fun Metadata.isCompilation() =
(xiph["compilation"]
?: xiph["itunescompilation"]
(xiph["COMPILATION"]
?: xiph["ITUNESCOMPILATION"]
?: id3v2["TCMP"] // This is a non-standard itunes extension
?: id3v2["TXXX:compilation"]
?: id3v2["TXXX:itunescompilation"])
?: id3v2["TXXX:COMPILATION"]
?: id3v2["TXXX:ITUNESCOMPILATION"])
?.let {
// Ignore invalid instances of this tag
it == listOf("1")
@ -180,14 +180,14 @@ fun Metadata.isCompilation() =
// ReplayGain information
fun Metadata.replayGainTrackAdjustment() =
(xiph["r128_track_gain"]?.parseR128Adjustment()
?: xiph["replaygain_track_gain"]?.parseReplayGainAdjustment()
?: id3v2["TXXX:replaygain_track_gain"]?.parseReplayGainAdjustment())
(xiph["R128_TRACK_GAIN"]?.parseR128Adjustment()
?: xiph["REPLAYGAIN_TRACK_GAIN"]?.parseReplayGainAdjustment()
?: id3v2["TXXX:REPLAYGAIN_TRACK_GAIN"]?.parseReplayGainAdjustment())
fun Metadata.replayGainAlbumAdjustment() =
(xiph["r128_album_gain"]?.parseR128Adjustment()
?: xiph["replaygain_album_gain"]?.parseReplayGainAdjustment()
?: id3v2["TXXX:replaygain_album_gain"]?.parseReplayGainAdjustment())
(xiph["R128_ALBUM_GAIN"]?.parseR128Adjustment()
?: xiph["REPLAYGAIN_ALBUM_GAIN"]?.parseReplayGainAdjustment()
?: id3v2["TXXX:REPLAYGAIN_ALBUM_GAIN"]?.parseReplayGainAdjustment())
private fun Metadata.parseId3v23Date(): Date? {
// Assume that TDAT/TIME can refer to TYER or TORY depending on if TORY

View file

@ -17,12 +17,11 @@ void JVMMetadataBuilder::setMimeType(const std::string_view mimeType) {
void JVMMetadataBuilder::setId3v2(const TagLib::ID3v2::Tag &tag) {
for (auto frame: tag.frameList()) {
if (auto txxxFrame = dynamic_cast<TagLib::ID3v2::UserTextIdentificationFrame *>(frame)) {
TagLib::String desc = std::string(txxxFrame->description().toCString(true));
// Make desc lowercase
std::transform(desc.begin(), desc.end(), desc.begin(), ::tolower);
TagLib::String key = TagLib::String(frame->frameID()) + ":" + desc;
TagLib::StringList frameText = txxxFrame->fieldList();
frameText.erase(frameText.begin()); // Remove description that exists for some insane reason
// Frame text starts with the description then the remaining values
auto begin = frameText.begin();
TagLib::String key = TagLib::String(frame->frameID()) + ":" + begin->upper();
frameText.erase(begin);
id3v2.add(key, frameText);
} else if (auto textFrame = dynamic_cast<TagLib::ID3v2::TextIdentificationFrame *>(frame)) {
TagLib::String key = frame->frameID();
@ -36,11 +35,9 @@ void JVMMetadataBuilder::setId3v2(const TagLib::ID3v2::Tag &tag) {
void JVMMetadataBuilder::setXiph(const TagLib::Ogg::XiphComment &tag) {
for (auto field: tag.fieldListMap()) {
auto fieldName = std::string(field.first.toCString(true));
std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower);
auto taglibFieldName = TagLib::String(fieldName);
auto fieldValue = field.second;
xiph.add(taglibFieldName, fieldValue);
auto key = field.first.upper();
auto values = field.second;
xiph.add(key, values);
}
}
@ -50,6 +47,8 @@ void JVMMetadataBuilder::setMp4(const TagLib::MP4::Tag &tag) {
auto itemValue = item.second;
auto type = itemValue.type();
// TODO: Handle internal atoms
// Only read out the atoms for the reasonable tags we are expecting.
// None of the crazy binary atoms.
if (type == TagLib::MP4::Item::Type::StringList) {
@ -125,7 +124,7 @@ jobject JVMMetadataBuilder::build() {
jobject mp4Map = mp4.getObject();
jbyteArray coverArray = nullptr;
if (cover.has_value()) {
coverArray = env->NewByteArray(cover->size());
coverArray = env->NewByteArray(static_cast<jsize>(cover->size());
env->SetByteArrayRegion(coverArray, 0, cover->size(), reinterpret_cast<const jbyte *>(cover->data()));
}
jobject metadataObj = env->NewObject(metadataClass, metadataInit, id3v2Map, xiphMap, mp4Map, coverArray, propertiesObj);