mirror of
https://github.com/house-of-vanity/mus-fuse.git
synced 2025-07-06 21:24:09 +00:00
Add readme.
This commit is contained in:
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
@ -15,7 +15,8 @@
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
"args": [
|
"args": [
|
||||||
"mnt"
|
"mnt",
|
||||||
|
"https://mus.hexor.ru"
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"postDebugTask": "Umount FUSE",
|
"postDebugTask": "Umount FUSE",
|
||||||
|
22
README.md
Normal file
22
README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# MusFuse
|
||||||
|
|
||||||
|
[](https://travis-ci.org/joemccann/dillinger)
|
||||||
|
|
||||||
|
MusFuse is a FUSE filesystem over HTTP for music. It is using [playongo](https://github.com/nixargh/playongo) media library. It's completely written in Rust stable.
|
||||||
|
|
||||||
|
|
||||||
|
# Features
|
||||||
|
- Using self hosted media library.
|
||||||
|
- Security relies on HTTPS.
|
||||||
|
- Any player can be used. (tested on [Cmus](https://github.com/cmus/cmus))
|
||||||
|
- Using cache.
|
||||||
|
- Leverages Rust correctness.
|
||||||
|
|
||||||
|
# How to use
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Compile
|
||||||
|
$ cargo build --release
|
||||||
|
# And run
|
||||||
|
$ ./target/release/musfuse <mountpoint> <server>
|
||||||
|
```
|
24
src/main.rs
24
src/main.rs
@ -33,7 +33,6 @@ pub struct Track {
|
|||||||
pub path: Option<String>,
|
pub path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_URL: &str = "https://mus.hexor.ru";
|
|
||||||
const CACHE_HEAD: i64 = 1024 * 1024;
|
const CACHE_HEAD: i64 = 1024 * 1024;
|
||||||
const MAX_CACHE_SIZE: i64 = 10 * 1024 * 1025; // Mb
|
const MAX_CACHE_SIZE: i64 = 10 * 1024 * 1025; // Mb
|
||||||
|
|
||||||
@ -53,8 +52,8 @@ fn get_basename(path: Option<&String>) -> Option<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn get_tracks() -> Result<Vec<Track>, Box<dyn std::error::Error>> {
|
async fn get_tracks(server: &String) -> Result<Vec<Track>, Box<dyn std::error::Error>> {
|
||||||
let resp = reqwest::get(format!("{}/songs", API_URL).as_str())
|
let resp = reqwest::get(format!("{}/songs", server).as_str())
|
||||||
.await?
|
.await?
|
||||||
.json::<Vec<Track>>()
|
.json::<Vec<Track>>()
|
||||||
.await?;
|
.await?;
|
||||||
@ -64,6 +63,7 @@ async fn get_tracks() -> Result<Vec<Track>, Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
struct JsonFilesystem {
|
struct JsonFilesystem {
|
||||||
|
server: String,
|
||||||
tree: Vec<Track>,
|
tree: Vec<Track>,
|
||||||
attrs: BTreeMap<u64, FileAttr>,
|
attrs: BTreeMap<u64, FileAttr>,
|
||||||
inodes: BTreeMap<String, u64>,
|
inodes: BTreeMap<String, u64>,
|
||||||
@ -73,7 +73,7 @@ struct JsonFilesystem {
|
|||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
impl JsonFilesystem {
|
impl JsonFilesystem {
|
||||||
fn new(tree: &Vec<Track>) -> JsonFilesystem {
|
fn new(tree: &Vec<Track>, server: String) -> JsonFilesystem {
|
||||||
let mut attrs = BTreeMap::new();
|
let mut attrs = BTreeMap::new();
|
||||||
let mut inodes = BTreeMap::new();
|
let mut inodes = BTreeMap::new();
|
||||||
let ts = time::now().to_timespec();
|
let ts = time::now().to_timespec();
|
||||||
@ -118,6 +118,7 @@ impl JsonFilesystem {
|
|||||||
inodes.insert(basename.clone(), attr.ino);
|
inodes.insert(basename.clone(), attr.ino);
|
||||||
}
|
}
|
||||||
JsonFilesystem {
|
JsonFilesystem {
|
||||||
|
server: server,
|
||||||
tree: tree.clone(),
|
tree: tree.clone(),
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
inodes: inodes,
|
inodes: inodes,
|
||||||
@ -174,7 +175,7 @@ impl Filesystem for JsonFilesystem {
|
|||||||
|
|
||||||
let url = &self.tree[(ino - 2) as usize].path.as_ref().unwrap();
|
let url = &self.tree[(ino - 2) as usize].path.as_ref().unwrap();
|
||||||
let id = &self.tree[(ino - 2) as usize].id.as_ref().unwrap();
|
let id = &self.tree[(ino - 2) as usize].id.as_ref().unwrap();
|
||||||
let full_url = format!("{}/{}", API_URL, url);
|
let full_url = format!("{}/{}", self.server, url);
|
||||||
let mut chunk: Vec<u8>;
|
let mut chunk: Vec<u8>;
|
||||||
let content_length: i64;
|
let content_length: i64;
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
@ -313,15 +314,22 @@ impl Filesystem for JsonFilesystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let lib = get_tracks().unwrap();
|
|
||||||
let fs = JsonFilesystem::new(&lib);
|
|
||||||
let mountpoint = match env::args().nth(1) {
|
let mountpoint = match env::args().nth(1) {
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
None => {
|
None => {
|
||||||
println!("Usage: {} <MOUNTPOINT>", env::args().nth(0).unwrap());
|
println!("Usage: {} <MOUNTPOINT> <SERVER>", env::args().nth(0).unwrap());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let server = match env::args().nth(2) {
|
||||||
|
Some(server) => server,
|
||||||
|
None => {
|
||||||
|
println!("Usage: {} <MOUNTPOINT> <SERVER>", env::args().nth(0).unwrap());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let lib = get_tracks(&server).unwrap();
|
||||||
|
let fs = JsonFilesystem::new(&lib, server);
|
||||||
let options = ["-o", "ro", "-o", "fsname=musfs", "-o", "async_read"]
|
let options = ["-o", "ro", "-o", "fsname=musfs", "-o", "async_read"]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|o| o.as_ref())
|
.map(|o| o.as_ref())
|
||||||
|
Reference in New Issue
Block a user