Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #15 from tsirysndr/serve-albumart

server: serve album art and audio files

authored by

Tsiry Sandratraina and committed by
GitHub
e68a2401 05d9eea8

+98 -4
+55
Cargo.lock
··· 70 70 ] 71 71 72 72 [[package]] 73 + name = "actix-files" 74 + version = "0.6.6" 75 + source = "registry+https://github.com/rust-lang/crates.io-index" 76 + checksum = "0773d59061dedb49a8aed04c67291b9d8cf2fe0b60130a381aab53c6dd86e9be" 77 + dependencies = [ 78 + "actix-http", 79 + "actix-service", 80 + "actix-utils", 81 + "actix-web", 82 + "bitflags 2.6.0", 83 + "bytes", 84 + "derive_more", 85 + "futures-core", 86 + "http-range", 87 + "log", 88 + "mime", 89 + "mime_guess", 90 + "percent-encoding", 91 + "pin-project-lite", 92 + "v_htmlescape", 93 + ] 94 + 95 + [[package]] 73 96 name = "actix-http" 74 97 version = "3.9.0" 75 98 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3479 3502 ] 3480 3503 3481 3504 [[package]] 3505 + name = "http-range" 3506 + version = "0.1.5" 3507 + source = "registry+https://github.com/rust-lang/crates.io-index" 3508 + checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" 3509 + 3510 + [[package]] 3482 3511 name = "httparse" 3483 3512 version = "1.9.4" 3484 3513 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4268 4297 checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 4269 4298 4270 4299 [[package]] 4300 + name = "mime_guess" 4301 + version = "2.0.5" 4302 + source = "registry+https://github.com/rust-lang/crates.io-index" 4303 + checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" 4304 + dependencies = [ 4305 + "mime", 4306 + "unicase", 4307 + ] 4308 + 4309 + [[package]] 4271 4310 name = "minimal-lexical" 4272 4311 version = "0.2.1" 4273 4312 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 5633 5672 version = "0.1.0" 5634 5673 dependencies = [ 5635 5674 "actix-cors", 5675 + "actix-files", 5636 5676 "actix-web", 5637 5677 "anyhow", 5638 5678 "async-graphql", ··· 7600 7640 ] 7601 7641 7602 7642 [[package]] 7643 + name = "unicase" 7644 + version = "2.7.0" 7645 + source = "registry+https://github.com/rust-lang/crates.io-index" 7646 + checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" 7647 + dependencies = [ 7648 + "version_check", 7649 + ] 7650 + 7651 + [[package]] 7603 7652 name = "unicode-bidi" 7604 7653 version = "0.3.15" 7605 7654 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 7755 7804 "thiserror", 7756 7805 "wtf8", 7757 7806 ] 7807 + 7808 + [[package]] 7809 + name = "v_htmlescape" 7810 + version = "0.15.8" 7811 + source = "registry+https://github.com/rust-lang/crates.io-index" 7812 + checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" 7758 7813 7759 7814 [[package]] 7760 7815 name = "value-trait"
+1
crates/graphql/Cargo.toml
··· 5 5 6 6 [dependencies] 7 7 actix-cors = "0.7.0" 8 + actix-files = "0.6.6" 8 9 actix-web = "4.9.0" 9 10 anyhow = "1.0.87" 10 11 async-graphql = "7.0.9"
+42 -4
crates/graphql/src/server.rs
··· 1 - use std::sync::{mpsc::Sender, Arc, Mutex}; 1 + use std::{ 2 + path::PathBuf, 3 + sync::{mpsc::Sender, Arc, Mutex}, 4 + }; 2 5 3 6 use actix_cors::Cors; 7 + use actix_files::{self as fs, NamedFile}; 4 8 use actix_web::{ 5 - http::header::HOST, 9 + error::ErrorNotFound, 10 + http::header::{ContentDisposition, DispositionType, HOST}, 6 11 web::{self, Data}, 7 12 App, HttpRequest, HttpResponse, HttpServer, Result, 8 13 }; ··· 10 15 use async_graphql::{http::GraphiQLSource, EmptySubscription, Schema}; 11 16 use async_graphql_actix_web::{GraphQLRequest, GraphQLResponse}; 12 17 use owo_colors::OwoColorize; 13 - use rockbox_library::create_connection_pool; 18 + use rockbox_library::{create_connection_pool, repo}; 14 19 use rockbox_sys::events::RockboxCommand; 20 + use sqlx::{Pool, Sqlite}; 15 21 16 22 use crate::{ 17 23 schema::{Mutation, Query}, ··· 48 54 )) 49 55 } 50 56 57 + async fn index_file(req: HttpRequest) -> Result<NamedFile, actix_web::Error> { 58 + let id = req.match_info().get("id").unwrap(); 59 + let id = id.split('.').next().unwrap(); 60 + let mut path = PathBuf::new(); 61 + 62 + println!("id: {}", id); 63 + 64 + let pool = req.app_data::<Pool<Sqlite>>().unwrap(); 65 + match repo::track::find(pool.clone(), id).await { 66 + Ok(Some(track)) => { 67 + path.push(track.path); 68 + println!("Serving file: {}", path.display()); 69 + let file = NamedFile::open(path)?; 70 + Ok(file.set_content_disposition(ContentDisposition { 71 + disposition: DispositionType::Attachment, 72 + parameters: vec![], 73 + })) 74 + } 75 + Ok(None) => Err(ErrorNotFound("Track not found").into()), 76 + Err(_) => Err(ErrorNotFound("Track not found").into()), 77 + } 78 + } 79 + 51 80 pub async fn start(cmd_tx: Arc<Mutex<Sender<RockboxCommand>>>) -> Result<(), Error> { 52 81 let client = reqwest::Client::new(); 53 82 let pool = create_connection_pool().await?; ··· 58 87 ) 59 88 .data(cmd_tx) 60 89 .data(client) 61 - .data(pool) 90 + .data(pool.clone()) 62 91 .finish(); 63 92 let graphql_port = std::env::var("ROCKBOX_GRAPHQL_PORT").unwrap_or("6062".to_string()); 64 93 let addr = format!("{}:{}", "0.0.0.0", graphql_port); ··· 70 99 ); 71 100 72 101 HttpServer::new(move || { 102 + let home = std::env::var("HOME").unwrap(); 103 + let rockbox_data_dir = format!("{}/.config/rockbox.org", home); 104 + let covers_path = format!("{}/covers", rockbox_data_dir); 105 + std::fs::create_dir_all(&covers_path).unwrap(); 106 + 73 107 let cors = Cors::permissive(); 74 108 App::new() 109 + .app_data(pool.clone()) 75 110 .app_data(Data::new(schema.clone())) 76 111 .wrap(cors) 77 112 .service(index_graphql) 78 113 .service(index_graphiql) 114 + .service(fs::Files::new("/covers", covers_path).show_files_listing()) 115 + .route("/tracks/{id}", web::get().to(index_file)) 116 + .route("/tracks/{id}", web::head().to(index_file)) 79 117 }) 80 118 .bind(addr)? 81 119 .run()