aboutsummaryrefslogtreecommitdiff
path: root/server/src/main.rs
blob: 5a9c6cfc06860367407d7385a8f2bd323775b226 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#![feature(box_syntax)]

use crate::frontend::{pages::MyError, style::CSS_BUNDLE};
use database::Database;
use frontend::pages::{home::page_home, node::page_library_node};
use jellyremuxer::{RemuxerContext, SendWriter};
use library::Library;
use log::{debug, warn};
use rocket::{
    get,
    http::ContentType,
    launch,
    response::stream::{ByteStream, ReaderStream},
    routes, State,
};
use std::{fs::read_to_string, sync::Arc};
use tokio::{
    io::{duplex, DuplexStream},
    sync::mpsc,
};
use tokio_util::io::SyncIoBridge;

pub mod database;
pub mod frontend;
pub mod library;

#[get("/assets/style.css")]
async fn assets_style() -> (ContentType, String) {
    (
        ContentType::CSS,
        if cfg!(debug_assertions) {
            read_to_string("server/src/frontend/style/layout.css").unwrap()
        } else {
            CSS_BUNDLE.to_string()
        },
    )
}

#[get("/stream?<selection>")]
fn stream(
    selection: String,
    state: &State<AppState>,
) -> Result<(ContentType, ReaderStream![DuplexStream]), MyError> {
    let (a, b) = duplex(8196);
    let item = state.library.nested("mili-bento-box-bivouac")?.get_item()?;
    let remuxer = state.remuxer.clone();

    let b = SyncIoBridge::new(b);
    tokio::task::spawn_blocking(move || {
        if let Err(e) = remuxer.generate_into(
            b,
            item.fs_path.parent().unwrap().to_path_buf(),
            item.data.clone(),
            selection.split(",").map(|e| e.parse().unwrap()).collect(),
        ) {
            warn!("stream stopped: {e}")
        }
    });
    debug!("starting stream");
    Ok((ContentType::WEBM, ReaderStream::one(a)))
}

pub struct AppState {
    pub database: Database,
    pub library: Library,
    pub remuxer: Arc<RemuxerContext>,
}

#[launch]
fn rocket() -> _ {
    env_logger::init_from_env("LOG");
    let db_path = std::env::var("DB_PATH").unwrap_or("data/db".to_string());
    let lib_path = std::env::var("LIB_PATH").unwrap_or("data/library".to_string());
    let state = AppState {
        remuxer: RemuxerContext::new(),
        library: Library::open(&lib_path).unwrap(),
        database: Database::open(&db_path).unwrap(),
    };

    rocket::build().manage(state).mount(
        "/",
        routes![page_home, page_library_node, assets_style, stream],
    )
}