use raw_window_handle::{HasWindowHandle, RawWindowHandle}; use vlc::{self, EventType, Instance, Media, MediaPlayer, State}; use winit::{ application::ApplicationHandler, event::{ElementState, WindowEvent}, event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy}, keyboard::{Key, NamedKey}, window::{Fullscreen, Window, WindowId}, }; #[derive(Debug)] enum UserEvent { MediaStopped, } struct App { md: Media, mdp: MediaPlayer, proxy: EventLoopProxy, window: Option, fullscreen: bool, } impl App { fn new(md: Media, mdp: MediaPlayer, proxy: EventLoopProxy) -> Self { Self { md, mdp, proxy, window: None, fullscreen: false, } } } impl ApplicationHandler for App { fn resumed(&mut self, event_loop: &ActiveEventLoop) { if self.window.is_some() { return; } // Create window let window_attributes = Window::default_attributes() .with_title("vlc-rs sample") .with_inner_size(winit::dpi::LogicalSize::new(800u16, 600u16)); let window = event_loop.create_window(window_attributes).unwrap(); // Request libvlc to draw in the window let handle = window.window_handle().unwrap(); match handle.as_raw() { RawWindowHandle::AppKit(handle) => { self.mdp.set_nsobject(handle.ns_view.as_ptr()); } RawWindowHandle::Xlib(handle) => { self.mdp.set_xwindow(handle.window as u32); } RawWindowHandle::Win32(handle) => { self.mdp.set_hwnd(isize::from(handle.hwnd) as *mut _); } _ => { panic!("Unknown Window handle type") } } // Link EventLoop and libvlc let proxy = self.proxy.clone(); let em = self.md.event_manager(); let _ = em.attach(EventType::MediaStateChanged, move |e, _| match e { vlc::Event::MediaStateChanged(s) => { println!("State : {:?}", s); if s == State::Ended || s == State::Error || s == State::Stopped { proxy.send_event(UserEvent::MediaStopped).unwrap(); } } _ => (), }); // Start self.mdp.set_media(&self.md); self.mdp.play().unwrap(); self.window = Some(window); } fn user_event(&mut self, event_loop: &ActiveEventLoop, event: UserEvent) { match event { UserEvent::MediaStopped => event_loop.exit(), } } fn window_event( &mut self, _event_loop: &ActiveEventLoop, _window_id: WindowId, event: WindowEvent, ) { match event { WindowEvent::CloseRequested => { self.mdp.stop(); } WindowEvent::KeyboardInput { event, .. } => { if event.state != ElementState::Pressed { return; } if let Key::Character(ref c) = event.logical_key { if c.as_str() == "f" || c.as_str() == "F" { let next_fullscreen_mode = if self.fullscreen { None } else { Some(Fullscreen::Borderless(None)) }; if let Some(window) = &self.window { window.set_fullscreen(next_fullscreen_mode); } self.fullscreen = !self.fullscreen; } } else if event.logical_key == Key::Named(NamedKey::Escape) && self.fullscreen { if let Some(window) = &self.window { window.set_fullscreen(None); } self.fullscreen = false; } } _ => {} } } } fn main() { let args: Vec = std::env::args().collect(); let path = match args.get(1) { Some(s) => s.clone(), None => { println!("Usage: winit_player path_to_a_media_file"); return; } }; // Instanciate libvlc let instance = Instance::new().unwrap(); let md = Media::new_path(&instance, &path).unwrap(); let mdp = MediaPlayer::new(&instance).unwrap(); let event_loop = EventLoop::::with_user_event().build().unwrap(); let proxy = event_loop.create_proxy(); let mut app = App::new(md, mdp, proxy); event_loop.run_app(&mut app).unwrap(); }