Browse Source

main: start building a non-poc artist management

master
Skia 8 months ago
parent
commit
550cad8223
1 changed files with 37 additions and 196 deletions
  1. 37
    196
      src/main.rs

+ 37
- 196
src/main.rs View File

@@ -8,137 +8,14 @@ use std::ffi::OsStr;
use libc::{ENOENT,EOF};
use time::Timespec;
use fuse::{FileType, FileAttr, Filesystem, Request, ReplyData, ReplyEntry, ReplyAttr, ReplyDirectory};
use std::collections::HashMap;

extern crate sunk;
use sunk::Streamable;

const SONG_ID: u64 = 1 << 63;
const ALBUM_ID: u64 = 1 << 62;
const ARTIST_ID: u64 = 1 << 61;

use sunk::{Artist, Streamable, ListType};

const TTL: Timespec = Timespec { sec: 1, nsec: 0 }; // 1 second

const CREATE_TIME: Timespec = Timespec { sec: 1381237736, nsec: 0 }; // 2013-10-08 08:56

struct Artist {
pub name: String,
pub id: usize,
}

impl Artist {
fn new_from_id(client: & sunk::Client, id: usize) -> Artist {
let a = sunk::Artist::get(&client, id).unwrap();
Artist {
id,
name: a.name,
}
}

fn new_from_ino(client: & sunk::Client, ino: u64) -> Artist {
let id = (ino & !ARTIST_ID) as usize;
Artist::new_from_id(&client, id)
}

fn get_ino(&self) -> u64 {
self.id as u64 | ARTIST_ID
}

fn get_attr(&self) -> FileAttr {
FileAttr {
ino: self.get_ino(),
size: 0,
blocks: 0,
atime: CREATE_TIME,
mtime: CREATE_TIME,
ctime: CREATE_TIME,
crtime: CREATE_TIME,
kind: FileType::RegularFile,
perm: 0o755,
nlink: 2,
uid: 501,
gid: 20,
rdev: 0,
flags: 0,
}
}
}

type Song = sunk::song::Song;

trait SubFSFile {
type File;
fn get_ino_from_id(id: usize) -> u64;
fn get_id_from_ino(ino: u64) -> usize;
fn new_from_id(client: & sunk::Client, id: usize) -> Self::File;
fn new_from_ino(client: & sunk::Client, ino: u64) -> Self::File;
fn get_ino(&self) -> u64;
fn get_attr(&self) -> FileAttr;
}

impl SubFSFile for Song {
type File = Song;

fn get_ino_from_id(id: usize) -> u64 {
id as u64 | SONG_ID
}
fn get_id_from_ino(ino: u64) -> usize {
ino as usize & !SONG_ID as usize
}

fn new_from_id(client: & sunk::Client, id: usize) -> Song {
Song::get(&client, id as u64).unwrap()
}

fn new_from_ino(client: & sunk::Client, ino: u64) -> Song {
let id = Song::get_id_from_ino(ino);
Song::new_from_id(&client, id)
}

fn get_ino(&self) -> u64 {
Song::get_ino_from_id(self.id as usize)
}

fn get_attr(&self) -> FileAttr {
FileAttr {
ino: self.get_ino(),
size: self.size,
blocks: 0,
atime: CREATE_TIME,
mtime: CREATE_TIME,
ctime: CREATE_TIME,
crtime: CREATE_TIME,
kind: FileType::RegularFile,
perm: 0o755,
nlink: 2,
uid: 501,
gid: 20,
rdev: 0,
flags: 0,
}
}
}


fn get_dir_attr(ino: u64) -> FileAttr {
FileAttr {
ino: ino,
size: 0,
blocks: 0,
atime: CREATE_TIME,
mtime: CREATE_TIME,
ctime: CREATE_TIME,
crtime: CREATE_TIME,
kind: FileType::Directory,
perm: 0o755,
nlink: 2,
uid: 501,
gid: 20,
rdev: 0,
flags: 0,
}
}

const SUBFS_DIR_ATTR: FileAttr = FileAttr {
ino: 1,
size: 0,
@@ -157,7 +34,6 @@ const SUBFS_DIR_ATTR: FileAttr = FileAttr {
};

const HELLO_TXT_CONTENT: &'static str = "Hello World!\n";

const SUBFS_TXT_ATTR: FileAttr = FileAttr {
ino: 2,
size: 13,
@@ -179,29 +55,45 @@ const SUBFS_TXT_ATTR: FileAttr = FileAttr {
struct SubsonicFS<'subfs> {
pub name: &'subfs str,
pub client: sunk::Client,
pub song: Song,
pub artists: Vec<Artist>,
pub artists_by_name: HashMap<&'subfs str, &'subfs Artist>, // key is the name
pub artists_by_ino: HashMap<u64, &'subfs Artist>, // key is the inode
}

impl<'subfs> SubsonicFS<'subfs> {
fn get_artist_by_ino(&self, ino: u64) -> Artist {
Artist::new_from_ino(&self.client, ino)
fn new(name: &str, client: sunk::Client) -> SubsonicFS {
SubsonicFS {
name: name,
client: client,
artists: Vec::new(),
artists_by_name: HashMap::new(),
artists_by_ino: HashMap::new(),
}
}

fn get_artist_by_id(&self, id: usize) -> Artist {
Artist::new_from_id(&self.client, id)
}
fn add_new_artist(&mut self, artist: Artist) {

fn get_artist_list(&self) -> Vec<Artist> {
vec![
Artist::new_from_id(&self.client, 1), // Lordi
]
}

fn get_artist_by_name(&self, name: &str) -> Option<Artist> {
if name == "Lordi" {
return Some(Artist::new_from_id(&self.client, 1));
fn build_artist_list(&mut self) {
let artist_list = sunk::Artist::list(&self.client, sunk::search::ALL).unwrap();
print!("{:#?}", artist_list);
for a in artist_list {
self.artists.push(a);
}
return None;
print!("{:#?}", self.artists);
}

fn get_artist_list(&self) -> & Vec<Artist> {
&self.artists
//if self.artists.len() < 1 {
//self.artists = vec![
//Artist::new_from_id(&self.client, &String::from("AR1")), // Lordi
//];
//self.artists
//} else {
//self.artists
//}
}
}

@@ -211,18 +103,6 @@ impl<'subfs> Filesystem for SubsonicFS<'subfs> {
if parent == 1 {
match name.to_str() {
Some("hello.txt") => reply.entry(&TTL, &SUBFS_TXT_ATTR, 0),
Some("Man Skin Boots") => {
println!("{} ---- {:#?}", &self.song, name);
reply.entry(&TTL, &self.song.get_attr(), 0);
},
Some("Artists") => reply.entry(&TTL, &get_dir_attr(ARTIST_ID), 0),
Some("Albums") => reply.entry(&TTL, &get_dir_attr(ALBUM_ID), 0),
_ => reply.error(ENOENT),
}
} else if parent == ARTIST_ID {
let a = self.get_artist_by_name(&name.to_str().unwrap());
match a {
Some(artist) => reply.entry(&TTL, &artist.get_attr(), 0),
_ => reply.error(ENOENT),
}
} else {
@@ -232,16 +112,8 @@ impl<'subfs> Filesystem for SubsonicFS<'subfs> {

fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
println!("getattr");
println!("===> {} - {}", ino, self.song.get_ino());
if ino == 1 { reply.attr(&TTL, &SUBFS_DIR_ATTR) }
else if ino == 2 { reply.attr(&TTL, &SUBFS_TXT_ATTR) }
else if ino == self.song.get_ino() {
println!("{}", ino);
reply.attr(&TTL, &self.song.get_attr()) }
else if ino == ARTIST_ID { reply.attr(&TTL, &get_dir_attr(ARTIST_ID)) }
else if ino == ALBUM_ID { reply.attr(&TTL, &SUBFS_DIR_ATTR) }
else if ino == SONG_ID { reply.attr(&TTL, &SUBFS_DIR_ATTR) }
else if ino & ARTIST_ID == ARTIST_ID { reply.attr(&TTL, &get_dir_attr(ino)) }
else { reply.error(ENOENT) };
}

@@ -249,21 +121,6 @@ impl<'subfs> Filesystem for SubsonicFS<'subfs> {
println!("read");
if ino == 2 {
reply.data(&HELLO_TXT_CONTENT.as_bytes()[offset as usize..]);
} else if ino == self.song.get_ino() {
println!("{}", self.song);
self.song.set_max_bit_rate(128);
let size;
if offset as usize + _size as usize > self.song.size as usize {
size = self.song.size as usize - offset as usize;
} else {
size = _size as usize;
}
println!("offset: {}, size: {}, _size: {}, song.size: {}", offset, size, _size, self.song.size);
if offset as usize >= self.song.size as usize {
reply.error(EOF);
} else {
reply.data(&self.song.stream(&self.client).unwrap()[offset as usize..offset as usize + size as usize]);
}
} else {
reply.error(ENOENT);
}
@@ -271,28 +128,14 @@ impl<'subfs> Filesystem for SubsonicFS<'subfs> {

fn readdir(&mut self, _req: &Request, ino: u64, _fh: u64, offset: i64, mut reply: ReplyDirectory) {
println!("readdir");
let artists = &self.get_artist_list();
let mut entries;
match ino {
1 => {
entries = vec![
(1, FileType::Directory, "."),
(1, FileType::Directory, ".."),
(ARTIST_ID, FileType::Directory, "Artists"),
(ALBUM_ID, FileType::Directory, "Albums"),
(SONG_ID, FileType::Directory, "Songs"),
(2, FileType::RegularFile, "hello.txt"),
(self.song.get_ino(), FileType::RegularFile, &self.song.title),
];
}
ARTIST_ID => {
entries = vec![
(ARTIST_ID, FileType::Directory, "."),
(ARTIST_ID, FileType::Directory, ".."),
];
for a in artists {
entries.push((a.get_ino(), FileType::Directory, &a.name))
}
}
_ => entries = vec![],
}
@@ -317,7 +160,7 @@ fn main() {
.map(|o| o.as_ref())
.collect::<Vec<&OsStr>>();

let site = "http://localhost/";
let site = "http://127.0.0.1:5000/";
let username = "skia";
let password = "skia";
// let site = "http://demo.subsonic.org/";
@@ -325,13 +168,11 @@ fn main() {
// let password = "guest";

let client = sunk::Client::new(site, username, password).unwrap();
let song = Song::new_from_id(&client, 1);
//let song = Song::new_from_id(&client, 1);

let mut fs = SubsonicFS::new("Subsonic FS", client);

let fs = SubsonicFS {
name: "Subsonic FS",
client: client,
song,
};
fs.build_artist_list();

// println!("client: {:#?}", client);
// let an_artist = sunk::Artist::get(&client, 1);

Loading…
Cancel
Save