Render a file list from the filesystem #24
|
@ -27,10 +27,10 @@ pub enum Message {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
Paused(Track, Duration),
|
Paused(TrackId, Duration),
|
||||||
Playing(Track, Duration),
|
Playing(TrackId, Duration),
|
||||||
Stopped,
|
Stopped,
|
||||||
Position(Track, Duration),
|
Position(TrackId, Duration),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -113,14 +113,16 @@ impl AsRef<String> for TrackId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||||
pub struct TrackInfo {
|
pub struct TrackInfo {
|
||||||
|
pub id: TrackId,
|
||||||
pub track_number: Option<i32>,
|
pub track_number: Option<i32>,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub album: Option<String>,
|
pub album: Option<String>,
|
||||||
pub artist: Option<String>,
|
pub artist: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Track {
|
pub struct Track {
|
||||||
|
@ -130,6 +132,7 @@ pub struct Track {
|
||||||
pub album: Option<String>,
|
pub album: Option<String>,
|
||||||
pub artist: Option<String>,
|
pub artist: Option<String>,
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
impl From<&mpris::Metadata> for Track {
|
impl From<&mpris::Metadata> for Track {
|
||||||
|
@ -154,13 +157,13 @@ impl From<mpris::Metadata> for Track {
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum State {
|
pub enum State {
|
||||||
Playing(Track),
|
Playing(TrackInfo),
|
||||||
Paused(Track),
|
Paused(TrackInfo),
|
||||||
Stopped,
|
Stopped,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CurrentlyPlaying {
|
pub struct CurrentlyPlaying {
|
||||||
track: Track,
|
track: TrackInfo,
|
||||||
position: Duration,
|
position: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,4 +178,11 @@ impl Core {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {}
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_lists_tracks() {
|
||||||
|
let index = MemoryIndex::new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
audio::{Track, TrackId, TrackInfo},
|
audio::{TrackId, TrackInfo},
|
||||||
FatalError,
|
FatalError,
|
||||||
};
|
};
|
||||||
use flow::{error, ok, Flow};
|
use flow::{error, ok, Flow};
|
||||||
|
@ -11,7 +11,7 @@ use std::{
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error, PartialEq)]
|
||||||
pub enum DatabaseError {
|
pub enum DatabaseError {
|
||||||
#[error("database is unreadable")]
|
#[error("database is unreadable")]
|
||||||
DatabaseUnreadable,
|
DatabaseUnreadable,
|
||||||
|
@ -20,13 +20,13 @@ pub enum DatabaseError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MusicIndex: Sync + Send {
|
pub trait MusicIndex: Sync + Send {
|
||||||
fn add_track(&mut self, track: &TrackInfo) -> Flow<Track, FatalError, DatabaseError>;
|
fn add_track(&self, track: TrackInfo) -> Flow<(), FatalError, DatabaseError>;
|
||||||
fn remove_track(&mut self, id: &TrackId) -> Flow<(), FatalError, DatabaseError>;
|
fn remove_track(&self, id: &TrackId) -> Flow<(), FatalError, DatabaseError>;
|
||||||
fn get_track_info(&self, id: &TrackId) -> Flow<Option<Track>, FatalError, DatabaseError>;
|
fn get_track_info(&self, id: &TrackId) -> Flow<Option<TrackInfo>, FatalError, DatabaseError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MemoryIndex {
|
pub struct MemoryIndex {
|
||||||
tracks: RwLock<HashMap<TrackId, Track>>,
|
tracks: RwLock<HashMap<TrackId, TrackInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemoryIndex {
|
impl MemoryIndex {
|
||||||
|
@ -38,21 +38,13 @@ impl MemoryIndex {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MusicIndex for MemoryIndex {
|
impl MusicIndex for MemoryIndex {
|
||||||
fn add_track(&mut self, info: &TrackInfo) -> Flow<Track, FatalError, DatabaseError> {
|
fn add_track(&self, info: TrackInfo) -> Flow<(), FatalError, DatabaseError> {
|
||||||
let id = TrackId::default();
|
|
||||||
let track = Track {
|
|
||||||
id: id.clone(),
|
|
||||||
track_number: info.track_number,
|
|
||||||
name: info.name.clone(),
|
|
||||||
album: info.album.clone(),
|
|
||||||
artist: info.artist.clone(),
|
|
||||||
};
|
|
||||||
let mut tracks = self.tracks.write().unwrap();
|
let mut tracks = self.tracks.write().unwrap();
|
||||||
tracks.insert(id, track.clone());
|
tracks.insert(info.id.clone(), info);
|
||||||
ok(track)
|
ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_track(&mut self, id: &TrackId) -> Flow<(), FatalError, DatabaseError> {
|
fn remove_track(&self, id: &TrackId) -> Flow<(), FatalError, DatabaseError> {
|
||||||
let mut tracks = self.tracks.write().unwrap();
|
let mut tracks = self.tracks.write().unwrap();
|
||||||
tracks.remove(&id);
|
tracks.remove(&id);
|
||||||
ok(())
|
ok(())
|
||||||
|
@ -61,7 +53,7 @@ impl MusicIndex for MemoryIndex {
|
||||||
fn get_track_info<'a>(
|
fn get_track_info<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
id: &TrackId,
|
id: &TrackId,
|
||||||
) -> Flow<Option<Track>, FatalError, DatabaseError> {
|
) -> Flow<Option<TrackInfo>, FatalError, DatabaseError> {
|
||||||
let track = {
|
let track = {
|
||||||
let tracks = self.tracks.read().unwrap();
|
let tracks = self.tracks.read().unwrap();
|
||||||
tracks.get(&id).cloned()
|
tracks.get(&id).cloned()
|
||||||
|
@ -104,3 +96,35 @@ impl Database {
|
||||||
pool.push(conn);
|
pool.push(conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn with_memory_index<F>(f: F)
|
||||||
|
where
|
||||||
|
F: Fn(&dyn MusicIndex),
|
||||||
|
{
|
||||||
|
let index = MemoryIndex::new();
|
||||||
|
f(&index)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_saves_and_loads_data() {
|
||||||
|
with_memory_index(|index| {
|
||||||
|
let info = TrackInfo {
|
||||||
|
id: TrackId::from("track_1".to_owned()),
|
||||||
|
track_number: None,
|
||||||
|
name: None,
|
||||||
|
album: None,
|
||||||
|
artist: None,
|
||||||
|
};
|
||||||
|
index.add_track(info.clone());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Flow::Ok(Some(info)),
|
||||||
|
index.get_track_info(&TrackId::from("track_1".to_owned()))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ pub mod database;
|
||||||
use database::DatabaseError;
|
use database::DatabaseError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("Database error: {0}")]
|
#[error("Database error: {0}")]
|
||||||
DatabaseError(DatabaseError),
|
DatabaseError(DatabaseError),
|
||||||
|
@ -16,7 +16,7 @@ impl From<DatabaseError> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error, PartialEq)]
|
||||||
pub enum FatalError {
|
pub enum FatalError {
|
||||||
#[error("Unexpected error")]
|
#[error("Unexpected error")]
|
||||||
UnexpectedError,
|
UnexpectedError,
|
||||||
|
|
Loading…
Reference in New Issue