spotify-dl/src/file_sink.rs

72 lines
2.1 KiB
Rust
Raw Normal View History

use std::path::Path;
2020-10-25 01:39:20 +02:00
use audiotags::{Tag, TagType};
use librespot::{playback::{audio_backend::{Open, Sink, SinkError}, config::AudioFormat, decoder::AudioPacket, convert::Converter}};
// extern crate flac_bound;
2020-10-25 01:39:20 +02:00
use flac_bound::{FlacEncoder};
use crate::TrackMetadata;
2020-10-25 01:39:20 +02:00
pub struct FileSink {
sink: String,
content: Vec<i32>,
metadata: Option<TrackMetadata>
}
impl FileSink {
pub fn add_metadata(&mut self, meta: TrackMetadata) {
self.metadata = Some(meta);
}
2020-10-25 01:39:20 +02:00
}
impl Open for FileSink {
fn open(path: Option<String>, _audio_format: AudioFormat) -> Self {
2020-10-25 01:39:20 +02:00
if let Some(path) = path {
let file = path;
FileSink {
sink: file,
content: Vec::new(),
metadata: None
2020-10-25 01:39:20 +02:00
}
} else {
panic!();
}
}
}
impl Sink for FileSink {
fn start(&mut self) -> Result<(), SinkError> {
2020-10-25 01:39:20 +02:00
Ok(())
}
fn stop(&mut self) -> Result<(), SinkError> {
let mut encoder = FlacEncoder::new().unwrap().channels(2).bits_per_sample(16).compression_level(4).init_file(&self.sink).unwrap();
2020-10-25 01:39:20 +02:00
encoder.process_interleaved(self.content.as_slice(), (self.content.len()/2) as u32).unwrap();
encoder.finish().unwrap();
match &self.metadata {
Some(meta) => {
let mut tag = Tag::new().with_tag_type(TagType::Flac).read_from_path(Path::new(&self.sink)).unwrap();
tag.set_album_title(&meta.album);
for artist in &meta.artists {
tag.add_artist(artist);
}
tag.set_title(&meta.track_name);
tag.write_to_path(&self.sink).expect("Failed to write metadata");
},
None => (),
}
2020-10-25 01:39:20 +02:00
Ok(())
}
fn write(&mut self, packet: &AudioPacket, converter: &mut Converter) -> Result<(), SinkError> {
let data = converter.f64_to_s16(packet.samples().unwrap());
let mut data32: Vec<i32> = data.iter().map(|el| i32::from(*el)).collect();
self.content.append(&mut data32);
2020-10-25 01:39:20 +02:00
Ok(())
}
}