Parse music metadata

This commit is contained in:
Alexander
2026-06-25 21:04:47 +02:00
parent b51c680af4
commit 536e117576
6 changed files with 264 additions and 10 deletions
+18 -1
View File
@@ -8,10 +8,12 @@ use std::{
time::{Duration, SystemTime},
};
use clap::builder::OsStr;
use fuser::{Errno, FileAttr, Filesystem, Generation, INodeNo, Request};
use notify::{Event, EventKind, RecursiveMode, Watcher};
use crate::file_watcher::FileWatcher;
use crate::music_metadata::MusicMetadata;
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
enum FileType {
@@ -27,6 +29,7 @@ struct LocalItem {
local_path: PathBuf,
file_type: FileType,
metadata: fs::Metadata,
music_metadata: Option<MusicMetadata>,
}
#[derive(Debug)]
@@ -49,6 +52,7 @@ impl LocalOrigin {
local_path: PathBuf::from(&destination),
file_type: FileType::Directory,
metadata: fs::metadata(&source).unwrap(),
music_metadata: Option::None,
};
map.lock().unwrap().insert(INodeNo::ROOT, local_root);
@@ -79,6 +83,7 @@ impl LocalOrigin {
local_path: destination.to_path_buf(),
file_type: FileType::Directory,
metadata: fs::metadata(&source).unwrap(),
music_metadata: Option::None,
};
map.lock().unwrap().insert(INodeNo::ROOT, local_root);
@@ -109,13 +114,25 @@ impl LocalOrigin {
// local_path.push(destination);
local_path.push(name.clone());
let music_metadata: Option<MusicMetadata> = if item_path
.extension()
.and_then(std::ffi::OsStr::to_str)
.unwrap()
== "flac"
{
MusicMetadata::parse_music_metadata(&item_path)
} else {
Option::None
};
let local_item = LocalItem {
inode: INodeNo(metadata.ino()),
name: name,
original_path: item_path.clone(),
local_path: local_path,
file_type: file_type,
metadata,
metadata: metadata,
music_metadata: music_metadata,
};
let inode = local_item.inode;
+1
View File
@@ -7,6 +7,7 @@ use std::time::Duration;
mod file_watcher;
mod local;
mod music_metadata;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
+56
View File
@@ -0,0 +1,56 @@
use std::{fs, path::Path};
use symphonia::core::{
formats::FormatOptions,
io::MediaSourceStream,
meta::{Metadata, MetadataOptions, MetadataRevision, StandardTagKey},
probe::Hint,
};
#[derive(Debug, Default)]
pub struct MusicMetadata {
artist: Vec<String>,
album: String,
track_number: i32,
track_title: String,
}
impl MusicMetadata {
pub fn parse_music_metadata(path: &Path) -> Option<MusicMetadata> {
let src = fs::File::open(path).expect("failed to open media");
let mss = MediaSourceStream::new(Box::new(src), Default::default());
let mut hint = Hint::new();
hint.with_extension("flac");
let meta_opts: MetadataOptions = Default::default();
let fmt_opts: FormatOptions = Default::default();
let mut format = symphonia::default::get_probe()
.format(&hint, mss, &fmt_opts, &meta_opts)
.expect("unsupported format");
let metadata: Metadata = format.format.metadata();
let revision: &MetadataRevision = metadata.current().unwrap();
let mut music_metadata = MusicMetadata {
..Default::default()
};
for tag in revision.tags() {
let tag_type = tag.std_key.expect("no std_key for tag found");
let value = tag.value.to_string();
match tag_type {
StandardTagKey::Artist => music_metadata.artist.push(value),
StandardTagKey::Album => music_metadata.album = value,
StandardTagKey::TrackNumber => {
music_metadata.track_number = value.parse::<i32>().unwrap()
}
StandardTagKey::TrackTitle => music_metadata.track_title = value,
_ => {}
}
}
return Some(music_metadata);
}
}