Add winit integration example

merge-requests/13/head
Romain Roffé 2022-06-07 17:01:16 +02:00 committed by Romain Roffé
parent 90729e2bd4
commit 34d69083e8
3 changed files with 1500 additions and 0 deletions

1344
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -26,3 +26,7 @@ libvlc-sys = { path = "libvlc-sys" }
# builds never compile it.
[workspace]
exclude = ["xtask"]
[dev-dependencies]
raw-window-handle = "0.6"
winit = { version = "0.30", default-features = false, features = ["x11", "rwh_06"] }

View File

@ -0,0 +1,152 @@
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<UserEvent>,
window: Option<Window>,
fullscreen: bool,
}
impl App {
fn new(md: Media, mdp: MediaPlayer, proxy: EventLoopProxy<UserEvent>) -> Self {
Self {
md,
mdp,
proxy,
window: None,
fullscreen: false,
}
}
}
impl ApplicationHandler<UserEvent> 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<String> = 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::<UserEvent>::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();
}