mirror of
https://github.com/Stremio/stremio-shell-ng.git
synced 2026-03-11 17:15:49 +00:00
File restructure. Working server
This commit is contained in:
parent
0e19d1b6aa
commit
3d51316c04
11 changed files with 157300 additions and 123 deletions
37
Cargo.lock
generated
37
Cargo.lock
generated
|
|
@ -134,6 +134,18 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0419348c027fa7be448d2ae7ea0e4e04c2334c31dc4e74ab29f00a2a7ca69204"
|
||||
|
||||
[[package]]
|
||||
name = "native-windows-derive"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8164b076b08fb63f7cb4da207abe8fd94b5c604e17d9f49618807482dbe25507"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-windows-gui"
|
||||
version = "1.0.12"
|
||||
|
|
@ -261,6 +273,15 @@ version = "0.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785"
|
||||
dependencies = [
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.27"
|
||||
|
|
@ -322,11 +343,18 @@ version = "0.3.24"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
|
||||
|
||||
[[package]]
|
||||
name = "stremio-shell-ng"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"mpv",
|
||||
"native-windows-derive",
|
||||
"native-windows-gui",
|
||||
"once_cell",
|
||||
"webview2",
|
||||
|
|
@ -355,6 +383,15 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
|
|
|
|||
157016
server.js
Normal file
157016
server.js
Normal file
File diff suppressed because one or more lines are too long
134
src/main.rs
134
src/main.rs
|
|
@ -1,9 +1,7 @@
|
|||
use native_windows_gui::{self as nwg, Window};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use webview2::Controller;
|
||||
use winapi::um::winuser::*;
|
||||
use native_windows_gui::{self as nwg, NativeUi};
|
||||
|
||||
mod stremio_app;
|
||||
use crate::stremio_app::{stremio_server::StremioServer, StremioApp};
|
||||
|
||||
fn main() {
|
||||
// native-windows-gui has some basic high DPI support with the high-dpi
|
||||
|
|
@ -12,124 +10,14 @@ fn main() {
|
|||
//
|
||||
// Use an application manifest to get rid of this deprecated warning.
|
||||
#[allow(deprecated)]
|
||||
unsafe { nwg::set_dpi_awareness() };
|
||||
unsafe {
|
||||
nwg::set_dpi_awareness()
|
||||
};
|
||||
|
||||
nwg::init().unwrap();
|
||||
|
||||
let mut window = Window::default();
|
||||
|
||||
Window::builder()
|
||||
.title("Stremio")
|
||||
.size((1600, 900))
|
||||
.build(&mut window)
|
||||
.unwrap();
|
||||
|
||||
let window_handle = window.handle;
|
||||
let hwnd = window_handle.hwnd().expect("unable to obtain hwnd");
|
||||
|
||||
// Initialize mpv
|
||||
let mut mpv_builder = mpv::MpvHandlerBuilder::new()
|
||||
.expect("Error while creating MPV builder");
|
||||
mpv_builder.set_option("wid", hwnd as i64).expect("failed setting wid");
|
||||
//mpv_builder.set_option("vo", "gpu").expect("unable to set vo");
|
||||
// win, opengl: works but least performancy, 10-15% CPU
|
||||
// winvk, vulkan: works as good as d3d11
|
||||
// d3d11, d1d11: works great
|
||||
// dxinterop, auto: works, slightly more cpu use than d3d11
|
||||
// default (auto) seems to be d3d11 (vo/gpu/d3d11)
|
||||
/*
|
||||
mpv_builder.set_option("gpu-context", "angle")
|
||||
.and_then(|_| mpv_builder.set_option("gpu-api", "auto"))
|
||||
.expect("setting gpu options failed");
|
||||
*/
|
||||
mpv_builder.try_hardware_decoding()
|
||||
.expect("failed setting hwdec");
|
||||
mpv_builder.set_option("terminal", "yes").expect("failed setting terminal");
|
||||
mpv_builder.set_option("msg-level", "all=v").expect("failed setting msg-level");
|
||||
//mpv_builder.set_option("quiet", "yes").expect("failed setting msg-level");
|
||||
let mut mpv = mpv_builder
|
||||
.build()
|
||||
.expect("Error while initializing MPV with opengl");
|
||||
//let video_path = "/home/ivo/storage/bbb_sunflower_1080p_30fps_normal.mp4";
|
||||
let video_path = "http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4";
|
||||
mpv.command(&["loadfile", video_path])
|
||||
.expect("Error loading file");
|
||||
|
||||
let controller: Rc<OnceCell<Controller>> = Rc::new(OnceCell::new());
|
||||
let controller_clone = controller.clone();
|
||||
let result = webview2::Environment::builder().build(move |env| {
|
||||
env.unwrap()
|
||||
.create_controller(hwnd, move |c| {
|
||||
let c = c.unwrap();
|
||||
|
||||
if let Ok(c2) = c.get_controller2() {
|
||||
c2.put_default_background_color(webview2_sys::Color {
|
||||
r: 255,
|
||||
g: 255,
|
||||
b: 255,
|
||||
a: 0,
|
||||
})
|
||||
.unwrap();
|
||||
} else {
|
||||
eprintln!("failed to get interface to controller2");
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let mut rect = mem::zeroed();
|
||||
GetClientRect(hwnd, &mut rect);
|
||||
c.put_bounds(rect).unwrap();
|
||||
}
|
||||
|
||||
let webview = c.get_webview().unwrap();
|
||||
webview.navigate("https://www.boyanpetrov.rip/stremio/index.html").unwrap();
|
||||
|
||||
controller_clone.set(c).unwrap();
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
if let Err(e) = result {
|
||||
nwg::modal_fatal_message(
|
||||
&window_handle,
|
||||
"Failed to Create WebView2 Environment",
|
||||
&format!("{}", e),
|
||||
);
|
||||
}
|
||||
let window_handle = window.handle;
|
||||
|
||||
// There isn't an OnWindowRestored event for SC_RESTORE in
|
||||
// native-windows-gui, so we use raw events.
|
||||
nwg::bind_raw_event_handler(&window_handle, 0xffff + 1, move |_, msg, w, _| {
|
||||
match (msg, w as usize) {
|
||||
(WM_SIZE, _) => {
|
||||
if let Some(controller) = controller.get() {
|
||||
unsafe {
|
||||
let mut rect = mem::zeroed();
|
||||
GetClientRect(window_handle.hwnd().unwrap(), &mut rect);
|
||||
controller.put_bounds(rect).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
(WM_MOVE, _) => {
|
||||
if let Some(controller) = controller.get() {
|
||||
controller.notify_parent_window_position_changed().unwrap();
|
||||
}
|
||||
}
|
||||
(WM_SYSCOMMAND, SC_MINIMIZE) => {
|
||||
if let Some(controller) = controller.get() {
|
||||
controller.put_is_visible(false).unwrap();
|
||||
}
|
||||
}
|
||||
(WM_SYSCOMMAND, SC_RESTORE) => {
|
||||
if let Some(controller) = controller.get() {
|
||||
controller.put_is_visible(true).unwrap();
|
||||
}
|
||||
}
|
||||
(WM_CLOSE, _) => nwg::stop_thread_dispatch(),
|
||||
_ => {}
|
||||
}
|
||||
None
|
||||
})
|
||||
.unwrap();
|
||||
let streaming_server = StremioServer::new();
|
||||
|
||||
nwg::init().expect("Failed to init Native Windows GUI");
|
||||
let _app = StremioApp::build_ui(Default::default()).expect("Failed to build UI");
|
||||
nwg::dispatch_thread_events();
|
||||
streaming_server.try_kill();
|
||||
}
|
||||
|
|
|
|||
8
src/stremio_app/mod.rs
Normal file
8
src/stremio_app/mod.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
pub mod stremio_app;
|
||||
pub use stremio_app::StremioApp;
|
||||
pub mod stremio_wevbiew;
|
||||
pub use stremio_wevbiew::WebView;
|
||||
pub mod stremio_player;
|
||||
pub use stremio_player::Player;
|
||||
pub mod stremio_server;
|
||||
pub use stremio_server::StremioServer;
|
||||
22
src/stremio_app/stremio_app.rs
Normal file
22
src/stremio_app/stremio_app.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
use native_windows_derive::NwgUi;
|
||||
use native_windows_gui as nwg;
|
||||
|
||||
use crate::stremio_app::stremio_wevbiew::WebView;
|
||||
use crate::stremio_app::stremio_player::Player;
|
||||
|
||||
#[derive(Default, NwgUi)]
|
||||
pub struct StremioApp {
|
||||
#[nwg_control(title: "Stremio", flags: "MAIN_WINDOW|VISIBLE")]
|
||||
#[nwg_events( OnWindowClose: [StremioApp::quit] )]
|
||||
window: nwg::Window,
|
||||
#[nwg_partial(parent: window)]
|
||||
webview: WebView,
|
||||
#[nwg_partial(parent: window)]
|
||||
player: Player,
|
||||
}
|
||||
|
||||
impl StremioApp {
|
||||
fn quit(&self) {
|
||||
nwg::stop_thread_dispatch();
|
||||
}
|
||||
}
|
||||
2
src/stremio_app/stremio_player/mod.rs
Normal file
2
src/stremio_app/stremio_player/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod stremio_player;
|
||||
pub use stremio_player::Player;
|
||||
48
src/stremio_app/stremio_player/stremio_player.rs
Normal file
48
src/stremio_app/stremio_player/stremio_player.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
use native_windows_gui::{self as nwg, PartialUi};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Player {
|
||||
mpv: Option<mpv::MpvHandler>,
|
||||
}
|
||||
|
||||
impl PartialUi for Player {
|
||||
fn build_partial<W: Into<nwg::ControlHandle>>(
|
||||
data: &mut Self,
|
||||
parent: Option<W>,
|
||||
) -> Result<(), nwg::NwgError> {
|
||||
let mut mpv_builder =
|
||||
mpv::MpvHandlerBuilder::new().expect("Error while creating MPV builder");
|
||||
mpv_builder
|
||||
.set_option("wid", parent.unwrap().into().hwnd().unwrap() as i64)
|
||||
.expect("failed setting wid");
|
||||
// mpv_builder.set_option("vo", "gpu").expect("unable to set vo");
|
||||
// win, opengl: works but least performancy, 10-15% CPU
|
||||
// winvk, vulkan: works as good as d3d11
|
||||
// d3d11, d1d11: works great
|
||||
// dxinterop, auto: works, slightly more cpu use than d3d11
|
||||
// default (auto) seems to be d3d11 (vo/gpu/d3d11)
|
||||
mpv_builder
|
||||
.set_option("gpu-context", "angle")
|
||||
.and_then(|_| mpv_builder.set_option("gpu-api", "auto"))
|
||||
.expect("setting gpu options failed");
|
||||
mpv_builder
|
||||
.try_hardware_decoding()
|
||||
.expect("failed setting hwdec");
|
||||
mpv_builder
|
||||
.set_option("terminal", "yes")
|
||||
.expect("failed setting terminal");
|
||||
mpv_builder
|
||||
.set_option("msg-level", "all=v")
|
||||
.expect("failed setting msg-level");
|
||||
//mpv_builder.set_option("quiet", "yes").expect("failed setting msg-level");
|
||||
data.mpv = mpv_builder.build().ok();
|
||||
let mpv = data.mpv.as_mut().expect("Failed to create MPV");
|
||||
// let video_path = "/home/ivo/storage/bbb_sunflower_1080p_30fps_normal.mp4";
|
||||
let video_path = "http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4";
|
||||
mpv.command(&["loadfile", video_path])
|
||||
.expect("Error loading file");
|
||||
// mpv.command(&["stop"]).expect("Error stopping");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
2
src/stremio_app/stremio_server/mod.rs
Normal file
2
src/stremio_app/stremio_server/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod stremio_server;
|
||||
pub use stremio_server::StremioServer;
|
||||
64
src/stremio_app/stremio_server/stremio_server.rs
Normal file
64
src/stremio_app/stremio_server/stremio_server.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
use std::process::Command;
|
||||
use std::thread;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Duration;
|
||||
use winapi::um::processthreadsapi::{OpenProcess, TerminateProcess};
|
||||
use winapi::um::winnt::PROCESS_TERMINATE;
|
||||
use winapi::um::handleapi::CloseHandle;
|
||||
|
||||
pub struct StremioServer {
|
||||
should_stop: Arc<std::sync::Mutex<u32>>,
|
||||
handle: Option<thread::JoinHandle<()>>,
|
||||
}
|
||||
|
||||
impl StremioServer {
|
||||
pub fn new() -> StremioServer {
|
||||
let server_pid_mutex = Arc::new(Mutex::new(0));
|
||||
let server_pid_mutex2 = server_pid_mutex.clone();
|
||||
StremioServer {
|
||||
should_stop: server_pid_mutex,
|
||||
handle: Some(thread::spawn(move || loop {
|
||||
let mut child = Command::new("node")
|
||||
.arg("server.js")
|
||||
.spawn()
|
||||
.expect("Cannot run the server");
|
||||
{
|
||||
let mut kill_request = server_pid_mutex2.lock().unwrap();
|
||||
*kill_request = child.id();
|
||||
};
|
||||
let _status = child.wait().expect("Cannot wait for the server");
|
||||
let kill_request = server_pid_mutex2.lock().unwrap();
|
||||
if *kill_request == 0 {
|
||||
dbg!("Exit server guard loop...");
|
||||
break;
|
||||
}
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
dbg!("Trying to restart the server...");
|
||||
})),
|
||||
}
|
||||
}
|
||||
pub fn try_kill(mut self) {
|
||||
dbg!("Trying to kill the server...");
|
||||
let should_stop = self.should_stop.clone();
|
||||
let mut tremination_request = should_stop.lock().unwrap();
|
||||
unsafe {
|
||||
let handle = OpenProcess(PROCESS_TERMINATE, 0, *tremination_request);
|
||||
if !handle.is_null() {
|
||||
TerminateProcess(handle, 101);
|
||||
CloseHandle(handle);
|
||||
}
|
||||
}
|
||||
*tremination_request = 0;
|
||||
|
||||
drop(self.handle.take())
|
||||
// .map(thread::JoinHandle::join);
|
||||
}
|
||||
}
|
||||
|
||||
// impl Drop for StremioServer {
|
||||
// fn drop(&mut self) {
|
||||
// dbg!("Server dropped!");
|
||||
// self.try_kill();
|
||||
// }
|
||||
// }
|
||||
2
src/stremio_app/stremio_wevbiew/mod.rs
Normal file
2
src/stremio_app/stremio_wevbiew/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod stremio_wevbiew;
|
||||
pub use stremio_wevbiew::WebView;
|
||||
88
src/stremio_app/stremio_wevbiew/stremio_wevbiew.rs
Normal file
88
src/stremio_app/stremio_wevbiew/stremio_wevbiew.rs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// mod stremio_wevbiew {
|
||||
use native_windows_gui::{self as nwg, PartialUi};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use webview2::Controller;
|
||||
use winapi::um::winuser::*;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WebView {
|
||||
controller: Rc<OnceCell<Controller>>,
|
||||
}
|
||||
impl PartialUi for WebView {
|
||||
fn build_partial<W: Into<nwg::ControlHandle>>(
|
||||
data: &mut Self,
|
||||
parent: Option<W>,
|
||||
) -> Result<(), nwg::NwgError> {
|
||||
let parent = parent.unwrap().into();
|
||||
let hwnd = parent.hwnd().unwrap();
|
||||
let controller_clone = data.controller.clone();
|
||||
let result = webview2::EnvironmentBuilder::new()
|
||||
.with_additional_browser_arguments("--disable-gpu")
|
||||
.build(move |env| {
|
||||
env.unwrap().create_controller(hwnd, move |c| {
|
||||
let c = c.unwrap();
|
||||
if let Ok(c2) = c.get_controller2() {
|
||||
c2.put_default_background_color(webview2_sys::Color {
|
||||
r: 255,
|
||||
g: 255,
|
||||
b: 255,
|
||||
a: 0,
|
||||
})
|
||||
.unwrap();
|
||||
} else {
|
||||
eprintln!("failed to get interface to controller2");
|
||||
}
|
||||
unsafe {
|
||||
let mut rect = mem::zeroed();
|
||||
GetClientRect(hwnd, &mut rect);
|
||||
c.put_bounds(rect).unwrap();
|
||||
}
|
||||
let webview = c.get_webview().unwrap();
|
||||
webview.navigate("edge://gpu").unwrap();
|
||||
webview
|
||||
.navigate("https://www.boyanpetrov.rip/stremio/index.html")
|
||||
.unwrap();
|
||||
// c.put_is_visible(true).expect("Cannot show the WebView");
|
||||
controller_clone.set(c).unwrap();
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
if let Err(e) = result {
|
||||
nwg::modal_fatal_message(
|
||||
&parent,
|
||||
"Failed to Create WebView2 Environment",
|
||||
&format!("{}", e),
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn process_event<'a>(
|
||||
&self,
|
||||
evt: nwg::Event,
|
||||
_evt_data: &nwg::EventData,
|
||||
handle: nwg::ControlHandle,
|
||||
) {
|
||||
use nwg::Event as E;
|
||||
match evt {
|
||||
E::OnResize | E::OnWindowMaximize => {
|
||||
if let Some(controller) = self.controller.get() {
|
||||
unsafe {
|
||||
let mut rect = mem::zeroed();
|
||||
GetClientRect(handle.hwnd().unwrap(), &mut rect);
|
||||
controller.put_bounds(rect).unwrap();
|
||||
controller.put_is_visible(true).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
E::OnWindowMinimize => {
|
||||
if let Some(controller) = self.controller.get() {
|
||||
controller.put_is_visible(false).unwrap();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
Loading…
Reference in a new issue