aboutsummaryrefslogtreecommitdiff
path: root/server/src/main.rs
blob: 3f8d241a72dab043eacaa811fb03eb3bbfd6fce1 (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
#![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;
use rocket::{get, http::ContentType, launch, response::stream::ByteStream, routes, State};
use std::{fs::read_to_string, sync::Arc};
use tokio::sync::mpsc;

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, ByteStream![Vec<u8>]), MyError> {
    let (tx, mut rx) = mpsc::channel(16);
    let item = state.library.nested("mili-bento-box-bivouac")?.get_item()?;
    debug!("generating matroska");
    let remuxer = state.remuxer.clone();
    tokio::task::spawn_blocking(move || {
        remuxer
            .generate_into(
                SendWriter(tx),
                // SyncIoBridge()
                item.fs_path.parent().unwrap().to_path_buf(),
                item.data.clone(),
                selection.split(",").map(|e| e.parse().unwrap()).collect(),
            )
            .unwrap();
    });
    debug!("starting stream");
    Ok((
        ContentType::WEBM,
        ByteStream! {
            while let Some(x) = rx.recv().await {
                debug!("yield {x:?}");
                yield x
            }
        },
    ))
}

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],
    )
}