From 6b45477a9de201e1284442d9fa96716af8907d39 Mon Sep 17 00:00:00 2001 From: Toasterkitten Date: Mon, 24 Aug 2026 16:46:42 -0400 Subject: [PATCH] cover art --- src/adopt.rs | 9 +++++---- src/coverartarchive.rs | 19 +++++++++++++++++++ src/main.rs | 2 ++ src/tagging.rs | 25 +++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 src/coverartarchive.rs diff --git a/src/adopt.rs b/src/adopt.rs index 4834baa..f5b0934 100644 --- a/src/adopt.rs +++ b/src/adopt.rs @@ -9,7 +9,7 @@ use std::{ time::{SystemTime, UNIX_EPOCH}, }; -use crate::{import, musicbrainz::get_disc_info, tagging}; +use crate::{coverartarchive::fetch_cover_art, import, musicbrainz::get_disc_info, tagging}; // adopt = rip a disc but ripping sounds like destroying so i'm not using it pub fn adopt(timbre_dir: &Path) { @@ -79,12 +79,12 @@ pub fn adopt(timbre_dir: &Path) { } child.wait().expect("cdparanoia didn't finish cleanly :(\n"); - let flac_name = format!("track{track_num:02}.flac"); - let flac_path = tmp_dir.join(&flac_name); + let wav_path = tmp_dir.join(format!("track{track_num:02}.wav")); + let flac_path = tmp_dir.join(format!("track{track_num:02}.flac")); Command::new("flac") .arg("--best") // max compression, lossless - .arg(&flac_path) // input WAV + .arg(&wav_path) // input WAV .output() .expect("flac wouldn't encode :( is it installed?\n"); @@ -94,6 +94,7 @@ pub fn adopt(timbre_dir: &Path) { ¤t_track.artist_credit[0].name, &release.title, track_num as u32, + fetch_cover_art(&release.id).as_deref(), ); import::import_file(&flac_path, timbre_dir); diff --git a/src/coverartarchive.rs b/src/coverartarchive.rs new file mode 100644 index 0000000..0e939b9 --- /dev/null +++ b/src/coverartarchive.rs @@ -0,0 +1,19 @@ +use std::io::Read; + +pub fn fetch_cover_art(release_id: &str) -> Option> { + let url = format!("https://coverartarchive.org/release/{}/front", release_id); + let response = ureq::get(&url) + .header("User-Agent", "Timbre/0.1 ( ...your repo... )") + .call(); + match response { + Ok(resp) => { + let mut bytes = Vec::new(); + resp.into_body() + .into_reader() + .read_to_end(&mut bytes) + .expect("i couldn't read the cover art :(\n"); + Some(bytes) + } + Err(_) => None, + } +} diff --git a/src/main.rs b/src/main.rs index 9891f6a..6c6c3d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,10 @@ mod adopt; +mod coverartarchive; mod disc_id; mod import; mod musicbrainz; mod tagging; + use clap::{ Parser, Subcommand, builder::styling::{AnsiColor, Effects, Styles}, diff --git a/src/tagging.rs b/src/tagging.rs index fb2f031..77f31c5 100644 --- a/src/tagging.rs +++ b/src/tagging.rs @@ -1,7 +1,20 @@ -use lofty::{config::WriteOptions, prelude::*, probe::Probe, tag::Tag}; +use lofty::{ + config::WriteOptions, + picture::{MimeType, Picture, PictureType}, + prelude::*, + probe::Probe, + tag::Tag, +}; use std::path::Path; -pub fn write_tags(path: &Path, title: &str, artist: &str, album: &str, track_num: u32) { +pub fn write_tags( + path: &Path, + title: &str, + artist: &str, + album: &str, + track_num: u32, + cover: Option<&[u8]>, +) { let mut tagged_file = Probe::open(path) .expect("couldn't open the flac :(\n") .read() @@ -24,6 +37,14 @@ pub fn write_tags(path: &Path, title: &str, artist: &str, album: &str, track_num tag.set_album(album.to_string()); tag.set_track(track_num); + if let Some(image_bytes) = cover { + let picture = Picture::unchecked(image_bytes.to_vec()) + .pic_type(PictureType::CoverFront) + .mime_type(MimeType::Jpeg) + .build(); + tag.set_picture(0, picture); + } + tag.save_to_path(path, WriteOptions::default()) .expect("couldn't save the tags :(\n"); }