From 4badc2fd7b1c69755e4751479582be0b762524f8 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 5 Apr 2025 14:54:38 +0300 Subject: [PATCH] wip: create/update/remove modified_tag --- Justfile | 2 + src/model/metadata.rs | 150 +++++++++++++++++------------------------- src/view.rs | 4 +- 3 files changed, 64 insertions(+), 92 deletions(-) diff --git a/Justfile b/Justfile index e7ffb7f..49a4cd9 100644 --- a/Justfile +++ b/Justfile @@ -2,6 +2,8 @@ run: cargo run -- -j16 ~/Studio/Camp run2: cargo run -- -j16 ~/Music +run3: + cargo run -- -j16 ~/Studio/Releases build-release: time cargo build -j4 --release diff --git a/src/model/metadata.rs b/src/model/metadata.rs index 8a8a453..d0bae1d 100644 --- a/src/model/metadata.rs +++ b/src/model/metadata.rs @@ -7,7 +7,7 @@ use lofty::{ probe::Probe, file::TaggedFileExt, config::{ParseOptions, ParsingMode}, - tag::{Accessor, Tag, TagItem, ItemKey, ItemValue} + tag::{Accessor, Tag, TagItem, ItemKey, ItemValue, TagType} }; pub enum Metadata { @@ -22,7 +22,7 @@ pub enum Metadata { hash: Arc, size: Arc, original_tag: Option>, - modified_tag: Option>, + modified_tag: Option>>, }, Image { invalid: bool, @@ -57,7 +57,7 @@ impl Metadata { size: format!("{:#>8.2}", size).into(), invalid: false, original_tag: tag.map(|t|t.clone().into()), - modified_tag: tag.map(|t|t.clone().into()), + modified_tag: tag.map(|t|Arc::new(t.clone().into())), }) } else { Self::new_fallback(path) @@ -124,132 +124,102 @@ impl Metadata { } macro_rules! music_tag_field { - (string: $get:ident $set:ident $key:expr) => { + (string: $get:ident $set:ident $del:ident $key:expr) => { impl Metadata { pub fn $get (&self) -> Option> { if let Metadata::Music { original_tag, modified_tag, .. } = self { - return modified_tag - .as_ref() - .map(|tag|tag.$get().map(|t|t.into())) + return modified_tag.as_ref() + .map(|tag|tag.read().unwrap().$get().map(|t|t.into())) .flatten() - .or_else(||original_tag - .as_ref() + .or_else(||original_tag.as_ref() .map(|tag|tag.$get().map(|t|t.into())) .flatten()) } None } pub fn $set (&mut self, value: &impl AsRef) -> Option { - if let Metadata::Music { original_tag, modified_tag, .. } = self { - let value = value.as_ref().trim(); - match (value.len(), original_tag, modified_tag) { - (0, Some(old_tag), Some(new_tag)) => { + let value = value.as_ref().trim(); + if let &mut Metadata::Music { ref original_tag, ref mut modified_tag, .. } = self { + match (value.len(), &modified_tag) { + (0, Some(new_tag)) => { + if new_tag.read().unwrap().item_count() <= 1 { + // removing last entry removes modified_tag + *modified_tag = None; + } else { + // remove entry from modified_tag + new_tag.write().unwrap().$del(); + } }, - (_, Some(old_tag), Some(new_tag)) => { + (_, Some(new_tag)) => { + // add entry to modified_tag + new_tag.write().unwrap().$set(value.into()) }, - (0, Some(old_tag), None) => { + (0, None) => { + // leave modified_tag empty }, - (_, Some(old_tag), None) => { - }, - (0, None, Some(new_tag)) => { - }, - (_, None, Some(new_tag)) => { - }, - (0, None, None) => { - unimplemented!("specifying new tag type") - }, - (_, None, None) => { - unimplemented!("specifying new tag type") + (_, None) => { + // first entry creates modified_tag + let mut new_tag = Tag::new(TagType::Id3v2); // FIXME other types + new_tag.$set(value.into()); + *modified_tag = Some(Arc::new(RwLock::new(new_tag))); }, } - //let value = value.as_ref().trim(); - //if value.len() > 0 { - //if old_tag.$get().is_none() { - //old_tag.$set(value) - //} - //if let Some(old_value) = old_tag.$get() { - //} - //} else { - //} } - //if let Metadata::Music { tag: Some(tag), .. } = self - //&& Some(value.as_ref()) != tag.$get().as_deref() - //{ - //*$field = Some(value.as_ref().into()); - //return Some(TagItem::new($key, ItemValue::Text(value.as_ref().into()))) - //} None } } }; - (number: $get:ident $set:ident $key:expr) => { + (number: $get:ident $set:ident $del:ident $key:expr) => { impl Metadata { pub fn $get (&self) -> Option> { if let Metadata::Music { original_tag, modified_tag, .. } = self { - return modified_tag - .as_ref() - .map(|tag|tag.$get().map(|t|format!("{t}").into())) + return modified_tag.as_ref() + .map(|tag|tag.read().unwrap().$get().map(|t|format!("{t}").into())) .flatten() - .or_else(||original_tag - .as_ref() + .or_else(||original_tag.as_ref() .map(|tag|tag.$get().map(|t|format!("{t}").into())) .flatten()) } None } pub fn $set (&mut self, value: &impl AsRef) -> Option { - if let Metadata::Music { original_tag, modified_tag, .. } = self { - let value = value.as_ref().trim(); - match (value.len(), original_tag, modified_tag) { - (0, Some(old_tag), Some(new_tag)) => { + let value = value.as_ref().trim(); + if let &mut Metadata::Music { ref original_tag, ref mut modified_tag, .. } = self + && let Ok(numeric_value) = value.parse::() + { + match (value.len(), &modified_tag) { + (0, Some(new_tag)) => { + if new_tag.read().unwrap().item_count() <= 1 { + // removing last entry removes modified_tag + *modified_tag = None; + } else { + // remove entry from modified_tag + new_tag.write().unwrap().$del(); + } }, - (_, Some(old_tag), Some(new_tag)) => { + (_, Some(new_tag)) => { + // add entry to modified_tag + new_tag.write().unwrap().$set(numeric_value) }, - (0, Some(old_tag), None) => { + (0, None) => { + // leave modified_tag empty }, - (_, Some(old_tag), None) => { - }, - (0, None, Some(new_tag)) => { - }, - (_, None, Some(new_tag)) => { - }, - (0, None, None) => { - unimplemented!("specifying new tag type") - }, - (_, None, None) => { - unimplemented!("specifying new tag type") + (_, None) => { + // first entry creates modified_tag + let mut new_tag = Tag::new(TagType::Id3v2); // FIXME other types + new_tag.$set(numeric_value); + *modified_tag = Some(Arc::new(RwLock::new(new_tag))); }, } } None - //let value = value.as_ref().trim(); - //if value.len() > 0 { - //if let Ok(value) = value.parse::() { - //if let Metadata::Music { - //tag: Some(old_tag), new_tag: Some(new_tag), .. - //} = self { - //if old_tag.$get().is_none() { - //} - //if let Some(old_value) = old_tag.$get() { - //} - //} - //} - //} else { - //} - //if let Metadata::Music { tag: Some(tag), .. } = self - //&& let Ok(value) = value.as_ref().trim().parse::() - //&& Some(value) != *$field - //{ - //*$field = Some(value); - //return Some(TagItem::new($key, ItemValue::Text(format!("{value}")))) - //} } } }; } -music_tag_field!(string: artist set_artist ItemKey::TrackArtist); -music_tag_field!(number: year set_year ItemKey::Year); -music_tag_field!(string: album set_album ItemKey::AlbumTitle); -music_tag_field!(number: track set_track ItemKey::TrackNumber); -music_tag_field!(string: title set_title ItemKey::TrackTitle); +music_tag_field!(string: artist set_artist remove_artist ItemKey::TrackArtist); +music_tag_field!(number: year set_year remove_year ItemKey::Year); +music_tag_field!(string: album set_album remove_album ItemKey::AlbumTitle); +music_tag_field!(number: track set_track remove_track ItemKey::TrackNumber); +music_tag_field!(string: title set_title remove_title ItemKey::TrackTitle); diff --git a/src/view.rs b/src/view.rs index cad70a0..7d39869 100644 --- a/src/view.rs +++ b/src/view.rs @@ -87,11 +87,11 @@ impl Taggart { Fill::x( Bsp::a( Fill::x(Align::w(format!( - " {}/{} {}", + " {:>03}/{:>03} {}", self.cursor + 1, self.entries.len(), (self.columns.0[self.column].getter)(&self.entries[self.cursor]) - .map(|value|format!("{}: {value}", self.columns.0[self.column].title,)) + .map(|value|format!("{}: {}", self.columns.0[self.column].title, value.trim())) .unwrap_or(String::default()) ))), Fill::x(Align::e(format!(