aboutsummaryrefslogtreecommitdiff
path: root/server/src/routes/ui/player.rs
blob: aaed5eefb4782120664ae73624628a1017e80b9d (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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use super::HtmlTemplate;
use crate::routes::stream::stream_uri;
use crate::{library::Item, routes::ui::error::MyResult, AppState};
use jellycommon::SourceTrackKind;
use log::warn;
use rocket::{get, FromForm, State};
use std::{path::PathBuf, sync::Arc};

pub fn player_uri(path: &PathBuf) -> String {
    format!("/player/{}", path.to_str().unwrap())
}

#[derive(FromForm, Default, Clone, Debug)]
pub struct PlayerConfig {
    pub a: Option<u64>,
    pub v: Option<u64>,
    pub s: Option<u64>,
    pub webm: bool,
}

#[get("/player/<path..>?<conf..>", rank = 4)]
pub fn r_player(
    state: &State<AppState>,
    path: PathBuf,
    conf: PlayerConfig,
) -> MyResult<HtmlTemplate<markup::DynRender<'_>>> {
    warn!("{conf:?}");
    let item = state.library.nested_path(&path)?.get_item()?;
    if conf.a.is_none() && conf.v.is_none() && conf.s.is_none() {
        return player_conf(item.clone());
    }

    let tracks = conf
        .a
        .into_iter()
        .chain(conf.v.into_iter())
        .chain(conf.s.into_iter())
        .collect::<Vec<_>>();

    Ok(HtmlTemplate(
        "Configure Player".to_string(),
        markup::new! {
            video[src=stream_uri(&item.lib_path, &tracks), controls];
        },
    ))
}

pub fn player_conf<'a>(item: Arc<Item>) -> MyResult<HtmlTemplate<markup::DynRender<'a>>> {
    let mut audio_tracks = vec![];
    let mut video_tracks = vec![];
    let mut sub_tracks = vec![];
    for (tid, track) in item.info.tracks.clone() {
        match &track.kind {
            SourceTrackKind::Audio { .. } => audio_tracks.push((tid, track)),
            SourceTrackKind::Video { .. } => video_tracks.push((tid, track)),
            SourceTrackKind::Subtitles { .. } => sub_tracks.push((tid, track)),
        }
    }

    Ok(HtmlTemplate(
        "Configure Player".to_string(),
        markup::new! {
            h2 { "Watch: " @item.info.title }
            form[method = "GET", action = ""] {
                h3 { "Select tracks" }

                label[for="select-v"] { "Video: " }
                select[name="v", id="select-v"] {
                    @for (tid, track) in &video_tracks {
                        option[value=tid] { @format!("{track}") }
                    }
                    option[value=""] { "Disable" }
                }
                br;

                label[for="select-a"] { "Audio: " }
                select[name="a", id="select-a"] {
                    @for (tid, track) in &audio_tracks {
                        option[value=tid] { @format!("{track}") }
                    }
                    option[value=""] { "Disable" }
                }
                br;

                label[for="select-s"] { "Subtitles: " }
                select[name="s", id="select-s"] {
                    option[value="", selected] { "None" }
                    @for (tid, track) in &sub_tracks {
                        option[value=tid] { @format!("{track}") }
                    }
                }
                br;

                input[type="submit", value="Start playback"];
            }
        },
    ))
}