use std::time::{Duration, UNIX_EPOCH};
use rusqlite::{named_params, Connection, Row};
use crate::{const_str, track::Track};
#[derive(Clone, Debug)]
pub struct TrackDB {
pub id: u64,
pub artist: String,
pub title: String,
pub album: String,
pub genre: String,
pub file: String,
pub duration: Duration,
pub name: String,
pub ext: String,
pub directory: String,
pub last_modified: String,
pub last_position: Duration,
}
impl TrackDB {
pub fn try_from_row_id(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
let d_u64: u64 = row.get(6)?;
let last_position_u64: u64 = row.get(11)?;
Ok(TrackDB {
id: row.get(0)?,
artist: row.get(1)?,
title: row.get(2)?,
album: row.get(3)?,
genre: row.get(4)?,
file: row.get(5)?,
duration: Duration::from_secs(d_u64),
name: row.get(7)?,
ext: row.get(8)?,
directory: row.get(9)?,
last_modified: row.get(10)?,
last_position: Duration::from_secs(last_position_u64),
})
}
pub fn try_from_row_named(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
let d_u64: u64 = row.get("duration")?;
let last_position_u64: u64 = row.get("last_position")?;
Ok(TrackDB {
id: row.get("id")?,
artist: row.get("artist")?,
title: row.get("title")?,
album: row.get("album")?,
genre: row.get("genre")?,
file: row.get("file")?,
duration: Duration::from_secs(d_u64),
name: row.get("name")?,
ext: row.get("ext")?,
directory: row.get("directory")?,
last_modified: row.get("last_modified")?,
last_position: Duration::from_secs(last_position_u64),
})
}
}
#[derive(Clone, Debug)]
pub struct TrackDBInsertable<'a> {
pub artist: &'a str,
pub title: &'a str,
pub album: &'a str,
pub genre: &'a str,
pub file: &'a str,
pub duration: Duration,
pub name: &'a str,
pub ext: &'a str,
pub directory: &'a str,
pub last_modified: String,
pub last_position: Duration,
}
const_str! {
UNKNOWN_ARTIST "Unknown Artist",
UNKNOWN_TITLE "Unknown Title",
UNKNOWN_ALBUM "empty",
UNKNOWN_GENRE "no type",
UNKNOWN_FILE "Unknown File",
}
impl<'a> From<&'a Track> for TrackDBInsertable<'a> {
fn from(value: &'a Track) -> Self {
Self {
artist: value.artist().unwrap_or(UNKNOWN_ARTIST),
title: value.title().unwrap_or(UNKNOWN_TITLE),
album: value.album().unwrap_or(UNKNOWN_ALBUM),
genre: value.genre().unwrap_or(UNKNOWN_GENRE),
file: value.file().unwrap_or(UNKNOWN_FILE),
duration: value.duration(),
name: value.name().unwrap_or_default(),
ext: value.ext().unwrap_or_default(),
directory: value.directory().unwrap_or_default(),
last_modified: value
.last_modified
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs()
.to_string(),
last_position: Duration::default(),
}
}
}
impl TrackDBInsertable<'_> {
#[inline]
pub fn insert_track(&self, con: &Connection) -> Result<usize, rusqlite::Error> {
con.execute(
"INSERT INTO tracks (artist, title, album, genre, file, duration, name, ext, directory, last_modified, last_position)
values (:artist, :title, :album, :genre, :file, :duration, :name, :ext, :directory, :last_modified, :last_position)",
named_params![
":artist": &self.artist,
":title": &self.title,
":album": &self.album,
":genre": &self.genre,
":file": &self.file,
":duration": &self.duration.as_secs(),
":name": &self.name,
":ext": &self.ext,
":directory": &self.directory,
":last_modified": &self.last_modified,
":last_position": &self.last_position.as_secs().to_string(),
],
)
}
}