/* 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) 2025 metamuffin */ use super::error::MyResult; use crate::{ helper::{language::AcceptLanguage, A}, CONF, }; use jellycommon::{ api::NodeFilterSort, stream::{StreamContainer, StreamSpec}, user::{PermissionSet, PlayerKind}, NodeID, }; use jellyimport::is_importing; use jellylogic::{node::get_node, session::Session, Database}; use jellyui::{ node_page::NodePage, render_page, scaffold::{RenderInfo, SessionInfo}, }; use rocket::{ get, response::{content::RawHtml, Redirect}, Either, State, }; use std::time::Duration; 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 { segment: 0, container: StreamContainer::Matroska } .to_query() ); format!("jellynative://{action}/{secret}/{session}/{seek}/{protocol}://{host}{stream_url}",) } #[get("/n//player?", rank = 4)] pub fn r_player( session: A, lang: AcceptLanguage, db: &State, t: Option, id: A, ) -> MyResult, Redirect>> { let AcceptLanguage(lang) = lang; let r = get_node( &db, id.0, &session.0, false, true, NodeFilterSort::default(), )?; let native_session = |action: &str| { Ok(Either::Right(Redirect::temporary(jellynative_url( action, t.unwrap_or(0.), &session.0.user.native_secret, &id.0.to_string(), &jellylogic::session::create( session.0.user.name.clone(), PermissionSet::default(), // TODO Duration::from_hours(24), ), )))) }; match session.0.user.player_preference { PlayerKind::Browser => (), PlayerKind::Native => { return native_session("player-v2"); } PlayerKind::NativeFullscreen => { return native_session("player-fullscreen-v2"); } } // TODO // let spec = StreamSpec { // track: None // .into_iter() // .chain(conf.v) // .chain(conf.a) // .chain(conf.s) // .collect::>(), // format: StreamFormat::Matroska, // webm: Some(true), // ..Default::default() // }; // let playing = false; // !spec.track.is_empty(); // let conf = player_conf(node.clone(), playing)?; Ok(Either::Left(RawHtml(render_page( &NodePage { node: &r.node, udata: &r.userdata, children: &r.children, parents: &r.parents, similar: &[], filter: &NodeFilterSort::default(), lang: &lang, player: true, }, RenderInfo { importing: is_importing(), session: Some(SessionInfo { user: session.0.user, }), }, lang, )))) } // pub fn player_conf<'a>(item: Arc, playing: bool) -> anyhow::Result> { // 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" }]; // } // }) // }