diff --git a/src/main.rs b/src/main.rs index 3f2f73b..c3510ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use native_windows_gui::{self as nwg, NativeUi}; mod stremio_app; -use crate::stremio_app::{stremio_server::StremioServer, StremioApp}; +use crate::stremio_app::{stremio_server::StremioServer, MainWindow}; fn main() { // native-windows-gui has some basic high DPI support with the high-dpi @@ -17,7 +17,7 @@ fn main() { 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"); + let _app = MainWindow::build_ui(Default::default()).expect("Failed to build UI"); nwg::dispatch_thread_events(); streaming_server.try_kill(); } diff --git a/src/stremio_app/mod.rs b/src/stremio_app/mod.rs index 1e2393f..cdeff12 100644 --- a/src/stremio_app/mod.rs +++ b/src/stremio_app/mod.rs @@ -1,5 +1,5 @@ pub mod stremio_app; -pub use stremio_app::StremioApp; +pub use stremio_app::MainWindow; pub mod stremio_wevbiew; pub use stremio_wevbiew::WebView; pub mod stremio_player; diff --git a/src/stremio_app/stremio_app.rs b/src/stremio_app/stremio_app.rs index baf5188..a68ac0d 100644 --- a/src/stremio_app/stremio_app.rs +++ b/src/stremio_app/stremio_app.rs @@ -1,14 +1,14 @@ -use std::cmp; use native_windows_derive::NwgUi; use native_windows_gui as nwg; +use std::cmp; +use crate::stremio_app::stremio_player::{Player, PlayerInterface}; use crate::stremio_app::stremio_wevbiew::WebView; -use crate::stremio_app::stremio_player::Player; #[derive(Default, NwgUi)] -pub struct StremioApp { +pub struct MainWindow { #[nwg_control(title: "Stremio", flags: "MAIN_WINDOW|VISIBLE")] - #[nwg_events( OnWindowClose: [StremioApp::on_quit], OnInit: [StremioApp::on_init] )] + #[nwg_events( OnWindowClose: [MainWindow::on_quit], OnInit: [MainWindow::on_init] )] window: nwg::Window, #[nwg_partial(parent: window)] webview: WebView, @@ -16,15 +16,22 @@ pub struct StremioApp { player: Player, } -impl StremioApp { +impl MainWindow { fn on_init(&self) { let small_side = cmp::min(nwg::Monitor::width(), nwg::Monitor::height()) * 70 / 100; let dimensions = (small_side * 16 / 9, small_side); let [total_width, total_height] = [nwg::Monitor::width(), nwg::Monitor::height()]; - let x = (total_width-dimensions.0)/2; - let y = (total_height-dimensions.1)/2; - self.window.set_size(dimensions.0 as u32, dimensions.1 as u32); + let x = (total_width - dimensions.0) / 2; + let y = (total_height - dimensions.1) / 2; + self.window + .set_size(dimensions.0 as u32, dimensions.1 as u32); self.window.set_position(x, y); + // 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"; + self.player.play(video_path); + // self.player.seek(120.0); + self.player.speed(2.0); + // self.player.pause(true); } fn on_quit(&self) { nwg::stop_thread_dispatch(); diff --git a/src/stremio_app/stremio_player/mod.rs b/src/stremio_app/stremio_player/mod.rs index 6a11b83..5bbd796 100644 --- a/src/stremio_app/stremio_player/mod.rs +++ b/src/stremio_app/stremio_player/mod.rs @@ -1,2 +1,2 @@ pub mod stremio_player; -pub use stremio_player::Player; \ No newline at end of file +pub use stremio_player::{Player, PlayerInterface}; \ No newline at end of file diff --git a/src/stremio_app/stremio_player/stremio_player.rs b/src/stremio_app/stremio_player/stremio_player.rs index 86f0b4c..55d8945 100644 --- a/src/stremio_app/stremio_player/stremio_player.rs +++ b/src/stremio_app/stremio_player/stremio_player.rs @@ -1,8 +1,52 @@ use native_windows_gui::{self as nwg, PartialUi}; +use std::cell::RefCell; + +pub trait PlayerInterface { + fn play(&self, media_path: &str); + fn pause(&self, paused: bool); + fn seek(&self, time: f64); + fn speed(&self, factor: f64); + fn stop(&self); +} #[derive(Default)] pub struct Player { - mpv: Option, + mpv: RefCell>, +} + +impl Player { + fn command(&self, args: &[&str]) { + let mut mpv = self.mpv.borrow_mut(); + let mpv = mpv.as_mut().expect("Failed to create MPV"); + if let Err(e) = mpv.command(args) { + eprintln!("Failed to execute command {:?} - {:?}", args, e); + } + } + fn set_prop(&self, prop: &str, val: T) { + let mut mpv = self.mpv.borrow_mut(); + let mpv = mpv.as_mut().expect("Failed to create MPV"); + if let Err(e) = mpv.set_property(prop, val) { + eprintln!("Failed to set property {} - {:?}", prop, e); + } + } +} + +impl PlayerInterface for Player { + fn play(&self, media_path: &str) { + self.command(&["loadfile", media_path]); + } + fn pause(&self, paused: bool) { + self.set_prop("pause", paused); + } + fn seek(&self, pos: f64) { + self.set_prop("time-pos", pos); + } + fn speed(&self, factor: f64) { + self.set_prop("speed", factor); + } + fn stop(&self) { + self.command(&["stop"]); + } } impl PartialUi for Player { @@ -10,10 +54,18 @@ impl PartialUi for Player { data: &mut Self, parent: Option, ) -> 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) + .set_option( + "wid", + parent + .expect("No parent window") + .into() + .hwnd() + .expect("Cannot obtain window handle") 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 @@ -35,14 +87,7 @@ impl PartialUi for Player { .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"); - + data.mpv = RefCell::new(mpv_builder.build().ok()); Ok(()) } }