diff --git a/Makefile b/Makefile
index d80c7f62c92ee90533dbb31b90ab9d1ccc09be32..6c90da1617381c7b3c887d7441a3f37c418df0ee 100644
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,8 @@ UNAME_S := $(shell uname -s)
 
 CXXFLAGS = -I./
 CXXFLAGS += -g -Wall -Wformat
-LIBS =
+CXXFLAGS += `pkg-config --cflags mpv`
+LIBS = `pkg-config --libs mpv`
 
 ##---------------------------------------------------------------------
 ## OPENGL LOADER
diff --git a/imgui.ini b/imgui.ini
index b7ed50cf9cfde7e99d0eaa7d67933dff71760e9d..de57d2a63646551c564a582b5876fac13c06cbc5 100644
--- a/imgui.ini
+++ b/imgui.ini
@@ -4,12 +4,12 @@ Size=400,400
 Collapsed=0
 
 [Window][Hello, world!]
-Pos=307,102
-Size=1086,775
+Pos=323,198
+Size=703,254
 Collapsed=0
 
 [Window][Dear ImGui Demo]
-Pos=878,103
+Pos=1256,131
 Size=550,680
 Collapsed=0
 
diff --git a/main.cpp b/main.cpp
index cd5bbba4176d73a5430ec40e659da198cc409f15..c2b892afc7b45eaab25ab2e47315615cd4617da0 100644
--- a/main.cpp
+++ b/main.cpp
@@ -4,6 +4,36 @@
 #include <stdio.h>
 #include <SDL.h>
 
+// mpv stuff
+#include <mpv/client.h>
+#include <mpv/render_gl.h>
+
+// Ugly stuff for mpv
+static Uint32 wakeup_on_mpv_render_update, 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_render_update(void *ctx)
+{
+    SDL_Event event = {.type = wakeup_on_mpv_render_update};
+    SDL_PushEvent(&event);
+}
+
 // About Desktop OpenGL function loaders:
 //  Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
 //  Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
@@ -29,8 +59,26 @@ using namespace gl;
 #endif
 
 // Main code
-int main(int, char**)
+int main(int argc, char **argv)
 {
+    // MPV init before SDL init
+    // If I remenber, we need to set an idle thing for mpv, so that it won't close even after the end of the video (which is facheux)
+    if (argc != 2)
+        die("pass a single media file as argument");
+
+    mpv_handle *mpv = mpv_create();
+    if (!mpv)
+        die("context init failed");
+
+    // Some minor options can only be set before mpv_initialize().
+    if (mpv_initialize(mpv) < 0)
+        die("mpv init failed");
+
+    mpv_request_log_messages(mpv, "debug");
+
+    // Jesus Christ SDL, you suck!
+    SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "no");
+
     // Setup SDL
     // (Some versions of SDL before <2.0.10 appears to have performance/stalling issues on a minority of Windows systems,
     // depending on whether SDL_INIT_GAMECONTROLLER is enabled or disabled.. updating to latest version of SDL is recommended!)
@@ -61,7 +109,7 @@ int main(int, char**)
     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
     SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
     SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
-    SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
+    SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI);
     SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
     SDL_GLContext gl_context = SDL_GL_CreateContext(window);
     SDL_GL_MakeCurrent(window, gl_context);
@@ -89,6 +137,63 @@ int main(int, char**)
         return 1;
     }
 
+    // Bind mpv and sdl
+    SDL_GLContext glcontext = SDL_GL_CreateContext(window);
+    if (!glcontext)
+        die("failed to create SDL GL context");
+
+    // TODO Name correctly those things
+    int __one[] = {1};
+    auto __something = (mpv_opengl_init_params){
+        .get_proc_address = get_proc_address_mpv,
+    };
+
+    mpv_render_param params[] = {
+        {MPV_RENDER_PARAM_API_TYPE, (void *) MPV_RENDER_API_TYPE_OPENGL},
+        {MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &__something},
+        // Tell libmpv that you will call mpv_render_context_update() on render
+        // context update callbacks, and that you will _not_ block on the core
+        // ever (see <libmpv/render.h> "Threading" section for what libmpv
+        // functions you can call at all when this is active).
+        // In particular, this means you must call e.g. mpv_command_async()
+        // instead of mpv_command().
+        // If you want to use synchronous calls, either make them on a separate
+        // thread, or remove the option below (this will disable features like
+        // DR and is not recommended anyway).
+        {MPV_RENDER_PARAM_ADVANCED_CONTROL, &__one},
+        {(mpv_render_param_type)0}
+    };
+
+     // This makes mpv use the currently set GL context. It will use the callback
+    // (passed via params) to resolve GL builtin functions, as well as extensions.
+    mpv_render_context *mpv_gl;
+    if (mpv_render_context_create(&mpv_gl, mpv, params) < 0)
+        die("failed to initialize mpv GL context");
+
+      // We use events for thread-safe notification of the SDL main loop.
+    // Generally, the wakeup callbacks (set further below) should do as least
+    // work as possible, and merely wake up another thread to do actual work.
+    // On SDL, waking up the mainloop is the ideal course of action. SDL's
+    // SDL_PushEvent() is thread-safe, so we use that.
+    wakeup_on_mpv_render_update = SDL_RegisterEvents(1);
+    wakeup_on_mpv_events = SDL_RegisterEvents(1);
+    if (wakeup_on_mpv_render_update == (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 there is a need to call mpv_render_context_update(), which can
+    // request a new frame to be rendered.
+    // (Separate from the normal event handling mechanism for the sake of
+    //  users which run OpenGL on a different thread.)
+    mpv_render_context_set_update_callback(mpv_gl, on_mpv_render_update, NULL);
+
+    // Play this file.
+    const char *cmd[] = {"loadfile", argv[1], NULL};
+    mpv_command_async(mpv, 0, cmd);
+
     // Setup Dear ImGui context
     IMGUI_CHECKVERSION();
     ImGui::CreateContext();
@@ -134,6 +239,7 @@ int main(int, char**)
         // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
         // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
         SDL_Event event;
+        int redraw = 0;
         while (SDL_PollEvent(&event))
         {
             ImGui_ImplSDL2_ProcessEvent(&event);
@@ -141,6 +247,81 @@ int main(int, char**)
                 done = true;
             if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
                 done = true;
+            if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_EXPOSED)
+                redraw = 1;
+            if (event.type == SDL_KEYDOWN)
+            {
+                if (event.key.keysym.sym == SDLK_SPACE)
+                {
+                    const char *cmd_pause[] = {"cycle", "pause", NULL};
+                    mpv_command_async(mpv, 0, cmd_pause);
+                }
+                if (event.key.keysym.sym == SDLK_s)
+                {
+                    // Also requires MPV_RENDER_PARAM_ADVANCED_CONTROL if you want
+                    // screenshots to be rendered on GPU (like --vo=gpu would do).
+                    const char *cmd_scr[] = {"screenshot-to-file",
+                        "screenshot.png",
+                        "window",
+                        NULL};
+                    printf("attempting to save screenshot to %s\n", cmd_scr[1]);
+                    mpv_command_async(mpv, 0, cmd_scr);
+                }
+            }
+            if (event.type == wakeup_on_mpv_render_update)
+            {
+                uint64_t flags = mpv_render_context_update(mpv_gl);
+                if (flags & MPV_RENDER_UPDATE_FRAME)
+                    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_event*) mpv_wait_event(mpv, 0);
+                    if (mp_event->event_id == MPV_EVENT_NONE)
+                        break;
+                    if (mp_event->event_id == MPV_EVENT_LOG_MESSAGE) {
+                        mpv_event_log_message *msg = (mpv_event_log_message *) mp_event->data;
+                        // Print log messages about DR allocations, just to
+                        // test whether it works. If there is more than 1 of
+                        // these, it works. (The log message can actually change
+                        // any time, so it's possible this logging stops working
+                        // in the future.)
+                        if (strstr(msg->text, "DR image"))
+                            printf("log: %s", msg->text);
+                        continue;
+                    }
+                    printf("event: %s\n", mpv_event_name(mp_event->event_id));
+                }
+            }
+        }
+
+        if (redraw)
+        {
+            int w, h;
+            auto __thing1 = (mpv_opengl_fbo){
+                .fbo = 0,
+                .w = w,
+                .h = h,
+            };
+            int __one__one = 1;
+            SDL_GetWindowSize(window, &w, &h);
+            mpv_render_param params[] = {
+                // Specify the default framebuffer (0) as target. This will
+                // render onto the entire screen. If you want to show the video
+                // in a smaller rectangle or apply fancy transformations, you'll
+                // need to render into a separate FBO and draw it manually.
+                {MPV_RENDER_PARAM_OPENGL_FBO, &__thing1},
+                // Flip rendering (needed due to flipped GL coordinate system).
+                {MPV_RENDER_PARAM_FLIP_Y, &__one__one},
+                {(mpv_render_param_type)0}
+            };
+            // See render_gl.h on what OpenGL environment mpv expects, and
+            // other API details.
+            mpv_render_context_render(mpv_gl, params);
+            SDL_GL_SwapWindow(window);
         }
 
         // Start the Dear ImGui frame
@@ -194,6 +375,12 @@ int main(int, char**)
         SDL_GL_SwapWindow(window);
     }
 
+    // Destroy the GL renderer and all of the GL objects it allocated. If video
+    // is still running, the video track will be deselected.
+    mpv_render_context_free(mpv_gl);
+
+    mpv_detach_destroy(mpv);
+
     // Cleanup
     ImGui_ImplOpenGL3_Shutdown();
     ImGui_ImplSDL2_Shutdown();