From 2dffd4411bfb9b25668539856de01765459860a4 Mon Sep 17 00:00:00 2001 From: UnknownSuperficialNight <88142731+UnknownSuperficialNight@users.noreply.github.com> Date: Wed, 12 Nov 2025 13:41:12 +1300 Subject: [PATCH 1/5] feat: Add `ReleaseCountry` to `tag` --- lofty/src/tag/item.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lofty/src/tag/item.rs b/lofty/src/tag/item.rs index aaef3bebb..a6d9f88c1 100644 --- a/lofty/src/tag/item.rs +++ b/lofty/src/tag/item.rs @@ -366,6 +366,7 @@ gen_map!( "MOVEMENTNAME" => Movement, "MOVEMENT" => MovementNumber, "MOVEMENTTOTAL" => MovementTotal, + "RELEASECOUNTRY" => ReleaseCountry, "ALBUMSORT" => AlbumTitleSortOrder, "ALBUMARTISTSORT" => AlbumArtistSortOrder, "TITLESORT" => TrackTitleSortOrder, @@ -605,6 +606,7 @@ gen_item_keys!( Movement, MovementNumber, MovementTotal, + ReleaseCountry, /////////////////////////////////////////////////////////////// // MusicBrainz Identifiers From 34d85ec566c8c2dd5740d9e2c7d13187ab8fd712 Mon Sep 17 00:00:00 2001 From: UnknownSuperficialNight <88142731+UnknownSuperficialNight@users.noreply.github.com> Date: Wed, 12 Nov 2025 14:00:22 +1300 Subject: [PATCH 2/5] feat: Add `ReleaseCountry` to `APE_MAP` and `RIFF_INFO_MAP` --- lofty/src/tag/item.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lofty/src/tag/item.rs b/lofty/src/tag/item.rs index a6d9f88c1..47a391893 100644 --- a/lofty/src/tag/item.rs +++ b/lofty/src/tag/item.rs @@ -93,6 +93,7 @@ gen_map!( "MOVEMENTNAME" => Movement, "MOVEMENT" => MovementNumber, "MOVEMENTTOTAL" => MovementTotal, + "RELEASECOUNTRY" => ReleaseCountry, "ALBUMSORT" => AlbumTitleSortOrder, "ALBUMARTISTSORT" => AlbumArtistSortOrder, "TITLESORT" => TrackTitleSortOrder, @@ -351,7 +352,8 @@ gen_map!( "IGNR" => Genre, "ICOP" => CopyrightMessage, "ICMT" => Comment, - "ILNG" => Language + "ILNG" => Language, + "ICNT" => ReleaseCountry ); gen_map!( From b6d9dd693e7059bb1b3349a7a31cfebe5b658a65 Mon Sep 17 00:00:00 2001 From: UnknownSuperficialNight <88142731+UnknownSuperficialNight@users.noreply.github.com> Date: Wed, 12 Nov 2025 17:32:11 +1300 Subject: [PATCH 3/5] feat: Add `ReleaseCountry` to `ID3V2_MAP` --- lofty/src/id3/v2/tag.rs | 1 + lofty/src/tag/item.rs | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lofty/src/id3/v2/tag.rs b/lofty/src/id3/v2/tag.rs index ccc52966a..ee1cbbc11 100644 --- a/lofty/src/id3/v2/tag.rs +++ b/lofty/src/id3/v2/tag.rs @@ -1420,6 +1420,7 @@ impl MergeTag for SplitTagRemainder { ItemKey::MusicBrainzArtistId, ItemKey::MusicBrainzReleaseArtistId, ItemKey::MusicBrainzWorkId, + ItemKey::ReleaseCountry, ] { let frame_id = item_key.map_key(TagType::Id3v2).expect("valid frame id"); if let Some(text) = join_text_items(&mut tag, [item_key]) { diff --git a/lofty/src/tag/item.rs b/lofty/src/tag/item.rs index 47a391893..f6100f6ea 100644 --- a/lofty/src/tag/item.rs +++ b/lofty/src/tag/item.rs @@ -245,7 +245,8 @@ gen_map!( "MusicBrainz Release Group Id" => MusicBrainzReleaseGroupId, "MusicBrainz Artist Id" => MusicBrainzArtistId, "MusicBrainz Album Artist Id" => MusicBrainzReleaseArtistId, - "MusicBrainz Work Id" => MusicBrainzWorkId + "MusicBrainz Work Id" => MusicBrainzWorkId, + "MusicBrainz Album Release Country" => ReleaseCountry ); gen_map!( From bb5209bb088a472b9cb3f164a61ec9c42c3033de Mon Sep 17 00:00:00 2001 From: UnknownSuperficialNight <88142731+UnknownSuperficialNight@users.noreply.github.com> Date: Wed, 12 Nov 2025 17:39:36 +1300 Subject: [PATCH 4/5] feat: Add `ReleaseCountry` to `ILST_MAP` --- lofty/src/tag/item.rs | 155 +++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 77 deletions(-) diff --git a/lofty/src/tag/item.rs b/lofty/src/tag/item.rs index f6100f6ea..541ccfc17 100644 --- a/lofty/src/tag/item.rs +++ b/lofty/src/tag/item.rs @@ -252,85 +252,86 @@ gen_map!( gen_map!( ILST_MAP; - "\u{a9}alb" => AlbumTitle, - "----:com.apple.iTunes:DISCSUBTITLE" => SetSubtitle, - "tvsh" => ShowName, - "\u{a9}grp" => ContentGroup, - "\u{a9}nam" => TrackTitle, - "----:com.apple.iTunes:SUBTITLE" => TrackSubtitle, - "\u{a9}wrk" => Work, - "\u{a9}mvn" => Movement, - "\u{a9}mvi" => MovementNumber, - "\u{a9}mvc" => MovementTotal, - "soal" => AlbumTitleSortOrder, - "soaa" => AlbumArtistSortOrder, - "sonm" => TrackTitleSortOrder, - "soar" => TrackArtistSortOrder, - "sosn" => ShowNameSortOrder, - "soco" => ComposerSortOrder, - "aART" => AlbumArtist, - "----:com.apple.iTunes:ALBUMARTISTS" => AlbumArtists, - "\u{a9}ART" => TrackArtist, - "----:com.apple.iTunes:ARTISTS" => TrackArtists, - "\u{a9}wrt" => Composer, - "\u{a9}dir" => Director, - "----:com.apple.iTunes:CONDUCTOR" => Conductor, - "----:com.apple.iTunes:ENGINEER" => Engineer, - "----:com.apple.iTunes:LYRICIST" => Lyricist, - "----:com.apple.iTunes:DJMIXER" => MixDj, - "----:com.apple.iTunes:MIXER" => MixEngineer, - "----:com.apple.iTunes:PRODUCER" => Producer, - "----:com.apple.iTunes:LABEL" => Label, - "----:com.apple.iTunes:REMIXER" => Remixer, - "disk" => DiscNumber, - "disk" => DiscTotal, - "trkn" => TrackNumber, - "trkn" => TrackTotal, - "rate" => Popularimeter, - "rtng" => ParentalAdvisory, - "\u{a9}day" => RecordingDate, - "----:com.apple.iTunes:ORIGINALDATE" => OriginalReleaseDate, // TagLib v2.0 - "----:com.apple.iTunes:RELEASEDATE" => ReleaseDate, - "----:com.apple.iTunes:ISRC" => Isrc, - "----:com.apple.iTunes:BARCODE" => Barcode, - "----:com.apple.iTunes:CATALOGNUMBER" => CatalogNumber, - "cpil" => FlagCompilation, - "pcst" => FlagPodcast, - "----:com.apple.iTunes:MEDIA" => OriginalMediaType, - "\u{a9}enc" => EncodedBy, - "\u{a9}too" => EncoderSoftware, - "\u{a9}gen" => Genre, - "----:com.apple.iTunes:COLOR" => Color, - "----:com.apple.iTunes:MOOD" => Mood, - "tmpo" => IntegerBpm, - "----:com.apple.iTunes:BPM" => Bpm, - "----:com.apple.iTunes:initialkey" => InitialKey, - "----:com.apple.iTunes:replaygain_album_gain" => ReplayGainAlbumGain, - "----:com.apple.iTunes:replaygain_album_peak" => ReplayGainAlbumPeak, - "----:com.apple.iTunes:replaygain_track_gain" => ReplayGainTrackGain, - "----:com.apple.iTunes:replaygain_track_peak" => ReplayGainTrackPeak, - "cprt" => CopyrightMessage, - "----:com.apple.iTunes:LICENSE" => License, - "ldes" => PodcastDescription, - "catg" => PodcastSeriesCategory, - "purl" => PodcastUrl, - "egid" => PodcastGlobalUniqueId, - "keyw" => PodcastKeywords, - "\u{a9}cmt" => Comment, - "desc" => Description, - "----:com.apple.iTunes:LANGUAGE" => Language, - "----:com.apple.iTunes:SCRIPT" => Script, + "\u{a9}alb" => AlbumTitle, + "----:com.apple.iTunes:DISCSUBTITLE" => SetSubtitle, + "tvsh" => ShowName, + "\u{a9}grp" => ContentGroup, + "\u{a9}nam" => TrackTitle, + "----:com.apple.iTunes:SUBTITLE" => TrackSubtitle, + "\u{a9}wrk" => Work, + "\u{a9}mvn" => Movement, + "\u{a9}mvi" => MovementNumber, + "\u{a9}mvc" => MovementTotal, + "soal" => AlbumTitleSortOrder, + "soaa" => AlbumArtistSortOrder, + "sonm" => TrackTitleSortOrder, + "soar" => TrackArtistSortOrder, + "sosn" => ShowNameSortOrder, + "soco" => ComposerSortOrder, + "aART" => AlbumArtist, + "----:com.apple.iTunes:ALBUMARTISTS" => AlbumArtists, + "\u{a9}ART" => TrackArtist, + "----:com.apple.iTunes:ARTISTS" => TrackArtists, + "\u{a9}wrt" => Composer, + "\u{a9}dir" => Director, + "----:com.apple.iTunes:CONDUCTOR" => Conductor, + "----:com.apple.iTunes:ENGINEER" => Engineer, + "----:com.apple.iTunes:LYRICIST" => Lyricist, + "----:com.apple.iTunes:DJMIXER" => MixDj, + "----:com.apple.iTunes:MIXER" => MixEngineer, + "----:com.apple.iTunes:PRODUCER" => Producer, + "----:com.apple.iTunes:LABEL" => Label, + "----:com.apple.iTunes:REMIXER" => Remixer, + "disk" => DiscNumber, + "disk" => DiscTotal, + "trkn" => TrackNumber, + "trkn" => TrackTotal, + "rate" => Popularimeter, + "rtng" => ParentalAdvisory, + "\u{a9}day" => RecordingDate, + "----:com.apple.iTunes:ORIGINALDATE" => OriginalReleaseDate, // TagLib v2.0 + "----:com.apple.iTunes:RELEASEDATE" => ReleaseDate, + "----:com.apple.iTunes:ISRC" => Isrc, + "----:com.apple.iTunes:BARCODE" => Barcode, + "----:com.apple.iTunes:CATALOGNUMBER" => CatalogNumber, + "cpil" => FlagCompilation, + "pcst" => FlagPodcast, + "----:com.apple.iTunes:MEDIA" => OriginalMediaType, + "\u{a9}enc" => EncodedBy, + "\u{a9}too" => EncoderSoftware, + "\u{a9}gen" => Genre, + "----:com.apple.iTunes:COLOR" => Color, + "----:com.apple.iTunes:MOOD" => Mood, + "tmpo" => IntegerBpm, + "----:com.apple.iTunes:BPM" => Bpm, + "----:com.apple.iTunes:initialkey" => InitialKey, + "----:com.apple.iTunes:replaygain_album_gain" => ReplayGainAlbumGain, + "----:com.apple.iTunes:replaygain_album_peak" => ReplayGainAlbumPeak, + "----:com.apple.iTunes:replaygain_track_gain" => ReplayGainTrackGain, + "----:com.apple.iTunes:replaygain_track_peak" => ReplayGainTrackPeak, + "cprt" => CopyrightMessage, + "----:com.apple.iTunes:LICENSE" => License, + "ldes" => PodcastDescription, + "catg" => PodcastSeriesCategory, + "purl" => PodcastUrl, + "egid" => PodcastGlobalUniqueId, + "keyw" => PodcastKeywords, + "\u{a9}cmt" => Comment, + "desc" => Description, + "----:com.apple.iTunes:LANGUAGE" => Language, + "----:com.apple.iTunes:SCRIPT" => Script, // Don't know of any key for synchronized lyrics, nor if any apps actually support them, so // just treat both keys the same like ID3v2. - "\u{a9}lyr" => Lyrics | UnsyncLyrics, - "xid " => AppleXid, - "----:com.apple.iTunes:MusicBrainz Track Id" => MusicBrainzRecordingId, - "----:com.apple.iTunes:MusicBrainz Release Track Id" => MusicBrainzTrackId, - "----:com.apple.iTunes:MusicBrainz Album Id" => MusicBrainzReleaseId, - "----:com.apple.iTunes:MusicBrainz Release Group Id" => MusicBrainzReleaseGroupId, - "----:com.apple.iTunes:MusicBrainz Artist Id" => MusicBrainzArtistId, - "----:com.apple.iTunes:MusicBrainz Album Artist Id" => MusicBrainzReleaseArtistId, - "----:com.apple.iTunes:MusicBrainz Work Id" => MusicBrainzWorkId + "\u{a9}lyr" => Lyrics | UnsyncLyrics, + "xid " => AppleXid, + "----:com.apple.iTunes:MusicBrainz Track Id" => MusicBrainzRecordingId, + "----:com.apple.iTunes:MusicBrainz Release Track Id" => MusicBrainzTrackId, + "----:com.apple.iTunes:MusicBrainz Album Id" => MusicBrainzReleaseId, + "----:com.apple.iTunes:MusicBrainz Release Group Id" => MusicBrainzReleaseGroupId, + "----:com.apple.iTunes:MusicBrainz Artist Id" => MusicBrainzArtistId, + "----:com.apple.iTunes:MusicBrainz Album Artist Id" => MusicBrainzReleaseArtistId, + "----:com.apple.iTunes:MusicBrainz Work Id" => MusicBrainzWorkId, + "----:com.apple.iTunes:MusicBrainz Album Release Country" => ReleaseCountry ); gen_map!( From 9befac72a786c21c9baf34ff8e54380a20f3c671 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Wed, 12 Nov 2025 08:19:12 -0500 Subject: [PATCH 5/5] changelog: Add entry for `ItemKey::ReleaseCountry` --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3eddb000..d74f4a6b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - In formats like Vorbis Comments, `ItemKey::Lyrics` may actually contain synchronized lyrics in LRC format. To help with the ambiguity, some apps may write a separate field containing normal, unsynchronized lyrics. - In other formats where the difference doesn't matter (like ID3v2), this will act exactly the same as `ItemKey::Lyrics`. + - `ItemKey::ReleaseCountry` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/573)) + - Currently, this maps to the [fields](https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#id30) used by MusicBrainz Picard, which expect an + ISO 3166-1 code. - **Serde**: [Serde] support for `*Type` enums (`FileType`, `TagType`, `PictureType`) - Support can be enabled with the new `serde` feature (not enabled by default) - **Probe**: `Probe::read_bound()` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/557))