about summary refs log tree commit diff stats
path: root/libmpv2/examples/opengl.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libmpv2/examples/opengl.rs139
1 files changed, 139 insertions, 0 deletions
diff --git a/libmpv2/examples/opengl.rs b/libmpv2/examples/opengl.rs
new file mode 100644
index 0000000..1de307f
--- /dev/null
+++ b/libmpv2/examples/opengl.rs
@@ -0,0 +1,139 @@
+// yt - A fully featured command line YouTube client
+//
+// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of Yt.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+use libmpv2::{
+    render::{OpenGLInitParams, RenderContext, RenderParam, RenderParamApiType},
+    Mpv,
+};
+use std::{env, ffi::c_void};
+
+fn get_proc_address(display: &sdl2::VideoSubsystem, name: &str) -> *mut c_void {
+    display.gl_get_proc_address(name) as *mut c_void
+}
+
+const VIDEO_URL: &str = "test-data/jellyfish.mp4";
+
+#[derive(Debug)]
+enum UserEvent {
+    MpvEventAvailable,
+    RedrawRequested,
+}
+
+fn main() {
+    let (window, mut events_loop, event_subsystem, video, _context) = create_sdl2_context();
+
+    let path = env::args()
+        .nth(1)
+        .unwrap_or_else(|| String::from(VIDEO_URL));
+
+    let mut mpv = Mpv::with_initializer(|init| {
+        init.set_property("vo", "libmpv")?;
+        Ok(())
+    })
+    .unwrap();
+    let mut render_context = RenderContext::new(
+        unsafe { mpv.ctx.as_mut() },
+        vec![
+            RenderParam::ApiType(RenderParamApiType::OpenGl),
+            RenderParam::InitParams(OpenGLInitParams {
+                get_proc_address,
+                ctx: video,
+            }),
+        ],
+    )
+    .expect("Failed creating render context");
+
+    event_subsystem
+        .register_custom_event::<UserEvent>()
+        .unwrap();
+
+    mpv.event_context_mut().disable_deprecated_events().unwrap();
+
+    let event_sender = event_subsystem.event_sender();
+    render_context.set_update_callback(move || {
+        event_sender
+            .push_custom_event(UserEvent::RedrawRequested)
+            .unwrap();
+    });
+
+    let event_sender = event_subsystem.event_sender();
+    mpv.event_context_mut().set_wakeup_callback(move || {
+        event_sender
+            .push_custom_event(UserEvent::MpvEventAvailable)
+            .unwrap();
+    });
+    mpv.command("loadfile", &[&path, "replace"]).unwrap();
+
+    'render: loop {
+        for event in events_loop.poll_iter() {
+            use sdl2::event::Event;
+
+            if event.is_user_event() {
+                match event.as_user_event_type::<UserEvent>().unwrap() {
+                    UserEvent::RedrawRequested => {
+                        let (width, height) = window.drawable_size();
+                        render_context
+                            .render::<sdl2::VideoSubsystem>(0, width as _, height as _, true)
+                            .expect("Failed to draw on sdl2 window");
+                        window.gl_swap_window();
+                    }
+                    UserEvent::MpvEventAvailable => loop {
+                        match mpv.event_context_mut().wait_event(0.0) {
+                            Some(Ok(libmpv2::events::Event::EndFile(_))) => {
+                                break 'render;
+                            }
+                            Some(Ok(mpv_event)) => {
+                                eprintln!("MPV event: {:?}", mpv_event);
+                            }
+                            Some(Err(err)) => {
+                                eprintln!("MPV Error: {}", err);
+                                break 'render;
+                            }
+                            None => break,
+                        }
+                    },
+                }
+            }
+
+            match event {
+                Event::Quit { .. } => {
+                    break 'render;
+                }
+                _ => (),
+            }
+        }
+    }
+}
+
+fn create_sdl2_context() -> (
+    sdl2::video::Window,
+    sdl2::EventPump,
+    sdl2::EventSubsystem,
+    sdl2::VideoSubsystem,
+    sdl2::video::GLContext,
+) {
+    let sdl = sdl2::init().unwrap();
+    let video = sdl.video().unwrap();
+    let event_subsystem = sdl.event().unwrap();
+    let gl_attr = video.gl_attr();
+    gl_attr.set_context_profile(sdl2::video::GLProfile::Core);
+    gl_attr.set_context_version(3, 3);
+    gl_attr.set_context_flags().forward_compatible().set();
+    let window = video
+        .window("OpenGL mpv", 960, 540)
+        .opengl()
+        .resizable()
+        .build()
+        .unwrap();
+    let gl_context = window.gl_create_context().unwrap();
+    let event_loop = sdl.event_pump().unwrap();
+
+    (window, event_loop, event_subsystem, video, gl_context)
+}