From 508185c48cd46d6c4c29dbd99ebd2a173e014415 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Mon, 30 May 2022 08:45:08 -0400 Subject: [PATCH] WavPack: Support writing tags --- src/ape/tag/write.rs | 2 +- src/file.rs | 2 +- src/id3/v1/write.rs | 2 +- src/properties.rs | 21 +++++++++++++++++++++ src/tag/utils.rs | 3 ++- src/wavpack/mod.rs | 1 + src/wavpack/write.rs | 24 ++++++++++++++++++++++++ tests/files/wavpack.rs | 13 ++++--------- 8 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 src/wavpack/write.rs diff --git a/src/ape/tag/write.rs b/src/ape/tag/write.rs index 1b9ba93f..dd410def 100644 --- a/src/ape/tag/write.rs +++ b/src/ape/tag/write.rs @@ -22,7 +22,7 @@ where let probe = Probe::new(data).guess_file_type()?; match probe.file_type() { - Some(FileType::APE | FileType::MP3) => {}, + Some(FileType::APE | FileType::MP3 | FileType::WavPack) => {}, _ => return Err(LoftyError::new(ErrorKind::UnsupportedTag)), } diff --git a/src/file.rs b/src/file.rs index 8d3a1878..c3af3085 100644 --- a/src/file.rs +++ b/src/file.rs @@ -388,7 +388,7 @@ impl FileType { None }, - 82 if buf.len() >= 4 && &buf[..4] == b"wvpk" => Some(Self::WavPack), + 119 if buf.len() >= 4 && &buf[..4] == b"wvpk" => Some(Self::WavPack), _ if buf.len() >= 8 && &buf[4..8] == b"ftyp" => Some(Self::MP4), _ => None, } diff --git a/src/id3/v1/write.rs b/src/id3/v1/write.rs index d1a6f576..7e20ddeb 100644 --- a/src/id3/v1/write.rs +++ b/src/id3/v1/write.rs @@ -14,7 +14,7 @@ pub(crate) fn write_id3v1(writer: &mut File, tag: &Id3v1TagRef<'_>) -> Result<() let probe = Probe::new(writer).guess_file_type()?; match probe.file_type() { - Some(ft) if ft == FileType::APE || ft == FileType::MP3 => {}, + Some(FileType::APE | FileType::MP3 | FileType::WavPack) => {}, _ => return Err(LoftyError::new(ErrorKind::UnsupportedTag)), } diff --git a/src/properties.rs b/src/properties.rs index d2f35735..cbdcc753 100644 --- a/src/properties.rs +++ b/src/properties.rs @@ -67,6 +67,7 @@ mod tests { use crate::ogg::{ OpusFile, OpusProperties, SpeexFile, SpeexProperties, VorbisFile, VorbisProperties, }; + use crate::wavpack::{WavPackFile, WavPackProperties}; use crate::{AudioFile, FileProperties}; use std::fs::File; @@ -194,6 +195,17 @@ mod tests { channels: 2, }; + const WAVPACK_PROPERTIES: WavPackProperties = WavPackProperties { + version: 0, + duration: Duration::from_millis(1428), + overall_bitrate: 598, + audio_bitrate: 598, + sample_rate: 48000, + channels: 2, + bit_depth: 16, + lossless: false, + }; + fn get_properties(path: &str) -> T::Properties where T: AudioFile, @@ -293,4 +305,13 @@ mod tests { WAV_PROPERTIES ) } + + #[test] + #[ignore] // TODO + fn wavpack_properties() { + assert_eq!( + get_properties::("tests/files/assets/minimal/full_test.wv"), + WAVPACK_PROPERTIES + ) + } } diff --git a/src/tag/utils.rs b/src/tag/utils.rs index e1779a8c..73bf7fc9 100644 --- a/src/tag/utils.rs +++ b/src/tag/utils.rs @@ -1,7 +1,7 @@ use crate::error::{ErrorKind, LoftyError, Result}; use crate::file::FileType; use crate::tag::{Tag, TagType}; -use crate::{ape, iff, mp3}; +use crate::{ape, iff, mp3, wavpack}; #[cfg(feature = "id3v1")] use crate::id3::v1::tag::Id3v1TagRef; @@ -36,6 +36,7 @@ pub(crate) fn write_tag(tag: &Tag, file: &mut File, file_type: FileType) -> Resu crate::mp4::ilst::write::write_to(file, &mut Into::::into(tag.clone()).as_ref()) }, FileType::WAV => iff::wav::write::write_to(file, tag), + FileType::WavPack => wavpack::write::write_to(file, tag), _ => Err(LoftyError::new(ErrorKind::UnsupportedTag)), } } diff --git a/src/wavpack/mod.rs b/src/wavpack/mod.rs index 8db65853..66c38129 100644 --- a/src/wavpack/mod.rs +++ b/src/wavpack/mod.rs @@ -1,6 +1,7 @@ //! WavPack specific items mod properties; mod read; +pub(crate) mod write; #[cfg(feature = "ape")] use crate::ape::tag::ApeTag; diff --git a/src/wavpack/write.rs b/src/wavpack/write.rs new file mode 100644 index 00000000..8481f06f --- /dev/null +++ b/src/wavpack/write.rs @@ -0,0 +1,24 @@ +#[cfg(feature = "ape")] +use crate::ape; +use crate::error::{ErrorKind, LoftyError, Result}; +#[cfg(feature = "id3v1")] +use crate::id3::v1; +#[allow(unused_imports)] +use crate::tag::{Tag, TagType}; + +use std::fs::File; + +#[allow(unused_variables)] +pub(crate) fn write_to(data: &mut File, tag: &Tag) -> Result<()> { + match tag.tag_type() { + #[cfg(feature = "ape")] + TagType::Ape => ape::tag::ApeTagRef { + read_only: false, + items: ape::tag::tagitems_into_ape(tag.items()), + } + .write_to(data), + #[cfg(feature = "id3v1")] + TagType::Id3v1 => Into::>::into(tag).write_to(data), + _ => Err(LoftyError::new(ErrorKind::UnsupportedTag)), + } +} diff --git a/tests/files/wavpack.rs b/tests/files/wavpack.rs index 7ec22467..f7c5bf21 100644 --- a/tests/files/wavpack.rs +++ b/tests/files/wavpack.rs @@ -16,10 +16,7 @@ fn read() { crate::verify_artist!(file, tag, TagType::Id3v1, "Bar artist", 1); } -// TODO - #[test] -#[ignore] fn write() { let mut file = temp_file!("tests/files/assets/minimal/full_test.wv"); @@ -28,28 +25,26 @@ fn write() { assert_eq!(tagged_file.file_type(), FileType::WavPack); // APE - crate::set_artist!(tagged_file, primary_tag_mut, "Foo artist", 1 => file, "Bar artist"); + set_artist!(tagged_file, primary_tag_mut, "Foo artist", 1 => file, "Bar artist"); // ID3v1 - crate::set_artist!(tagged_file, tag_mut, TagType::Id3v1, "Bar artist", 1 => file, "Baz artist"); + set_artist!(tagged_file, tag_mut, TagType::Id3v1, "Bar artist", 1 => file, "Baz artist"); // Now reread the file file.rewind().unwrap(); let mut tagged_file = lofty::read_from(&mut file, false).unwrap(); - crate::set_artist!(tagged_file, primary_tag_mut, "Bar artist", 1 => file, "Foo artist"); + set_artist!(tagged_file, primary_tag_mut, "Bar artist", 1 => file, "Foo artist"); - crate::set_artist!(tagged_file, tag_mut, TagType::Id3v1, "Baz artist", 1 => file, "Bar artist"); + set_artist!(tagged_file, tag_mut, TagType::Id3v1, "Baz artist", 1 => file, "Bar artist"); } #[test] -#[ignore] fn remove_id3v1() { crate::remove_tag!("tests/files/assets/minimal/full_test.wv", TagType::Id3v1); } #[test] -#[ignore] fn remove_ape() { crate::remove_tag!("tests/files/assets/minimal/full_test.wv", TagType::Ape); }