Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VorbisComments: Support current/total TRACKNUMBER fields #500

Merged
merged 3 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.22.1] - 2024-01-11

### Changed
- **VorbisComments**: Support `TRACKNUMBER` fields with the `current/total` format. ([issue](https://github.com/Serial-ATA/lofty-rs/issues/493)) ([issue](https://github.com/Serial-ATA/lofty-rs/issues/499)) ([PR](https://github.com/Serial-ATA/lofty-rs/pull/500))
- These fields will now properly be split into `TRACKNUMBER` and `TRACKTOTAL`, making it possible to use them with
[Accessor::track()](https://docs.rs/lofty/latest/lofty/tag/trait.Accessor.html#method.track) and [Accessor::track_total()](https://docs.rs/lofty/latest/lofty/tag/trait.Accessor.html#method.track_total).

## [0.22.0] - 2024-01-05

### Added
Expand Down
34 changes: 34 additions & 0 deletions lofty/src/ogg/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::config::{ParseOptions, ParsingMode};
use crate::error::{ErrorKind, LoftyError, Result};
use crate::macros::{decode_err, err, parse_mode_choice};
use crate::picture::{MimeType, Picture, PictureInformation, PictureType};
use crate::tag::Accessor;
use crate::util::text::{utf16_decode, utf8_decode, utf8_decode_str};

use std::borrow::Cow;
Expand Down Expand Up @@ -167,6 +168,39 @@ where
},
}
},
// Support the case of TRACKNUMBER being equal to current/total
k if k.eq_ignore_ascii_case(b"TRACKNUMBER") => {
match utf8_decode_str(value) {
Ok(value) => {
// try to parse as current/total
let mut value_split = value.splitn(2, '/');
let track_number: Option<u32> =
value_split.next().and_then(|b| b.parse().ok());
let track_total: Option<u32> =
value_split.next().and_then(|b| b.parse().ok());

if let Some(n) = track_number {
Copy link
Owner

Choose a reason for hiding this comment

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

The workaround here also mentions vinyl track numbers. I think in the case that the track number doesn't parse, just insert it into the tag like any other item.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added vinyl track numbers and another test. Also pushing this tag if track number can't be parsed.

Copy link
Owner

Choose a reason for hiding this comment

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

Sorry for the confusion! I meant Lofty shouldn't do anything special with vinyl tracks, since I imagine there are weird formats for those out in the wild. In the case that no track number is parsed, just insert it into the tag like normal.

Made that change in e961455 (#500)

tag.set_track(n);
} else {
// Probably some other format, like a vinyl track number (A1, B1, etc.).
// Just leave it up to the caller to deal with.
tag.items
.push((String::from("TRACKNUMBER"), value.to_owned()));
}
if let Some(n) = track_total {
tag.set_track_total(n);
}
},
Err(e) => {
if parse_mode == ParsingMode::Strict {
return Err(e);
}

log::warn!("Non UTF-8 value found, discarding field {key:?}");
continue;
},
}
},
// The valid range is 0x20..=0x7D not including 0x3D
k if k.iter().all(|c| (b' '..=b'}').contains(c) && *c != b'=') => {
// SAFETY: We just verified that all of the bytes fall within the subset of ASCII
Expand Down
Binary file added lofty/tests/files/assets/issue_499.opus
Binary file not shown.
Binary file not shown.
28 changes: 28 additions & 0 deletions lofty/tests/files/ogg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,34 @@ fn flac_with_id3v2() {
assert!(flac_file.vorbis_comments().is_some());
}

// case TRACKNUMBER=11/22 (<current>/<total>)
#[test_log::test]
fn opus_issue_499() {
use lofty::ogg::OpusFile;

let file = std::fs::read("tests/files/assets/issue_499.opus").unwrap();
let opus_file =
OpusFile::read_from(&mut std::io::Cursor::new(file), ParseOptions::new()).unwrap();

let comments = opus_file.vorbis_comments();
assert_eq!(comments.track(), Some(11));
assert_eq!(comments.track_total(), Some(22));
}

// case TRACKNUMBER=a5 (vinyl format)
#[test_log::test]
fn opus_issue_499_vinyl_track_number() {
use lofty::ogg::OpusFile;

let file = std::fs::read("tests/files/assets/issue_499_vinyl_track_number.opus").unwrap();
let opus_file =
OpusFile::read_from(&mut std::io::Cursor::new(file), ParseOptions::new()).unwrap();

let comments = opus_file.vorbis_comments();
assert_eq!(comments.track(), None);
assert_eq!(comments.get("TRACKNUMBER"), Some("a5"));
}

#[test_log::test]
fn flac_remove_id3v2() {
crate::remove_tag!("tests/files/assets/flac_with_id3v2.flac", TagType::Id3v2);
Expand Down
Loading