use std::path::PathBuf;
use mineral_model::{AudioFormat, BitRate, Song};
use crate::player::PlayerCore;
pub(crate) struct CaptureHarvest {
pub(crate) song: Song,
pub(crate) quality: BitRate,
pub(crate) format: Option<AudioFormat>,
pub(crate) path: PathBuf,
}
pub(crate) async fn harvest_capture(player: &PlayerCore, cap: CaptureHarvest) {
let cache = player.media_cache();
let song_id = cap.song.id.clone();
let quality = cap.quality.as_str().to_owned();
let format = cap
.format
.as_ref()
.map_or("unknown", mineral_model::AudioFormat::as_str)
.to_owned();
let (outcome, bytes) = match std::fs::metadata(&cap.path) {
Ok(metadata) if metadata.len() > 0 => {
let bytes = i64::try_from(metadata.len()).ok();
match cache
.put_played(&cap.song, cap.quality, cap.format.as_ref(), &cap.path)
.await
{
Err(error) => {
mineral_log::warn!(target: "player", error = mineral_log::chain(&error), "音频入缓存失败");
(mineral_stats::CacheHarvestOutcome::Discarded, bytes)
}
Ok(evicted) => {
for eviction in evicted {
player.inner.stats.event(mineral_stats::StatsEvent::System(
mineral_stats::SystemEvent::CacheEviction {
cache_key: eviction.key,
bytes: i64::try_from(eviction.bytes).unwrap_or(i64::MAX),
},
));
}
if let Some(path) = cache.get(&cap.song.id, cap.quality) {
mineral_log::info!(
target: "player",
song_id = %cap.song.id.qualified(),
path = %path.display(),
"playback capture cached"
);
player.ensure_envelope(cap.song.id.clone(), path.clone());
player
.tagging()
.enqueue(cap.song.clone(), path, cap.quality);
}
(mineral_stats::CacheHarvestOutcome::Cached, bytes)
}
}
}
_ => {
mineral_log::debug!(target: "player", "capture 文件缺失/空,不入缓存");
drop(std::fs::remove_file(&cap.path));
(mineral_stats::CacheHarvestOutcome::Discarded, None)
}
};
player.inner.stats.event(mineral_stats::StatsEvent::System(
mineral_stats::SystemEvent::CacheHarvest {
song: song_id,
quality,
format,
outcome,
bytes,
},
));
}