diff --git a/CHANGELOG.md b/CHANGELOG.md index 9adba5ddf..368b62f73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- **ItemKey**: `ItemKey::AlbumArtists`, available for ID3v2, Vorbis Comments, APE, and MP4 Ilst ([PR](https://github.com/Serial-ATA/lofty-rs/pull/523)) + - This is a multi-value item that stores each artist for a track. It should be retrieved with `Tag::get_strings` or `Tag::take_strings`. + - For example, a track has `ItemKey::TrackArtist` = "Foo & Bar", then `ItemKey::AlbumArtists` = ["Foo", "Bar"]. + +### Changed +- **ID3v2**: Check `TXXX:ALBUMARTIST` and `TXXX:ALBUM ARTIST` for `ItemKey::AlbumArtist` conversions +- **Vorbis Comments**: Check `ALBUM ARTIST` for `ItemKey::AlbumArtist` conversions + ## [0.22.4] - 2025-04-29 ### Changed diff --git a/lofty/src/tag/item.rs b/lofty/src/tag/item.rs index 2918ccc78..84d8ef95f 100644 --- a/lofty/src/tag/item.rs +++ b/lofty/src/tag/item.rs @@ -73,161 +73,163 @@ gen_map!( gen_map!( APE_MAP; - "Album" => AlbumTitle, - "DiscSubtitle" => SetSubtitle, - "Grouping" => ContentGroup, - "Title" => TrackTitle, - "Subtitle" => TrackSubtitle, - "WORKTITLE" => Work, - "MOVEMENTNAME" => Movement, - "MOVEMENT" => MovementNumber, - "MOVEMENTTOTAL" => MovementTotal, - "ALBUMSORT" => AlbumTitleSortOrder, - "ALBUMARTISTSORT" => AlbumArtistSortOrder, - "TITLESORT" => TrackTitleSortOrder, - "ARTISTSORT" => TrackArtistSortOrder, - "Album Artist" | "ALBUMARTIST" => AlbumArtist, - "Artist" => TrackArtist, - "Artists" => TrackArtists, - "Arranger" => Arranger, - "Writer" => Writer, - "Composer" => Composer, - "Conductor" => Conductor, - "Director" => Director, - "Engineer" => Engineer, - "Lyricist" => Lyricist, - "DjMixer" => MixDj, - "Mixer" => MixEngineer, - "Performer" => Performer, - "Producer" => Producer, - "Label" => Label, - "MixArtist" => Remixer, - "Disc" => DiscNumber, - "Disc" => DiscTotal, - "Track" => TrackNumber, - "Track" => TrackTotal, - "Year" => Year, - "ORIGINALYEAR" => OriginalReleaseDate, - "RELEASEDATE" => ReleaseDate, - "ISRC" => Isrc, - "Barcode" => Barcode, - "CatalogNumber" => CatalogNumber, - "Compilation" => FlagCompilation, - "Media" => OriginalMediaType, - "EncodedBy" => EncodedBy, - "REPLAYGAIN_ALBUM_GAIN" => ReplayGainAlbumGain, - "REPLAYGAIN_ALBUM_PEAK" => ReplayGainAlbumPeak, - "REPLAYGAIN_TRACK_GAIN" => ReplayGainTrackGain, - "REPLAYGAIN_TRACK_PEAK" => ReplayGainTrackPeak, - "Genre" => Genre, - "Color" => Color, - "Mood" => Mood, - "Copyright" => CopyrightMessage, - "Comment" => Comment, - "language" => Language, - "Script" => Script, - "Lyrics" => Lyrics, - "MUSICBRAINZ_TRACKID" => MusicBrainzRecordingId, - "MUSICBRAINZ_RELEASETRACKID" => MusicBrainzTrackId, - "MUSICBRAINZ_ALBUMID" => MusicBrainzReleaseId, - "MUSICBRAINZ_RELEASEGROUPID" => MusicBrainzReleaseGroupId, - "MUSICBRAINZ_ARTISTID" => MusicBrainzArtistId, - "MUSICBRAINZ_ALBUMARTISTID" => MusicBrainzReleaseArtistId, - "MUSICBRAINZ_WORKID" => MusicBrainzWorkId + "Album" => AlbumTitle, + "DiscSubtitle" => SetSubtitle, + "Grouping" => ContentGroup, + "Title" => TrackTitle, + "Subtitle" => TrackSubtitle, + "WORKTITLE" => Work, + "MOVEMENTNAME" => Movement, + "MOVEMENT" => MovementNumber, + "MOVEMENTTOTAL" => MovementTotal, + "ALBUMSORT" => AlbumTitleSortOrder, + "ALBUMARTISTSORT" => AlbumArtistSortOrder, + "TITLESORT" => TrackTitleSortOrder, + "ARTISTSORT" => TrackArtistSortOrder, + "Album Artist" | "ALBUMARTIST" => AlbumArtist, + "ALBUMARTISTS" | "ALBUM ARTISTS" => AlbumArtists, + "Artist" => TrackArtist, + "Artists" => TrackArtists, + "Arranger" => Arranger, + "Writer" => Writer, + "Composer" => Composer, + "Conductor" => Conductor, + "Director" => Director, + "Engineer" => Engineer, + "Lyricist" => Lyricist, + "DjMixer" => MixDj, + "Mixer" => MixEngineer, + "Performer" => Performer, + "Producer" => Producer, + "Label" => Label, + "MixArtist" => Remixer, + "Disc" => DiscNumber, + "Disc" => DiscTotal, + "Track" => TrackNumber, + "Track" => TrackTotal, + "Year" => Year, + "ORIGINALYEAR" => OriginalReleaseDate, + "RELEASEDATE" => ReleaseDate, + "ISRC" => Isrc, + "Barcode" => Barcode, + "CatalogNumber" => CatalogNumber, + "Compilation" => FlagCompilation, + "Media" => OriginalMediaType, + "EncodedBy" => EncodedBy, + "REPLAYGAIN_ALBUM_GAIN" => ReplayGainAlbumGain, + "REPLAYGAIN_ALBUM_PEAK" => ReplayGainAlbumPeak, + "REPLAYGAIN_TRACK_GAIN" => ReplayGainTrackGain, + "REPLAYGAIN_TRACK_PEAK" => ReplayGainTrackPeak, + "Genre" => Genre, + "Color" => Color, + "Mood" => Mood, + "Copyright" => CopyrightMessage, + "Comment" => Comment, + "language" => Language, + "Script" => Script, + "Lyrics" => Lyrics, + "MUSICBRAINZ_TRACKID" => MusicBrainzRecordingId, + "MUSICBRAINZ_RELEASETRACKID" => MusicBrainzTrackId, + "MUSICBRAINZ_ALBUMID" => MusicBrainzReleaseId, + "MUSICBRAINZ_RELEASEGROUPID" => MusicBrainzReleaseGroupId, + "MUSICBRAINZ_ARTISTID" => MusicBrainzArtistId, + "MUSICBRAINZ_ALBUMARTISTID" => MusicBrainzReleaseArtistId, + "MUSICBRAINZ_WORKID" => MusicBrainzWorkId ); gen_map!( ID3V2_MAP; - "TALB" => AlbumTitle, - "TSST" => SetSubtitle, - "TIT1" => ContentGroup, - "GRP1" => AppleId3v2ContentGroup, - "TIT2" => TrackTitle, - "TIT3" => TrackSubtitle, - "TOAL" => OriginalAlbumTitle, - "TOPE" => OriginalArtist, - "TOLY" => OriginalLyricist, - "TSOA" => AlbumTitleSortOrder, - "TSO2" => AlbumArtistSortOrder, - "TSOT" => TrackTitleSortOrder, - "TSOP" => TrackArtistSortOrder, - "TSOC" => ComposerSortOrder, - "TPE2" => AlbumArtist, - "TPE1" => TrackArtist, - "ARTISTS" => TrackArtists, - "TEXT" => Writer, - "TCOM" => Composer, - "TPE3" => Conductor, - "DIRECTOR" => Director, - "TEXT" => Lyricist, - "TMCL" => MusicianCredits, - "TPUB" => Publisher, - "TPUB" => Label, - "TRSN" => InternetRadioStationName, - "TRSO" => InternetRadioStationOwner, - "TPE4" => Remixer, - "TPOS" => DiscNumber, - "TPOS" => DiscTotal, - "TRCK" => TrackNumber, - "TRCK" => TrackTotal, - "POPM" => Popularimeter, - "ITUNESADVISORY" => ParentalAdvisory, - "TDRC" => RecordingDate, - "TDOR" => OriginalReleaseDate, - "TSRC" => Isrc, - "BARCODE" => Barcode, - "CATALOGNUMBER" => CatalogNumber, - "WORK" => Work, // ID3v2.4: TXXX:WORK (Apple uses TIT1/ContentGroup, see GRP1/AppleId3v2ContentGroup for disambiguation) - "MVNM" => Movement, - "MVIN" => MovementNumber, - "MVIN" => MovementTotal, - "TCMP" => FlagCompilation, - "PCST" => FlagPodcast, - "TFLT" => FileType, - "TOWN" => FileOwner, - "TDTG" => TaggingTime, - "TLEN" => Length, - "TOFN" => OriginalFileName, - "TMED" => OriginalMediaType, - "TENC" => EncodedBy, - "TSSE" => EncoderSoftware, - "TSSE" => EncoderSettings, - "TDEN" => EncodingTime, - "REPLAYGAIN_ALBUM_GAIN" => ReplayGainAlbumGain, - "REPLAYGAIN_ALBUM_PEAK" => ReplayGainAlbumPeak, - "REPLAYGAIN_TRACK_GAIN" => ReplayGainTrackGain, - "REPLAYGAIN_TRACK_PEAK" => ReplayGainTrackPeak, - "WOAF" => AudioFileUrl, - "WOAS" => AudioSourceUrl, - "WCOM" => CommercialInformationUrl, - "WCOP" => CopyrightUrl, - "WOAR" => TrackArtistUrl, - "WORS" => RadioStationUrl, - "WPAY" => PaymentUrl, - "WPUB" => PublisherUrl, - "TCON" => Genre, - "TKEY" => InitialKey, - "COLOR" => Color, - "TMOO" => Mood, - "TBPM" => IntegerBpm, - "TCOP" => CopyrightMessage, - "TDES" => PodcastDescription, - "TCAT" => PodcastSeriesCategory, - "WFED" => PodcastUrl, - "TDRL" => ReleaseDate, - "TGID" => PodcastGlobalUniqueId, - "TKWD" => PodcastKeywords, - "COMM" => Comment, - "TLAN" => Language, - "USLT" => Lyrics, + "TALB" => AlbumTitle, + "TSST" => SetSubtitle, + "TIT1" => ContentGroup, + "GRP1" => AppleId3v2ContentGroup, + "TIT2" => TrackTitle, + "TIT3" => TrackSubtitle, + "TOAL" => OriginalAlbumTitle, + "TOPE" => OriginalArtist, + "TOLY" => OriginalLyricist, + "TSOA" => AlbumTitleSortOrder, + "TSO2" => AlbumArtistSortOrder, + "TSOT" => TrackTitleSortOrder, + "TSOP" => TrackArtistSortOrder, + "TSOC" => ComposerSortOrder, + "TPE2" | "ALBUMARTIST" | "ALBUM ARTIST" => AlbumArtist, + "ALBUMARTISTS" | "ALBUM ARTISTS" => AlbumArtists, + "TPE1" => TrackArtist, + "ARTISTS" => TrackArtists, + "TEXT" => Writer, + "TCOM" => Composer, + "TPE3" => Conductor, + "DIRECTOR" => Director, + "TEXT" => Lyricist, + "TMCL" => MusicianCredits, + "TPUB" => Publisher, + "TPUB" => Label, + "TRSN" => InternetRadioStationName, + "TRSO" => InternetRadioStationOwner, + "TPE4" => Remixer, + "TPOS" => DiscNumber, + "TPOS" => DiscTotal, + "TRCK" => TrackNumber, + "TRCK" => TrackTotal, + "POPM" => Popularimeter, + "ITUNESADVISORY" => ParentalAdvisory, + "TDRC" => RecordingDate, + "TDOR" => OriginalReleaseDate, + "TSRC" => Isrc, + "BARCODE" => Barcode, + "CATALOGNUMBER" => CatalogNumber, + "WORK" => Work, // ID3v2.4: TXXX:WORK (Apple uses TIT1/ContentGroup, see GRP1/AppleId3v2ContentGroup for disambiguation) + "MVNM" => Movement, + "MVIN" => MovementNumber, + "MVIN" => MovementTotal, + "TCMP" => FlagCompilation, + "PCST" => FlagPodcast, + "TFLT" => FileType, + "TOWN" => FileOwner, + "TDTG" => TaggingTime, + "TLEN" => Length, + "TOFN" => OriginalFileName, + "TMED" => OriginalMediaType, + "TENC" => EncodedBy, + "TSSE" => EncoderSoftware, + "TSSE" => EncoderSettings, + "TDEN" => EncodingTime, + "REPLAYGAIN_ALBUM_GAIN" => ReplayGainAlbumGain, + "REPLAYGAIN_ALBUM_PEAK" => ReplayGainAlbumPeak, + "REPLAYGAIN_TRACK_GAIN" => ReplayGainTrackGain, + "REPLAYGAIN_TRACK_PEAK" => ReplayGainTrackPeak, + "WOAF" => AudioFileUrl, + "WOAS" => AudioSourceUrl, + "WCOM" => CommercialInformationUrl, + "WCOP" => CopyrightUrl, + "WOAR" => TrackArtistUrl, + "WORS" => RadioStationUrl, + "WPAY" => PaymentUrl, + "WPUB" => PublisherUrl, + "TCON" => Genre, + "TKEY" => InitialKey, + "COLOR" => Color, + "TMOO" => Mood, + "TBPM" => IntegerBpm, + "TCOP" => CopyrightMessage, + "TDES" => PodcastDescription, + "TCAT" => PodcastSeriesCategory, + "WFED" => PodcastUrl, + "TDRL" => ReleaseDate, + "TGID" => PodcastGlobalUniqueId, + "TKWD" => PodcastKeywords, + "COMM" => Comment, + "TLAN" => Language, + "USLT" => Lyrics, // Mapping of MusicBrainzRecordingId is implemented as a special case - "MusicBrainz Release Track Id" => MusicBrainzTrackId, - "MusicBrainz Album Id" => MusicBrainzReleaseId, - "MusicBrainz Release Group Id" => MusicBrainzReleaseGroupId, - "MusicBrainz Artist Id" => MusicBrainzArtistId, - "MusicBrainz Album Artist Id" => MusicBrainzReleaseArtistId, - "MusicBrainz Work Id" => MusicBrainzWorkId + "MusicBrainz Release Track Id" => MusicBrainzTrackId, + "MusicBrainz Album Id" => MusicBrainzReleaseId, + "MusicBrainz Release Group Id" => MusicBrainzReleaseGroupId, + "MusicBrainz Artist Id" => MusicBrainzArtistId, + "MusicBrainz Album Artist Id" => MusicBrainzReleaseArtistId, + "MusicBrainz Work Id" => MusicBrainzWorkId ); gen_map!( @@ -250,6 +252,7 @@ gen_map!( "sosn" => ShowNameSortOrder, "soco" => ComposerSortOrder, "aART" => AlbumArtist, + "----:com.apple.iTunes:ALBUMARTISTS" => AlbumArtists, "\u{a9}ART" => TrackArtist, "----:com.apple.iTunes:ARTISTS" => TrackArtists, "\u{a9}wrt" => Composer, @@ -350,7 +353,8 @@ gen_map!( "ALBUMARTISTSORT" => AlbumArtistSortOrder, "TITLESORT" => TrackTitleSortOrder, "ARTISTSORT" => TrackArtistSortOrder, - "ALBUMARTIST" => AlbumArtist, + "ALBUMARTIST" | "ALBUM ARTIST" => AlbumArtist, + "ALBUMARTISTS" | "ALBUM ARTISTS" => AlbumArtists, "ARTIST" => TrackArtist, "ARTISTS" => TrackArtists, "ARRANGER" => Arranger, @@ -523,6 +527,14 @@ gen_item_keys!( // People & Organizations AlbumArtist, + /// The name of each credited album-level artist + /// + /// This tag is meant to appear multiple times in a tag, so it should be retrieved with + /// [`Tag::get_strings`] or [`Tag::take_strings`]. + /// + /// [`Tag::get_strings`]: crate::tag::Tag::get_strings + /// [`Tag::take_strings`]: crate::tag::Tag::take_strings + AlbumArtists, TrackArtist, /// The name of each credited artist ///