Skip to content

Commit da4dea1

Browse files
committed
ItemKey: Add ItemKey::TrackArtists
This is a multi-valued item where each entry contains one artist name. See <https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#artists>.
1 parent e787f81 commit da4dea1

File tree

4 files changed

+49
-0
lines changed

4 files changed

+49
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9+
### Added
10+
- **ItemKey**: `ItemKey::TrackArtists`, available for ID3v2, Vorbis Comments, APE, and MP4 Ilst ([PR](https://github.com/Serial-ATA/lofty-rs/issues/454))
11+
- 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`.
12+
- For example, a track has `ItemKey::TrackArtist` = "Foo & Bar", then `ItemKey::TrackArtists` = ["Foo", "Bar"].
13+
- See <https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#artists>
14+
915
### Fixed
1016
- **MusePack**: Fix potential panic when the beginning silence makes up the entire sample count ([PR](https://github.com/Serial-ATA/lofty-rs/pull/449))
1117
- **Timestamp**: Support timestamps without separators (ex. "20240906" vs "2024-09-06") ([issue](https://github.com/Serial-ATA/lofty-rs/issues/452)) ([PR](https://github.com/Serial-ATA/lofty-rs/issues/453))

lofty/src/id3/v2/tag.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,6 +1402,20 @@ impl MergeTag for SplitTagRemainder {
14021402
}
14031403
}
14041404

1405+
// Multi-valued TXXX key-to-frame mappings
1406+
#[allow(clippy::single_element_loop)]
1407+
for item_key in [&ItemKey::TrackArtists] {
1408+
let frame_id = item_key
1409+
.map_key(TagType::Id3v2, false)
1410+
.expect("valid frame id");
1411+
if let Some(text) = join_text_items(&mut tag, [item_key]) {
1412+
let frame = new_user_text_frame(String::from(frame_id), text);
1413+
// Optimization: No duplicate checking according to the preconditions
1414+
debug_assert!(!merged.frames.contains(&frame));
1415+
merged.frames.push(frame);
1416+
}
1417+
}
1418+
14051419
// Multi-valued Label/Publisher key-to-frame mapping
14061420
{
14071421
let frame_id = ItemKey::Label

lofty/src/id3/v2/tag/tests.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,3 +1534,23 @@ fn split_tdrc_on_id3v23_save() {
15341534
.expect("Expected TIME frame");
15351535
assert_eq!(time, "1408");
15361536
}
1537+
1538+
#[test_log::test]
1539+
fn artists_tag_conversion() {
1540+
const ARTISTS: &[&str] = &["Foo", "Bar", "Baz"];
1541+
1542+
let mut tag = Tag::new(TagType::Id3v2);
1543+
1544+
for artist in ARTISTS {
1545+
tag.push(TagItem::new(
1546+
ItemKey::TrackArtists,
1547+
ItemValue::Text((*artist).to_string()),
1548+
));
1549+
}
1550+
1551+
let tag: Id3v2Tag = tag.into();
1552+
let txxx_artists = tag.get_user_text("ARTISTS").unwrap();
1553+
let id3v2_artists = txxx_artists.split('\0').collect::<Vec<_>>();
1554+
1555+
assert_eq!(id3v2_artists, ARTISTS);
1556+
}

lofty/src/tag/item.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ gen_map!(
8888
"ARTISTSORT" => TrackArtistSortOrder,
8989
"Album Artist" | "ALBUMARTIST" => AlbumArtist,
9090
"Artist" => TrackArtist,
91+
"Artists" => TrackArtists,
9192
"Arranger" => Arranger,
9293
"Writer" => Writer,
9394
"Composer" => Composer,
@@ -154,6 +155,7 @@ gen_map!(
154155
"TSOC" => ComposerSortOrder,
155156
"TPE2" => AlbumArtist,
156157
"TPE1" => TrackArtist,
158+
"ARTISTS" => TrackArtists,
157159
"TEXT" => Writer,
158160
"TCOM" => Composer,
159161
"TPE3" => Conductor,
@@ -249,6 +251,7 @@ gen_map!(
249251
"soco" => ComposerSortOrder,
250252
"aART" => AlbumArtist,
251253
"\u{a9}ART" => TrackArtist,
254+
"----:com.apple.iTunes:ARTISTS" => TrackArtists,
252255
"\u{a9}wrt" => Composer,
253256
"\u{a9}dir" => Director,
254257
"----:com.apple.iTunes:CONDUCTOR" => Conductor,
@@ -349,6 +352,7 @@ gen_map!(
349352
"ARTISTSORT" => TrackArtistSortOrder,
350353
"ALBUMARTIST" => AlbumArtist,
351354
"ARTIST" => TrackArtist,
355+
"ARTISTS" => TrackArtists,
352356
"ARRANGER" => Arranger,
353357
"AUTHOR" | "WRITER" => Writer,
354358
"COMPOSER" => Composer,
@@ -520,6 +524,11 @@ gen_item_keys!(
520524
// People & Organizations
521525
AlbumArtist,
522526
TrackArtist,
527+
/// The name of each credited artist
528+
///
529+
/// This tag is meant to appear multiple times in a tag, so it should be retrieved with
530+
/// [`Tag::get_strings`] or [`Tag::take_strings`].
531+
TrackArtists,
523532
Arranger,
524533
Writer,
525534
Composer,

0 commit comments

Comments
 (0)