summaryrefslogtreecommitdiffstats
path: root/DOCS
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-08-11 01:22:53 +0200
committerwm4 <wm4@nowhere>2015-08-11 01:23:09 +0200
commitf6a354e8463c9dae90fb71721eecada2ea493bf4 (patch)
tree97b658d21e5a5dad352b6f87313ac66d5dcc6c69 /DOCS
parent2d68a2e55ab1fdc6a624e5afda203da061ec381a (diff)
downloadmpv-f6a354e8463c9dae90fb71721eecada2ea493bf4.tar.bz2
mpv-f6a354e8463c9dae90fb71721eecada2ea493bf4.tar.xz
DOCS/client_api_examples: add SDL OpenGL example
Diffstat (limited to 'DOCS')
-rw-r--r--DOCS/client_api_examples/README.md5
-rw-r--r--DOCS/client_api_examples/sdl/main.c137
2 files changed, 142 insertions, 0 deletions
diff --git a/DOCS/client_api_examples/README.md b/DOCS/client_api_examples/README.md
index 1b6b40b082..013098bf14 100644
--- a/DOCS/client_api_examples/README.md
+++ b/DOCS/client_api_examples/README.md
@@ -24,6 +24,11 @@ qml_direct
Alternative example, which typically avoids a FBO indirection. Might be
slightly faster, but is less flexible and harder to use.
+sdl
+---
+
+Show how to embed the mpv OpenGL renderer in SDL.
+
simple
------
diff --git a/DOCS/client_api_examples/sdl/main.c b/DOCS/client_api_examples/sdl/main.c
new file mode 100644
index 0000000000..38d2cf57cc
--- /dev/null
+++ b/DOCS/client_api_examples/sdl/main.c
@@ -0,0 +1,137 @@
+// Build with: gcc -o main main.c `pkg-config --libs --cflags mpv sdl2`
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <SDL.h>
+
+#include <mpv/client.h>
+#include <mpv/opengl_cb.h>
+
+static Uint32 wakeup_on_mpv_redraw, wakeup_on_mpv_events;
+
+static void die(const char *msg)
+{
+ fprintf(stderr, "%s\n", msg);
+ exit(1);
+}
+
+static void *get_proc_address_mpv(void *fn_ctx, const char *name)
+{
+ return SDL_GL_GetProcAddress(name);
+}
+
+static void on_mpv_events(void *ctx)
+{
+ SDL_Event event = {.type = wakeup_on_mpv_events};
+ SDL_PushEvent(&event);
+}
+
+static void on_mpv_redraw(void *ctx)
+{
+ SDL_Event event = {.type = wakeup_on_mpv_redraw};
+ SDL_PushEvent(&event);
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ die("pass a single media file as argument");
+
+ mpv_handle *mpv = mpv_create();
+ if (!mpv)
+ die("context init failed");
+
+ // Done setting up options.
+ if (mpv_initialize(mpv) < 0)
+ die("mpv init failed");
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0)
+ die("SDL init failed");
+
+ SDL_Window *window =
+ SDL_CreateWindow("hi", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+ 1000, 500, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
+ if (!window)
+ die("failed to create SDL window");
+
+ mpv_opengl_cb_context *mpv_gl = mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB);
+ if (!mpv_gl)
+ die("failed to create mpv GL API handle");
+
+ SDL_GLContext glcontext = SDL_GL_CreateContext(window);
+ if (!glcontext)
+ die("failed to create SDL GL context");
+
+ if (mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address_mpv, NULL) < 0)
+ die("failed to initialize mpv GL context");
+
+ // Actually using the opengl_cb state has to be explicitly requested.
+ // Otherwise, mpv will create a separate platform window.
+ if (mpv_set_option_string(mpv, "vo", "opengl-cb") < 0)
+ die("failed to set VO");
+
+ // Play this file. Note that this asynchronously starts playback.
+ const char *cmd[] = {"loadfile", argv[1], NULL};
+ mpv_command(mpv, cmd);
+
+ // We use events for thread-safe notification of the SDL main loop.
+ wakeup_on_mpv_redraw = SDL_RegisterEvents(1);
+ wakeup_on_mpv_events = SDL_RegisterEvents(1);
+ if (wakeup_on_mpv_redraw == (Uint32)-1 || wakeup_on_mpv_events == (Uint32)-1)
+ die("could not register events");
+
+ // When normal mpv events are available.
+ mpv_set_wakeup_callback(mpv, on_mpv_events, NULL);
+
+ // When a new frame should be drawn with mpv_opengl_cb_draw().
+ // (Separate from the normal event handling mechanism for the sake of
+ // users which run OpenGL on a different thread.)
+ mpv_opengl_cb_set_update_callback(mpv_gl, on_mpv_redraw, NULL);
+
+ while (1) {
+ SDL_Event event;
+ if (SDL_WaitEvent(&event) != 1)
+ die("event loop error");
+ int redraw = 0;
+ switch (event.type) {
+ case SDL_QUIT:
+ goto done;
+ case SDL_WINDOWEVENT:
+ if (event.window.event == SDL_WINDOWEVENT_EXPOSED)
+ redraw = 1;
+ break;
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_SPACE)
+ mpv_command_string(mpv, "cycle pause");
+ break;
+ default:
+ // Happens when a new video frame should be rendered, or if the
+ // current frame has to be redrawn e.g. due to OSD changes.
+ if (event.type == wakeup_on_mpv_redraw)
+ redraw = 1;
+ // Happens when at least 1 new event is in the mpv event queue.
+ if (event.type == wakeup_on_mpv_events) {
+ // Handle all remaining mpv events.
+ while (1) {
+ mpv_event *mp_event = mpv_wait_event(mpv, 0);
+ if (mp_event->event_id == MPV_EVENT_NONE)
+ break;
+ printf("event: %s\n", mpv_event_name(mp_event->event_id));
+ }
+ }
+ }
+ if (redraw) {
+ int w, h;
+ SDL_GetWindowSize(window, &w, &h);
+ mpv_opengl_cb_draw(mpv_gl, 0, w, -h);
+ SDL_GL_SwapWindow(window);
+ }
+ }
+done:
+
+ mpv_opengl_cb_uninit_gl(mpv_gl);
+ mpv_terminate_destroy(mpv);
+ return 0;
+}