Skip to content

Commit

Permalink
fix clippy warnings & fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Fabus1184 committed Nov 17, 2023
1 parent b130052 commit 1a0b3e7
Show file tree
Hide file tree
Showing 15 changed files with 194 additions and 206 deletions.
32 changes: 10 additions & 22 deletions src/cache.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::{config::Config, song::Song};
use std::{
collections::HashMap,
fs::Metadata,
path::{Path, PathBuf},
};

Expand Down Expand Up @@ -45,7 +44,7 @@ impl Cache {
config
.search_directories
.iter()
.flat_map(|d| WalkDir::new(d))
.flat_map(WalkDir::new)
.filter_map(|e| e.ok())
.filter(|e| e.file_type().is_file())
.filter(|e| {
Expand All @@ -54,33 +53,27 @@ impl Cache {
.map(|e| config.extensions.contains(e.to_str().unwrap_or("")))
.unwrap_or(false)
})
.filter_map(|e| {
e.metadata()
.map(|m| (e, m))
.map_err(|e| warn!("Failed to read metadata {:?}", e))
.ok()
})
.inspect(|(e, _)| {
.inspect(|e| {
trace!("Found file {}", e.path().display());
})
.filter_map(|(e, m)| {
.filter_map(|e| {
Song::load(e.path())
.map(|s| (e.path().to_path_buf(), m, s))
.map(|s| (e.path().to_path_buf(), s))
.map_err(|e| {
warn!("Failed to read song from {:?}: {}", e, e);
})
.ok()
})
.for_each(|(p, m, s)| {
.for_each(|(p, s)| {
cache
.insert_file(&p, m, s)
.insert_file(&p, s)
.unwrap_or_else(|e| warn!("Failed to insert file {:?}: {}", p, e));
});

cache
}

fn insert_file<P>(&mut self, path: P, meta: Metadata, song: Song) -> anyhow::Result<()>
fn insert_file<P>(&mut self, path: P, song: Song) -> anyhow::Result<()>
where
P: AsRef<Path>,
{
Expand All @@ -105,7 +98,7 @@ impl Cache {
.or_insert(CacheEntry::Directory {
children: HashMap::new(),
})
.insert_file(cs, meta, song)?;
.insert_file(cs, song)?;

Ok(())
}
Expand Down Expand Up @@ -229,12 +222,7 @@ impl CacheEntry {
}
}

fn insert_file(
&mut self,
mut path: Vec<&str>,
meta: Metadata,
song: Song,
) -> anyhow::Result<()> {
fn insert_file(&mut self, mut path: Vec<&str>, song: Song) -> anyhow::Result<()> {
match self {
CacheEntry::File { .. } => {
anyhow::bail!("CacheEntry::insert_file called on {:?}", self)
Expand All @@ -260,7 +248,7 @@ impl CacheEntry {
.or_insert_with(|| CacheEntry::Directory {
children: HashMap::new(),
})
.insert_file(path, meta, song)
.insert_file(path, song)
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ impl Config {
Ok(())
}

pub fn default_from_config_dir(config_dir: &PathBuf) -> Self {
pub fn default_from_config_dir<P: AsRef<std::path::Path>>(config_dir: P) -> Self {
Self {
search_directories: vec![],
extensions: HashSet::new(),
cache_path: config_dir.join("ramp.cache"),
log_path: config_dir.join("ramp.log"),
cache_path: config_dir.as_ref().join("ramp.cache"),
log_path: config_dir.as_ref().join("ramp.log"),
gain: OrderedFloat(0.0),
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ fn main() -> anyhow::Result<()> {
}

let config = Arc::new(
Config::load(&config_dir.join("config.json")).unwrap_or_else(|e| {
Config::load(config_dir.join("config.json")).unwrap_or_else(|e| {
eprintln!("Failed to load config, using default: {e:?}");
let config = Config::default_from_config_dir(&config_dir);
config
.save(&config_dir.join("config.json"))
.save(config_dir.join("config.json"))
.unwrap_or_else(|e| {
eprintln!("Failed to save config: {e:?}");
});
Expand Down
8 changes: 4 additions & 4 deletions src/player/facade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::song::Song;
use super::Player;

#[derive(Default)]
#[allow(clippy::large_enum_variant)]
pub enum PlayerStatus {
PlayingOrPaused {
song: Song,
Expand All @@ -27,14 +28,13 @@ impl PlayerStatus {
super::InternalPlayerStatus::PlayingOrPaused {
song,
metadata,
playing_duration,
stream_paused,
playback,
..
} => PlayerStatus::PlayingOrPaused {
song: song.clone(),
metadata: metadata.clone(),
playing_duration: playing_duration.clone(),
paused: stream_paused.clone(),
playing_duration: playback.played_duration.clone(),
paused: playback.pause.clone(),
},
super::InternalPlayerStatus::Stopped => PlayerStatus::Stopped,
}
Expand Down
9 changes: 5 additions & 4 deletions src/player/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ use symphonia::core::{

use crate::song::Song;

pub type Decoder = dyn FnMut() -> anyhow::Result<(Option<SampleBuffer<f32>>, bool)> + Send;

pub struct LoadedSong {
pub song: Song,
pub metadata: Option<MetadataRevision>,
pub signal_spec: SignalSpec,
pub decoder: Box<dyn FnMut() -> anyhow::Result<(Option<SampleBuffer<f32>>, bool)> + Send>,
pub decoder: Box<Decoder>,
}

impl LoadedSong {
Expand All @@ -44,7 +46,7 @@ impl LoadedSong {

let track = format_reader
.tracks()
.into_iter()
.iter()
.find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
.ok_or(anyhow::anyhow!("No audio tracks found"))?;

Expand All @@ -65,7 +67,6 @@ impl LoadedSong {
);
debug!("Signal spec: {:?}", signal_spec);

let signal_spec2 = signal_spec.clone();
let decoder = move || match format_reader.next_packet() {
Ok(packet) => {
if packet.track_id() == track_id {
Expand All @@ -76,7 +77,7 @@ impl LoadedSong {
}
};

let mut sample_buffer = SampleBuffer::new(data.capacity() as u64, signal_spec2);
let mut sample_buffer = SampleBuffer::new(data.capacity() as u64, signal_spec);
sample_buffer.copy_interleaved_ref(data);

trace!(
Expand Down
125 changes: 22 additions & 103 deletions src/player/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,29 @@ use crate::{
song::{Song, StandardTagKey},
};
use anyhow::Context;
use cpal::{
traits::{DeviceTrait, HostTrait},
Stream, StreamConfig,
};
use log::{debug, warn};
use log::warn;
use souvlaki::{MediaControls, MediaMetadata, MediaPlayback, MediaPosition, PlatformConfig};
use std::{
collections::VecDeque,
io::{Seek, Write},
sync::{atomic::AtomicBool, mpsc, Arc, RwLock},
time::Duration,
io::Write,
sync::{mpsc, Arc, RwLock},
};
use symphonia::core::meta::MetadataRevision;
use tempfile::NamedTempFile;

use self::{command::Command, facade::PlayerFacade, loader::LoadedSong};
use self::{command::Command, facade::PlayerFacade, loader::LoadedSong, playback::Playback};

pub mod command;
pub mod facade;
mod loader;
mod playback;

#[allow(clippy::large_enum_variant)]
enum InternalPlayerStatus {
PlayingOrPaused {
song: Song,
metadata: Option<MetadataRevision>,
playing_duration: Arc<RwLock<Duration>>,
stream_paused: Arc<AtomicBool>,
_stream: Stream,
playback: Playback,
},
Stopped,
}
Expand All @@ -47,12 +42,11 @@ impl Player {
/// command player to continue playing or start playing the next song
fn play(&mut self) -> anyhow::Result<()> {
match &self.status {
InternalPlayerStatus::PlayingOrPaused {
stream_paused: paused,
..
} => {
if paused.load(std::sync::atomic::Ordering::Relaxed) {
paused.store(false, std::sync::atomic::Ordering::Relaxed);
InternalPlayerStatus::PlayingOrPaused { playback, .. } => {
if playback.pause.load(std::sync::atomic::Ordering::Relaxed) {
playback
.pause
.store(false, std::sync::atomic::Ordering::Relaxed);
}
}
InternalPlayerStatus::Stopped => {}
Expand All @@ -72,15 +66,12 @@ impl Player {
let loaded_song = LoadedSong::load(song.clone()).context("Failed to load song")?;

let metadata = loaded_song.metadata.clone();
let (stream_paused, playing_duration, _stream) =
self.create_playback(loaded_song)?;
let playback = Playback::new(self.command_tx.clone(), loaded_song)?;

self.status = InternalPlayerStatus::PlayingOrPaused {
song,
metadata,
playing_duration,
stream_paused,
_stream,
playback,
}
}
}
Expand All @@ -91,11 +82,10 @@ impl Player {
/// command player to pause
fn pause(&mut self) -> anyhow::Result<()> {
match &self.status {
InternalPlayerStatus::PlayingOrPaused {
stream_paused: paused,
..
} => {
paused.store(true, std::sync::atomic::Ordering::Relaxed);
InternalPlayerStatus::PlayingOrPaused { playback, .. } => {
playback
.pause
.store(true, std::sync::atomic::Ordering::Relaxed);
}
InternalPlayerStatus::Stopped => {}
}
Expand All @@ -106,11 +96,10 @@ impl Player {
/// command player to play if paused or pause if playing
fn play_pause(&mut self) -> anyhow::Result<()> {
match &self.status {
InternalPlayerStatus::PlayingOrPaused {
stream_paused: paused,
..
} => {
paused.fetch_xor(true, std::sync::atomic::Ordering::Relaxed);
InternalPlayerStatus::PlayingOrPaused { playback, .. } => {
playback
.pause
.fetch_xor(true, std::sync::atomic::Ordering::Relaxed);
}
InternalPlayerStatus::Stopped => {}
}
Expand Down Expand Up @@ -162,76 +151,6 @@ impl Player {
Ok(())
}

/// create playback stream for song
fn create_playback(
&mut self,
mut song: LoadedSong,
) -> anyhow::Result<(Arc<AtomicBool>, Arc<RwLock<Duration>>, Stream)> {
let config = StreamConfig {
channels: song.signal_spec.channels.count() as u16,
sample_rate: cpal::SampleRate(song.signal_spec.rate),
buffer_size: cpal::BufferSize::Default,
};
debug!("Stream config: {:?}", config);

let mut buffer = VecDeque::<f32>::new();

let pause_stream = Arc::new(AtomicBool::new(false));
let playing_duration = Arc::new(RwLock::new(Duration::from_secs(0)));

let gain_factor = song.song.gain_factor;
let pause_stream2 = pause_stream.clone();
let playing_duration2 = playing_duration.clone();
let command_tx = self.command_tx.clone();

let stream = cpal::default_host()
.default_output_device()
.expect("Failed to get default output device")
.build_output_stream::<f32, _, _>(
&config,
move |dest, _info| {
if pause_stream2.load(std::sync::atomic::Ordering::Relaxed) {
dest.fill(0.0);
return;
}

let mut duration = playing_duration2.write().unwrap();

let mut byte_count = 0;
while byte_count < dest.len() {
if buffer.len() < dest.len() {
let (sample_buffer, end_of_stream) = (song.decoder)().unwrap();
if let Some(sample_buffer) = sample_buffer {
buffer.extend(sample_buffer.samples());
}

if end_of_stream {
command_tx.send(Command::Skip).unwrap();
}
}

buffer
.drain(..(dest.len() - byte_count).min(buffer.len()))
.for_each(|sample| {
dest[byte_count] = sample * gain_factor;
byte_count += 1;
});
}

*duration += Duration::from_secs_f64(
dest.len() as f64 / config.channels as f64 / config.sample_rate.0 as f64,
);
},
|e| {
warn!("Error in playback stream: {:?}", e);
},
None,
)
.expect("Failed to build output stream");

Ok((pause_stream, playing_duration, stream))
}

pub fn run(
cache: Arc<Cache>,
) -> anyhow::Result<(mpsc::Sender<Command>, Arc<RwLock<PlayerFacade>>)> {
Expand Down
Loading

0 comments on commit 1a0b3e7

Please sign in to comment.