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
99
100
101
102
103
104
105
106
107
108
|
/*
This file is part of jellything (https://codeberg.org/metamuffin/jellything)
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
use super::error::MyResult;
use crate::{request_info::RequestInfo, ui_responder::UiResponse};
use jellycommon::{
NKU_NODE, NO_SLUG, VIEW_PLAYER,
jellyobject::{Object, ObjectBuffer, ObjectBufferBuilder, Path},
};
use jellydb::{Filter, Query, Sort};
use rocket::get;
// fn jellynative_url(action: &str, seek: f64, secret: &str, node: &str, session: &str) -> String {
// let protocol = if CONF.tls { "https" } else { "http" };
// let host = &CONF.hostname;
// let stream_url = format!(
// "/n/{node}/stream{}",
// StreamSpec::HlsMultiVariant {
// container: StreamContainer::Matroska
// }
// .to_query()
// );
// format!("jellynative://{action}/{secret}/{session}/{seek}/{protocol}://{host}{stream_url}",)
// }
#[get("/n/<slug>/player?<t>", rank = 4)]
pub fn r_player(ri: RequestInfo<'_>, t: Option<f64>, slug: &str) -> MyResult<UiResponse> {
ri.require_user()?;
let _ = t;
let mut page_out = ObjectBuffer::empty();
ri.state.database.transaction(&mut |txn| {
if let Some(row) = txn.query_single(Query {
filter: Filter::Match(Path(vec![NO_SLUG.0]), slug.into()),
sort: Sort::None,
})? {
let n = txn.get(row)?.unwrap();
let nku = Object::EMPTY.insert(NKU_NODE, n.as_object());
let mut page = ObjectBufferBuilder::default();
page.push(VIEW_PLAYER, nku.as_object());
page_out = page.finish();
}
Ok(())
})?;
Ok(ri.respond_ui(page_out))
}
// pub fn player_conf<'a>(item: Arc<Node>, playing: bool) -> anyhow::Result<DynRender<'a>> {
// let mut audio_tracks = vec![];
// let mut video_tracks = vec![];
// let mut sub_tracks = vec![];
// let tracks = item
// .media
// .clone()
// .ok_or(anyhow!("node does not have media"))?
// .tracks
// .clone();
// for (tid, track) in tracks.into_iter().enumerate() {
// 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(markup::new! {
// form.playerconf[method = "GET", action = ""] {
// h2 { "Select tracks for " @item.title }
// fieldset.video {
// legend { "Video" }
// @for (i, (tid, track)) in video_tracks.iter().enumerate() {
// input[type="radio", id=tid, name="v", value=tid, checked=i==0];
// label[for=tid] { @format!("{track}") } br;
// }
// input[type="radio", id="v-none", name="v", value=""];
// label[for="v-none"] { "No video" }
// }
// fieldset.audio {
// legend { "Audio" }
// @for (i, (tid, track)) in audio_tracks.iter().enumerate() {
// input[type="radio", id=tid, name="a", value=tid, checked=i==0];
// label[for=tid] { @format!("{track}") } br;
// }
// input[type="radio", id="a-none", name="a", value=""];
// label[for="a-none"] { "No audio" }
// }
// fieldset.subtitles {
// legend { "Subtitles" }
// @for (_i, (tid, track)) in sub_tracks.iter().enumerate() {
// input[type="radio", id=tid, name="s", value=tid];
// label[for=tid] { @format!("{track}") } br;
// }
// input[type="radio", id="s-none", name="s", value="", checked=true];
// label[for="s-none"] { "No subtitles" }
// }
// input[type="submit", value=if playing { "Change tracks" } else { "Start playback" }];
// }
// })
// }
|