From 1d88825feb5a73a50d019914ba9d0008562a58ce Mon Sep 17 00:00:00 2001
From: Pete Alexandrou <pete@ozmartians.com>
Date: Tue, 22 Feb 2022 11:29:00 +1100
Subject: [PATCH] Patches to pympv to workaround opengl_cb deprecation from
 libmpv

---
 vidcutter/libs/pympv/client.pxd |    54 +-
 vidcutter/libs/pympv/mpv.c      | 46394 ++++++++++++++----------------
 vidcutter/libs/pympv/mpv.pyx    |   192 +-
 3 files changed, 21832 insertions(+), 24808 deletions(-)

diff --git a/vidcutter/libs/pympv/client.pxd b/vidcutter/libs/pympv/client.pxd
index befe219e..d9a8816f 100644
--- a/vidcutter/libs/pympv/client.pxd
+++ b/vidcutter/libs/pympv/client.pxd
@@ -112,9 +112,9 @@ cdef extern from "mpv/client.h":
 
     int mpv_load_config_file(mpv_handle *ctx, const char *filename) nogil
 
-    void mpv_suspend(mpv_handle *ctx) nogil
+    # void mpv_suspend(mpv_handle *ctx) nogil
 
-    void mpv_resume(mpv_handle *ctx) nogil
+    # void mpv_resume(mpv_handle *ctx) nogil
 
     int64_t mpv_get_time_us(mpv_handle *ctx) nogil
 
@@ -200,21 +200,21 @@ cdef extern from "mpv/client.h":
         MPV_EVENT_START_FILE
         MPV_EVENT_END_FILE
         MPV_EVENT_FILE_LOADED
-        MPV_EVENT_TRACKS_CHANGED
-        MPV_EVENT_TRACK_SWITCHED
+        # MPV_EVENT_TRACKS_CHANGED
+        # MPV_EVENT_TRACK_SWITCHED
         MPV_EVENT_IDLE
-        MPV_EVENT_PAUSE
-        MPV_EVENT_UNPAUSE
+        # MPV_EVENT_PAUSE
+        # MPV_EVENT_UNPAUSE
         MPV_EVENT_TICK
-        MPV_EVENT_SCRIPT_INPUT_DISPATCH
+        # MPV_EVENT_SCRIPT_INPUT_DISPATCH
         MPV_EVENT_CLIENT_MESSAGE
         MPV_EVENT_VIDEO_RECONFIG
         MPV_EVENT_AUDIO_RECONFIG
-        MPV_EVENT_METADATA_UPDATE
+        # MPV_EVENT_METADATA_UPDATE
         MPV_EVENT_SEEK
         MPV_EVENT_PLAYBACK_RESTART
         MPV_EVENT_PROPERTY_CHANGE
-        MPV_EVENT_CHAPTER_CHANGE
+        # MPV_EVENT_CHAPTER_CHANGE
 
     const char *mpv_event_name(mpv_event_id event) nogil
 
@@ -249,9 +249,9 @@ cdef extern from "mpv/client.h":
         int reason
         int error
 
-    cdef struct mpv_event_script_input_dispatch:
-        int arg0
-        const char *type
+    # cdef struct mpv_event_script_input_dispatch:
+    #     int arg0
+    #     const char *type
 
     cdef struct mpv_event_client_message:
         int num_args
@@ -282,27 +282,27 @@ cdef extern from "mpv/client.h":
 
     void *mpv_get_sub_api(mpv_handle *ctx, mpv_sub_api sub_api) nogil
 
-cdef extern from "mpv/opengl_cb.h":
-    struct mpv_opengl_cb_context:
-        pass
+# cdef extern from "mpv/opengl_cb.h":
+#     struct mpv_opengl_cb_context:
+#         pass
 
-    ctypedef void (*mpv_opengl_cb_update_fn)(void *cb_ctx) nogil
-    ctypedef void *(*mpv_opengl_cb_get_proc_address_fn)(void *fn_ctx,
-                                                        const char *name) nogil
+#     ctypedef void (*mpv_opengl_cb_update_fn)(void *cb_ctx) nogil
+#     ctypedef void *(*mpv_opengl_cb_get_proc_address_fn)(void *fn_ctx,
+#                                                         const char *name) nogil
 
-    void mpv_opengl_cb_set_update_callback(mpv_opengl_cb_context *ctx,
-                                           mpv_opengl_cb_update_fn callback,
-                                           void *callback_ctx) nogil
+#     void mpv_opengl_cb_set_update_callback(mpv_opengl_cb_context *ctx,
+#                                            mpv_opengl_cb_update_fn callback,
+#                                            void *callback_ctx) nogil
 
-    int mpv_opengl_cb_init_gl(mpv_opengl_cb_context *ctx, const char *exts,
-                              mpv_opengl_cb_get_proc_address_fn get_proc_address,
-                              void *get_proc_address_ctx) nogil
+#     int mpv_opengl_cb_init_gl(mpv_opengl_cb_context *ctx, const char *exts,
+#                               mpv_opengl_cb_get_proc_address_fn get_proc_address,
+#                               void *get_proc_address_ctx) nogil
 
-    int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int w, int h) nogil
+#     int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int w, int h) nogil
 
-    int mpv_opengl_cb_report_flip(mpv_opengl_cb_context *ctx, int64_t time) nogil
+#     int mpv_opengl_cb_report_flip(mpv_opengl_cb_context *ctx, int64_t time) nogil
 
-    int mpv_opengl_cb_uninit_gl(mpv_opengl_cb_context *ctx) nogil
+#     int mpv_opengl_cb_uninit_gl(mpv_opengl_cb_context *ctx) nogil
 
 
 cdef extern from "mpv/render.h":
diff --git a/vidcutter/libs/pympv/mpv.c b/vidcutter/libs/pympv/mpv.c
index 202aae8c..a3522ef5 100644
--- a/vidcutter/libs/pympv/mpv.c
+++ b/vidcutter/libs/pympv/mpv.c
@@ -1,4 +1,4 @@
-/* Generated by Cython 0.29.21 */
+/* Generated by Cython 0.29.28 */
 
 /* BEGIN: Cython Metadata
 {
@@ -19,15 +19,17 @@
 }
 END: Cython Metadata */
 
+#ifndef PY_SSIZE_T_CLEAN
 #define PY_SSIZE_T_CLEAN
+#endif /* PY_SSIZE_T_CLEAN */
 #include "Python.h"
 #ifndef Py_PYTHON_H
     #error Python headers needed to compile C extensions, please install development version of Python.
 #elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)
     #error Cython requires Python 2.6+ or Python 3.3+.
 #else
-#define CYTHON_ABI "0_29_21"
-#define CYTHON_HEX_VERSION 0x001D15F0
+#define CYTHON_ABI "0_29_28"
+#define CYTHON_HEX_VERSION 0x001D1CF0
 #define CYTHON_FUTURE_DIVISION 0
 #include <stddef.h>
 #ifndef offsetof
@@ -174,7 +176,7 @@ END: Cython Metadata */
   #ifndef CYTHON_USE_UNICODE_INTERNALS
     #define CYTHON_USE_UNICODE_INTERNALS 1
   #endif
-  #if PY_VERSION_HEX < 0x030300F0
+  #if PY_VERSION_HEX < 0x030300F0 || PY_VERSION_HEX >= 0x030B00A2
     #undef CYTHON_USE_UNICODE_WRITER
     #define CYTHON_USE_UNICODE_WRITER 0
   #elif !defined(CYTHON_USE_UNICODE_WRITER)
@@ -189,11 +191,14 @@ END: Cython Metadata */
   #ifndef CYTHON_UNPACK_METHODS
     #define CYTHON_UNPACK_METHODS 1
   #endif
-  #ifndef CYTHON_FAST_THREAD_STATE
+  #if PY_VERSION_HEX >= 0x030B00A4
+    #undef CYTHON_FAST_THREAD_STATE
+    #define CYTHON_FAST_THREAD_STATE 0
+  #elif !defined(CYTHON_FAST_THREAD_STATE)
     #define CYTHON_FAST_THREAD_STATE 1
   #endif
   #ifndef CYTHON_FAST_PYCALL
-    #define CYTHON_FAST_PYCALL 1
+    #define CYTHON_FAST_PYCALL (PY_VERSION_HEX < 0x030B00A1)
   #endif
   #ifndef CYTHON_PEP489_MULTI_PHASE_INIT
     #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000)
@@ -204,7 +209,10 @@ END: Cython Metadata */
   #ifndef CYTHON_USE_DICT_VERSIONS
     #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1)
   #endif
-  #ifndef CYTHON_USE_EXC_INFO_STACK
+  #if PY_VERSION_HEX >= 0x030B00A4
+    #undef CYTHON_USE_EXC_INFO_STACK
+    #define CYTHON_USE_EXC_INFO_STACK 0
+  #elif !defined(CYTHON_USE_EXC_INFO_STACK)
     #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3)
   #endif
 #endif
@@ -212,7 +220,9 @@ END: Cython Metadata */
 #define CYTHON_FAST_PYCCALL  (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1)
 #endif
 #if CYTHON_USE_PYLONG_INTERNALS
-  #include "longintrepr.h"
+  #if PY_MAJOR_VERSION < 3
+    #include "longintrepr.h"
+  #endif
   #undef SHIFT
   #undef BASE
   #undef MASK
@@ -329,9 +339,68 @@ END: Cython Metadata */
   #define __Pyx_DefaultClassType PyClass_Type
 #else
   #define __Pyx_BUILTIN_MODULE_NAME "builtins"
-#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2
-  #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
-          PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
+  #define __Pyx_DefaultClassType PyType_Type
+#if PY_VERSION_HEX >= 0x030B00A1
+    static CYTHON_INLINE PyCodeObject* __Pyx_PyCode_New(int a, int k, int l, int s, int f,
+                                                    PyObject *code, PyObject *c, PyObject* n, PyObject *v,
+                                                    PyObject *fv, PyObject *cell, PyObject* fn,
+                                                    PyObject *name, int fline, PyObject *lnos) {
+        PyObject *kwds=NULL, *argcount=NULL, *posonlyargcount=NULL, *kwonlyargcount=NULL;
+        PyObject *nlocals=NULL, *stacksize=NULL, *flags=NULL, *replace=NULL, *call_result=NULL, *empty=NULL;
+        const char *fn_cstr=NULL;
+        const char *name_cstr=NULL;
+        PyCodeObject* co=NULL;
+        PyObject *type, *value, *traceback;
+        PyErr_Fetch(&type, &value, &traceback);
+        if (!(kwds=PyDict_New())) goto end;
+        if (!(argcount=PyLong_FromLong(a))) goto end;
+        if (PyDict_SetItemString(kwds, "co_argcount", argcount) != 0) goto end;
+        if (!(posonlyargcount=PyLong_FromLong(0))) goto end;
+        if (PyDict_SetItemString(kwds, "co_posonlyargcount", posonlyargcount) != 0) goto end;
+        if (!(kwonlyargcount=PyLong_FromLong(k))) goto end;
+        if (PyDict_SetItemString(kwds, "co_kwonlyargcount", kwonlyargcount) != 0) goto end;
+        if (!(nlocals=PyLong_FromLong(l))) goto end;
+        if (PyDict_SetItemString(kwds, "co_nlocals", nlocals) != 0) goto end;
+        if (!(stacksize=PyLong_FromLong(s))) goto end;
+        if (PyDict_SetItemString(kwds, "co_stacksize", stacksize) != 0) goto end;
+        if (!(flags=PyLong_FromLong(f))) goto end;
+        if (PyDict_SetItemString(kwds, "co_flags", flags) != 0) goto end;
+        if (PyDict_SetItemString(kwds, "co_code", code) != 0) goto end;
+        if (PyDict_SetItemString(kwds, "co_consts", c) != 0) goto end;
+        if (PyDict_SetItemString(kwds, "co_names", n) != 0) goto end;
+        if (PyDict_SetItemString(kwds, "co_varnames", v) != 0) goto end;
+        if (PyDict_SetItemString(kwds, "co_freevars", fv) != 0) goto end;
+        if (PyDict_SetItemString(kwds, "co_cellvars", cell) != 0) goto end;
+        if (PyDict_SetItemString(kwds, "co_linetable", lnos) != 0) goto end;
+        if (!(fn_cstr=PyUnicode_AsUTF8AndSize(fn, NULL))) goto end;
+        if (!(name_cstr=PyUnicode_AsUTF8AndSize(name, NULL))) goto end;
+        if (!(co = PyCode_NewEmpty(fn_cstr, name_cstr, fline))) goto end;
+        if (!(replace = PyObject_GetAttrString((PyObject*)co, "replace"))) goto cleanup_code_too;
+        if (!(empty = PyTuple_New(0))) goto cleanup_code_too; // unfortunately __pyx_empty_tuple isn't available here
+        if (!(call_result = PyObject_Call(replace, empty, kwds))) goto cleanup_code_too;
+        Py_XDECREF((PyObject*)co);
+        co = (PyCodeObject*)call_result;
+        call_result = NULL;
+        if (0) {
+            cleanup_code_too:
+            Py_XDECREF((PyObject*)co);
+            co = NULL;
+        }
+        end:
+        Py_XDECREF(kwds);
+        Py_XDECREF(argcount);
+        Py_XDECREF(posonlyargcount);
+        Py_XDECREF(kwonlyargcount);
+        Py_XDECREF(nlocals);
+        Py_XDECREF(stacksize);
+        Py_XDECREF(replace);
+        Py_XDECREF(call_result);
+        Py_XDECREF(empty);
+        if (type) {
+            PyErr_Restore(type, value, traceback);
+        }
+        return co;
+    }
 #else
   #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\
           PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
@@ -445,8 +514,12 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
 #endif
 #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND)
   #define CYTHON_PEP393_ENABLED 1
+  #if defined(PyUnicode_IS_READY)
   #define __Pyx_PyUnicode_READY(op)       (likely(PyUnicode_IS_READY(op)) ?\
                                               0 : _PyUnicode_Ready((PyObject *)(op)))
+  #else
+  #define __Pyx_PyUnicode_READY(op)       (0)
+  #endif
   #define __Pyx_PyUnicode_GET_LENGTH(u)   PyUnicode_GET_LENGTH(u)
   #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
   #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u)   PyUnicode_MAX_CHAR_VALUE(u)
@@ -455,7 +528,11 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) {
   #define __Pyx_PyUnicode_READ(k, d, i)   PyUnicode_READ(k, d, i)
   #define __Pyx_PyUnicode_WRITE(k, d, i, ch)  PyUnicode_WRITE(k, d, i, ch)
   #if defined(PyUnicode_IS_READY) && defined(PyUnicode_GET_SIZE)
+  #if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03090000
+  #define __Pyx_PyUnicode_IS_TRUE(u)      (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : ((PyCompactUnicodeObject *)(u))->wstr_length))
+  #else
   #define __Pyx_PyUnicode_IS_TRUE(u)      (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u)))
+  #endif
   #else
   #define __Pyx_PyUnicode_IS_TRUE(u)      (0 != PyUnicode_GET_LENGTH(u))
   #endif
@@ -627,7 +704,6 @@ static CYTHON_INLINE float __PYX_NAN() {
 #include <string.h>
 #include <stdlib.h>
 #include "mpv/client.h"
-#include "mpv/opengl_cb.h"
 #include "mpv/render.h"
 #include "mpv/render_gl.h"
 #ifdef _OPENMP
@@ -857,12 +933,10 @@ static const char *__pyx_f[] = {
 
 /*--- Type declarations ---*/
 struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached;
-struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch;
 struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage;
 struct __pyx_obj_9vidcutter_4libs_3mpv_Property;
 struct __pyx_obj_9vidcutter_4libs_3mpv_Event;
 struct __pyx_obj_9vidcutter_4libs_3mpv_Context;
-struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext;
 struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams;
 struct __pyx_obj_9vidcutter_4libs_3mpv_RenderFrameInfo;
 struct __pyx_obj_9vidcutter_4libs_3mpv_RenderContext;
@@ -897,21 +971,6 @@ struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached {
 };
 
 
-/* "vidcutter/libs/pympv/mpv.pyx":169
- * 
- * 
- * cdef class InputDispatch(object):             # <<<<<<<<<<<<<<
- *     """Data field for MPV_EVENT_SCRIPT_INPUT_DISPATCH events.
- * 
- */
-struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch {
-  PyObject_HEAD
-  struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_InputDispatch *__pyx_vtab;
-  PyObject *arg0;
-  PyObject *type;
-};
-
-
 /* "vidcutter/libs/pympv/mpv.pyx":182
  * 
  * 
@@ -978,21 +1037,6 @@ struct __pyx_obj_9vidcutter_4libs_3mpv_Context {
 };
 
 
-/* "vidcutter/libs/pympv/mpv.pyx":822
- *     (<object>ctx)()
- * 
- * cdef class OpenGLContext(object):             # <<<<<<<<<<<<<<
- *     cdef:
- *         mpv_opengl_cb_context *_ctx
- */
-struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext {
-  PyObject_HEAD
-  struct mpv_opengl_cb_context *_ctx;
-  int inited;
-  PyObject *update_cb;
-};
-
-
 /* "vidcutter/libs/pympv/mpv.pyx":881
  * DEF MAX_RENDER_PARAMS = 32
  * 
@@ -1080,20 +1124,6 @@ struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_EndOfFileReached {
 static struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_EndOfFileReached *__pyx_vtabptr_9vidcutter_4libs_3mpv_EndOfFileReached;
 
 
-/* "vidcutter/libs/pympv/mpv.pyx":169
- * 
- * 
- * cdef class InputDispatch(object):             # <<<<<<<<<<<<<<
- *     """Data field for MPV_EVENT_SCRIPT_INPUT_DISPATCH events.
- * 
- */
-
-struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_InputDispatch {
-  PyObject *(*_init)(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *, struct mpv_event_script_input_dispatch *);
-};
-static struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_InputDispatch *__pyx_vtabptr_9vidcutter_4libs_3mpv_InputDispatch;
-
-
 /* "vidcutter/libs/pympv/mpv.pyx":182
  * 
  * 
@@ -1318,6 +1348,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
 #ifndef Py_MEMBER_SIZE
 #define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
 #endif
+#if CYTHON_FAST_PYCALL
   static size_t __pyx_pyframe_localsplus_offset = 0;
   #include "frameobject.h"
   #define __Pxy_PyFrame_Initialize_Offsets()\
@@ -1325,6 +1356,7 @@ static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args,
      (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus)))
   #define __Pyx_PyFrame_GetLocalsplus(frame)\
     (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset))
+#endif // CYTHON_FAST_PYCALL
 #endif
 
 /* PyCFunctionFastCall.proto */
@@ -1747,12 +1779,23 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object);
 static void __Pyx_AddTraceback(const char *funcname, int c_line,
                                int py_line, const char *filename);
 
+/* GCCDiagnostics.proto */
+#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#define __Pyx_HAS_GCC_DIAGNOSTIC
+#endif
+
 /* CIntToPy.proto */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value);
 
+/* CIntFromPy.proto */
+static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *);
+
 /* CIntToPy.proto */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__mpv_event_id(enum mpv_event_id value);
 
+/* CIntFromPy.proto */
+static CYTHON_INLINE enum mpv_event_id __Pyx_PyInt_As_enum__mpv_event_id(PyObject *);
+
 /* CIntToPy.proto */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_unsigned_long(unsigned long value);
 
@@ -1768,30 +1811,21 @@ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__mpv_end_file_reason(enum m
 /* CIntToPy.proto */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__mpv_render_update_flag(enum mpv_render_update_flag value);
 
+/* CIntFromPy.proto */
+static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *);
+
 /* CIntToPy.proto */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int64_t(int64_t value);
 
 /* CIntToPy.proto */
 static CYTHON_INLINE PyObject* __Pyx_PyInt_From_uint64_t(uint64_t value);
 
-/* CIntToPy.proto */
-static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__mpv_format(enum mpv_format value);
-
-/* CIntToPy.proto */
-static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value);
-
-/* CIntFromPy.proto */
-static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *);
-
-/* CIntFromPy.proto */
-static CYTHON_INLINE enum mpv_event_id __Pyx_PyInt_As_enum__mpv_event_id(PyObject *);
-
-/* CIntFromPy.proto */
-static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *);
-
 /* CIntFromPy.proto */
 static CYTHON_INLINE uint64_t __Pyx_PyInt_As_uint64_t(PyObject *);
 
+/* CIntToPy.proto */
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_enum__mpv_format(enum mpv_format value);
+
 /* CIntFromPy.proto */
 static CYTHON_INLINE enum mpv_format __Pyx_PyInt_As_enum__mpv_format(PyObject *);
 
@@ -1801,6 +1835,9 @@ static CYTHON_INLINE int64_t __Pyx_PyInt_As_int64_t(PyObject *);
 /* CIntFromPy.proto */
 static CYTHON_INLINE intptr_t __Pyx_PyInt_As_intptr_t(PyObject *);
 
+/* CIntToPy.proto */
+static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value);
+
 /* CheckBinaryVersion.proto */
 static int __Pyx_check_binary_version(void);
 
@@ -1808,7 +1845,6 @@ static int __Pyx_check_binary_version(void);
 static int __Pyx_InitStrings(__Pyx_StringTabEntry *t);
 
 static PyObject *__pyx_f_9vidcutter_4libs_3mpv_16EndOfFileReached__init(struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached *__pyx_v_self, struct mpv_event_end_file *__pyx_v_eof); /* proto*/
-static PyObject *__pyx_f_9vidcutter_4libs_3mpv_13InputDispatch__init(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self, struct mpv_event_script_input_dispatch *__pyx_v_input); /* proto*/
 static PyObject *__pyx_f_9vidcutter_4libs_3mpv_10LogMessage__init(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, struct mpv_event_log_message *__pyx_v_msg); /* proto*/
 static PyObject *__pyx_f_9vidcutter_4libs_3mpv_8Property__init(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self, struct mpv_event_property *__pyx_v_prop); /* proto*/
 static PyObject *__pyx_f_9vidcutter_4libs_3mpv_5Event__data(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, struct mpv_event *__pyx_v_event); /* proto*/
@@ -1834,12 +1870,10 @@ static PyObject *__pyx_f_9vidcutter_4libs_3mpv_15RenderFrameInfo__from_struct(st
 
 /* Module declarations from 'vidcutter.libs.mpv' */
 static PyTypeObject *__pyx_ptype_9vidcutter_4libs_3mpv_EndOfFileReached = 0;
-static PyTypeObject *__pyx_ptype_9vidcutter_4libs_3mpv_InputDispatch = 0;
 static PyTypeObject *__pyx_ptype_9vidcutter_4libs_3mpv_LogMessage = 0;
 static PyTypeObject *__pyx_ptype_9vidcutter_4libs_3mpv_Property = 0;
 static PyTypeObject *__pyx_ptype_9vidcutter_4libs_3mpv_Event = 0;
 static PyTypeObject *__pyx_ptype_9vidcutter_4libs_3mpv_Context = 0;
-static PyTypeObject *__pyx_ptype_9vidcutter_4libs_3mpv_OpenGLContext = 0;
 static PyTypeObject *__pyx_ptype_9vidcutter_4libs_3mpv__RenderParams = 0;
 static PyTypeObject *__pyx_ptype_9vidcutter_4libs_3mpv_RenderFrameInfo = 0;
 static PyTypeObject *__pyx_ptype_9vidcutter_4libs_3mpv_RenderContext = 0;
@@ -1855,7 +1889,6 @@ static void __pyx_f_9vidcutter_4libs_3mpv__c_updatecb(void *); /*proto*/
 static void *__pyx_f_9vidcutter_4libs_3mpv_get_pointer(char const *, PyObject *); /*proto*/
 static void __pyx_f_9vidcutter_4libs_3mpv__c_callback(void *); /*proto*/
 static PyObject *__pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_EndOfFileReached__set_state(struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached *, PyObject *); /*proto*/
-static PyObject *__pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_InputDispatch__set_state(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *, PyObject *); /*proto*/
 static PyObject *__pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_LogMessage__set_state(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *, PyObject *); /*proto*/
 static PyObject *__pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_Property__set_state(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *, PyObject *); /*proto*/
 static PyObject *__pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_Event__set_state(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *, PyObject *); /*proto*/
@@ -1873,7 +1906,6 @@ static PyObject *__pyx_builtin_range;
 static PyObject *__pyx_builtin_id;
 static PyObject *__pyx_builtin_enumerate;
 static PyObject *__pyx_builtin_TypeError;
-static PyObject *__pyx_builtin_DeprecationWarning;
 static const char __pyx_k_e[] = "e";
 static const char __pyx_k_h[] = "h";
 static const char __pyx_k_k[] = "k";
@@ -1900,7 +1932,6 @@ static const char __pyx_k_call[] = "call";
 static const char __pyx_k_code[] = "code";
 static const char __pyx_k_data[] = "data";
 static const char __pyx_k_dict[] = "__dict__";
-static const char __pyx_k_exts[] = "exts";
 static const char __pyx_k_idle[] = "idle";
 static const char __pyx_k_info[] = "info";
 static const char __pyx_k_init[] = "__init__";
@@ -1926,7 +1957,6 @@ static const char __pyx_k_error[] = "error";
 static const char __pyx_k_event[] = "event";
 static const char __pyx_k_fatal[] = "fatal";
 static const char __pyx_k_nomem[] = "nomem";
-static const char __pyx_k_pause[] = "pause";
 static const char __pyx_k_range[] = "range";
 static const char __pyx_k_start[] = "start";
 static const char __pyx_k_trace[] = "trace";
@@ -1973,7 +2003,6 @@ static const char __pyx_k_present[] = "present";
 static const char __pyx_k_release[] = "release";
 static const char __pyx_k_success[] = "success";
 static const char __pyx_k_timeout[] = "timeout";
-static const char __pyx_k_unpause[] = "unpause";
 static const char __pyx_k_version[] = "__version__";
 static const char __pyx_k_wrapped[] = "wrapped";
 static const char __pyx_k_MPVError[] = "MPVError";
@@ -1998,7 +2027,6 @@ static const char __pyx_k_pyx_state[] = "__pyx_state";
 static const char __pyx_k_reduce_ex[] = "__reduce_ex__";
 static const char __pyx_k_render_fd[] = "render_fd";
 static const char __pyx_k_threading[] = "threading";
-static const char __pyx_k_uninit_gl[] = "uninit_gl";
 static const char __pyx_k_API_OPENGL[] = "API_OPENGL";
 static const char __pyx_k_CAPI_MAJOR[] = "_CAPI_MAJOR";
 static const char __pyx_k_CAPI_MINOR[] = "_CAPI_MINOR";
@@ -2038,8 +2066,6 @@ static const char __pyx_k_pyx_checksum[] = "__pyx_checksum";
 static const char __pyx_k_set_property[] = "set_property";
 static const char __pyx_k_stringsource[] = "stringsource";
 static const char __pyx_k_version_info[] = "version_info";
-static const char __pyx_k_InputDispatch[] = "InputDispatch";
-static const char __pyx_k_OpenGLContext[] = "OpenGLContext";
 static const char __pyx_k_RenderContext[] = "RenderContext";
 static const char __pyx_k_ReplyUserData[] = "_ReplyUserData";
 static const char __pyx_k_command_error[] = "command_error";
@@ -2053,18 +2079,15 @@ static const char __pyx_k_CallbackThread[] = "CallbackThread";
 static const char __pyx_k_MIN_CAPI_MINOR[] = "_MIN_CAPI_MINOR";
 static const char __pyx_k_ao_init_failed[] = "ao_init_failed";
 static const char __pyx_k_audio_reconfig[] = "audio_reconfig";
-static const char __pyx_k_chapter_change[] = "chapter_change";
 static const char __pyx_k_client_message[] = "client_message";
 static const char __pyx_k_loading_failed[] = "loading_failed";
 static const char __pyx_k_property_error[] = "property_error";
 static const char __pyx_k_skip_rendering[] = "skip_rendering";
-static const char __pyx_k_tracks_changed[] = "tracks_changed";
 static const char __pyx_k_unknown_format[] = "unknown_format";
 static const char __pyx_k_video_reconfig[] = "video_reconfig";
 static const char __pyx_k_vo_init_failed[] = "vo_init_failed";
 static const char __pyx_k_MPVError___init[] = "MPVError.__init__";
 static const char __pyx_k_internal_format[] = "internal_format";
-static const char __pyx_k_metadata_update[] = "metadata_update";
 static const char __pyx_k_not_implemented[] = "not_implemented";
 static const char __pyx_k_nothing_to_play[] = "nothing_to_play";
 static const char __pyx_k_property_change[] = "property_change";
@@ -2073,7 +2096,6 @@ static const char __pyx_k_pyx_PickleError[] = "__pyx_PickleError";
 static const char __pyx_k_set_icc_profile[] = "set_icc_profile";
 static const char __pyx_k_setstate_cython[] = "__setstate_cython__";
 static const char __pyx_k_surrogateescape[] = "surrogateescape";
-static const char __pyx_k_tracks_switched[] = "tracks_switched";
 static const char __pyx_k_EndOfFileReached[] = "EndOfFileReached";
 static const char __pyx_k_advanced_control[] = "advanced_control";
 static const char __pyx_k_drmModeAtomicReq[] = "drmModeAtomicReq*";
@@ -2085,7 +2107,6 @@ static const char __pyx_k_invalid_parameter[] = "invalid_parameter";
 static const char __pyx_k_set_ambient_light[] = "set_ambient_light";
 static const char __pyx_k_CallbackThread_run[] = "CallbackThread.run";
 static const char __pyx_k_CallbackThread_set[] = "CallbackThread.set";
-static const char __pyx_k_DeprecationWarning[] = "DeprecationWarning";
 static const char __pyx_k_UnicodeDecodeError[] = "UnicodeDecodeError";
 static const char __pyx_k_UnicodeEncodeError[] = "UnicodeEncodeError";
 static const char __pyx_k_Unknown_api_type_r[] = "Unknown api_type %r";
@@ -2109,12 +2130,9 @@ static const char __pyx_k_RenderParams_overflow[] = "RenderParams overflow";
 static const char __pyx_k_block_for_target_time[] = "block_for_target_time";
 static const char __pyx_k_errors_locals_wrapped[] = "_errors.<locals>.wrapped";
 static const char __pyx_k_pyx_unpickle_Property[] = "__pyx_unpickle_Property";
-static const char __pyx_k_script_input_dispatch[] = "script_input_dispatch";
 static const char __pyx_k_Context_creation_error[] = "Context creation error";
 static const char __pyx_k_CallbackThread_shutdown[] = "CallbackThread.shutdown";
 static const char __pyx_k_pyx_unpickle_LogMessage[] = "__pyx_unpickle_LogMessage";
-static const char __pyx_k_OpenGL_API_not_available[] = "OpenGL API not available";
-static const char __pyx_k_pyx_unpickle_InputDispatch[] = "__pyx_unpickle_InputDispatch";
 static const char __pyx_k_CallbackThread_mpv_callback[] = "CallbackThread.mpv_callback";
 static const char __pyx_k_pyx_unpickle_RenderFrameInfo[] = "__pyx_unpickle_RenderFrameInfo";
 static const char __pyx_k_vidcutter_libs_pympv_mpv_pyx[] = "vidcutter/libs/pympv/mpv.pyx";
@@ -2125,11 +2143,9 @@ static const char __pyx_k_self_params_cannot_be_converted[] = "self.params canno
 static const char __pyx_k_Incompatible_checksums_s_vs_0x05[] = "Incompatible checksums (%s vs 0x0572d11 = (data, name))";
 static const char __pyx_k_Incompatible_checksums_s_vs_0x56[] = "Incompatible checksums (%s vs 0x56be9b6 = (error, reason))";
 static const char __pyx_k_Incompatible_checksums_s_vs_0x87[] = "Incompatible checksums (%s vs 0x8774fae = (level, log_level, prefix, text))";
-static const char __pyx_k_Incompatible_checksums_s_vs_0xbf[] = "Incompatible checksums (%s vs 0xbf641a9 = (arg0, type))";
 static const char __pyx_k_Incompatible_checksums_s_vs_0xd4[] = "Incompatible checksums (%s vs 0xd41d8cd = ())";
 static const char __pyx_k_Incompatible_checksums_s_vs_0xda[] = "Incompatible checksums (%s vs 0xda38c25 = (data, error, id, reply_userdata))";
 static const char __pyx_k_Known_possible_values_for_EndOfF[] = "Known possible values for EndOfFileReached reason.\n\n    You should handle the possibility that the reason may not be any of these values.\n    ";
-static const char __pyx_k_OpenGLContext_is_deprecated_plea[] = "OpenGLContext is deprecated, please switch to RenderContext";
 static const char __pyx_k_Set_of_known_error_codes_from_Mp[] = "Set of known error codes from MpvError and Event responses.\n\n    Mostly wraps the enum mpv_error.\n    Values might not always be integers in the future.\n    You should handle the possibility that error codes may not be any of these values.\n    ";
 static const char __pyx_k_Set_of_known_values_for_Event_id[] = "Set of known values for Event ids.\n\n    Mostly wraps the enum mpv_event_id.\n    Values might not always be integers in the future.\n    You should handle the possibility that event ids may not be any of these values.\n    ";
 static const char __pyx_k_Unknown_or_invalid_pointer_objec[] = "Unknown or invalid pointer object: %r";
@@ -2151,7 +2167,6 @@ static PyObject *__pyx_n_s_CallbackThread_set;
 static PyObject *__pyx_n_s_CallbackThread_shutdown;
 static PyObject *__pyx_n_s_Context;
 static PyObject *__pyx_kp_s_Context_creation_error;
-static PyObject *__pyx_n_s_DeprecationWarning;
 static PyObject *__pyx_n_s_EOFReasons;
 static PyObject *__pyx_n_s_EndOfFileReached;
 static PyObject *__pyx_n_s_Errors;
@@ -2161,20 +2176,15 @@ static PyObject *__pyx_n_s_ImportError;
 static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0x05;
 static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0x56;
 static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0x87;
-static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0xbf;
 static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0xd4;
 static PyObject *__pyx_kp_s_Incompatible_checksums_s_vs_0xda;
-static PyObject *__pyx_n_s_InputDispatch;
 static PyObject *__pyx_kp_s_Known_possible_values_for_EndOfF;
 static PyObject *__pyx_n_s_LogLevels;
 static PyObject *__pyx_n_s_LogMessage;
 static PyObject *__pyx_n_s_MIN_CAPI_MINOR;
 static PyObject *__pyx_n_s_MPVError;
 static PyObject *__pyx_n_s_MPVError___init;
-static PyObject *__pyx_n_s_OpenGLContext;
-static PyObject *__pyx_kp_s_OpenGLContext_is_deprecated_plea;
 static PyObject *__pyx_n_s_OpenGLRenderContext;
-static PyObject *__pyx_kp_s_OpenGL_API_not_available;
 static PyObject *__pyx_n_s_PickleError;
 static PyObject *__pyx_n_s_Property;
 static PyObject *__pyx_n_s_PyMPVError;
@@ -2211,7 +2221,6 @@ static PyObject *__pyx_n_s_block_for_target_time;
 static PyObject *__pyx_n_s_block_vsync;
 static PyObject *__pyx_n_s_call;
 static PyObject *__pyx_n_s_callback;
-static PyObject *__pyx_n_s_chapter_change;
 static PyObject *__pyx_n_s_client_message;
 static PyObject *__pyx_n_s_cline_in_traceback;
 static PyObject *__pyx_n_s_close;
@@ -2244,7 +2253,6 @@ static PyObject *__pyx_n_s_error;
 static PyObject *__pyx_n_s_errors;
 static PyObject *__pyx_n_s_errors_locals_wrapped;
 static PyObject *__pyx_n_s_event;
-static PyObject *__pyx_n_s_exts;
 static PyObject *__pyx_n_s_fatal;
 static PyObject *__pyx_n_s_fbo;
 static PyObject *__pyx_n_s_fd;
@@ -2280,7 +2288,6 @@ static PyObject *__pyx_n_s_lock;
 static PyObject *__pyx_n_s_log_message;
 static PyObject *__pyx_n_s_main;
 static PyObject *__pyx_n_s_metaclass;
-static PyObject *__pyx_n_s_metadata_update;
 static PyObject *__pyx_n_s_module;
 static PyObject *__pyx_n_s_mpv;
 static PyObject *__pyx_n_s_mpv_callback;
@@ -2301,7 +2308,6 @@ static PyObject *__pyx_n_s_opengl_fbo;
 static PyObject *__pyx_n_s_opengl_init_params;
 static PyObject *__pyx_n_s_option_error;
 static PyObject *__pyx_n_s_option_format;
-static PyObject *__pyx_n_s_pause;
 static PyObject *__pyx_n_s_pickle;
 static PyObject *__pyx_n_s_playback_restart;
 static PyObject *__pyx_n_s_prepare;
@@ -2319,7 +2325,6 @@ static PyObject *__pyx_n_s_pyx_state;
 static PyObject *__pyx_n_s_pyx_type;
 static PyObject *__pyx_n_s_pyx_unpickle_EndOfFileReached;
 static PyObject *__pyx_n_s_pyx_unpickle_Event;
-static PyObject *__pyx_n_s_pyx_unpickle_InputDispatch;
 static PyObject *__pyx_n_s_pyx_unpickle_LogMessage;
 static PyObject *__pyx_n_s_pyx_unpickle_Property;
 static PyObject *__pyx_n_s_pyx_unpickle_RenderFrameInfo;
@@ -2340,7 +2345,6 @@ static PyObject *__pyx_n_s_repeat;
 static PyObject *__pyx_n_s_request_event;
 static PyObject *__pyx_n_s_run;
 static PyObject *__pyx_n_s_s;
-static PyObject *__pyx_n_s_script_input_dispatch;
 static PyObject *__pyx_n_s_seek;
 static PyObject *__pyx_n_s_self;
 static PyObject *__pyx_kp_s_self__ctx_cannot_be_converted_to;
@@ -2373,13 +2377,9 @@ static PyObject *__pyx_n_s_threading;
 static PyObject *__pyx_n_s_tick;
 static PyObject *__pyx_n_s_timeout;
 static PyObject *__pyx_n_s_trace;
-static PyObject *__pyx_n_s_tracks_changed;
-static PyObject *__pyx_n_s_tracks_switched;
-static PyObject *__pyx_n_s_uninit_gl;
 static PyObject *__pyx_n_s_uninitialized;
 static PyObject *__pyx_n_s_unknown_format;
 static PyObject *__pyx_n_s_unobserve_property;
-static PyObject *__pyx_n_s_unpause;
 static PyObject *__pyx_n_s_unsupported;
 static PyObject *__pyx_n_s_update;
 static PyObject *__pyx_kp_s_utf_8;
@@ -2409,14 +2409,6 @@ static int __pyx_pf_9vidcutter_4libs_3mpv_16EndOfFileReached_5error_2__set__(str
 static int __pyx_pf_9vidcutter_4libs_3mpv_16EndOfFileReached_5error_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_16EndOfFileReached___reduce_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_16EndOfFileReached_2__setstate_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self); /* proto */
-static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
-static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self); /* proto */
-static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
-static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch___reduce_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_2__setstate_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self, PyObject *__pyx_v___pyx_state); /* proto */
 static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self); /* proto */
 static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
 static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self); /* proto */
@@ -2462,41 +2454,29 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData_4remove(CYTHON_
 static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_11api_version___get__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_4name___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_4time___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_suspend(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_2resume(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_4request_event(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_event, PyObject *__pyx_v_enable); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_6set_log_level(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_loglevel); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_8load_config(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_10_format_for(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_12command(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_asynchronous, PyObject *__pyx_v_data, PyObject *__pyx_v_cmdlist); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_14get_property_async(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_16try_get_property_async(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data, PyObject *__pyx_v_default); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_18try_get_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_default); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_20get_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_22set_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_value, PyObject *__pyx_v_asynchronous, PyObject *__pyx_v_data); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_24set_option(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_value); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_26initialize(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_28wait_event(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_timeout); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_30wakeup(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_32set_wakeup_callback(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_callback); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_34get_wakeup_pipe(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static int __pyx_pf_9vidcutter_4libs_3mpv_7Context_36__cinit__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_38observe_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_40unobserve_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_data); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_42shutdown(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_44opengl_cb_api(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static void __pyx_pf_9vidcutter_4libs_3mpv_7Context_46__dealloc__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_48__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_50__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
-static int __pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext___init__(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_2init_gl(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self, PyObject *__pyx_v_exts, PyObject *__pyx_v_get_proc_address); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_4set_update_callback(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self, PyObject *__pyx_v_cb); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_6draw(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self, PyObject *__pyx_v_fbo, PyObject *__pyx_v_w, PyObject *__pyx_v_h); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_8report_flip(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self, PyObject *__pyx_v_time); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_10uninit_gl(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self); /* proto */
-static void __pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_12__dealloc__(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_14__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_16__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_request_event(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_event, PyObject *__pyx_v_enable); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_2set_log_level(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_loglevel); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_4load_config(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_filename); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_6_format_for(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_value); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_8command(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_asynchronous, PyObject *__pyx_v_data, PyObject *__pyx_v_cmdlist); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_10get_property_async(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_12try_get_property_async(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data, PyObject *__pyx_v_default); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_14try_get_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_default); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_16get_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_18set_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_value, PyObject *__pyx_v_asynchronous, PyObject *__pyx_v_data); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_20set_option(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_value); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_22initialize(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_24wait_event(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_timeout); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_26wakeup(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_28set_wakeup_callback(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_callback); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_30get_wakeup_pipe(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
+static int __pyx_pf_9vidcutter_4libs_3mpv_7Context_32__cinit__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_34observe_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_36unobserve_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_data); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_38shutdown(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
+static void __pyx_pf_9vidcutter_4libs_3mpv_7Context_40__dealloc__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_42__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_44__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state); /* proto */
 static int __pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams___init__(struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_self); /* proto */
 static void __pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams_2__dealloc__(struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams_4__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_self); /* proto */
@@ -2526,18 +2506,15 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14CallbackThread_6set(CYTHON_UNU
 static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14CallbackThread_8run(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self); /* proto */
 static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14CallbackThread_10mpv_callback(CYTHON_UNUSED PyObject *__pyx_self, CYTHON_UNUSED PyObject *__pyx_v_self, PyObject *__pyx_v_callback); /* proto */
 static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_6__pyx_unpickle_EndOfFileReached(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8__pyx_unpickle_InputDispatch(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10__pyx_unpickle_LogMessage(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_12__pyx_unpickle_Property(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14__pyx_unpickle_Event(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_16__pyx_unpickle_RenderFrameInfo(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8__pyx_unpickle_LogMessage(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10__pyx_unpickle_Property(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_12__pyx_unpickle_Event(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14__pyx_unpickle_RenderFrameInfo(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v___pyx_type, long __pyx_v___pyx_checksum, PyObject *__pyx_v___pyx_state); /* proto */
 static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv_EndOfFileReached(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
-static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv_InputDispatch(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv_LogMessage(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv_Property(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv_Event(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv_Context(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
-static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv_OpenGLContext(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv__RenderParams(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv_RenderFrameInfo(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv_RenderContext(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
@@ -2545,13 +2522,12 @@ static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv_OpenGLRenderContext(PyTypeOb
 static PyObject *__pyx_tp_new_9vidcutter_4libs_3mpv___pyx_scope_struct___errors(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/
 static PyObject *__pyx_int_0;
 static PyObject *__pyx_int_1;
+static PyObject *__pyx_int_2;
 static PyObject *__pyx_int_3;
-static PyObject *__pyx_int_9;
 static PyObject *__pyx_int_32;
 static PyObject *__pyx_int_5713169;
 static PyObject *__pyx_int_90958262;
 static PyObject *__pyx_int_142036910;
-static PyObject *__pyx_int_200688041;
 static PyObject *__pyx_int_222419149;
 static PyObject *__pyx_int_228822053;
 static PyObject *__pyx_int_neg_1;
@@ -2573,48 +2549,43 @@ static PyObject *__pyx_tuple__16;
 static PyObject *__pyx_tuple__17;
 static PyObject *__pyx_tuple__18;
 static PyObject *__pyx_tuple__19;
-static PyObject *__pyx_tuple__20;
 static PyObject *__pyx_tuple__21;
-static PyObject *__pyx_tuple__22;
-static PyObject *__pyx_tuple__24;
-static PyObject *__pyx_tuple__26;
+static PyObject *__pyx_tuple__23;
+static PyObject *__pyx_tuple__25;
+static PyObject *__pyx_tuple__27;
 static PyObject *__pyx_tuple__28;
 static PyObject *__pyx_tuple__30;
-static PyObject *__pyx_tuple__31;
-static PyObject *__pyx_tuple__33;
-static PyObject *__pyx_tuple__35;
-static PyObject *__pyx_tuple__37;
-static PyObject *__pyx_tuple__39;
-static PyObject *__pyx_tuple__41;
-static PyObject *__pyx_tuple__43;
-static PyObject *__pyx_tuple__45;
-static PyObject *__pyx_tuple__47;
-static PyObject *__pyx_tuple__49;
-static PyObject *__pyx_tuple__51;
-static PyObject *__pyx_tuple__53;
-static PyObject *__pyx_tuple__55;
-static PyObject *__pyx_tuple__57;
-static PyObject *__pyx_tuple__59;
+static PyObject *__pyx_tuple__32;
+static PyObject *__pyx_tuple__34;
+static PyObject *__pyx_tuple__36;
+static PyObject *__pyx_tuple__38;
+static PyObject *__pyx_tuple__40;
+static PyObject *__pyx_tuple__42;
+static PyObject *__pyx_tuple__44;
+static PyObject *__pyx_tuple__46;
+static PyObject *__pyx_tuple__48;
+static PyObject *__pyx_tuple__50;
+static PyObject *__pyx_tuple__52;
+static PyObject *__pyx_tuple__54;
 static PyObject *__pyx_codeobj__2;
-static PyObject *__pyx_codeobj__23;
-static PyObject *__pyx_codeobj__25;
-static PyObject *__pyx_codeobj__27;
+static PyObject *__pyx_codeobj__20;
+static PyObject *__pyx_codeobj__22;
+static PyObject *__pyx_codeobj__24;
+static PyObject *__pyx_codeobj__26;
 static PyObject *__pyx_codeobj__29;
-static PyObject *__pyx_codeobj__32;
-static PyObject *__pyx_codeobj__34;
-static PyObject *__pyx_codeobj__36;
-static PyObject *__pyx_codeobj__38;
-static PyObject *__pyx_codeobj__40;
-static PyObject *__pyx_codeobj__42;
-static PyObject *__pyx_codeobj__44;
-static PyObject *__pyx_codeobj__46;
-static PyObject *__pyx_codeobj__48;
-static PyObject *__pyx_codeobj__50;
-static PyObject *__pyx_codeobj__52;
-static PyObject *__pyx_codeobj__54;
-static PyObject *__pyx_codeobj__56;
-static PyObject *__pyx_codeobj__58;
-static PyObject *__pyx_codeobj__60;
+static PyObject *__pyx_codeobj__31;
+static PyObject *__pyx_codeobj__33;
+static PyObject *__pyx_codeobj__35;
+static PyObject *__pyx_codeobj__37;
+static PyObject *__pyx_codeobj__39;
+static PyObject *__pyx_codeobj__41;
+static PyObject *__pyx_codeobj__43;
+static PyObject *__pyx_codeobj__45;
+static PyObject *__pyx_codeobj__47;
+static PyObject *__pyx_codeobj__49;
+static PyObject *__pyx_codeobj__51;
+static PyObject *__pyx_codeobj__53;
+static PyObject *__pyx_codeobj__55;
 /* Late includes */
 
 /* "vidcutter/libs/pympv/mpv.pyx":55
@@ -2987,7 +2958,7 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_2_strenc(CYTHON_UNUSED PyObject
  *         # In python2, assume bytes and walk right through
  *         return s             # <<<<<<<<<<<<<<
  * 
- * PyEval_InitThreads()
+ * Py_Initialize()
  */
       __Pyx_XDECREF(__pyx_r);
       __Pyx_INCREF(__pyx_v_s);
@@ -3616,15 +3587,15 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_16EndOfFileReached_2__setstate_c
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":176
- *     cdef public object arg0, type
+/* "vidcutter/libs/pympv/mpv.pyx":189
+ *     cdef public object prefix, level, text, log_level
  * 
- *     cdef _init(self, mpv_event_script_input_dispatch* input):             # <<<<<<<<<<<<<<
- *         self.arg0 = input.arg0
- *         self.type = _strdec(input.type)
+ *     cdef _init(self, mpv_event_log_message* msg):             # <<<<<<<<<<<<<<
+ *         self.level = _strdec(msg.level)
+ *         self.prefix = _strdec(msg.prefix)
  */
 
-static PyObject *__pyx_f_9vidcutter_4libs_3mpv_13InputDispatch__init(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self, struct mpv_event_script_input_dispatch *__pyx_v_input) {
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv_10LogMessage__init(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, struct mpv_event_log_message *__pyx_v_msg) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -3636,31 +3607,82 @@ static PyObject *__pyx_f_9vidcutter_4libs_3mpv_13InputDispatch__init(struct __py
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("_init", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":177
+  /* "vidcutter/libs/pympv/mpv.pyx":190
  * 
- *     cdef _init(self, mpv_event_script_input_dispatch* input):
- *         self.arg0 = input.arg0             # <<<<<<<<<<<<<<
- *         self.type = _strdec(input.type)
- *         return self
+ *     cdef _init(self, mpv_event_log_message* msg):
+ *         self.level = _strdec(msg.level)             # <<<<<<<<<<<<<<
+ *         self.prefix = _strdec(msg.prefix)
+ *         self.text = _strdec(msg.text)
+ */
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 190, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_msg->level); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 190, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_4)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_4);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 190, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->level);
+  __Pyx_DECREF(__pyx_v_self->level);
+  __pyx_v_self->level = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":191
+ *     cdef _init(self, mpv_event_log_message* msg):
+ *         self.level = _strdec(msg.level)
+ *         self.prefix = _strdec(msg.prefix)             # <<<<<<<<<<<<<<
+ *         self.text = _strdec(msg.text)
+ *         self.log_level = msg.log_level
  */
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_input->arg0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 177, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 191, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_msg->prefix); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 191, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_4)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_4);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 191, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->arg0);
-  __Pyx_DECREF(__pyx_v_self->arg0);
-  __pyx_v_self->arg0 = __pyx_t_1;
+  __Pyx_GOTREF(__pyx_v_self->prefix);
+  __Pyx_DECREF(__pyx_v_self->prefix);
+  __pyx_v_self->prefix = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":178
- *     cdef _init(self, mpv_event_script_input_dispatch* input):
- *         self.arg0 = input.arg0
- *         self.type = _strdec(input.type)             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":192
+ *         self.level = _strdec(msg.level)
+ *         self.prefix = _strdec(msg.prefix)
+ *         self.text = _strdec(msg.text)             # <<<<<<<<<<<<<<
+ *         self.log_level = msg.log_level
  *         return self
- * 
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 178, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 192, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_input->type); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 178, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_msg->text); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 192, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
@@ -3675,18 +3697,33 @@ static PyObject *__pyx_f_9vidcutter_4libs_3mpv_13InputDispatch__init(struct __py
   __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 178, __pyx_L1_error)
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 192, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->type);
-  __Pyx_DECREF(__pyx_v_self->type);
-  __pyx_v_self->type = __pyx_t_1;
+  __Pyx_GOTREF(__pyx_v_self->text);
+  __Pyx_DECREF(__pyx_v_self->text);
+  __pyx_v_self->text = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":193
+ *         self.prefix = _strdec(msg.prefix)
+ *         self.text = _strdec(msg.text)
+ *         self.log_level = msg.log_level             # <<<<<<<<<<<<<<
+ *         return self
+ * 
+ */
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_msg->log_level); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 193, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->log_level);
+  __Pyx_DECREF(__pyx_v_self->log_level);
+  __pyx_v_self->log_level = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":179
- *         self.arg0 = input.arg0
- *         self.type = _strdec(input.type)
+  /* "vidcutter/libs/pympv/mpv.pyx":194
+ *         self.text = _strdec(msg.text)
+ *         self.log_level = msg.log_level
  *         return self             # <<<<<<<<<<<<<<
  * 
  * 
@@ -3696,12 +3733,12 @@ static PyObject *__pyx_f_9vidcutter_4libs_3mpv_13InputDispatch__init(struct __py
   __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":176
- *     cdef public object arg0, type
+  /* "vidcutter/libs/pympv/mpv.pyx":189
+ *     cdef public object prefix, level, text, log_level
  * 
- *     cdef _init(self, mpv_event_script_input_dispatch* input):             # <<<<<<<<<<<<<<
- *         self.arg0 = input.arg0
- *         self.type = _strdec(input.type)
+ *     cdef _init(self, mpv_event_log_message* msg):             # <<<<<<<<<<<<<<
+ *         self.level = _strdec(msg.level)
+ *         self.prefix = _strdec(msg.prefix)
  */
 
   /* function exit code */
@@ -3710,7 +3747,7 @@ static PyObject *__pyx_f_9vidcutter_4libs_3mpv_13InputDispatch__init(struct __py
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.InputDispatch._init", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.LogMessage._init", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
@@ -3718,34 +3755,34 @@ static PyObject *__pyx_f_9vidcutter_4libs_3mpv_13InputDispatch__init(struct __py
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":174
- *     Wraps: mpv_event_script_input_dispatch
+/* "vidcutter/libs/pympv/mpv.pyx":187
+ *     Wraps: mpv_event_log_message
  *     """
- *     cdef public object arg0, type             # <<<<<<<<<<<<<<
+ *     cdef public object prefix, level, text, log_level             # <<<<<<<<<<<<<<
  * 
- *     cdef _init(self, mpv_event_script_input_dispatch* input):
+ *     cdef _init(self, mpv_event_log_message* msg):
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_1__get__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_1__get__(PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__get__", 0);
   __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->arg0);
-  __pyx_r = __pyx_v_self->arg0;
+  __Pyx_INCREF(__pyx_v_self->prefix);
+  __pyx_r = __pyx_v_self->prefix;
   goto __pyx_L0;
 
   /* function exit code */
@@ -3756,27 +3793,27 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0___get__(st
 }
 
 /* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self), ((PyObject *)__pyx_v_value));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self, PyObject *__pyx_v_value) {
+static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v_value) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__", 0);
   __Pyx_INCREF(__pyx_v_value);
   __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->arg0);
-  __Pyx_DECREF(__pyx_v_self->arg0);
-  __pyx_v_self->arg0 = __pyx_v_value;
+  __Pyx_GOTREF(__pyx_v_self->prefix);
+  __Pyx_DECREF(__pyx_v_self->prefix);
+  __pyx_v_self->prefix = __pyx_v_value;
 
   /* function exit code */
   __pyx_r = 0;
@@ -3785,27 +3822,27 @@ static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_2__set__(struct
 }
 
 /* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_5__del__(PyObject *__pyx_v_self) {
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_5__del__(PyObject *__pyx_v_self); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_5__del__(PyObject *__pyx_v_self) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self) {
+static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__del__", 0);
   __Pyx_INCREF(Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->arg0);
-  __Pyx_DECREF(__pyx_v_self->arg0);
-  __pyx_v_self->arg0 = Py_None;
+  __Pyx_GOTREF(__pyx_v_self->prefix);
+  __Pyx_DECREF(__pyx_v_self->prefix);
+  __pyx_v_self->prefix = Py_None;
 
   /* function exit code */
   __pyx_r = 0;
@@ -3814,25 +3851,25 @@ static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4arg0_4__del__(struct
 }
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4type_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4type_1__get__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_1__get__(PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__get__", 0);
   __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->type);
-  __pyx_r = __pyx_v_self->type;
+  __Pyx_INCREF(__pyx_v_self->level);
+  __pyx_r = __pyx_v_self->level;
   goto __pyx_L0;
 
   /* function exit code */
@@ -3843,27 +3880,27 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type___get__(st
 }
 
 /* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4type_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4type_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self), ((PyObject *)__pyx_v_value));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self, PyObject *__pyx_v_value) {
+static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v_value) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__set__", 0);
   __Pyx_INCREF(__pyx_v_value);
   __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->type);
-  __Pyx_DECREF(__pyx_v_self->type);
-  __pyx_v_self->type = __pyx_v_value;
+  __Pyx_GOTREF(__pyx_v_self->level);
+  __Pyx_DECREF(__pyx_v_self->level);
+  __pyx_v_self->level = __pyx_v_value;
 
   /* function exit code */
   __pyx_r = 0;
@@ -3872,27 +3909,27 @@ static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type_2__set__(struct
 }
 
 /* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4type_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_4type_5__del__(PyObject *__pyx_v_self) {
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_5__del__(PyObject *__pyx_v_self); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_5__del__(PyObject *__pyx_v_self) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self) {
+static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__del__", 0);
   __Pyx_INCREF(Py_None);
   __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->type);
-  __Pyx_DECREF(__pyx_v_self->type);
-  __pyx_v_self->type = Py_None;
+  __Pyx_GOTREF(__pyx_v_self->level);
+  __Pyx_DECREF(__pyx_v_self->level);
+  __pyx_v_self->level = Py_None;
 
   /* function exit code */
   __pyx_r = 0;
@@ -3900,63 +3937,243 @@ static int __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_4type_4__del__(struct
   return __pyx_r;
 }
 
-/* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     cdef tuple state
- *     cdef object _dict
- */
-
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_1__get__(PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch___reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch___reduce_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self) {
-  PyObject *__pyx_v_state = 0;
-  PyObject *__pyx_v__dict = 0;
-  int __pyx_v_use_setstate;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  int __pyx_t_2;
-  int __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  int __pyx_t_5;
-  PyObject *__pyx_t_6 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_self->text);
+  __pyx_r = __pyx_v_self->text;
+  goto __pyx_L0;
 
-  /* "(tree fragment)":5
- *     cdef object _dict
- *     cdef bint use_setstate
- *     state = (self.arg0, self.type)             # <<<<<<<<<<<<<<
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:
- */
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_v_self->arg0);
-  __Pyx_GIVEREF(__pyx_v_self->arg0);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->arg0);
-  __Pyx_INCREF(__pyx_v_self->type);
-  __Pyx_GIVEREF(__pyx_v_self->type);
-  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_self->type);
+  /* function exit code */
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__", 0);
+  __Pyx_INCREF(__pyx_v_value);
+  __Pyx_GIVEREF(__pyx_v_value);
+  __Pyx_GOTREF(__pyx_v_self->text);
+  __Pyx_DECREF(__pyx_v_self->text);
+  __pyx_v_self->text = __pyx_v_value;
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_5__del__(PyObject *__pyx_v_self); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_5__del__(PyObject *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__", 0);
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->text);
+  __Pyx_DECREF(__pyx_v_self->text);
+  __pyx_v_self->text = Py_None;
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_self->log_level);
+  __pyx_r = __pyx_v_self->log_level;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__", 0);
+  __Pyx_INCREF(__pyx_v_value);
+  __Pyx_GIVEREF(__pyx_v_value);
+  __Pyx_GOTREF(__pyx_v_self->log_level);
+  __Pyx_DECREF(__pyx_v_self->log_level);
+  __pyx_v_self->log_level = __pyx_v_value;
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_5__del__(PyObject *__pyx_v_self); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_5__del__(PyObject *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__", 0);
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->log_level);
+  __Pyx_DECREF(__pyx_v_self->log_level);
+  __pyx_v_self->log_level = Py_None;
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "(tree fragment)":1
+ * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
+ *     cdef tuple state
+ *     cdef object _dict
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage___reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage___reduce_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
+  PyObject *__pyx_v_state = 0;
+  PyObject *__pyx_v__dict = 0;
+  int __pyx_v_use_setstate;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_t_5;
+  PyObject *__pyx_t_6 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
+
+  /* "(tree fragment)":5
+ *     cdef object _dict
+ *     cdef bint use_setstate
+ *     state = (self.level, self.log_level, self.prefix, self.text)             # <<<<<<<<<<<<<<
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:
+ */
+  __pyx_t_1 = PyTuple_New(4); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_v_self->level);
+  __Pyx_GIVEREF(__pyx_v_self->level);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->level);
+  __Pyx_INCREF(__pyx_v_self->log_level);
+  __Pyx_GIVEREF(__pyx_v_self->log_level);
+  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_self->log_level);
+  __Pyx_INCREF(__pyx_v_self->prefix);
+  __Pyx_GIVEREF(__pyx_v_self->prefix);
+  PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_self->prefix);
+  __Pyx_INCREF(__pyx_v_self->text);
+  __Pyx_GIVEREF(__pyx_v_self->text);
+  PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_self->text);
   __pyx_v_state = ((PyObject*)__pyx_t_1);
   __pyx_t_1 = 0;
 
   /* "(tree fragment)":6
  *     cdef bint use_setstate
- *     state = (self.arg0, self.type)
+ *     state = (self.level, self.log_level, self.prefix, self.text)
  *     _dict = getattr(self, '__dict__', None)             # <<<<<<<<<<<<<<
  *     if _dict is not None:
  *         state += (_dict,)
@@ -3967,7 +4184,7 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch___reduce_cython_
   __pyx_t_1 = 0;
 
   /* "(tree fragment)":7
- *     state = (self.arg0, self.type)
+ *     state = (self.level, self.log_level, self.prefix, self.text)
  *     _dict = getattr(self, '__dict__', None)
  *     if _dict is not None:             # <<<<<<<<<<<<<<
  *         state += (_dict,)
@@ -4000,12 +4217,12 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch___reduce_cython_
  *         state += (_dict,)
  *         use_setstate = True             # <<<<<<<<<<<<<<
  *     else:
- *         use_setstate = self.arg0 is not None or self.type is not None
+ *         use_setstate = self.level is not None or self.log_level is not None or self.prefix is not None or self.text is not None
  */
     __pyx_v_use_setstate = 1;
 
     /* "(tree fragment)":7
- *     state = (self.arg0, self.type)
+ *     state = (self.level, self.log_level, self.prefix, self.text)
  *     _dict = getattr(self, '__dict__', None)
  *     if _dict is not None:             # <<<<<<<<<<<<<<
  *         state += (_dict,)
@@ -4017,19 +4234,33 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch___reduce_cython_
   /* "(tree fragment)":11
  *         use_setstate = True
  *     else:
- *         use_setstate = self.arg0 is not None or self.type is not None             # <<<<<<<<<<<<<<
+ *         use_setstate = self.level is not None or self.log_level is not None or self.prefix is not None or self.text is not None             # <<<<<<<<<<<<<<
  *     if use_setstate:
- *         return __pyx_unpickle_InputDispatch, (type(self), 0xbf641a9, None), state
+ *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, None), state
  */
   /*else*/ {
-    __pyx_t_2 = (__pyx_v_self->arg0 != Py_None);
+    __pyx_t_2 = (__pyx_v_self->level != Py_None);
+    __pyx_t_5 = (__pyx_t_2 != 0);
+    if (!__pyx_t_5) {
+    } else {
+      __pyx_t_3 = __pyx_t_5;
+      goto __pyx_L4_bool_binop_done;
+    }
+    __pyx_t_5 = (__pyx_v_self->log_level != Py_None);
+    __pyx_t_2 = (__pyx_t_5 != 0);
+    if (!__pyx_t_2) {
+    } else {
+      __pyx_t_3 = __pyx_t_2;
+      goto __pyx_L4_bool_binop_done;
+    }
+    __pyx_t_2 = (__pyx_v_self->prefix != Py_None);
     __pyx_t_5 = (__pyx_t_2 != 0);
     if (!__pyx_t_5) {
     } else {
       __pyx_t_3 = __pyx_t_5;
       goto __pyx_L4_bool_binop_done;
     }
-    __pyx_t_5 = (__pyx_v_self->type != Py_None);
+    __pyx_t_5 = (__pyx_v_self->text != Py_None);
     __pyx_t_2 = (__pyx_t_5 != 0);
     __pyx_t_3 = __pyx_t_2;
     __pyx_L4_bool_binop_done:;
@@ -4039,32 +4270,32 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch___reduce_cython_
 
   /* "(tree fragment)":12
  *     else:
- *         use_setstate = self.arg0 is not None or self.type is not None
+ *         use_setstate = self.level is not None or self.log_level is not None or self.prefix is not None or self.text is not None
  *     if use_setstate:             # <<<<<<<<<<<<<<
- *         return __pyx_unpickle_InputDispatch, (type(self), 0xbf641a9, None), state
+ *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, None), state
  *     else:
  */
   __pyx_t_3 = (__pyx_v_use_setstate != 0);
   if (__pyx_t_3) {
 
     /* "(tree fragment)":13
- *         use_setstate = self.arg0 is not None or self.type is not None
+ *         use_setstate = self.level is not None or self.log_level is not None or self.prefix is not None or self.text is not None
  *     if use_setstate:
- *         return __pyx_unpickle_InputDispatch, (type(self), 0xbf641a9, None), state             # <<<<<<<<<<<<<<
+ *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, None), state             # <<<<<<<<<<<<<<
  *     else:
- *         return __pyx_unpickle_InputDispatch, (type(self), 0xbf641a9, state)
+ *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, state)
  */
     __Pyx_XDECREF(__pyx_r);
-    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_InputDispatch); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 13, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_LogMessage); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 13, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
     __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
     __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
     PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_INCREF(__pyx_int_200688041);
-    __Pyx_GIVEREF(__pyx_int_200688041);
-    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_200688041);
+    __Pyx_INCREF(__pyx_int_142036910);
+    __Pyx_GIVEREF(__pyx_int_142036910);
+    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_142036910);
     __Pyx_INCREF(Py_None);
     __Pyx_GIVEREF(Py_None);
     PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None);
@@ -4085,32 +4316,32 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch___reduce_cython_
 
     /* "(tree fragment)":12
  *     else:
- *         use_setstate = self.arg0 is not None or self.type is not None
+ *         use_setstate = self.level is not None or self.log_level is not None or self.prefix is not None or self.text is not None
  *     if use_setstate:             # <<<<<<<<<<<<<<
- *         return __pyx_unpickle_InputDispatch, (type(self), 0xbf641a9, None), state
+ *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, None), state
  *     else:
  */
   }
 
   /* "(tree fragment)":15
- *         return __pyx_unpickle_InputDispatch, (type(self), 0xbf641a9, None), state
+ *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, None), state
  *     else:
- *         return __pyx_unpickle_InputDispatch, (type(self), 0xbf641a9, state)             # <<<<<<<<<<<<<<
+ *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, state)             # <<<<<<<<<<<<<<
  * def __setstate_cython__(self, __pyx_state):
- *     __pyx_unpickle_InputDispatch__set_state(self, __pyx_state)
+ *     __pyx_unpickle_LogMessage__set_state(self, __pyx_state)
  */
   /*else*/ {
     __Pyx_XDECREF(__pyx_r);
-    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pyx_unpickle_InputDispatch); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 15, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pyx_unpickle_LogMessage); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 15, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_6);
     __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
     __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
     __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
     PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_INCREF(__pyx_int_200688041);
-    __Pyx_GIVEREF(__pyx_int_200688041);
-    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_200688041);
+    __Pyx_INCREF(__pyx_int_142036910);
+    __Pyx_GIVEREF(__pyx_int_142036910);
+    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_142036910);
     __Pyx_INCREF(__pyx_v_state);
     __Pyx_GIVEREF(__pyx_v_state);
     PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state);
@@ -4138,7 +4369,7 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch___reduce_cython_
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.InputDispatch.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.LogMessage.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XDECREF(__pyx_v_state);
@@ -4150,25 +4381,25 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch___reduce_cython_
 
 /* "(tree fragment)":16
  *     else:
- *         return __pyx_unpickle_InputDispatch, (type(self), 0xbf641a9, state)
+ *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, state)
  * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     __pyx_unpickle_InputDispatch__set_state(self, __pyx_state)
+ *     __pyx_unpickle_LogMessage__set_state(self, __pyx_state)
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13InputDispatch_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_2__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_2__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_2__setstate_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_2__setstate_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -4178,20 +4409,20 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_2__setstate_cyth
   __Pyx_RefNannySetupContext("__setstate_cython__", 0);
 
   /* "(tree fragment)":17
- *         return __pyx_unpickle_InputDispatch, (type(self), 0xbf641a9, state)
+ *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, state)
  * def __setstate_cython__(self, __pyx_state):
- *     __pyx_unpickle_InputDispatch__set_state(self, __pyx_state)             # <<<<<<<<<<<<<<
+ *     __pyx_unpickle_LogMessage__set_state(self, __pyx_state)             # <<<<<<<<<<<<<<
  */
   if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error)
-  __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_InputDispatch__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_LogMessage__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
   /* "(tree fragment)":16
  *     else:
- *         return __pyx_unpickle_InputDispatch, (type(self), 0xbf641a9, state)
+ *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, state)
  * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     __pyx_unpickle_InputDispatch__set_state(self, __pyx_state)
+ *     __pyx_unpickle_LogMessage__set_state(self, __pyx_state)
  */
 
   /* function exit code */
@@ -4199,7 +4430,7 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_2__setstate_cyth
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.InputDispatch.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.LogMessage.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
@@ -4207,1494 +4438,1687 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13InputDispatch_2__setstate_cyth
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":189
- *     cdef public object prefix, level, text, log_level
+/* "vidcutter/libs/pympv/mpv.pyx":197
  * 
- *     cdef _init(self, mpv_event_log_message* msg):             # <<<<<<<<<<<<<<
- *         self.level = _strdec(msg.level)
- *         self.prefix = _strdec(msg.prefix)
+ * 
+ * cdef _convert_node_value(mpv_node node):             # <<<<<<<<<<<<<<
+ *     if node.format == MPV_FORMAT_STRING:
+ *         return _strdec(node.u.string)
  */
 
-static PyObject *__pyx_f_9vidcutter_4libs_3mpv_10LogMessage__init(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, struct mpv_event_log_message *__pyx_v_msg) {
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv__convert_node_value(struct mpv_node __pyx_v_node) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
+  int __pyx_t_5;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_init", 0);
+  __Pyx_RefNannySetupContext("_convert_node_value", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":190
+  /* "vidcutter/libs/pympv/mpv.pyx":198
  * 
- *     cdef _init(self, mpv_event_log_message* msg):
- *         self.level = _strdec(msg.level)             # <<<<<<<<<<<<<<
- *         self.prefix = _strdec(msg.prefix)
- *         self.text = _strdec(msg.text)
- */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 190, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_msg->level); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 190, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 190, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->level);
-  __Pyx_DECREF(__pyx_v_self->level);
-  __pyx_v_self->level = __pyx_t_1;
-  __pyx_t_1 = 0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":191
- *     cdef _init(self, mpv_event_log_message* msg):
- *         self.level = _strdec(msg.level)
- *         self.prefix = _strdec(msg.prefix)             # <<<<<<<<<<<<<<
- *         self.text = _strdec(msg.text)
- *         self.log_level = msg.log_level
+ * cdef _convert_node_value(mpv_node node):
+ *     if node.format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
+ *         return _strdec(node.u.string)
+ *     elif node.format == MPV_FORMAT_FLAG:
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 191, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_msg->prefix); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 191, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 191, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->prefix);
-  __Pyx_DECREF(__pyx_v_self->prefix);
-  __pyx_v_self->prefix = __pyx_t_1;
-  __pyx_t_1 = 0;
+  switch (__pyx_v_node.format) {
+    case MPV_FORMAT_STRING:
 
-  /* "vidcutter/libs/pympv/mpv.pyx":192
- *         self.level = _strdec(msg.level)
- *         self.prefix = _strdec(msg.prefix)
- *         self.text = _strdec(msg.text)             # <<<<<<<<<<<<<<
- *         self.log_level = msg.log_level
- *         return self
+    /* "vidcutter/libs/pympv/mpv.pyx":199
+ * cdef _convert_node_value(mpv_node node):
+ *     if node.format == MPV_FORMAT_STRING:
+ *         return _strdec(node.u.string)             # <<<<<<<<<<<<<<
+ *     elif node.format == MPV_FORMAT_FLAG:
+ *         return not not int(node.u.flag)
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 192, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_msg->text); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 192, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
+    __Pyx_XDECREF(__pyx_r);
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 199, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_node.u.string); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 199, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
     }
-  }
-  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 192, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->text);
-  __Pyx_DECREF(__pyx_v_self->text);
-  __pyx_v_self->text = __pyx_t_1;
-  __pyx_t_1 = 0;
+    __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 199, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_r = __pyx_t_1;
+    __pyx_t_1 = 0;
+    goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":193
- *         self.prefix = _strdec(msg.prefix)
- *         self.text = _strdec(msg.text)
- *         self.log_level = msg.log_level             # <<<<<<<<<<<<<<
- *         return self
+    /* "vidcutter/libs/pympv/mpv.pyx":198
  * 
+ * cdef _convert_node_value(mpv_node node):
+ *     if node.format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
+ *         return _strdec(node.u.string)
+ *     elif node.format == MPV_FORMAT_FLAG:
  */
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_msg->log_level); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 193, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->log_level);
-  __Pyx_DECREF(__pyx_v_self->log_level);
-  __pyx_v_self->log_level = __pyx_t_1;
-  __pyx_t_1 = 0;
+    break;
+    case MPV_FORMAT_FLAG:
 
-  /* "vidcutter/libs/pympv/mpv.pyx":194
- *         self.text = _strdec(msg.text)
- *         self.log_level = msg.log_level
- *         return self             # <<<<<<<<<<<<<<
- * 
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":201
+ *         return _strdec(node.u.string)
+ *     elif node.format == MPV_FORMAT_FLAG:
+ *         return not not int(node.u.flag)             # <<<<<<<<<<<<<<
+ *     elif node.format == MPV_FORMAT_INT64:
+ *         return int(node.u.int64)
  */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(((PyObject *)__pyx_v_self));
-  __pyx_r = ((PyObject *)__pyx_v_self);
-  goto __pyx_L0;
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_node.u.flag); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 201, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_2 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyInt_Type)), __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 201, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 201, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_t_2 = __Pyx_PyBool_FromLong((!((!__pyx_t_5) != 0))); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 201, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_r = __pyx_t_2;
+    __pyx_t_2 = 0;
+    goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":189
- *     cdef public object prefix, level, text, log_level
- * 
- *     cdef _init(self, mpv_event_log_message* msg):             # <<<<<<<<<<<<<<
- *         self.level = _strdec(msg.level)
- *         self.prefix = _strdec(msg.prefix)
+    /* "vidcutter/libs/pympv/mpv.pyx":200
+ *     if node.format == MPV_FORMAT_STRING:
+ *         return _strdec(node.u.string)
+ *     elif node.format == MPV_FORMAT_FLAG:             # <<<<<<<<<<<<<<
+ *         return not not int(node.u.flag)
+ *     elif node.format == MPV_FORMAT_INT64:
  */
+    break;
+    case MPV_FORMAT_INT64:
 
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.LogMessage._init", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":203
+ *         return not not int(node.u.flag)
+ *     elif node.format == MPV_FORMAT_INT64:
+ *         return int(node.u.int64)             # <<<<<<<<<<<<<<
+ *     elif node.format == MPV_FORMAT_DOUBLE:
+ *         return float(node.u.double_)
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_v_node.u.int64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 203, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_1 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyInt_Type)), __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 203, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_r = __pyx_t_1;
+    __pyx_t_1 = 0;
+    goto __pyx_L0;
 
-/* "vidcutter/libs/pympv/mpv.pyx":187
- *     Wraps: mpv_event_log_message
- *     """
- *     cdef public object prefix, level, text, log_level             # <<<<<<<<<<<<<<
- * 
- *     cdef _init(self, mpv_event_log_message* msg):
+    /* "vidcutter/libs/pympv/mpv.pyx":202
+ *     elif node.format == MPV_FORMAT_FLAG:
+ *         return not not int(node.u.flag)
+ *     elif node.format == MPV_FORMAT_INT64:             # <<<<<<<<<<<<<<
+ *         return int(node.u.int64)
+ *     elif node.format == MPV_FORMAT_DOUBLE:
  */
+    break;
+    case MPV_FORMAT_DOUBLE:
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__", 0);
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->prefix);
-  __pyx_r = __pyx_v_self->prefix;
-  goto __pyx_L0;
-
-  /* function exit code */
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":205
+ *         return int(node.u.int64)
+ *     elif node.format == MPV_FORMAT_DOUBLE:
+ *         return float(node.u.double_)             # <<<<<<<<<<<<<<
+ *     elif node.format == MPV_FORMAT_NODE_MAP:
+ *         return _convert_value(node.u.list, node.format)
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_1 = PyFloat_FromDouble(__pyx_v_node.u.double_); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 205, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_r = __pyx_t_1;
+    __pyx_t_1 = 0;
+    goto __pyx_L0;
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+    /* "vidcutter/libs/pympv/mpv.pyx":204
+ *     elif node.format == MPV_FORMAT_INT64:
+ *         return int(node.u.int64)
+ *     elif node.format == MPV_FORMAT_DOUBLE:             # <<<<<<<<<<<<<<
+ *         return float(node.u.double_)
+ *     elif node.format == MPV_FORMAT_NODE_MAP:
+ */
+    break;
+    case MPV_FORMAT_NODE_MAP:
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":207
+ *         return float(node.u.double_)
+ *     elif node.format == MPV_FORMAT_NODE_MAP:
+ *         return _convert_value(node.u.list, node.format)             # <<<<<<<<<<<<<<
+ *     elif node.format == MPV_FORMAT_NODE_ARRAY:
+ *         return _convert_value(node.u.list, node.format)
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_value(__pyx_v_node.u.list, __pyx_v_node.format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 207, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_r = __pyx_t_1;
+    __pyx_t_1 = 0;
+    goto __pyx_L0;
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __Pyx_INCREF(__pyx_v_value);
-  __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->prefix);
-  __Pyx_DECREF(__pyx_v_self->prefix);
-  __pyx_v_self->prefix = __pyx_v_value;
+    /* "vidcutter/libs/pympv/mpv.pyx":206
+ *     elif node.format == MPV_FORMAT_DOUBLE:
+ *         return float(node.u.double_)
+ *     elif node.format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
+ *         return _convert_value(node.u.list, node.format)
+ *     elif node.format == MPV_FORMAT_NODE_ARRAY:
+ */
+    break;
+    case MPV_FORMAT_NODE_ARRAY:
 
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":209
+ *         return _convert_value(node.u.list, node.format)
+ *     elif node.format == MPV_FORMAT_NODE_ARRAY:
+ *         return _convert_value(node.u.list, node.format)             # <<<<<<<<<<<<<<
+ *     return None
+ * 
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_value(__pyx_v_node.u.list, __pyx_v_node.format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 209, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_r = __pyx_t_1;
+    __pyx_t_1 = 0;
+    goto __pyx_L0;
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_6prefix_5__del__(PyObject *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
+    /* "vidcutter/libs/pympv/mpv.pyx":208
+ *     elif node.format == MPV_FORMAT_NODE_MAP:
+ *         return _convert_value(node.u.list, node.format)
+ *     elif node.format == MPV_FORMAT_NODE_ARRAY:             # <<<<<<<<<<<<<<
+ *         return _convert_value(node.u.list, node.format)
+ *     return None
+ */
+    break;
+    default: break;
+  }
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  /* "vidcutter/libs/pympv/mpv.pyx":210
+ *     elif node.format == MPV_FORMAT_NODE_ARRAY:
+ *         return _convert_value(node.u.list, node.format)
+ *     return None             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_6prefix_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__", 0);
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->prefix);
-  __Pyx_DECREF(__pyx_v_self->prefix);
-  __pyx_v_self->prefix = Py_None;
+  /* "vidcutter/libs/pympv/mpv.pyx":197
+ * 
+ * 
+ * cdef _convert_node_value(mpv_node node):             # <<<<<<<<<<<<<<
+ *     if node.format == MPV_FORMAT_STRING:
+ *         return _strdec(node.u.string)
+ */
 
   /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._convert_node_value", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+/* "vidcutter/libs/pympv/mpv.pyx":213
+ * 
+ * 
+ * cdef _convert_value(void* data, mpv_format format):             # <<<<<<<<<<<<<<
+ *     cdef mpv_node node
+ *     cdef mpv_node_list nodelist
+ */
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv__convert_value(void *__pyx_v_data, enum mpv_format __pyx_v_format) {
+  struct mpv_node __pyx_v_node;
+  struct mpv_node_list __pyx_v_nodelist;
+  PyObject *__pyx_v_values = NULL;
+  int __pyx_v_i;
+  PyObject *__pyx_v_value = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__", 0);
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->level);
-  __pyx_r = __pyx_v_self->level;
-  goto __pyx_L0;
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_t_3;
+  int __pyx_t_4;
+  int __pyx_t_5;
+  PyObject *__pyx_t_6 = NULL;
+  PyObject *__pyx_t_7 = NULL;
+  PyObject *__pyx_t_8 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("_convert_value", 0);
 
-  /* function exit code */
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  /* "vidcutter/libs/pympv/mpv.pyx":216
+ *     cdef mpv_node node
+ *     cdef mpv_node_list nodelist
+ *     if format == MPV_FORMAT_NODE:             # <<<<<<<<<<<<<<
+ *         node = (<mpv_node*>data)[0]
+ *         return _convert_node_value(node)
+ */
+  switch (__pyx_v_format) {
+    case MPV_FORMAT_NODE:
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+    /* "vidcutter/libs/pympv/mpv.pyx":217
+ *     cdef mpv_node_list nodelist
+ *     if format == MPV_FORMAT_NODE:
+ *         node = (<mpv_node*>data)[0]             # <<<<<<<<<<<<<<
+ *         return _convert_node_value(node)
+ *     elif format == MPV_FORMAT_NODE_ARRAY:
+ */
+    __pyx_v_node = (((struct mpv_node *)__pyx_v_data)[0]);
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":218
+ *     if format == MPV_FORMAT_NODE:
+ *         node = (<mpv_node*>data)[0]
+ *         return _convert_node_value(node)             # <<<<<<<<<<<<<<
+ *     elif format == MPV_FORMAT_NODE_ARRAY:
+ *         nodelist = (<mpv_node_list*>data)[0]
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_node_value(__pyx_v_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 218, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_r = __pyx_t_1;
+    __pyx_t_1 = 0;
+    goto __pyx_L0;
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __Pyx_INCREF(__pyx_v_value);
-  __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->level);
-  __Pyx_DECREF(__pyx_v_self->level);
-  __pyx_v_self->level = __pyx_v_value;
+    /* "vidcutter/libs/pympv/mpv.pyx":216
+ *     cdef mpv_node node
+ *     cdef mpv_node_list nodelist
+ *     if format == MPV_FORMAT_NODE:             # <<<<<<<<<<<<<<
+ *         node = (<mpv_node*>data)[0]
+ *         return _convert_node_value(node)
+ */
+    break;
+    case MPV_FORMAT_NODE_ARRAY:
 
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":220
+ *         return _convert_node_value(node)
+ *     elif format == MPV_FORMAT_NODE_ARRAY:
+ *         nodelist = (<mpv_node_list*>data)[0]             # <<<<<<<<<<<<<<
+ *         values = []
+ *         for i in range(nodelist.num):
+ */
+    __pyx_v_nodelist = (((struct mpv_node_list *)__pyx_v_data)[0]);
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_5level_5__del__(PyObject *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
+    /* "vidcutter/libs/pympv/mpv.pyx":221
+ *     elif format == MPV_FORMAT_NODE_ARRAY:
+ *         nodelist = (<mpv_node_list*>data)[0]
+ *         values = []             # <<<<<<<<<<<<<<
+ *         for i in range(nodelist.num):
+ *             values.append(_convert_node_value(nodelist.values[i]))
+ */
+    __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 221, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_v_values = __pyx_t_1;
+    __pyx_t_1 = 0;
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":222
+ *         nodelist = (<mpv_node_list*>data)[0]
+ *         values = []
+ *         for i in range(nodelist.num):             # <<<<<<<<<<<<<<
+ *             values.append(_convert_node_value(nodelist.values[i]))
+ *         return values
+ */
+    __pyx_t_2 = __pyx_v_nodelist.num;
+    __pyx_t_3 = __pyx_t_2;
+    for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
+      __pyx_v_i = __pyx_t_4;
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_5level_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__", 0);
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->level);
-  __Pyx_DECREF(__pyx_v_self->level);
-  __pyx_v_self->level = Py_None;
+      /* "vidcutter/libs/pympv/mpv.pyx":223
+ *         values = []
+ *         for i in range(nodelist.num):
+ *             values.append(_convert_node_value(nodelist.values[i]))             # <<<<<<<<<<<<<<
+ *         return values
+ *     elif format == MPV_FORMAT_NODE_MAP:
+ */
+      __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_node_value((__pyx_v_nodelist.values[__pyx_v_i])); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 223, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_t_5 = __Pyx_PyObject_Append(__pyx_v_values, __pyx_t_1); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(0, 223, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    }
 
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":224
+ *         for i in range(nodelist.num):
+ *             values.append(_convert_node_value(nodelist.values[i]))
+ *         return values             # <<<<<<<<<<<<<<
+ *     elif format == MPV_FORMAT_NODE_MAP:
+ *         nodelist = (<mpv_node_list*>data)[0]
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __Pyx_INCREF(__pyx_v_values);
+    __pyx_r = __pyx_v_values;
+    goto __pyx_L0;
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
+    /* "vidcutter/libs/pympv/mpv.pyx":219
+ *         node = (<mpv_node*>data)[0]
+ *         return _convert_node_value(node)
+ *     elif format == MPV_FORMAT_NODE_ARRAY:             # <<<<<<<<<<<<<<
+ *         nodelist = (<mpv_node_list*>data)[0]
+ *         values = []
+ */
+    break;
+    case MPV_FORMAT_NODE_MAP:
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":226
+ *         return values
+ *     elif format == MPV_FORMAT_NODE_MAP:
+ *         nodelist = (<mpv_node_list*>data)[0]             # <<<<<<<<<<<<<<
+ *         values = {}
+ *         for i in range(nodelist.num):
+ */
+    __pyx_v_nodelist = (((struct mpv_node_list *)__pyx_v_data)[0]);
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__", 0);
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->text);
-  __pyx_r = __pyx_v_self->text;
-  goto __pyx_L0;
+    /* "vidcutter/libs/pympv/mpv.pyx":227
+ *     elif format == MPV_FORMAT_NODE_MAP:
+ *         nodelist = (<mpv_node_list*>data)[0]
+ *         values = {}             # <<<<<<<<<<<<<<
+ *         for i in range(nodelist.num):
+ *             value = _convert_node_value(nodelist.values[i])
+ */
+    __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 227, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_v_values = __pyx_t_1;
+    __pyx_t_1 = 0;
 
-  /* function exit code */
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":228
+ *         nodelist = (<mpv_node_list*>data)[0]
+ *         values = {}
+ *         for i in range(nodelist.num):             # <<<<<<<<<<<<<<
+ *             value = _convert_node_value(nodelist.values[i])
+ *             values[_strdec(nodelist.keys[i])] = value
+ */
+    __pyx_t_2 = __pyx_v_nodelist.num;
+    __pyx_t_3 = __pyx_t_2;
+    for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
+      __pyx_v_i = __pyx_t_4;
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+      /* "vidcutter/libs/pympv/mpv.pyx":229
+ *         values = {}
+ *         for i in range(nodelist.num):
+ *             value = _convert_node_value(nodelist.values[i])             # <<<<<<<<<<<<<<
+ *             values[_strdec(nodelist.keys[i])] = value
+ *         return values
+ */
+      __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_node_value((__pyx_v_nodelist.values[__pyx_v_i])); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 229, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_XDECREF_SET(__pyx_v_value, __pyx_t_1);
+      __pyx_t_1 = 0;
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+      /* "vidcutter/libs/pympv/mpv.pyx":230
+ *         for i in range(nodelist.num):
+ *             value = _convert_node_value(nodelist.values[i])
+ *             values[_strdec(nodelist.keys[i])] = value             # <<<<<<<<<<<<<<
+ *         return values
+ *     elif format == MPV_FORMAT_STRING:
+ */
+      __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_strdec); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 230, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_6);
+      __pyx_t_7 = __Pyx_PyBytes_FromString((__pyx_v_nodelist.keys[__pyx_v_i])); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 230, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      __pyx_t_8 = NULL;
+      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) {
+        __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_6);
+        if (likely(__pyx_t_8)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
+          __Pyx_INCREF(__pyx_t_8);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_6, function);
+        }
+      }
+      __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_8, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_7);
+      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 230, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+      if (unlikely(PyObject_SetItem(__pyx_v_values, __pyx_t_1, __pyx_v_value) < 0)) __PYX_ERR(0, 230, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __Pyx_INCREF(__pyx_v_value);
-  __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->text);
-  __Pyx_DECREF(__pyx_v_self->text);
-  __pyx_v_self->text = __pyx_v_value;
+    /* "vidcutter/libs/pympv/mpv.pyx":231
+ *             value = _convert_node_value(nodelist.values[i])
+ *             values[_strdec(nodelist.keys[i])] = value
+ *         return values             # <<<<<<<<<<<<<<
+ *     elif format == MPV_FORMAT_STRING:
+ *         return _strdec(((<char**>data)[0]))
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __Pyx_INCREF(__pyx_v_values);
+    __pyx_r = __pyx_v_values;
+    goto __pyx_L0;
 
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":225
+ *             values.append(_convert_node_value(nodelist.values[i]))
+ *         return values
+ *     elif format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
+ *         nodelist = (<mpv_node_list*>data)[0]
+ *         values = {}
+ */
+    break;
+    case MPV_FORMAT_STRING:
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_4text_5__del__(PyObject *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_4text_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__", 0);
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->text);
-  __Pyx_DECREF(__pyx_v_self->text);
-  __pyx_v_self->text = Py_None;
-
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":233
+ *         return values
+ *     elif format == MPV_FORMAT_STRING:
+ *         return _strdec(((<char**>data)[0]))             # <<<<<<<<<<<<<<
+ *     elif format == MPV_FORMAT_FLAG:
+ *         return not not (<uint64_t*>data)[0]
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_strdec); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 233, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_7 = __Pyx_PyBytes_FromString((((char **)__pyx_v_data)[0])); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 233, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_8 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) {
+      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_6);
+      if (likely(__pyx_t_8)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
+        __Pyx_INCREF(__pyx_t_8);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_6, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_8, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_7);
+    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 233, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __pyx_r = __pyx_t_1;
+    __pyx_t_1 = 0;
+    goto __pyx_L0;
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__", 0);
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->log_level);
-  __pyx_r = __pyx_v_self->log_level;
-  goto __pyx_L0;
+    /* "vidcutter/libs/pympv/mpv.pyx":232
+ *             values[_strdec(nodelist.keys[i])] = value
+ *         return values
+ *     elif format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
+ *         return _strdec(((<char**>data)[0]))
+ *     elif format == MPV_FORMAT_FLAG:
+ */
+    break;
+    case MPV_FORMAT_FLAG:
 
-  /* function exit code */
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":235
+ *         return _strdec(((<char**>data)[0]))
+ *     elif format == MPV_FORMAT_FLAG:
+ *         return not not (<uint64_t*>data)[0]             # <<<<<<<<<<<<<<
+ *     elif format == MPV_FORMAT_INT64:
+ *         return int((<uint64_t*>data)[0])
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_1 = __Pyx_PyBool_FromLong((!((!((((uint64_t *)__pyx_v_data)[0]) != 0)) != 0))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 235, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_r = __pyx_t_1;
+    __pyx_t_1 = 0;
+    goto __pyx_L0;
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+    /* "vidcutter/libs/pympv/mpv.pyx":234
+ *     elif format == MPV_FORMAT_STRING:
+ *         return _strdec(((<char**>data)[0]))
+ *     elif format == MPV_FORMAT_FLAG:             # <<<<<<<<<<<<<<
+ *         return not not (<uint64_t*>data)[0]
+ *     elif format == MPV_FORMAT_INT64:
+ */
+    break;
+    case MPV_FORMAT_INT64:
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":237
+ *         return not not (<uint64_t*>data)[0]
+ *     elif format == MPV_FORMAT_INT64:
+ *         return int((<uint64_t*>data)[0])             # <<<<<<<<<<<<<<
+ *     elif format == MPV_FORMAT_DOUBLE:
+ *         return float((<double*>data)[0])
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_1 = __Pyx_PyInt_From_uint64_t((((uint64_t *)__pyx_v_data)[0])); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 237, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_6 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyInt_Type)), __pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 237, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __pyx_r = __pyx_t_6;
+    __pyx_t_6 = 0;
+    goto __pyx_L0;
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __Pyx_INCREF(__pyx_v_value);
-  __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->log_level);
-  __Pyx_DECREF(__pyx_v_self->log_level);
-  __pyx_v_self->log_level = __pyx_v_value;
+    /* "vidcutter/libs/pympv/mpv.pyx":236
+ *     elif format == MPV_FORMAT_FLAG:
+ *         return not not (<uint64_t*>data)[0]
+ *     elif format == MPV_FORMAT_INT64:             # <<<<<<<<<<<<<<
+ *         return int((<uint64_t*>data)[0])
+ *     elif format == MPV_FORMAT_DOUBLE:
+ */
+    break;
+    case MPV_FORMAT_DOUBLE:
 
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":239
+ *         return int((<uint64_t*>data)[0])
+ *     elif format == MPV_FORMAT_DOUBLE:
+ *         return float((<double*>data)[0])             # <<<<<<<<<<<<<<
+ *     return None
+ * 
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_6 = PyFloat_FromDouble((((double *)__pyx_v_data)[0])); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 239, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_r = __pyx_t_6;
+    __pyx_t_6 = 0;
+    goto __pyx_L0;
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_9log_level_5__del__(PyObject *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
+    /* "vidcutter/libs/pympv/mpv.pyx":238
+ *     elif format == MPV_FORMAT_INT64:
+ *         return int((<uint64_t*>data)[0])
+ *     elif format == MPV_FORMAT_DOUBLE:             # <<<<<<<<<<<<<<
+ *         return float((<double*>data)[0])
+ *     return None
+ */
+    break;
+    default: break;
+  }
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  /* "vidcutter/libs/pympv/mpv.pyx":240
+ *     elif format == MPV_FORMAT_DOUBLE:
+ *         return float((<double*>data)[0])
+ *     return None             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_9log_level_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__", 0);
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->log_level);
-  __Pyx_DECREF(__pyx_v_self->log_level);
-  __pyx_v_self->log_level = Py_None;
+  /* "vidcutter/libs/pympv/mpv.pyx":213
+ * 
+ * 
+ * cdef _convert_value(void* data, mpv_format format):             # <<<<<<<<<<<<<<
+ *     cdef mpv_node node
+ *     cdef mpv_node_list nodelist
+ */
 
   /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._convert_value", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_values);
+  __Pyx_XDECREF(__pyx_v_value);
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     cdef tuple state
- *     cdef object _dict
+/* "vidcutter/libs/pympv/mpv.pyx":250
+ *     cdef public object name, data
+ * 
+ *     cdef _init(self, mpv_event_property* prop):             # <<<<<<<<<<<<<<
+ *         self.name = _strdec(prop.name)
+ *         self.data = _convert_value(prop.data, prop.format)
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv_8Property__init(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self, struct mpv_event_property *__pyx_v_prop) {
+  PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage___reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self));
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("_init", 0);
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage___reduce_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self) {
-  PyObject *__pyx_v_state = 0;
-  PyObject *__pyx_v__dict = 0;
-  int __pyx_v_use_setstate;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  int __pyx_t_2;
-  int __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  int __pyx_t_5;
-  PyObject *__pyx_t_6 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
-
-  /* "(tree fragment)":5
- *     cdef object _dict
- *     cdef bint use_setstate
- *     state = (self.level, self.log_level, self.prefix, self.text)             # <<<<<<<<<<<<<<
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:
+  /* "vidcutter/libs/pympv/mpv.pyx":251
+ * 
+ *     cdef _init(self, mpv_event_property* prop):
+ *         self.name = _strdec(prop.name)             # <<<<<<<<<<<<<<
+ *         self.data = _convert_value(prop.data, prop.format)
+ *         return self
  */
-  __pyx_t_1 = PyTuple_New(4); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 251, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_prop->name); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 251, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_4)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_4);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 251, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_v_self->level);
-  __Pyx_GIVEREF(__pyx_v_self->level);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->level);
-  __Pyx_INCREF(__pyx_v_self->log_level);
-  __Pyx_GIVEREF(__pyx_v_self->log_level);
-  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_self->log_level);
-  __Pyx_INCREF(__pyx_v_self->prefix);
-  __Pyx_GIVEREF(__pyx_v_self->prefix);
-  PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_self->prefix);
-  __Pyx_INCREF(__pyx_v_self->text);
-  __Pyx_GIVEREF(__pyx_v_self->text);
-  PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_self->text);
-  __pyx_v_state = ((PyObject*)__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->name);
+  __Pyx_DECREF(__pyx_v_self->name);
+  __pyx_v_self->name = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "(tree fragment)":6
- *     cdef bint use_setstate
- *     state = (self.level, self.log_level, self.prefix, self.text)
- *     _dict = getattr(self, '__dict__', None)             # <<<<<<<<<<<<<<
- *     if _dict is not None:
- *         state += (_dict,)
+  /* "vidcutter/libs/pympv/mpv.pyx":252
+ *     cdef _init(self, mpv_event_property* prop):
+ *         self.name = _strdec(prop.name)
+ *         self.data = _convert_value(prop.data, prop.format)             # <<<<<<<<<<<<<<
+ *         return self
+ * 
  */
-  __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_value(__pyx_v_prop->data, __pyx_v_prop->format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 252, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v__dict = __pyx_t_1;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->data);
+  __Pyx_DECREF(__pyx_v_self->data);
+  __pyx_v_self->data = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "(tree fragment)":7
- *     state = (self.level, self.log_level, self.prefix, self.text)
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:             # <<<<<<<<<<<<<<
- *         state += (_dict,)
- *         use_setstate = True
+  /* "vidcutter/libs/pympv/mpv.pyx":253
+ *         self.name = _strdec(prop.name)
+ *         self.data = _convert_value(prop.data, prop.format)
+ *         return self             # <<<<<<<<<<<<<<
+ * 
+ * 
  */
-  __pyx_t_2 = (__pyx_v__dict != Py_None);
-  __pyx_t_3 = (__pyx_t_2 != 0);
-  if (__pyx_t_3) {
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_self));
+  __pyx_r = ((PyObject *)__pyx_v_self);
+  goto __pyx_L0;
 
-    /* "(tree fragment)":8
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:
- *         state += (_dict,)             # <<<<<<<<<<<<<<
- *         use_setstate = True
- *     else:
+  /* "vidcutter/libs/pympv/mpv.pyx":250
+ *     cdef public object name, data
+ * 
+ *     cdef _init(self, mpv_event_property* prop):             # <<<<<<<<<<<<<<
+ *         self.name = _strdec(prop.name)
+ *         self.data = _convert_value(prop.data, prop.format)
  */
-    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_INCREF(__pyx_v__dict);
-    __Pyx_GIVEREF(__pyx_v__dict);
-    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict);
-    __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 8, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4));
-    __pyx_t_4 = 0;
 
-    /* "(tree fragment)":9
- *     if _dict is not None:
- *         state += (_dict,)
- *         use_setstate = True             # <<<<<<<<<<<<<<
- *     else:
- *         use_setstate = self.level is not None or self.log_level is not None or self.prefix is not None or self.text is not None
- */
-    __pyx_v_use_setstate = 1;
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Property._init", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-    /* "(tree fragment)":7
- *     state = (self.level, self.log_level, self.prefix, self.text)
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:             # <<<<<<<<<<<<<<
- *         state += (_dict,)
- *         use_setstate = True
+/* "vidcutter/libs/pympv/mpv.pyx":248
+ *     Wraps: mpv_event_property
+ *     """
+ *     cdef public object name, data             # <<<<<<<<<<<<<<
+ * 
+ *     cdef _init(self, mpv_event_property* prop):
  */
-    goto __pyx_L3;
-  }
 
-  /* "(tree fragment)":11
- *         use_setstate = True
- *     else:
- *         use_setstate = self.level is not None or self.log_level is not None or self.prefix is not None or self.text is not None             # <<<<<<<<<<<<<<
- *     if use_setstate:
- *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, None), state
- */
-  /*else*/ {
-    __pyx_t_2 = (__pyx_v_self->level != Py_None);
-    __pyx_t_5 = (__pyx_t_2 != 0);
-    if (!__pyx_t_5) {
-    } else {
-      __pyx_t_3 = __pyx_t_5;
-      goto __pyx_L4_bool_binop_done;
-    }
-    __pyx_t_5 = (__pyx_v_self->log_level != Py_None);
-    __pyx_t_2 = (__pyx_t_5 != 0);
-    if (!__pyx_t_2) {
-    } else {
-      __pyx_t_3 = __pyx_t_2;
-      goto __pyx_L4_bool_binop_done;
-    }
-    __pyx_t_2 = (__pyx_v_self->prefix != Py_None);
-    __pyx_t_5 = (__pyx_t_2 != 0);
-    if (!__pyx_t_5) {
-    } else {
-      __pyx_t_3 = __pyx_t_5;
-      goto __pyx_L4_bool_binop_done;
-    }
-    __pyx_t_5 = (__pyx_v_self->text != Py_None);
-    __pyx_t_2 = (__pyx_t_5 != 0);
-    __pyx_t_3 = __pyx_t_2;
-    __pyx_L4_bool_binop_done:;
-    __pyx_v_use_setstate = __pyx_t_3;
-  }
-  __pyx_L3:;
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4name___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self));
 
-  /* "(tree fragment)":12
- *     else:
- *         use_setstate = self.level is not None or self.log_level is not None or self.prefix is not None or self.text is not None
- *     if use_setstate:             # <<<<<<<<<<<<<<
- *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, None), state
- *     else:
- */
-  __pyx_t_3 = (__pyx_v_use_setstate != 0);
-  if (__pyx_t_3) {
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-    /* "(tree fragment)":13
- *         use_setstate = self.level is not None or self.log_level is not None or self.prefix is not None or self.text is not None
- *     if use_setstate:
- *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, None), state             # <<<<<<<<<<<<<<
- *     else:
- *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, state)
- */
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_LogMessage); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 13, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_INCREF(__pyx_int_142036910);
-    __Pyx_GIVEREF(__pyx_int_142036910);
-    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_142036910);
-    __Pyx_INCREF(Py_None);
-    __Pyx_GIVEREF(Py_None);
-    PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None);
-    __pyx_t_6 = PyTuple_New(3); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 13, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_GIVEREF(__pyx_t_4);
-    PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4);
-    __Pyx_GIVEREF(__pyx_t_1);
-    PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_1);
-    __Pyx_INCREF(__pyx_v_state);
-    __Pyx_GIVEREF(__pyx_v_state);
-    PyTuple_SET_ITEM(__pyx_t_6, 2, __pyx_v_state);
-    __pyx_t_4 = 0;
-    __pyx_t_1 = 0;
-    __pyx_r = __pyx_t_6;
-    __pyx_t_6 = 0;
-    goto __pyx_L0;
-
-    /* "(tree fragment)":12
- *     else:
- *         use_setstate = self.level is not None or self.log_level is not None or self.prefix is not None or self.text is not None
- *     if use_setstate:             # <<<<<<<<<<<<<<
- *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, None), state
- *     else:
- */
-  }
-
-  /* "(tree fragment)":15
- *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, None), state
- *     else:
- *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, state)             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     __pyx_unpickle_LogMessage__set_state(self, __pyx_state)
- */
-  /*else*/ {
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pyx_unpickle_LogMessage); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 15, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_INCREF(__pyx_int_142036910);
-    __Pyx_GIVEREF(__pyx_int_142036910);
-    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_142036910);
-    __Pyx_INCREF(__pyx_v_state);
-    __Pyx_GIVEREF(__pyx_v_state);
-    PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state);
-    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 15, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_GIVEREF(__pyx_t_6);
-    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
-    __Pyx_GIVEREF(__pyx_t_1);
-    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1);
-    __pyx_t_6 = 0;
-    __pyx_t_1 = 0;
-    __pyx_r = __pyx_t_4;
-    __pyx_t_4 = 0;
-    goto __pyx_L0;
-  }
-
-  /* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     cdef tuple state
- *     cdef object _dict
- */
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8Property_4name___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_self->name);
+  __pyx_r = __pyx_v_self->name;
+  goto __pyx_L0;
 
   /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.LogMessage.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_state);
-  __Pyx_XDECREF(__pyx_v__dict);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "(tree fragment)":16
- *     else:
- *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, state)
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     __pyx_unpickle_LogMessage__set_state(self, __pyx_state)
- */
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4name_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_9vidcutter_4libs_3mpv_8Property_4name_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__", 0);
+  __Pyx_INCREF(__pyx_v_value);
+  __Pyx_GIVEREF(__pyx_v_value);
+  __Pyx_GOTREF(__pyx_v_self->name);
+  __Pyx_DECREF(__pyx_v_self->name);
+  __pyx_v_self->name = __pyx_v_value;
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_10LogMessage_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = 0;
+static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_5__del__(PyObject *__pyx_v_self); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_5__del__(PyObject *__pyx_v_self) {
+  int __pyx_r;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_2__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
+  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4name_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_10LogMessage_2__setstate_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
-  PyObject *__pyx_r = NULL;
+static int __pyx_pf_9vidcutter_4libs_3mpv_8Property_4name_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self) {
+  int __pyx_r;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
+  __Pyx_RefNannySetupContext("__del__", 0);
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->name);
+  __Pyx_DECREF(__pyx_v_self->name);
+  __pyx_v_self->name = Py_None;
 
-  /* "(tree fragment)":17
- *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, state)
- * def __setstate_cython__(self, __pyx_state):
- *     __pyx_unpickle_LogMessage__set_state(self, __pyx_state)             # <<<<<<<<<<<<<<
- */
-  if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error)
-  __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_LogMessage__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-  /* "(tree fragment)":16
- *     else:
- *         return __pyx_unpickle_LogMessage, (type(self), 0x8774fae, state)
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     __pyx_unpickle_LogMessage__set_state(self, __pyx_state)
- */
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4data___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self));
 
   /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8Property_4data___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_self->data);
+  __pyx_r = __pyx_v_self->data;
   goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.LogMessage.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
+
+  /* function exit code */
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":197
- * 
- * 
- * cdef _convert_node_value(mpv_node node):             # <<<<<<<<<<<<<<
- *     if node.format == MPV_FORMAT_STRING:
- *         return _strdec(node.u.string)
- */
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4data_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self), ((PyObject *)__pyx_v_value));
 
-static PyObject *__pyx_f_9vidcutter_4libs_3mpv__convert_node_value(struct mpv_node __pyx_v_node) {
-  PyObject *__pyx_r = NULL;
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_9vidcutter_4libs_3mpv_8Property_4data_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  int __pyx_t_5;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_convert_node_value", 0);
+  __Pyx_RefNannySetupContext("__set__", 0);
+  __Pyx_INCREF(__pyx_v_value);
+  __Pyx_GIVEREF(__pyx_v_value);
+  __Pyx_GOTREF(__pyx_v_self->data);
+  __Pyx_DECREF(__pyx_v_self->data);
+  __pyx_v_self->data = __pyx_v_value;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":198
- * 
- * cdef _convert_node_value(mpv_node node):
- *     if node.format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
- *         return _strdec(node.u.string)
- *     elif node.format == MPV_FORMAT_FLAG:
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_5__del__(PyObject *__pyx_v_self); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_5__del__(PyObject *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4data_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_9vidcutter_4libs_3mpv_8Property_4data_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__", 0);
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->data);
+  __Pyx_DECREF(__pyx_v_self->data);
+  __pyx_v_self->data = Py_None;
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "(tree fragment)":1
+ * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
+ *     cdef tuple state
+ *     cdef object _dict
  */
-  switch (__pyx_v_node.format) {
-    case MPV_FORMAT_STRING:
 
-    /* "vidcutter/libs/pympv/mpv.pyx":199
- * cdef _convert_node_value(mpv_node node):
- *     if node.format == MPV_FORMAT_STRING:
- *         return _strdec(node.u.string)             # <<<<<<<<<<<<<<
- *     elif node.format == MPV_FORMAT_FLAG:
- *         return not not int(node.u.flag)
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property___reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8Property___reduce_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self) {
+  PyObject *__pyx_v_state = 0;
+  PyObject *__pyx_v__dict = 0;
+  int __pyx_v_use_setstate;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_2;
+  int __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_t_5;
+  PyObject *__pyx_t_6 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
+
+  /* "(tree fragment)":5
+ *     cdef object _dict
+ *     cdef bint use_setstate
+ *     state = (self.data, self.name)             # <<<<<<<<<<<<<<
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:
  */
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 199, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_node.u.string); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 199, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-      if (likely(__pyx_t_4)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_4);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_2, function);
-      }
-    }
-    __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 199, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_r = __pyx_t_1;
-    __pyx_t_1 = 0;
-    goto __pyx_L0;
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_v_self->data);
+  __Pyx_GIVEREF(__pyx_v_self->data);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->data);
+  __Pyx_INCREF(__pyx_v_self->name);
+  __Pyx_GIVEREF(__pyx_v_self->name);
+  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_self->name);
+  __pyx_v_state = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":198
- * 
- * cdef _convert_node_value(mpv_node node):
- *     if node.format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
- *         return _strdec(node.u.string)
- *     elif node.format == MPV_FORMAT_FLAG:
+  /* "(tree fragment)":6
+ *     cdef bint use_setstate
+ *     state = (self.data, self.name)
+ *     _dict = getattr(self, '__dict__', None)             # <<<<<<<<<<<<<<
+ *     if _dict is not None:
+ *         state += (_dict,)
  */
-    break;
-    case MPV_FORMAT_FLAG:
+  __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v__dict = __pyx_t_1;
+  __pyx_t_1 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":201
- *         return _strdec(node.u.string)
- *     elif node.format == MPV_FORMAT_FLAG:
- *         return not not int(node.u.flag)             # <<<<<<<<<<<<<<
- *     elif node.format == MPV_FORMAT_INT64:
- *         return int(node.u.int64)
+  /* "(tree fragment)":7
+ *     state = (self.data, self.name)
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:             # <<<<<<<<<<<<<<
+ *         state += (_dict,)
+ *         use_setstate = True
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_node.u.flag); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 201, __pyx_L1_error)
+  __pyx_t_2 = (__pyx_v__dict != Py_None);
+  __pyx_t_3 = (__pyx_t_2 != 0);
+  if (__pyx_t_3) {
+
+    /* "(tree fragment)":8
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:
+ *         state += (_dict,)             # <<<<<<<<<<<<<<
+ *         use_setstate = True
+ *     else:
+ */
+    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_2 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyInt_Type)), __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 201, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_INCREF(__pyx_v__dict);
+    __Pyx_GIVEREF(__pyx_v__dict);
+    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict);
+    __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 8, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 201, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_2 = __Pyx_PyBool_FromLong((!((!__pyx_t_5) != 0))); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 201, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_r = __pyx_t_2;
-    __pyx_t_2 = 0;
-    goto __pyx_L0;
+    __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4));
+    __pyx_t_4 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":200
- *     if node.format == MPV_FORMAT_STRING:
- *         return _strdec(node.u.string)
- *     elif node.format == MPV_FORMAT_FLAG:             # <<<<<<<<<<<<<<
- *         return not not int(node.u.flag)
- *     elif node.format == MPV_FORMAT_INT64:
+    /* "(tree fragment)":9
+ *     if _dict is not None:
+ *         state += (_dict,)
+ *         use_setstate = True             # <<<<<<<<<<<<<<
+ *     else:
+ *         use_setstate = self.data is not None or self.name is not None
  */
-    break;
-    case MPV_FORMAT_INT64:
+    __pyx_v_use_setstate = 1;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":203
- *         return not not int(node.u.flag)
- *     elif node.format == MPV_FORMAT_INT64:
- *         return int(node.u.int64)             # <<<<<<<<<<<<<<
- *     elif node.format == MPV_FORMAT_DOUBLE:
- *         return float(node.u.double_)
+    /* "(tree fragment)":7
+ *     state = (self.data, self.name)
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:             # <<<<<<<<<<<<<<
+ *         state += (_dict,)
+ *         use_setstate = True
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_2 = __Pyx_PyInt_From_int64_t(__pyx_v_node.u.int64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 203, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyInt_Type)), __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 203, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_r = __pyx_t_1;
-    __pyx_t_1 = 0;
-    goto __pyx_L0;
+    goto __pyx_L3;
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":202
- *     elif node.format == MPV_FORMAT_FLAG:
- *         return not not int(node.u.flag)
- *     elif node.format == MPV_FORMAT_INT64:             # <<<<<<<<<<<<<<
- *         return int(node.u.int64)
- *     elif node.format == MPV_FORMAT_DOUBLE:
+  /* "(tree fragment)":11
+ *         use_setstate = True
+ *     else:
+ *         use_setstate = self.data is not None or self.name is not None             # <<<<<<<<<<<<<<
+ *     if use_setstate:
+ *         return __pyx_unpickle_Property, (type(self), 0x0572d11, None), state
  */
-    break;
-    case MPV_FORMAT_DOUBLE:
+  /*else*/ {
+    __pyx_t_2 = (__pyx_v_self->data != Py_None);
+    __pyx_t_5 = (__pyx_t_2 != 0);
+    if (!__pyx_t_5) {
+    } else {
+      __pyx_t_3 = __pyx_t_5;
+      goto __pyx_L4_bool_binop_done;
+    }
+    __pyx_t_5 = (__pyx_v_self->name != Py_None);
+    __pyx_t_2 = (__pyx_t_5 != 0);
+    __pyx_t_3 = __pyx_t_2;
+    __pyx_L4_bool_binop_done:;
+    __pyx_v_use_setstate = __pyx_t_3;
+  }
+  __pyx_L3:;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":205
- *         return int(node.u.int64)
- *     elif node.format == MPV_FORMAT_DOUBLE:
- *         return float(node.u.double_)             # <<<<<<<<<<<<<<
- *     elif node.format == MPV_FORMAT_NODE_MAP:
- *         return _convert_value(node.u.list, node.format)
+  /* "(tree fragment)":12
+ *     else:
+ *         use_setstate = self.data is not None or self.name is not None
+ *     if use_setstate:             # <<<<<<<<<<<<<<
+ *         return __pyx_unpickle_Property, (type(self), 0x0572d11, None), state
+ *     else:
+ */
+  __pyx_t_3 = (__pyx_v_use_setstate != 0);
+  if (__pyx_t_3) {
+
+    /* "(tree fragment)":13
+ *         use_setstate = self.data is not None or self.name is not None
+ *     if use_setstate:
+ *         return __pyx_unpickle_Property, (type(self), 0x0572d11, None), state             # <<<<<<<<<<<<<<
+ *     else:
+ *         return __pyx_unpickle_Property, (type(self), 0x0572d11, state)
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_1 = PyFloat_FromDouble(__pyx_v_node.u.double_); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 205, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_Property); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 13, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_r = __pyx_t_1;
+    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_INCREF(__pyx_int_5713169);
+    __Pyx_GIVEREF(__pyx_int_5713169);
+    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_5713169);
+    __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(Py_None);
+    PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None);
+    __pyx_t_6 = PyTuple_New(3); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 13, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_GIVEREF(__pyx_t_4);
+    PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4);
+    __Pyx_GIVEREF(__pyx_t_1);
+    PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_1);
+    __Pyx_INCREF(__pyx_v_state);
+    __Pyx_GIVEREF(__pyx_v_state);
+    PyTuple_SET_ITEM(__pyx_t_6, 2, __pyx_v_state);
+    __pyx_t_4 = 0;
     __pyx_t_1 = 0;
+    __pyx_r = __pyx_t_6;
+    __pyx_t_6 = 0;
     goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":204
- *     elif node.format == MPV_FORMAT_INT64:
- *         return int(node.u.int64)
- *     elif node.format == MPV_FORMAT_DOUBLE:             # <<<<<<<<<<<<<<
- *         return float(node.u.double_)
- *     elif node.format == MPV_FORMAT_NODE_MAP:
+    /* "(tree fragment)":12
+ *     else:
+ *         use_setstate = self.data is not None or self.name is not None
+ *     if use_setstate:             # <<<<<<<<<<<<<<
+ *         return __pyx_unpickle_Property, (type(self), 0x0572d11, None), state
+ *     else:
  */
-    break;
-    case MPV_FORMAT_NODE_MAP:
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":207
- *         return float(node.u.double_)
- *     elif node.format == MPV_FORMAT_NODE_MAP:
- *         return _convert_value(node.u.list, node.format)             # <<<<<<<<<<<<<<
- *     elif node.format == MPV_FORMAT_NODE_ARRAY:
- *         return _convert_value(node.u.list, node.format)
+  /* "(tree fragment)":15
+ *         return __pyx_unpickle_Property, (type(self), 0x0572d11, None), state
+ *     else:
+ *         return __pyx_unpickle_Property, (type(self), 0x0572d11, state)             # <<<<<<<<<<<<<<
+ * def __setstate_cython__(self, __pyx_state):
+ *     __pyx_unpickle_Property__set_state(self, __pyx_state)
  */
+  /*else*/ {
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_value(__pyx_v_node.u.list, __pyx_v_node.format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 207, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pyx_unpickle_Property); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 15, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
-    __pyx_r = __pyx_t_1;
+    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_INCREF(__pyx_int_5713169);
+    __Pyx_GIVEREF(__pyx_int_5713169);
+    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_5713169);
+    __Pyx_INCREF(__pyx_v_state);
+    __Pyx_GIVEREF(__pyx_v_state);
+    PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state);
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 15, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_GIVEREF(__pyx_t_6);
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
+    __Pyx_GIVEREF(__pyx_t_1);
+    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1);
+    __pyx_t_6 = 0;
     __pyx_t_1 = 0;
+    __pyx_r = __pyx_t_4;
+    __pyx_t_4 = 0;
     goto __pyx_L0;
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":206
- *     elif node.format == MPV_FORMAT_DOUBLE:
- *         return float(node.u.double_)
- *     elif node.format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
- *         return _convert_value(node.u.list, node.format)
- *     elif node.format == MPV_FORMAT_NODE_ARRAY:
+  /* "(tree fragment)":1
+ * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
+ *     cdef tuple state
+ *     cdef object _dict
  */
-    break;
-    case MPV_FORMAT_NODE_ARRAY:
 
-    /* "vidcutter/libs/pympv/mpv.pyx":209
- *         return _convert_value(node.u.list, node.format)
- *     elif node.format == MPV_FORMAT_NODE_ARRAY:
- *         return _convert_value(node.u.list, node.format)             # <<<<<<<<<<<<<<
- *     return None
- * 
- */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_value(__pyx_v_node.u.list, __pyx_v_node.format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 209, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_r = __pyx_t_1;
-    __pyx_t_1 = 0;
-    goto __pyx_L0;
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Property.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_state);
+  __Pyx_XDECREF(__pyx_v__dict);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-    /* "vidcutter/libs/pympv/mpv.pyx":208
- *     elif node.format == MPV_FORMAT_NODE_MAP:
- *         return _convert_value(node.u.list, node.format)
- *     elif node.format == MPV_FORMAT_NODE_ARRAY:             # <<<<<<<<<<<<<<
- *         return _convert_value(node.u.list, node.format)
- *     return None
+/* "(tree fragment)":16
+ *     else:
+ *         return __pyx_unpickle_Property, (type(self), 0x0572d11, state)
+ * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
+ *     __pyx_unpickle_Property__set_state(self, __pyx_state)
  */
-    break;
-    default: break;
-  }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":210
- *     elif node.format == MPV_FORMAT_NODE_ARRAY:
- *         return _convert_value(node.u.list, node.format)
- *     return None             # <<<<<<<<<<<<<<
- * 
- * 
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_2__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8Property_2__setstate_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
+
+  /* "(tree fragment)":17
+ *         return __pyx_unpickle_Property, (type(self), 0x0572d11, state)
+ * def __setstate_cython__(self, __pyx_state):
+ *     __pyx_unpickle_Property__set_state(self, __pyx_state)             # <<<<<<<<<<<<<<
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
+  if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_Property__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":197
- * 
- * 
- * cdef _convert_node_value(mpv_node node):             # <<<<<<<<<<<<<<
- *     if node.format == MPV_FORMAT_STRING:
- *         return _strdec(node.u.string)
+  /* "(tree fragment)":16
+ *     else:
+ *         return __pyx_unpickle_Property, (type(self), 0x0572d11, state)
+ * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
+ *     __pyx_unpickle_Property__set_state(self, __pyx_state)
  */
 
   /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv._convert_node_value", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Property.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":213
- * 
+/* "vidcutter/libs/pympv/mpv.pyx":263
  * 
- * cdef _convert_value(void* data, mpv_format format):             # <<<<<<<<<<<<<<
- *     cdef mpv_node node
- *     cdef mpv_node_list nodelist
+ *     @property
+ *     def error_str(self):             # <<<<<<<<<<<<<<
+ *         """mpv_error_string of the error proeprty"""
+ *         cdef const char* err_c
  */
 
-static PyObject *__pyx_f_9vidcutter_4libs_3mpv__convert_value(void *__pyx_v_data, enum mpv_format __pyx_v_format) {
-  struct mpv_node __pyx_v_node;
-  struct mpv_node_list __pyx_v_nodelist;
-  PyObject *__pyx_v_values = NULL;
-  int __pyx_v_i;
-  PyObject *__pyx_v_value = NULL;
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_9error_str_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_9error_str_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_9error_str___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_9error_str___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
+  char const *__pyx_v_err_c;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_t_2;
-  int __pyx_t_3;
-  int __pyx_t_4;
-  int __pyx_t_5;
-  PyObject *__pyx_t_6 = NULL;
-  PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_convert_value", 0);
+  __Pyx_RefNannySetupContext("__get__", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":216
- *     cdef mpv_node node
- *     cdef mpv_node_list nodelist
- *     if format == MPV_FORMAT_NODE:             # <<<<<<<<<<<<<<
- *         node = (<mpv_node*>data)[0]
- *         return _convert_node_value(node)
+  /* "vidcutter/libs/pympv/mpv.pyx":266
+ *         """mpv_error_string of the error proeprty"""
+ *         cdef const char* err_c
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err_c = mpv_error_string(self.error)
+ *         return _strdec(err_c)
  */
-  switch (__pyx_v_format) {
-    case MPV_FORMAT_NODE:
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":217
- *     cdef mpv_node_list nodelist
- *     if format == MPV_FORMAT_NODE:
- *         node = (<mpv_node*>data)[0]             # <<<<<<<<<<<<<<
- *         return _convert_node_value(node)
- *     elif format == MPV_FORMAT_NODE_ARRAY:
+        /* "vidcutter/libs/pympv/mpv.pyx":267
+ *         cdef const char* err_c
+ *         with nogil:
+ *             err_c = mpv_error_string(self.error)             # <<<<<<<<<<<<<<
+ *         return _strdec(err_c)
+ * 
  */
-    __pyx_v_node = (((struct mpv_node *)__pyx_v_data)[0]);
+        __pyx_v_err_c = mpv_error_string(__pyx_v_self->error);
+      }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":218
- *     if format == MPV_FORMAT_NODE:
- *         node = (<mpv_node*>data)[0]
- *         return _convert_node_value(node)             # <<<<<<<<<<<<<<
- *     elif format == MPV_FORMAT_NODE_ARRAY:
- *         nodelist = (<mpv_node_list*>data)[0]
+      /* "vidcutter/libs/pympv/mpv.pyx":266
+ *         """mpv_error_string of the error proeprty"""
+ *         cdef const char* err_c
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err_c = mpv_error_string(self.error)
+ *         return _strdec(err_c)
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_node_value(__pyx_v_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 218, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_r = __pyx_t_1;
-    __pyx_t_1 = 0;
-    goto __pyx_L0;
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
+      }
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":216
- *     cdef mpv_node node
- *     cdef mpv_node_list nodelist
- *     if format == MPV_FORMAT_NODE:             # <<<<<<<<<<<<<<
- *         node = (<mpv_node*>data)[0]
- *         return _convert_node_value(node)
+  /* "vidcutter/libs/pympv/mpv.pyx":268
+ *         with nogil:
+ *             err_c = mpv_error_string(self.error)
+ *         return _strdec(err_c)             # <<<<<<<<<<<<<<
+ * 
+ *     cdef _data(self, mpv_event* event):
  */
-    break;
-    case MPV_FORMAT_NODE_ARRAY:
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 268, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_err_c); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 268, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_4)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_4);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 268, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":220
- *         return _convert_node_value(node)
- *     elif format == MPV_FORMAT_NODE_ARRAY:
- *         nodelist = (<mpv_node_list*>data)[0]             # <<<<<<<<<<<<<<
- *         values = []
- *         for i in range(nodelist.num):
+  /* "vidcutter/libs/pympv/mpv.pyx":263
+ * 
+ *     @property
+ *     def error_str(self):             # <<<<<<<<<<<<<<
+ *         """mpv_error_string of the error proeprty"""
+ *         cdef const char* err_c
  */
-    __pyx_v_nodelist = (((struct mpv_node_list *)__pyx_v_data)[0]);
 
-    /* "vidcutter/libs/pympv/mpv.pyx":221
- *     elif format == MPV_FORMAT_NODE_ARRAY:
- *         nodelist = (<mpv_node_list*>data)[0]
- *         values = []             # <<<<<<<<<<<<<<
- *         for i in range(nodelist.num):
- *             values.append(_convert_node_value(nodelist.values[i]))
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.error_str.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "vidcutter/libs/pympv/mpv.pyx":270
+ *         return _strdec(err_c)
+ * 
+ *     cdef _data(self, mpv_event* event):             # <<<<<<<<<<<<<<
+ *         cdef void* data = event.data
+ *         cdef mpv_event_client_message* climsg
  */
-    __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 221, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_v_values = __pyx_t_1;
-    __pyx_t_1 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":222
- *         nodelist = (<mpv_node_list*>data)[0]
- *         values = []
- *         for i in range(nodelist.num):             # <<<<<<<<<<<<<<
- *             values.append(_convert_node_value(nodelist.values[i]))
- *         return values
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv_5Event__data(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, struct mpv_event *__pyx_v_event) {
+  void *__pyx_v_data;
+  struct mpv_event_client_message *__pyx_v_climsg;
+  PyObject *__pyx_v_args = NULL;
+  int __pyx_v_num_args;
+  int __pyx_v_i;
+  PyObject *__pyx_v_arg = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  void *__pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_t_4;
+  int __pyx_t_5;
+  int __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
+  int __pyx_t_8;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("_data", 0);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":271
+ * 
+ *     cdef _data(self, mpv_event* event):
+ *         cdef void* data = event.data             # <<<<<<<<<<<<<<
+ *         cdef mpv_event_client_message* climsg
+ *         if self.id == MPV_EVENT_GET_PROPERTY_REPLY:
  */
-    __pyx_t_2 = __pyx_v_nodelist.num;
-    __pyx_t_3 = __pyx_t_2;
-    for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
-      __pyx_v_i = __pyx_t_4;
+  __pyx_t_1 = __pyx_v_event->data;
+  __pyx_v_data = __pyx_t_1;
 
-      /* "vidcutter/libs/pympv/mpv.pyx":223
- *         values = []
- *         for i in range(nodelist.num):
- *             values.append(_convert_node_value(nodelist.values[i]))             # <<<<<<<<<<<<<<
- *         return values
- *     elif format == MPV_FORMAT_NODE_MAP:
+  /* "vidcutter/libs/pympv/mpv.pyx":273
+ *         cdef void* data = event.data
+ *         cdef mpv_event_client_message* climsg
+ *         if self.id == MPV_EVENT_GET_PROPERTY_REPLY:             # <<<<<<<<<<<<<<
+ *             return Property()._init(<mpv_event_property*>data)
+ *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:
  */
-      __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_node_value((__pyx_v_nodelist.values[__pyx_v_i])); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 223, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __pyx_t_5 = __Pyx_PyObject_Append(__pyx_v_values, __pyx_t_1); if (unlikely(__pyx_t_5 == ((int)-1))) __PYX_ERR(0, 223, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    }
+  switch (__pyx_v_self->id) {
+    case MPV_EVENT_GET_PROPERTY_REPLY:
 
-    /* "vidcutter/libs/pympv/mpv.pyx":224
- *         for i in range(nodelist.num):
- *             values.append(_convert_node_value(nodelist.values[i]))
- *         return values             # <<<<<<<<<<<<<<
- *     elif format == MPV_FORMAT_NODE_MAP:
- *         nodelist = (<mpv_node_list*>data)[0]
+    /* "vidcutter/libs/pympv/mpv.pyx":274
+ *         cdef mpv_event_client_message* climsg
+ *         if self.id == MPV_EVENT_GET_PROPERTY_REPLY:
+ *             return Property()._init(<mpv_event_property*>data)             # <<<<<<<<<<<<<<
+ *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:
+ *             return Property()._init(<mpv_event_property*>data)
  */
     __Pyx_XDECREF(__pyx_r);
-    __Pyx_INCREF(__pyx_v_values);
-    __pyx_r = __pyx_v_values;
+    __pyx_t_2 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_Property)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 274, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_3 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Property *)((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_t_2)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_t_2), ((struct mpv_event_property *)__pyx_v_data)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 274, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_r = __pyx_t_3;
+    __pyx_t_3 = 0;
     goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":219
- *         node = (<mpv_node*>data)[0]
- *         return _convert_node_value(node)
- *     elif format == MPV_FORMAT_NODE_ARRAY:             # <<<<<<<<<<<<<<
- *         nodelist = (<mpv_node_list*>data)[0]
- *         values = []
+    /* "vidcutter/libs/pympv/mpv.pyx":273
+ *         cdef void* data = event.data
+ *         cdef mpv_event_client_message* climsg
+ *         if self.id == MPV_EVENT_GET_PROPERTY_REPLY:             # <<<<<<<<<<<<<<
+ *             return Property()._init(<mpv_event_property*>data)
+ *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:
  */
     break;
-    case MPV_FORMAT_NODE_MAP:
+    case MPV_EVENT_PROPERTY_CHANGE:
 
-    /* "vidcutter/libs/pympv/mpv.pyx":226
- *         return values
- *     elif format == MPV_FORMAT_NODE_MAP:
- *         nodelist = (<mpv_node_list*>data)[0]             # <<<<<<<<<<<<<<
- *         values = {}
- *         for i in range(nodelist.num):
+    /* "vidcutter/libs/pympv/mpv.pyx":276
+ *             return Property()._init(<mpv_event_property*>data)
+ *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:
+ *             return Property()._init(<mpv_event_property*>data)             # <<<<<<<<<<<<<<
+ *         elif self.id == MPV_EVENT_LOG_MESSAGE:
+ *             return LogMessage()._init(<mpv_event_log_message*>data)
  */
-    __pyx_v_nodelist = (((struct mpv_node_list *)__pyx_v_data)[0]);
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_3 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_Property)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 276, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_2 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Property *)((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_t_3)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_t_3), ((struct mpv_event_property *)__pyx_v_data)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 276, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_r = __pyx_t_2;
+    __pyx_t_2 = 0;
+    goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":227
- *     elif format == MPV_FORMAT_NODE_MAP:
- *         nodelist = (<mpv_node_list*>data)[0]
- *         values = {}             # <<<<<<<<<<<<<<
- *         for i in range(nodelist.num):
- *             value = _convert_node_value(nodelist.values[i])
+    /* "vidcutter/libs/pympv/mpv.pyx":275
+ *         if self.id == MPV_EVENT_GET_PROPERTY_REPLY:
+ *             return Property()._init(<mpv_event_property*>data)
+ *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:             # <<<<<<<<<<<<<<
+ *             return Property()._init(<mpv_event_property*>data)
+ *         elif self.id == MPV_EVENT_LOG_MESSAGE:
  */
-    __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 227, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_v_values = __pyx_t_1;
-    __pyx_t_1 = 0;
+    break;
+    case MPV_EVENT_LOG_MESSAGE:
 
-    /* "vidcutter/libs/pympv/mpv.pyx":228
- *         nodelist = (<mpv_node_list*>data)[0]
- *         values = {}
- *         for i in range(nodelist.num):             # <<<<<<<<<<<<<<
- *             value = _convert_node_value(nodelist.values[i])
- *             values[_strdec(nodelist.keys[i])] = value
+    /* "vidcutter/libs/pympv/mpv.pyx":278
+ *             return Property()._init(<mpv_event_property*>data)
+ *         elif self.id == MPV_EVENT_LOG_MESSAGE:
+ *             return LogMessage()._init(<mpv_event_log_message*>data)             # <<<<<<<<<<<<<<
+ *         # elif self.id == MPV_EVENT_SCRIPT_INPUT_DISPATCH:
+ *         #     return InputDispatch()._init(<mpv_event_script_input_dispatch*>data)
  */
-    __pyx_t_2 = __pyx_v_nodelist.num;
-    __pyx_t_3 = __pyx_t_2;
-    for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
-      __pyx_v_i = __pyx_t_4;
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_2 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_LogMessage)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 278, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_3 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_LogMessage *)((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_t_2)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_t_2), ((struct mpv_event_log_message *)__pyx_v_data)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 278, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_r = __pyx_t_3;
+    __pyx_t_3 = 0;
+    goto __pyx_L0;
 
-      /* "vidcutter/libs/pympv/mpv.pyx":229
- *         values = {}
- *         for i in range(nodelist.num):
- *             value = _convert_node_value(nodelist.values[i])             # <<<<<<<<<<<<<<
- *             values[_strdec(nodelist.keys[i])] = value
- *         return values
- */
-      __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_node_value((__pyx_v_nodelist.values[__pyx_v_i])); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 229, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_XDECREF_SET(__pyx_v_value, __pyx_t_1);
-      __pyx_t_1 = 0;
+    /* "vidcutter/libs/pympv/mpv.pyx":277
+ *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:
+ *             return Property()._init(<mpv_event_property*>data)
+ *         elif self.id == MPV_EVENT_LOG_MESSAGE:             # <<<<<<<<<<<<<<
+ *             return LogMessage()._init(<mpv_event_log_message*>data)
+ *         # elif self.id == MPV_EVENT_SCRIPT_INPUT_DISPATCH:
+ */
+    break;
+    case MPV_EVENT_CLIENT_MESSAGE:
 
-      /* "vidcutter/libs/pympv/mpv.pyx":230
- *         for i in range(nodelist.num):
- *             value = _convert_node_value(nodelist.values[i])
- *             values[_strdec(nodelist.keys[i])] = value             # <<<<<<<<<<<<<<
- *         return values
- *     elif format == MPV_FORMAT_STRING:
+    /* "vidcutter/libs/pympv/mpv.pyx":282
+ *         #     return InputDispatch()._init(<mpv_event_script_input_dispatch*>data)
+ *         elif self.id == MPV_EVENT_CLIENT_MESSAGE:
+ *             climsg = <mpv_event_client_message*>data             # <<<<<<<<<<<<<<
+ *             args = []
+ *             num_args = climsg.num_args
  */
-      __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_strdec); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 230, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      __pyx_t_7 = __Pyx_PyBytes_FromString((__pyx_v_nodelist.keys[__pyx_v_i])); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 230, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __pyx_t_8 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) {
-        __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_6);
-        if (likely(__pyx_t_8)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
-          __Pyx_INCREF(__pyx_t_8);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_6, function);
-        }
-      }
-      __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_8, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_7);
-      __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 230, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      if (unlikely(PyObject_SetItem(__pyx_v_values, __pyx_t_1, __pyx_v_value) < 0)) __PYX_ERR(0, 230, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    }
+    __pyx_v_climsg = ((struct mpv_event_client_message *)__pyx_v_data);
 
-    /* "vidcutter/libs/pympv/mpv.pyx":231
- *             value = _convert_node_value(nodelist.values[i])
- *             values[_strdec(nodelist.keys[i])] = value
- *         return values             # <<<<<<<<<<<<<<
- *     elif format == MPV_FORMAT_STRING:
- *         return _strdec(((<char**>data)[0]))
+    /* "vidcutter/libs/pympv/mpv.pyx":283
+ *         elif self.id == MPV_EVENT_CLIENT_MESSAGE:
+ *             climsg = <mpv_event_client_message*>data
+ *             args = []             # <<<<<<<<<<<<<<
+ *             num_args = climsg.num_args
+ *             for i in range(num_args):
  */
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_INCREF(__pyx_v_values);
-    __pyx_r = __pyx_v_values;
-    goto __pyx_L0;
+    __pyx_t_3 = PyList_New(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 283, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_v_args = ((PyObject*)__pyx_t_3);
+    __pyx_t_3 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":225
- *             values.append(_convert_node_value(nodelist.values[i]))
- *         return values
- *     elif format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
- *         nodelist = (<mpv_node_list*>data)[0]
- *         values = {}
+    /* "vidcutter/libs/pympv/mpv.pyx":284
+ *             climsg = <mpv_event_client_message*>data
+ *             args = []
+ *             num_args = climsg.num_args             # <<<<<<<<<<<<<<
+ *             for i in range(num_args):
+ *                 arg = <char*>climsg.args[i]
  */
-    break;
-    case MPV_FORMAT_STRING:
+    __pyx_t_4 = __pyx_v_climsg->num_args;
+    __pyx_v_num_args = __pyx_t_4;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":233
- *         return values
- *     elif format == MPV_FORMAT_STRING:
- *         return _strdec(((<char**>data)[0]))             # <<<<<<<<<<<<<<
- *     elif format == MPV_FORMAT_FLAG:
- *         return not not (<uint64_t*>data)[0]
+    /* "vidcutter/libs/pympv/mpv.pyx":285
+ *             args = []
+ *             num_args = climsg.num_args
+ *             for i in range(num_args):             # <<<<<<<<<<<<<<
+ *                 arg = <char*>climsg.args[i]
+ *                 arg = _strdec(arg)
  */
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_strdec); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 233, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_7 = __Pyx_PyBytes_FromString((((char **)__pyx_v_data)[0])); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 233, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_8 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_6))) {
-      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_6);
-      if (likely(__pyx_t_8)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_6);
-        __Pyx_INCREF(__pyx_t_8);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_6, function);
-      }
-    }
-    __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_6, __pyx_t_8, __pyx_t_7) : __Pyx_PyObject_CallOneArg(__pyx_t_6, __pyx_t_7);
-    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 233, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __pyx_r = __pyx_t_1;
-    __pyx_t_1 = 0;
-    goto __pyx_L0;
+    __pyx_t_4 = __pyx_v_num_args;
+    __pyx_t_5 = __pyx_t_4;
+    for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
+      __pyx_v_i = __pyx_t_6;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":232
- *             values[_strdec(nodelist.keys[i])] = value
- *         return values
- *     elif format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
- *         return _strdec(((<char**>data)[0]))
- *     elif format == MPV_FORMAT_FLAG:
+      /* "vidcutter/libs/pympv/mpv.pyx":286
+ *             num_args = climsg.num_args
+ *             for i in range(num_args):
+ *                 arg = <char*>climsg.args[i]             # <<<<<<<<<<<<<<
+ *                 arg = _strdec(arg)
+ *                 args.append(arg)
  */
-    break;
-    case MPV_FORMAT_FLAG:
+      __pyx_t_3 = __Pyx_PyBytes_FromString(((char *)(__pyx_v_climsg->args[__pyx_v_i]))); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 286, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_XDECREF_SET(__pyx_v_arg, __pyx_t_3);
+      __pyx_t_3 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":235
- *         return _strdec(((<char**>data)[0]))
- *     elif format == MPV_FORMAT_FLAG:
- *         return not not (<uint64_t*>data)[0]             # <<<<<<<<<<<<<<
- *     elif format == MPV_FORMAT_INT64:
- *         return int((<uint64_t*>data)[0])
+      /* "vidcutter/libs/pympv/mpv.pyx":287
+ *             for i in range(num_args):
+ *                 arg = <char*>climsg.args[i]
+ *                 arg = _strdec(arg)             # <<<<<<<<<<<<<<
+ *                 args.append(arg)
+ *             return args
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_1 = __Pyx_PyBool_FromLong((!((!((((uint64_t *)__pyx_v_data)[0]) != 0)) != 0))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 235, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_r = __pyx_t_1;
-    __pyx_t_1 = 0;
-    goto __pyx_L0;
+      __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 287, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_7 = NULL;
+      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+        __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_2);
+        if (likely(__pyx_t_7)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+          __Pyx_INCREF(__pyx_t_7);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_2, function);
+        }
+      }
+      __pyx_t_3 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_7, __pyx_v_arg) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_arg);
+      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+      if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 287, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      __Pyx_DECREF_SET(__pyx_v_arg, __pyx_t_3);
+      __pyx_t_3 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":234
- *     elif format == MPV_FORMAT_STRING:
- *         return _strdec(((<char**>data)[0]))
- *     elif format == MPV_FORMAT_FLAG:             # <<<<<<<<<<<<<<
- *         return not not (<uint64_t*>data)[0]
- *     elif format == MPV_FORMAT_INT64:
+      /* "vidcutter/libs/pympv/mpv.pyx":288
+ *                 arg = <char*>climsg.args[i]
+ *                 arg = _strdec(arg)
+ *                 args.append(arg)             # <<<<<<<<<<<<<<
+ *             return args
+ *         elif self.id == MPV_EVENT_END_FILE:
  */
-    break;
-    case MPV_FORMAT_INT64:
+      __pyx_t_8 = __Pyx_PyList_Append(__pyx_v_args, __pyx_v_arg); if (unlikely(__pyx_t_8 == ((int)-1))) __PYX_ERR(0, 288, __pyx_L1_error)
+    }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":237
- *         return not not (<uint64_t*>data)[0]
- *     elif format == MPV_FORMAT_INT64:
- *         return int((<uint64_t*>data)[0])             # <<<<<<<<<<<<<<
- *     elif format == MPV_FORMAT_DOUBLE:
- *         return float((<double*>data)[0])
+    /* "vidcutter/libs/pympv/mpv.pyx":289
+ *                 arg = _strdec(arg)
+ *                 args.append(arg)
+ *             return args             # <<<<<<<<<<<<<<
+ *         elif self.id == MPV_EVENT_END_FILE:
+ *             return EndOfFileReached()._init(<mpv_event_end_file*>data)
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_1 = __Pyx_PyInt_From_uint64_t((((uint64_t *)__pyx_v_data)[0])); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 237, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_6 = __Pyx_PyObject_CallOneArg(((PyObject *)(&PyInt_Type)), __pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 237, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_r = __pyx_t_6;
-    __pyx_t_6 = 0;
+    __Pyx_INCREF(__pyx_v_args);
+    __pyx_r = __pyx_v_args;
     goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":236
- *     elif format == MPV_FORMAT_FLAG:
- *         return not not (<uint64_t*>data)[0]
- *     elif format == MPV_FORMAT_INT64:             # <<<<<<<<<<<<<<
- *         return int((<uint64_t*>data)[0])
- *     elif format == MPV_FORMAT_DOUBLE:
+    /* "vidcutter/libs/pympv/mpv.pyx":281
+ *         # elif self.id == MPV_EVENT_SCRIPT_INPUT_DISPATCH:
+ *         #     return InputDispatch()._init(<mpv_event_script_input_dispatch*>data)
+ *         elif self.id == MPV_EVENT_CLIENT_MESSAGE:             # <<<<<<<<<<<<<<
+ *             climsg = <mpv_event_client_message*>data
+ *             args = []
  */
     break;
-    case MPV_FORMAT_DOUBLE:
+    case MPV_EVENT_END_FILE:
 
-    /* "vidcutter/libs/pympv/mpv.pyx":239
- *         return int((<uint64_t*>data)[0])
- *     elif format == MPV_FORMAT_DOUBLE:
- *         return float((<double*>data)[0])             # <<<<<<<<<<<<<<
- *     return None
+    /* "vidcutter/libs/pympv/mpv.pyx":291
+ *             return args
+ *         elif self.id == MPV_EVENT_END_FILE:
+ *             return EndOfFileReached()._init(<mpv_event_end_file*>data)             # <<<<<<<<<<<<<<
+ *         return None
  * 
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_6 = PyFloat_FromDouble((((double *)__pyx_v_data)[0])); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 239, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_r = __pyx_t_6;
-    __pyx_t_6 = 0;
+    __pyx_t_3 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_EndOfFileReached)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 291, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_2 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_EndOfFileReached *)((struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached *)__pyx_t_3)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached *)__pyx_t_3), ((struct mpv_event_end_file *)__pyx_v_data)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 291, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_r = __pyx_t_2;
+    __pyx_t_2 = 0;
     goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":238
- *     elif format == MPV_FORMAT_INT64:
- *         return int((<uint64_t*>data)[0])
- *     elif format == MPV_FORMAT_DOUBLE:             # <<<<<<<<<<<<<<
- *         return float((<double*>data)[0])
- *     return None
+    /* "vidcutter/libs/pympv/mpv.pyx":290
+ *                 args.append(arg)
+ *             return args
+ *         elif self.id == MPV_EVENT_END_FILE:             # <<<<<<<<<<<<<<
+ *             return EndOfFileReached()._init(<mpv_event_end_file*>data)
+ *         return None
  */
     break;
     default: break;
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":240
- *     elif format == MPV_FORMAT_DOUBLE:
- *         return float((<double*>data)[0])
- *     return None             # <<<<<<<<<<<<<<
- * 
- * 
- */
+  /* "vidcutter/libs/pympv/mpv.pyx":292
+ *         elif self.id == MPV_EVENT_END_FILE:
+ *             return EndOfFileReached()._init(<mpv_event_end_file*>data)
+ *         return None             # <<<<<<<<<<<<<<
+ * 
+ *     @property
+ */
   __Pyx_XDECREF(__pyx_r);
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":213
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":270
+ *         return _strdec(err_c)
  * 
- * cdef _convert_value(void* data, mpv_format format):             # <<<<<<<<<<<<<<
- *     cdef mpv_node node
- *     cdef mpv_node_list nodelist
+ *     cdef _data(self, mpv_event* event):             # <<<<<<<<<<<<<<
+ *         cdef void* data = event.data
+ *         cdef mpv_event_client_message* climsg
  */
 
   /* function exit code */
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_AddTraceback("vidcutter.libs.mpv._convert_value", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Event._data", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = 0;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_values);
-  __Pyx_XDECREF(__pyx_v_value);
+  __Pyx_XDECREF(__pyx_v_args);
+  __Pyx_XDECREF(__pyx_v_arg);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":250
- *     cdef public object name, data
+/* "vidcutter/libs/pympv/mpv.pyx":295
  * 
- *     cdef _init(self, mpv_event_property* prop):             # <<<<<<<<<<<<<<
- *         self.name = _strdec(prop.name)
- *         self.data = _convert_value(prop.data, prop.format)
+ *     @property
+ *     def name(self):             # <<<<<<<<<<<<<<
+ *         """mpv_event_name of the event id"""
+ *         cdef const char* name_c
  */
 
-static PyObject *__pyx_f_9vidcutter_4libs_3mpv_8Property__init(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self, struct mpv_event_property *__pyx_v_prop) {
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_4name_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_4name_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_4name___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_4name___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
+  char const *__pyx_v_name_c;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -5704,18 +6128,63 @@ static PyObject *__pyx_f_9vidcutter_4libs_3mpv_8Property__init(struct __pyx_obj_
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_init", 0);
+  __Pyx_RefNannySetupContext("__get__", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":251
+  /* "vidcutter/libs/pympv/mpv.pyx":298
+ *         """mpv_event_name of the event id"""
+ *         cdef const char* name_c
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             name_c = mpv_event_name(self.id)
+ *         return _strdec(name_c)
+ */
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
+
+        /* "vidcutter/libs/pympv/mpv.pyx":299
+ *         cdef const char* name_c
+ *         with nogil:
+ *             name_c = mpv_event_name(self.id)             # <<<<<<<<<<<<<<
+ *         return _strdec(name_c)
  * 
- *     cdef _init(self, mpv_event_property* prop):
- *         self.name = _strdec(prop.name)             # <<<<<<<<<<<<<<
- *         self.data = _convert_value(prop.data, prop.format)
- *         return self
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 251, __pyx_L1_error)
+        __pyx_v_name_c = mpv_event_name(__pyx_v_self->id);
+      }
+
+      /* "vidcutter/libs/pympv/mpv.pyx":298
+ *         """mpv_event_name of the event id"""
+ *         cdef const char* name_c
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             name_c = mpv_event_name(self.id)
+ *         return _strdec(name_c)
+ */
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
+      }
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":300
+ *         with nogil:
+ *             name_c = mpv_event_name(self.id)
+ *         return _strdec(name_c)             # <<<<<<<<<<<<<<
+ * 
+ *     cdef _init(self, mpv_event* event, ctx):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 300, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_prop->name); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 251, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_name_c); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 300, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_3);
   __pyx_t_4 = NULL;
   if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
@@ -5730,48 +6199,19 @@ static PyObject *__pyx_f_9vidcutter_4libs_3mpv_8Property__init(struct __pyx_obj_
   __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
   __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 251, __pyx_L1_error)
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 300, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->name);
-  __Pyx_DECREF(__pyx_v_self->name);
-  __pyx_v_self->name = __pyx_t_1;
-  __pyx_t_1 = 0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":252
- *     cdef _init(self, mpv_event_property* prop):
- *         self.name = _strdec(prop.name)
- *         self.data = _convert_value(prop.data, prop.format)             # <<<<<<<<<<<<<<
- *         return self
- * 
- */
-  __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_value(__pyx_v_prop->data, __pyx_v_prop->format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 252, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->data);
-  __Pyx_DECREF(__pyx_v_self->data);
-  __pyx_v_self->data = __pyx_t_1;
+  __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":253
- *         self.name = _strdec(prop.name)
- *         self.data = _convert_value(prop.data, prop.format)
- *         return self             # <<<<<<<<<<<<<<
- * 
- * 
- */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(((PyObject *)__pyx_v_self));
-  __pyx_r = ((PyObject *)__pyx_v_self);
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":250
- *     cdef public object name, data
+  /* "vidcutter/libs/pympv/mpv.pyx":295
  * 
- *     cdef _init(self, mpv_event_property* prop):             # <<<<<<<<<<<<<<
- *         self.name = _strdec(prop.name)
- *         self.data = _convert_value(prop.data, prop.format)
+ *     @property
+ *     def name(self):             # <<<<<<<<<<<<<<
+ *         """mpv_event_name of the event id"""
+ *         cdef const char* name_c
  */
 
   /* function exit code */
@@ -5780,1547 +6220,1710 @@ static PyObject *__pyx_f_9vidcutter_4libs_3mpv_8Property__init(struct __pyx_obj_
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Property._init", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.name.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":248
- *     Wraps: mpv_event_property
- *     """
- *     cdef public object name, data             # <<<<<<<<<<<<<<
+/* "vidcutter/libs/pympv/mpv.pyx":302
+ *         return _strdec(name_c)
  * 
- *     cdef _init(self, mpv_event_property* prop):
+ *     cdef _init(self, mpv_event* event, ctx):             # <<<<<<<<<<<<<<
+ *         cdef uint64_t ctxid = <uint64_t>id(ctx)
+ *         self.id = event.event_id
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4name___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8Property_4name___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self) {
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv_5Event__init(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, struct mpv_event *__pyx_v_event, PyObject *__pyx_v_ctx) {
+  uint64_t __pyx_v_ctxid;
+  PyObject *__pyx_v_userdata = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__", 0);
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->name);
-  __pyx_r = __pyx_v_self->name;
-  goto __pyx_L0;
-
-  /* function exit code */
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  PyObject *__pyx_t_1 = NULL;
+  uint64_t __pyx_t_2;
+  enum mpv_event_id __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  int __pyx_t_7;
+  PyObject *__pyx_t_8 = NULL;
+  int __pyx_t_9;
+  int __pyx_t_10;
+  int __pyx_t_11;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("_init", 0);
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4name_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+  /* "vidcutter/libs/pympv/mpv.pyx":303
+ * 
+ *     cdef _init(self, mpv_event* event, ctx):
+ *         cdef uint64_t ctxid = <uint64_t>id(ctx)             # <<<<<<<<<<<<<<
+ *         self.id = event.event_id
+ *         self.data = self._data(event)
+ */
+  __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, __pyx_v_ctx); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 303, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyInt_As_uint64_t(__pyx_t_1); if (unlikely((__pyx_t_2 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 303, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_ctxid = ((uint64_t)__pyx_t_2);
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  /* "vidcutter/libs/pympv/mpv.pyx":304
+ *     cdef _init(self, mpv_event* event, ctx):
+ *         cdef uint64_t ctxid = <uint64_t>id(ctx)
+ *         self.id = event.event_id             # <<<<<<<<<<<<<<
+ *         self.data = self._data(event)
+ *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)
+ */
+  __pyx_t_3 = __pyx_v_event->event_id;
+  __pyx_v_self->id = __pyx_t_3;
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_8Property_4name_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __Pyx_INCREF(__pyx_v_value);
-  __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->name);
-  __Pyx_DECREF(__pyx_v_self->name);
-  __pyx_v_self->name = __pyx_v_value;
+  /* "vidcutter/libs/pympv/mpv.pyx":305
+ *         cdef uint64_t ctxid = <uint64_t>id(ctx)
+ *         self.id = event.event_id
+ *         self.data = self._data(event)             # <<<<<<<<<<<<<<
+ *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)
+ *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:
+ */
+  __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Event *)__pyx_v_self->__pyx_vtab)->_data(__pyx_v_self, __pyx_v_event); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 305, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->data);
+  __Pyx_DECREF(__pyx_v_self->data);
+  __pyx_v_self->data = __pyx_t_1;
+  __pyx_t_1 = 0;
 
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  /* "vidcutter/libs/pympv/mpv.pyx":306
+ *         self.id = event.event_id
+ *         self.data = self._data(event)
+ *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)             # <<<<<<<<<<<<<<
+ *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:
+ *             userdata.remove()
+ */
+  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_9vidcutter_4libs_3mpv__reply_userdatas, __pyx_v_ctxid, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 306, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_get); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 306, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = __Pyx_PyInt_From_uint64_t(__pyx_v_event->reply_userdata); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 306, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_6 = NULL;
+  __pyx_t_7 = 0;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
+    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+    if (likely(__pyx_t_6)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+      __Pyx_INCREF(__pyx_t_6);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_5, function);
+      __pyx_t_7 = 1;
+    }
+  }
+  #if CYTHON_FAST_PYCALL
+  if (PyFunction_Check(__pyx_t_5)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_4, Py_None};
+    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 306, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  } else
+  #endif
+  #if CYTHON_FAST_PYCCALL
+  if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_4, Py_None};
+    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 306, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  } else
+  #endif
+  {
+    __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 306, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    if (__pyx_t_6) {
+      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
+    }
+    __Pyx_GIVEREF(__pyx_t_4);
+    PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_4);
+    __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(Py_None);
+    PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, Py_None);
+    __pyx_t_4 = 0;
+    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 306, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+  }
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_v_userdata = __pyx_t_1;
+  __pyx_t_1 = 0;
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4name_5__del__(PyObject *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4name_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self));
+  /* "vidcutter/libs/pympv/mpv.pyx":307
+ *         self.data = self._data(event)
+ *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)
+ *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:             # <<<<<<<<<<<<<<
+ *             userdata.remove()
+ *             if not userdata.observed and userdata.counter <= 0:
+ */
+  __pyx_t_10 = (__pyx_v_userdata != Py_None);
+  __pyx_t_11 = (__pyx_t_10 != 0);
+  if (__pyx_t_11) {
+  } else {
+    __pyx_t_9 = __pyx_t_11;
+    goto __pyx_L4_bool_binop_done;
+  }
+  __pyx_t_11 = ((__pyx_v_self->id != MPV_EVENT_PROPERTY_CHANGE) != 0);
+  __pyx_t_9 = __pyx_t_11;
+  __pyx_L4_bool_binop_done:;
+  if (__pyx_t_9) {
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":308
+ *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)
+ *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:
+ *             userdata.remove()             # <<<<<<<<<<<<<<
+ *             if not userdata.observed and userdata.counter <= 0:
+ *                 del _reply_userdatas[ctxid][event.reply_userdata]
+ */
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdata, __pyx_n_s_remove); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 308, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_8 = NULL;
+    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
+      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_5);
+      if (likely(__pyx_t_8)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_8);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_5, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_8) : __Pyx_PyObject_CallNoArg(__pyx_t_5);
+    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 308, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_8Property_4name_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__", 0);
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->name);
-  __Pyx_DECREF(__pyx_v_self->name);
-  __pyx_v_self->name = Py_None;
+    /* "vidcutter/libs/pympv/mpv.pyx":309
+ *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:
+ *             userdata.remove()
+ *             if not userdata.observed and userdata.counter <= 0:             # <<<<<<<<<<<<<<
+ *                 del _reply_userdatas[ctxid][event.reply_userdata]
+ *         if userdata is not None:
+ */
+    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdata, __pyx_n_s_observed); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 309, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 309, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __pyx_t_10 = ((!__pyx_t_11) != 0);
+    if (__pyx_t_10) {
+    } else {
+      __pyx_t_9 = __pyx_t_10;
+      goto __pyx_L7_bool_binop_done;
+    }
+    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdata, __pyx_n_s_counter); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 309, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_5 = PyObject_RichCompare(__pyx_t_1, __pyx_int_0, Py_LE); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 309, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __pyx_t_10 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_10 < 0)) __PYX_ERR(0, 309, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __pyx_t_9 = __pyx_t_10;
+    __pyx_L7_bool_binop_done:;
+    if (__pyx_t_9) {
 
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+      /* "vidcutter/libs/pympv/mpv.pyx":310
+ *             userdata.remove()
+ *             if not userdata.observed and userdata.counter <= 0:
+ *                 del _reply_userdatas[ctxid][event.reply_userdata]             # <<<<<<<<<<<<<<
+ *         if userdata is not None:
+ *             userdata = userdata.data
+ */
+      __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_9vidcutter_4libs_3mpv__reply_userdatas, __pyx_v_ctxid, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 310, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_5);
+      if (unlikely(__Pyx_DelItemInt(__pyx_t_5, __pyx_v_event->reply_userdata, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 310, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4data___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self));
+      /* "vidcutter/libs/pympv/mpv.pyx":309
+ *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:
+ *             userdata.remove()
+ *             if not userdata.observed and userdata.counter <= 0:             # <<<<<<<<<<<<<<
+ *                 del _reply_userdatas[ctxid][event.reply_userdata]
+ *         if userdata is not None:
+ */
+    }
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":307
+ *         self.data = self._data(event)
+ *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)
+ *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:             # <<<<<<<<<<<<<<
+ *             userdata.remove()
+ *             if not userdata.observed and userdata.counter <= 0:
+ */
+  }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8Property_4data___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__", 0);
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->data);
-  __pyx_r = __pyx_v_self->data;
-  goto __pyx_L0;
+  /* "vidcutter/libs/pympv/mpv.pyx":311
+ *             if not userdata.observed and userdata.counter <= 0:
+ *                 del _reply_userdatas[ctxid][event.reply_userdata]
+ *         if userdata is not None:             # <<<<<<<<<<<<<<
+ *             userdata = userdata.data
+ *         self.reply_userdata = userdata
+ */
+  __pyx_t_9 = (__pyx_v_userdata != Py_None);
+  __pyx_t_10 = (__pyx_t_9 != 0);
+  if (__pyx_t_10) {
 
-  /* function exit code */
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":312
+ *                 del _reply_userdatas[ctxid][event.reply_userdata]
+ *         if userdata is not None:
+ *             userdata = userdata.data             # <<<<<<<<<<<<<<
+ *         self.reply_userdata = userdata
+ *         self.error = event.error
+ */
+    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdata, __pyx_n_s_data); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 312, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF_SET(__pyx_v_userdata, __pyx_t_5);
+    __pyx_t_5 = 0;
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4data_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+    /* "vidcutter/libs/pympv/mpv.pyx":311
+ *             if not userdata.observed and userdata.counter <= 0:
+ *                 del _reply_userdatas[ctxid][event.reply_userdata]
+ *         if userdata is not None:             # <<<<<<<<<<<<<<
+ *             userdata = userdata.data
+ *         self.reply_userdata = userdata
+ */
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":313
+ *         if userdata is not None:
+ *             userdata = userdata.data
+ *         self.reply_userdata = userdata             # <<<<<<<<<<<<<<
+ *         self.error = event.error
+ *         return self
+ */
+  __Pyx_INCREF(__pyx_v_userdata);
+  __Pyx_GIVEREF(__pyx_v_userdata);
+  __Pyx_GOTREF(__pyx_v_self->reply_userdata);
+  __Pyx_DECREF(__pyx_v_self->reply_userdata);
+  __pyx_v_self->reply_userdata = __pyx_v_userdata;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":314
+ *             userdata = userdata.data
+ *         self.reply_userdata = userdata
+ *         self.error = event.error             # <<<<<<<<<<<<<<
+ *         return self
+ * 
+ */
+  __pyx_t_7 = __pyx_v_event->error;
+  __pyx_v_self->error = __pyx_t_7;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":315
+ *         self.reply_userdata = userdata
+ *         self.error = event.error
+ *         return self             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_self));
+  __pyx_r = ((PyObject *)__pyx_v_self);
+  goto __pyx_L0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":302
+ *         return _strdec(name_c)
+ * 
+ *     cdef _init(self, mpv_event* event, ctx):             # <<<<<<<<<<<<<<
+ *         cdef uint64_t ctxid = <uint64_t>id(ctx)
+ *         self.id = event.event_id
+ */
 
   /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Event._init", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_userdata);
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_8Property_4data_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
+/* "vidcutter/libs/pympv/mpv.pyx":258
+ * cdef class Event(object):
+ *     """Wraps: mpv_event"""
+ *     cdef public mpv_event_id id             # <<<<<<<<<<<<<<
+ *     cdef public int error
+ *     cdef public object data, reply_userdata
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_2id_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_2id_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __Pyx_INCREF(__pyx_v_value);
-  __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->data);
-  __Pyx_DECREF(__pyx_v_self->data);
-  __pyx_v_self->data = __pyx_v_value;
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_2id___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
 
   /* function exit code */
-  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_2id___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyInt_From_enum__mpv_event_id(__pyx_v_self->id); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 258, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.id.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
 /* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_8Property_4data_5__del__(PyObject *__pyx_v_self) {
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_2id_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_2id_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_4data_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_2id_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self), ((PyObject *)__pyx_v_value));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_8Property_4data_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self) {
+static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_2id_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, PyObject *__pyx_v_value) {
   int __pyx_r;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__", 0);
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->data);
-  __Pyx_DECREF(__pyx_v_self->data);
-  __pyx_v_self->data = Py_None;
+  enum mpv_event_id __pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__set__", 0);
+  __pyx_t_1 = ((enum mpv_event_id)__Pyx_PyInt_As_enum__mpv_event_id(__pyx_v_value)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 258, __pyx_L1_error)
+  __pyx_v_self->id = __pyx_t_1;
 
   /* function exit code */
   __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.id.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     cdef tuple state
- *     cdef object _dict
+/* "vidcutter/libs/pympv/mpv.pyx":259
+ *     """Wraps: mpv_event"""
+ *     cdef public mpv_event_id id
+ *     cdef public int error             # <<<<<<<<<<<<<<
+ *     cdef public object data, reply_userdata
+ * 
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_5error_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_5error_1__get__(PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property___reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_5error___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8Property___reduce_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self) {
-  PyObject *__pyx_v_state = 0;
-  PyObject *__pyx_v__dict = 0;
-  int __pyx_v_use_setstate;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_5error___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_t_2;
-  int __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  int __pyx_t_5;
-  PyObject *__pyx_t_6 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
-
-  /* "(tree fragment)":5
- *     cdef object _dict
- *     cdef bint use_setstate
- *     state = (self.data, self.name)             # <<<<<<<<<<<<<<
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:
- */
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error)
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->error); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 259, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_v_self->data);
-  __Pyx_GIVEREF(__pyx_v_self->data);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_self->data);
-  __Pyx_INCREF(__pyx_v_self->name);
-  __Pyx_GIVEREF(__pyx_v_self->name);
-  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_self->name);
-  __pyx_v_state = ((PyObject*)__pyx_t_1);
+  __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
+  goto __pyx_L0;
 
-  /* "(tree fragment)":6
- *     cdef bint use_setstate
- *     state = (self.data, self.name)
- *     _dict = getattr(self, '__dict__', None)             # <<<<<<<<<<<<<<
- *     if _dict is not None:
- *         state += (_dict,)
- */
-  __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v__dict = __pyx_t_1;
-  __pyx_t_1 = 0;
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.error.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-  /* "(tree fragment)":7
- *     state = (self.data, self.name)
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:             # <<<<<<<<<<<<<<
- *         state += (_dict,)
- *         use_setstate = True
- */
-  __pyx_t_2 = (__pyx_v__dict != Py_None);
-  __pyx_t_3 = (__pyx_t_2 != 0);
-  if (__pyx_t_3) {
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_5error_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_5error_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_5error_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self), ((PyObject *)__pyx_v_value));
 
-    /* "(tree fragment)":8
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:
- *         state += (_dict,)             # <<<<<<<<<<<<<<
- *         use_setstate = True
- *     else:
- */
-    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_INCREF(__pyx_v__dict);
-    __Pyx_GIVEREF(__pyx_v__dict);
-    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict);
-    __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 8, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4));
-    __pyx_t_4 = 0;
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-    /* "(tree fragment)":9
- *     if _dict is not None:
- *         state += (_dict,)
- *         use_setstate = True             # <<<<<<<<<<<<<<
- *     else:
- *         use_setstate = self.data is not None or self.name is not None
- */
-    __pyx_v_use_setstate = 1;
-
-    /* "(tree fragment)":7
- *     state = (self.data, self.name)
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:             # <<<<<<<<<<<<<<
- *         state += (_dict,)
- *         use_setstate = True
- */
-    goto __pyx_L3;
-  }
-
-  /* "(tree fragment)":11
- *         use_setstate = True
- *     else:
- *         use_setstate = self.data is not None or self.name is not None             # <<<<<<<<<<<<<<
- *     if use_setstate:
- *         return __pyx_unpickle_Property, (type(self), 0x0572d11, None), state
- */
-  /*else*/ {
-    __pyx_t_2 = (__pyx_v_self->data != Py_None);
-    __pyx_t_5 = (__pyx_t_2 != 0);
-    if (!__pyx_t_5) {
-    } else {
-      __pyx_t_3 = __pyx_t_5;
-      goto __pyx_L4_bool_binop_done;
-    }
-    __pyx_t_5 = (__pyx_v_self->name != Py_None);
-    __pyx_t_2 = (__pyx_t_5 != 0);
-    __pyx_t_3 = __pyx_t_2;
-    __pyx_L4_bool_binop_done:;
-    __pyx_v_use_setstate = __pyx_t_3;
-  }
-  __pyx_L3:;
-
-  /* "(tree fragment)":12
- *     else:
- *         use_setstate = self.data is not None or self.name is not None
- *     if use_setstate:             # <<<<<<<<<<<<<<
- *         return __pyx_unpickle_Property, (type(self), 0x0572d11, None), state
- *     else:
- */
-  __pyx_t_3 = (__pyx_v_use_setstate != 0);
-  if (__pyx_t_3) {
-
-    /* "(tree fragment)":13
- *         use_setstate = self.data is not None or self.name is not None
- *     if use_setstate:
- *         return __pyx_unpickle_Property, (type(self), 0x0572d11, None), state             # <<<<<<<<<<<<<<
- *     else:
- *         return __pyx_unpickle_Property, (type(self), 0x0572d11, state)
- */
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_Property); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 13, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_INCREF(__pyx_int_5713169);
-    __Pyx_GIVEREF(__pyx_int_5713169);
-    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_5713169);
-    __Pyx_INCREF(Py_None);
-    __Pyx_GIVEREF(Py_None);
-    PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None);
-    __pyx_t_6 = PyTuple_New(3); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 13, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_GIVEREF(__pyx_t_4);
-    PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_4);
-    __Pyx_GIVEREF(__pyx_t_1);
-    PyTuple_SET_ITEM(__pyx_t_6, 1, __pyx_t_1);
-    __Pyx_INCREF(__pyx_v_state);
-    __Pyx_GIVEREF(__pyx_v_state);
-    PyTuple_SET_ITEM(__pyx_t_6, 2, __pyx_v_state);
-    __pyx_t_4 = 0;
-    __pyx_t_1 = 0;
-    __pyx_r = __pyx_t_6;
-    __pyx_t_6 = 0;
-    goto __pyx_L0;
-
-    /* "(tree fragment)":12
- *     else:
- *         use_setstate = self.data is not None or self.name is not None
- *     if use_setstate:             # <<<<<<<<<<<<<<
- *         return __pyx_unpickle_Property, (type(self), 0x0572d11, None), state
- *     else:
- */
-  }
-
-  /* "(tree fragment)":15
- *         return __pyx_unpickle_Property, (type(self), 0x0572d11, None), state
- *     else:
- *         return __pyx_unpickle_Property, (type(self), 0x0572d11, state)             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     __pyx_unpickle_Property__set_state(self, __pyx_state)
- */
-  /*else*/ {
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_pyx_unpickle_Property); if (unlikely(!__pyx_t_6)) __PYX_ERR(1, 15, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_INCREF(__pyx_int_5713169);
-    __Pyx_GIVEREF(__pyx_int_5713169);
-    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_5713169);
-    __Pyx_INCREF(__pyx_v_state);
-    __Pyx_GIVEREF(__pyx_v_state);
-    PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state);
-    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 15, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_GIVEREF(__pyx_t_6);
-    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_6);
-    __Pyx_GIVEREF(__pyx_t_1);
-    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1);
-    __pyx_t_6 = 0;
-    __pyx_t_1 = 0;
-    __pyx_r = __pyx_t_4;
-    __pyx_t_4 = 0;
-    goto __pyx_L0;
-  }
-
-  /* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     cdef tuple state
- *     cdef object _dict
- */
+static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_5error_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__set__", 0);
+  __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 259, __pyx_L1_error)
+  __pyx_v_self->error = __pyx_t_1;
 
   /* function exit code */
+  __pyx_r = 0;
+  goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Property.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.error.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_state);
-  __Pyx_XDECREF(__pyx_v__dict);
-  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "(tree fragment)":16
- *     else:
- *         return __pyx_unpickle_Property, (type(self), 0x0572d11, state)
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     __pyx_unpickle_Property__set_state(self, __pyx_state)
+/* "vidcutter/libs/pympv/mpv.pyx":260
+ *     cdef public mpv_event_id id
+ *     cdef public int error
+ *     cdef public object data, reply_userdata             # <<<<<<<<<<<<<<
+ * 
+ *     @property
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8Property_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_1__get__(PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8Property_2__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_4data___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8Property_2__setstate_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_Property *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_4data___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
-
-  /* "(tree fragment)":17
- *         return __pyx_unpickle_Property, (type(self), 0x0572d11, state)
- * def __setstate_cython__(self, __pyx_state):
- *     __pyx_unpickle_Property__set_state(self, __pyx_state)             # <<<<<<<<<<<<<<
- */
-  if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error)
-  __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_Property__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-  /* "(tree fragment)":16
- *     else:
- *         return __pyx_unpickle_Property, (type(self), 0x0572d11, state)
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     __pyx_unpickle_Property__set_state(self, __pyx_state)
- */
+  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_self->data);
+  __pyx_r = __pyx_v_self->data;
+  goto __pyx_L0;
 
   /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Property.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":263
- * 
- *     @property
- *     def error_str(self):             # <<<<<<<<<<<<<<
- *         """mpv_error_string of the error proeprty"""
- *         cdef const char* err_c
- */
-
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_9error_str_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_9error_str_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_9error_str___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_4data_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self), ((PyObject *)__pyx_v_value));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_9error_str___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
-  char const *__pyx_v_err_c;
-  PyObject *__pyx_r = NULL;
+static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_4data_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_RefNannySetupContext("__set__", 0);
+  __Pyx_INCREF(__pyx_v_value);
+  __Pyx_GIVEREF(__pyx_v_value);
+  __Pyx_GOTREF(__pyx_v_self->data);
+  __Pyx_DECREF(__pyx_v_self->data);
+  __pyx_v_self->data = __pyx_v_value;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":266
- *         """mpv_error_string of the error proeprty"""
- *         cdef const char* err_c
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err_c = mpv_error_string(self.error)
- *         return _strdec(err_c)
- */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-        /* "vidcutter/libs/pympv/mpv.pyx":267
- *         cdef const char* err_c
- *         with nogil:
- *             err_c = mpv_error_string(self.error)             # <<<<<<<<<<<<<<
- *         return _strdec(err_c)
- * 
- */
-        __pyx_v_err_c = mpv_error_string(__pyx_v_self->error);
-      }
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_5__del__(PyObject *__pyx_v_self); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_5__del__(PyObject *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_4data_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
 
-      /* "vidcutter/libs/pympv/mpv.pyx":266
- *         """mpv_error_string of the error proeprty"""
- *         cdef const char* err_c
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err_c = mpv_error_string(self.error)
- *         return _strdec(err_c)
- */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
-  }
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-  /* "vidcutter/libs/pympv/mpv.pyx":268
- *         with nogil:
- *             err_c = mpv_error_string(self.error)
- *         return _strdec(err_c)             # <<<<<<<<<<<<<<
- * 
- *     cdef _data(self, mpv_event* event):
- */
+static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_4data_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__", 0);
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->data);
+  __Pyx_DECREF(__pyx_v_self->data);
+  __pyx_v_self->data = Py_None;
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__get__", 0);
   __Pyx_XDECREF(__pyx_r);
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 268, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_err_c); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 268, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 268, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
+  __Pyx_INCREF(__pyx_v_self->reply_userdata);
+  __pyx_r = __pyx_v_self->reply_userdata;
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":263
- * 
- *     @property
- *     def error_str(self):             # <<<<<<<<<<<<<<
- *         """mpv_error_string of the error proeprty"""
- *         cdef const char* err_c
- */
-
   /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.error_str.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":270
- *         return _strdec(err_c)
- * 
- *     cdef _data(self, mpv_event* event):             # <<<<<<<<<<<<<<
- *         cdef void* data = event.data
- *         cdef mpv_event_client_message* climsg
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, PyObject *__pyx_v_value) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__set__", 0);
+  __Pyx_INCREF(__pyx_v_value);
+  __Pyx_GIVEREF(__pyx_v_value);
+  __Pyx_GOTREF(__pyx_v_self->reply_userdata);
+  __Pyx_DECREF(__pyx_v_self->reply_userdata);
+  __pyx_v_self->reply_userdata = __pyx_v_value;
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_5__del__(PyObject *__pyx_v_self); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_5__del__(PyObject *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__del__", 0);
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->reply_userdata);
+  __Pyx_DECREF(__pyx_v_self->reply_userdata);
+  __pyx_v_self->reply_userdata = Py_None;
+
+  /* function exit code */
+  __pyx_r = 0;
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "(tree fragment)":1
+ * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
+ *     cdef tuple state
+ *     cdef object _dict
  */
 
-static PyObject *__pyx_f_9vidcutter_4libs_3mpv_5Event__data(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, struct mpv_event *__pyx_v_event) {
-  void *__pyx_v_data;
-  struct mpv_event_client_message *__pyx_v_climsg;
-  PyObject *__pyx_v_args = NULL;
-  int __pyx_v_num_args;
-  int __pyx_v_i;
-  PyObject *__pyx_v_arg = NULL;
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event___reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event___reduce_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
+  PyObject *__pyx_v_state = 0;
+  PyObject *__pyx_v__dict = 0;
+  int __pyx_v_use_setstate;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  void *__pyx_t_1;
+  PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
   int __pyx_t_4;
   int __pyx_t_5;
   int __pyx_t_6;
-  PyObject *__pyx_t_7 = NULL;
-  int __pyx_t_8;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_data", 0);
+  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":271
- * 
- *     cdef _data(self, mpv_event* event):
- *         cdef void* data = event.data             # <<<<<<<<<<<<<<
- *         cdef mpv_event_client_message* climsg
- *         if self.id == MPV_EVENT_GET_PROPERTY_REPLY:
+  /* "(tree fragment)":5
+ *     cdef object _dict
+ *     cdef bint use_setstate
+ *     state = (self.data, self.error, self.id, self.reply_userdata)             # <<<<<<<<<<<<<<
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:
  */
-  __pyx_t_1 = __pyx_v_event->data;
-  __pyx_v_data = __pyx_t_1;
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->error); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyInt_From_enum__mpv_event_id(__pyx_v_self->id); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyTuple_New(4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_self->data);
+  __Pyx_GIVEREF(__pyx_v_self->data);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_self->data);
+  __Pyx_GIVEREF(__pyx_t_1);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_2);
+  PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_2);
+  __Pyx_INCREF(__pyx_v_self->reply_userdata);
+  __Pyx_GIVEREF(__pyx_v_self->reply_userdata);
+  PyTuple_SET_ITEM(__pyx_t_3, 3, __pyx_v_self->reply_userdata);
+  __pyx_t_1 = 0;
+  __pyx_t_2 = 0;
+  __pyx_v_state = ((PyObject*)__pyx_t_3);
+  __pyx_t_3 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":273
- *         cdef void* data = event.data
- *         cdef mpv_event_client_message* climsg
- *         if self.id == MPV_EVENT_GET_PROPERTY_REPLY:             # <<<<<<<<<<<<<<
- *             return Property()._init(<mpv_event_property*>data)
- *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:
- */
-  switch (__pyx_v_self->id) {
-    case MPV_EVENT_GET_PROPERTY_REPLY:
-
-    /* "vidcutter/libs/pympv/mpv.pyx":274
- *         cdef mpv_event_client_message* climsg
- *         if self.id == MPV_EVENT_GET_PROPERTY_REPLY:
- *             return Property()._init(<mpv_event_property*>data)             # <<<<<<<<<<<<<<
- *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:
- *             return Property()._init(<mpv_event_property*>data)
+  /* "(tree fragment)":6
+ *     cdef bint use_setstate
+ *     state = (self.data, self.error, self.id, self.reply_userdata)
+ *     _dict = getattr(self, '__dict__', None)             # <<<<<<<<<<<<<<
+ *     if _dict is not None:
+ *         state += (_dict,)
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_2 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_Property)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 274, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Property *)((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_t_2)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_t_2), ((struct mpv_event_property *)__pyx_v_data)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 274, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_r = __pyx_t_3;
-    __pyx_t_3 = 0;
-    goto __pyx_L0;
+  __pyx_t_3 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 6, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_v__dict = __pyx_t_3;
+  __pyx_t_3 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":273
- *         cdef void* data = event.data
- *         cdef mpv_event_client_message* climsg
- *         if self.id == MPV_EVENT_GET_PROPERTY_REPLY:             # <<<<<<<<<<<<<<
- *             return Property()._init(<mpv_event_property*>data)
- *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:
+  /* "(tree fragment)":7
+ *     state = (self.data, self.error, self.id, self.reply_userdata)
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:             # <<<<<<<<<<<<<<
+ *         state += (_dict,)
+ *         use_setstate = True
  */
-    break;
-    case MPV_EVENT_PROPERTY_CHANGE:
+  __pyx_t_4 = (__pyx_v__dict != Py_None);
+  __pyx_t_5 = (__pyx_t_4 != 0);
+  if (__pyx_t_5) {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":276
- *             return Property()._init(<mpv_event_property*>data)
- *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:
- *             return Property()._init(<mpv_event_property*>data)             # <<<<<<<<<<<<<<
- *         elif self.id == MPV_EVENT_LOG_MESSAGE:
- *             return LogMessage()._init(<mpv_event_log_message*>data)
+    /* "(tree fragment)":8
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:
+ *         state += (_dict,)             # <<<<<<<<<<<<<<
+ *         use_setstate = True
+ *     else:
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_Property)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 276, __pyx_L1_error)
+    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 8, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Property *)((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_t_3)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_Property *)__pyx_t_3), ((struct mpv_event_property *)__pyx_v_data)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 276, __pyx_L1_error)
+    __Pyx_INCREF(__pyx_v__dict);
+    __Pyx_GIVEREF(__pyx_v__dict);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v__dict);
+    __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 8, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_r = __pyx_t_2;
+    __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_2));
     __pyx_t_2 = 0;
-    goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":275
- *         if self.id == MPV_EVENT_GET_PROPERTY_REPLY:
- *             return Property()._init(<mpv_event_property*>data)
- *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:             # <<<<<<<<<<<<<<
- *             return Property()._init(<mpv_event_property*>data)
- *         elif self.id == MPV_EVENT_LOG_MESSAGE:
+    /* "(tree fragment)":9
+ *     if _dict is not None:
+ *         state += (_dict,)
+ *         use_setstate = True             # <<<<<<<<<<<<<<
+ *     else:
+ *         use_setstate = self.data is not None or self.reply_userdata is not None
  */
-    break;
-    case MPV_EVENT_LOG_MESSAGE:
+    __pyx_v_use_setstate = 1;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":278
- *             return Property()._init(<mpv_event_property*>data)
- *         elif self.id == MPV_EVENT_LOG_MESSAGE:
- *             return LogMessage()._init(<mpv_event_log_message*>data)             # <<<<<<<<<<<<<<
- *         elif self.id == MPV_EVENT_SCRIPT_INPUT_DISPATCH:
- *             return InputDispatch()._init(<mpv_event_script_input_dispatch*>data)
+    /* "(tree fragment)":7
+ *     state = (self.data, self.error, self.id, self.reply_userdata)
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:             # <<<<<<<<<<<<<<
+ *         state += (_dict,)
+ *         use_setstate = True
+ */
+    goto __pyx_L3;
+  }
+
+  /* "(tree fragment)":11
+ *         use_setstate = True
+ *     else:
+ *         use_setstate = self.data is not None or self.reply_userdata is not None             # <<<<<<<<<<<<<<
+ *     if use_setstate:
+ *         return __pyx_unpickle_Event, (type(self), 0xda38c25, None), state
+ */
+  /*else*/ {
+    __pyx_t_4 = (__pyx_v_self->data != Py_None);
+    __pyx_t_6 = (__pyx_t_4 != 0);
+    if (!__pyx_t_6) {
+    } else {
+      __pyx_t_5 = __pyx_t_6;
+      goto __pyx_L4_bool_binop_done;
+    }
+    __pyx_t_6 = (__pyx_v_self->reply_userdata != Py_None);
+    __pyx_t_4 = (__pyx_t_6 != 0);
+    __pyx_t_5 = __pyx_t_4;
+    __pyx_L4_bool_binop_done:;
+    __pyx_v_use_setstate = __pyx_t_5;
+  }
+  __pyx_L3:;
+
+  /* "(tree fragment)":12
+ *     else:
+ *         use_setstate = self.data is not None or self.reply_userdata is not None
+ *     if use_setstate:             # <<<<<<<<<<<<<<
+ *         return __pyx_unpickle_Event, (type(self), 0xda38c25, None), state
+ *     else:
+ */
+  __pyx_t_5 = (__pyx_v_use_setstate != 0);
+  if (__pyx_t_5) {
+
+    /* "(tree fragment)":13
+ *         use_setstate = self.data is not None or self.reply_userdata is not None
+ *     if use_setstate:
+ *         return __pyx_unpickle_Event, (type(self), 0xda38c25, None), state             # <<<<<<<<<<<<<<
+ *     else:
+ *         return __pyx_unpickle_Event, (type(self), 0xda38c25, state)
  */
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_2 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_LogMessage)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 278, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_pyx_unpickle_Event); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 13, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_LogMessage *)((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_t_2)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_LogMessage *)__pyx_t_2), ((struct mpv_event_log_message *)__pyx_v_data)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 278, __pyx_L1_error)
+    __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 13, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_r = __pyx_t_3;
+    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_INCREF(__pyx_int_228822053);
+    __Pyx_GIVEREF(__pyx_int_228822053);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_int_228822053);
+    __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(Py_None);
+    PyTuple_SET_ITEM(__pyx_t_3, 2, Py_None);
+    __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_GIVEREF(__pyx_t_2);
+    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
+    __Pyx_GIVEREF(__pyx_t_3);
+    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3);
+    __Pyx_INCREF(__pyx_v_state);
+    __Pyx_GIVEREF(__pyx_v_state);
+    PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state);
+    __pyx_t_2 = 0;
     __pyx_t_3 = 0;
+    __pyx_r = __pyx_t_1;
+    __pyx_t_1 = 0;
     goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":277
- *         elif self.id == MPV_EVENT_PROPERTY_CHANGE:
- *             return Property()._init(<mpv_event_property*>data)
- *         elif self.id == MPV_EVENT_LOG_MESSAGE:             # <<<<<<<<<<<<<<
- *             return LogMessage()._init(<mpv_event_log_message*>data)
- *         elif self.id == MPV_EVENT_SCRIPT_INPUT_DISPATCH:
+    /* "(tree fragment)":12
+ *     else:
+ *         use_setstate = self.data is not None or self.reply_userdata is not None
+ *     if use_setstate:             # <<<<<<<<<<<<<<
+ *         return __pyx_unpickle_Event, (type(self), 0xda38c25, None), state
+ *     else:
  */
-    break;
-    case MPV_EVENT_SCRIPT_INPUT_DISPATCH:
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":280
- *             return LogMessage()._init(<mpv_event_log_message*>data)
- *         elif self.id == MPV_EVENT_SCRIPT_INPUT_DISPATCH:
- *             return InputDispatch()._init(<mpv_event_script_input_dispatch*>data)             # <<<<<<<<<<<<<<
- *         elif self.id == MPV_EVENT_CLIENT_MESSAGE:
- *             climsg = <mpv_event_client_message*>data
+  /* "(tree fragment)":15
+ *         return __pyx_unpickle_Event, (type(self), 0xda38c25, None), state
+ *     else:
+ *         return __pyx_unpickle_Event, (type(self), 0xda38c25, state)             # <<<<<<<<<<<<<<
+ * def __setstate_cython__(self, __pyx_state):
+ *     __pyx_unpickle_Event__set_state(self, __pyx_state)
  */
+  /*else*/ {
     __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_InputDispatch)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 280, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_pyx_unpickle_Event); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 15, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_2 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_InputDispatch *)((struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *)__pyx_t_3)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_InputDispatch *)__pyx_t_3), ((struct mpv_event_script_input_dispatch *)__pyx_v_data)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 280, __pyx_L1_error)
+    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_INCREF(__pyx_int_228822053);
+    __Pyx_GIVEREF(__pyx_int_228822053);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_int_228822053);
+    __Pyx_INCREF(__pyx_v_state);
+    __Pyx_GIVEREF(__pyx_v_state);
+    PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_state);
+    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 15, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_GIVEREF(__pyx_t_1);
+    PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
+    __Pyx_GIVEREF(__pyx_t_3);
+    PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3);
+    __pyx_t_1 = 0;
+    __pyx_t_3 = 0;
     __pyx_r = __pyx_t_2;
     __pyx_t_2 = 0;
     goto __pyx_L0;
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":279
- *         elif self.id == MPV_EVENT_LOG_MESSAGE:
- *             return LogMessage()._init(<mpv_event_log_message*>data)
- *         elif self.id == MPV_EVENT_SCRIPT_INPUT_DISPATCH:             # <<<<<<<<<<<<<<
- *             return InputDispatch()._init(<mpv_event_script_input_dispatch*>data)
- *         elif self.id == MPV_EVENT_CLIENT_MESSAGE:
+  /* "(tree fragment)":1
+ * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
+ *     cdef tuple state
+ *     cdef object _dict
  */
-    break;
-    case MPV_EVENT_CLIENT_MESSAGE:
 
-    /* "vidcutter/libs/pympv/mpv.pyx":282
- *             return InputDispatch()._init(<mpv_event_script_input_dispatch*>data)
- *         elif self.id == MPV_EVENT_CLIENT_MESSAGE:
- *             climsg = <mpv_event_client_message*>data             # <<<<<<<<<<<<<<
- *             args = []
- *             num_args = climsg.num_args
- */
-    __pyx_v_climsg = ((struct mpv_event_client_message *)__pyx_v_data);
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_state);
+  __Pyx_XDECREF(__pyx_v__dict);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-    /* "vidcutter/libs/pympv/mpv.pyx":283
- *         elif self.id == MPV_EVENT_CLIENT_MESSAGE:
- *             climsg = <mpv_event_client_message*>data
- *             args = []             # <<<<<<<<<<<<<<
- *             num_args = climsg.num_args
- *             for i in range(num_args):
+/* "(tree fragment)":16
+ *     else:
+ *         return __pyx_unpickle_Event, (type(self), 0xda38c25, state)
+ * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
+ *     __pyx_unpickle_Event__set_state(self, __pyx_state)
  */
-    __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 283, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_v_args = ((PyObject*)__pyx_t_2);
-    __pyx_t_2 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":284
- *             climsg = <mpv_event_client_message*>data
- *             args = []
- *             num_args = climsg.num_args             # <<<<<<<<<<<<<<
- *             for i in range(num_args):
- *                 arg = <char*>climsg.args[i]
- */
-    __pyx_t_4 = __pyx_v_climsg->num_args;
-    __pyx_v_num_args = __pyx_t_4;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":285
- *             args = []
- *             num_args = climsg.num_args
- *             for i in range(num_args):             # <<<<<<<<<<<<<<
- *                 arg = <char*>climsg.args[i]
- *                 arg = _strdec(arg)
- */
-    __pyx_t_4 = __pyx_v_num_args;
-    __pyx_t_5 = __pyx_t_4;
-    for (__pyx_t_6 = 0; __pyx_t_6 < __pyx_t_5; __pyx_t_6+=1) {
-      __pyx_v_i = __pyx_t_6;
-
-      /* "vidcutter/libs/pympv/mpv.pyx":286
- *             num_args = climsg.num_args
- *             for i in range(num_args):
- *                 arg = <char*>climsg.args[i]             # <<<<<<<<<<<<<<
- *                 arg = _strdec(arg)
- *                 args.append(arg)
- */
-      __pyx_t_2 = __Pyx_PyBytes_FromString(((char *)(__pyx_v_climsg->args[__pyx_v_i]))); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 286, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_XDECREF_SET(__pyx_v_arg, __pyx_t_2);
-      __pyx_t_2 = 0;
-
-      /* "vidcutter/libs/pympv/mpv.pyx":287
- *             for i in range(num_args):
- *                 arg = <char*>climsg.args[i]
- *                 arg = _strdec(arg)             # <<<<<<<<<<<<<<
- *                 args.append(arg)
- *             return args
- */
-      __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_strdec); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 287, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_7 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_7)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_7);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
-        }
-      }
-      __pyx_t_2 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_7, __pyx_v_arg) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_arg);
-      __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-      if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 287, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_2);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF_SET(__pyx_v_arg, __pyx_t_2);
-      __pyx_t_2 = 0;
-
-      /* "vidcutter/libs/pympv/mpv.pyx":288
- *                 arg = <char*>climsg.args[i]
- *                 arg = _strdec(arg)
- *                 args.append(arg)             # <<<<<<<<<<<<<<
- *             return args
- *         elif self.id == MPV_EVENT_END_FILE:
- */
-      __pyx_t_8 = __Pyx_PyList_Append(__pyx_v_args, __pyx_v_arg); if (unlikely(__pyx_t_8 == ((int)-1))) __PYX_ERR(0, 288, __pyx_L1_error)
-    }
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_2__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
 
-    /* "vidcutter/libs/pympv/mpv.pyx":289
- *                 arg = _strdec(arg)
- *                 args.append(arg)
- *             return args             # <<<<<<<<<<<<<<
- *         elif self.id == MPV_EVENT_END_FILE:
- *             return EndOfFileReached()._init(<mpv_event_end_file*>data)
- */
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_INCREF(__pyx_v_args);
-    __pyx_r = __pyx_v_args;
-    goto __pyx_L0;
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-    /* "vidcutter/libs/pympv/mpv.pyx":281
- *         elif self.id == MPV_EVENT_SCRIPT_INPUT_DISPATCH:
- *             return InputDispatch()._init(<mpv_event_script_input_dispatch*>data)
- *         elif self.id == MPV_EVENT_CLIENT_MESSAGE:             # <<<<<<<<<<<<<<
- *             climsg = <mpv_event_client_message*>data
- *             args = []
- */
-    break;
-    case MPV_EVENT_END_FILE:
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_2__setstate_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
 
-    /* "vidcutter/libs/pympv/mpv.pyx":291
- *             return args
- *         elif self.id == MPV_EVENT_END_FILE:
- *             return EndOfFileReached()._init(<mpv_event_end_file*>data)             # <<<<<<<<<<<<<<
- *         return None
- * 
+  /* "(tree fragment)":17
+ *         return __pyx_unpickle_Event, (type(self), 0xda38c25, state)
+ * def __setstate_cython__(self, __pyx_state):
+ *     __pyx_unpickle_Event__set_state(self, __pyx_state)             # <<<<<<<<<<<<<<
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_2 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_EndOfFileReached)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 291, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_EndOfFileReached *)((struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached *)__pyx_t_2)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_EndOfFileReached *)__pyx_t_2), ((struct mpv_event_end_file *)__pyx_v_data)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 291, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_r = __pyx_t_3;
-    __pyx_t_3 = 0;
-    goto __pyx_L0;
+  if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_Event__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":290
- *                 args.append(arg)
- *             return args
- *         elif self.id == MPV_EVENT_END_FILE:             # <<<<<<<<<<<<<<
- *             return EndOfFileReached()._init(<mpv_event_end_file*>data)
- *         return None
+  /* "(tree fragment)":16
+ *     else:
+ *         return __pyx_unpickle_Event, (type(self), 0xda38c25, state)
+ * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
+ *     __pyx_unpickle_Event__set_state(self, __pyx_state)
  */
-    break;
-    default: break;
-  }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":292
- *         elif self.id == MPV_EVENT_END_FILE:
- *             return EndOfFileReached()._init(<mpv_event_end_file*>data)
- *         return None             # <<<<<<<<<<<<<<
- * 
- *     @property
- */
-  __Pyx_XDECREF(__pyx_r);
+  /* function exit code */
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-  /* "vidcutter/libs/pympv/mpv.pyx":270
- *         return _strdec(err_c)
+/* "vidcutter/libs/pympv/mpv.pyx":318
  * 
- *     cdef _data(self, mpv_event* event):             # <<<<<<<<<<<<<<
- *         cdef void* data = event.data
- *         cdef mpv_event_client_message* climsg
+ * 
+ * def _errors(fn):             # <<<<<<<<<<<<<<
+ *     def wrapped(*k, **kw):
+ *         v = fn(*k, **kw)
  */
 
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5_errors(PyObject *__pyx_self, PyObject *__pyx_v_fn); /*proto*/
+static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_5_errors = {"_errors", (PyCFunction)__pyx_pw_9vidcutter_4libs_3mpv_5_errors, METH_O, 0};
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5_errors(PyObject *__pyx_self, PyObject *__pyx_v_fn) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("_errors (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_4_errors(__pyx_self, ((PyObject *)__pyx_v_fn));
+
   /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Event._data", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_args);
-  __Pyx_XDECREF(__pyx_v_arg);
-  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":295
+/* "vidcutter/libs/pympv/mpv.pyx":319
  * 
- *     @property
- *     def name(self):             # <<<<<<<<<<<<<<
- *         """mpv_event_name of the event id"""
- *         cdef const char* name_c
+ * def _errors(fn):
+ *     def wrapped(*k, **kw):             # <<<<<<<<<<<<<<
+ *         v = fn(*k, **kw)
+ *         if v < 0:
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_4name_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_4name_1__get__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7_errors_1wrapped(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_7_errors_1wrapped = {"wrapped", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9vidcutter_4libs_3mpv_7_errors_1wrapped, METH_VARARGS|METH_KEYWORDS, 0};
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7_errors_1wrapped(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_k = 0;
+  PyObject *__pyx_v_kw = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_4name___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("wrapped (wrapper)", 0);
+  if (unlikely(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "wrapped", 1))) return NULL;
+  __pyx_v_kw = (__pyx_kwds) ? PyDict_Copy(__pyx_kwds) : PyDict_New(); if (unlikely(!__pyx_v_kw)) return NULL;
+  __Pyx_GOTREF(__pyx_v_kw);
+  __Pyx_INCREF(__pyx_args);
+  __pyx_v_k = __pyx_args;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7_errors_wrapped(__pyx_self, __pyx_v_k, __pyx_v_kw);
 
   /* function exit code */
+  __Pyx_XDECREF(__pyx_v_k);
+  __Pyx_XDECREF(__pyx_v_kw);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_4name___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
-  char const *__pyx_v_name_c;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7_errors_wrapped(PyObject *__pyx_self, PyObject *__pyx_v_k, PyObject *__pyx_v_kw) {
+  struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *__pyx_cur_scope;
+  struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *__pyx_outer_scope;
+  PyObject *__pyx_v_v = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
+  int __pyx_t_3;
   PyObject *__pyx_t_4 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_RefNannySetupContext("wrapped", 0);
+  __pyx_outer_scope = (struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *) __Pyx_CyFunction_GetClosure(__pyx_self);
+  __pyx_cur_scope = __pyx_outer_scope;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":298
- *         """mpv_event_name of the event id"""
- *         cdef const char* name_c
- *         with nogil:             # <<<<<<<<<<<<<<
- *             name_c = mpv_event_name(self.id)
- *         return _strdec(name_c)
+  /* "vidcutter/libs/pympv/mpv.pyx":320
+ * def _errors(fn):
+ *     def wrapped(*k, **kw):
+ *         v = fn(*k, **kw)             # <<<<<<<<<<<<<<
+ *         if v < 0:
+ *             raise MPVError(v)
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+  if (unlikely(!__pyx_cur_scope->__pyx_v_fn)) { __Pyx_RaiseClosureNameError("fn"); __PYX_ERR(0, 320, __pyx_L1_error) }
+  __pyx_t_1 = PyDict_Copy(__pyx_v_kw); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 320, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyObject_Call(__pyx_cur_scope->__pyx_v_fn, __pyx_v_k, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 320, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_v = __pyx_t_2;
+  __pyx_t_2 = 0;
 
-        /* "vidcutter/libs/pympv/mpv.pyx":299
- *         cdef const char* name_c
- *         with nogil:
- *             name_c = mpv_event_name(self.id)             # <<<<<<<<<<<<<<
- *         return _strdec(name_c)
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":321
+ *     def wrapped(*k, **kw):
+ *         v = fn(*k, **kw)
+ *         if v < 0:             # <<<<<<<<<<<<<<
+ *             raise MPVError(v)
+ *     return wrapped
  */
-        __pyx_v_name_c = mpv_event_name(__pyx_v_self->id);
-      }
+  __pyx_t_2 = PyObject_RichCompare(__pyx_v_v, __pyx_int_0, Py_LT); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 321, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 321, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (unlikely(__pyx_t_3)) {
 
-      /* "vidcutter/libs/pympv/mpv.pyx":298
- *         """mpv_event_name of the event id"""
- *         cdef const char* name_c
- *         with nogil:             # <<<<<<<<<<<<<<
- *             name_c = mpv_event_name(self.id)
- *         return _strdec(name_c)
+    /* "vidcutter/libs/pympv/mpv.pyx":322
+ *         v = fn(*k, **kw)
+ *         if v < 0:
+ *             raise MPVError(v)             # <<<<<<<<<<<<<<
+ *     return wrapped
+ * 
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
+    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 322, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
+      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_1);
+      if (likely(__pyx_t_4)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
+        __Pyx_INCREF(__pyx_t_4);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_1, function);
       }
-  }
+    }
+    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_4, __pyx_v_v) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_v);
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 322, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 322, __pyx_L1_error)
 
-  /* "vidcutter/libs/pympv/mpv.pyx":300
- *         with nogil:
- *             name_c = mpv_event_name(self.id)
- *         return _strdec(name_c)             # <<<<<<<<<<<<<<
- * 
- *     cdef _init(self, mpv_event* event, ctx):
+    /* "vidcutter/libs/pympv/mpv.pyx":321
+ *     def wrapped(*k, **kw):
+ *         v = fn(*k, **kw)
+ *         if v < 0:             # <<<<<<<<<<<<<<
+ *             raise MPVError(v)
+ *     return wrapped
  */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 300, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_name_c); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 300, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-    }
   }
-  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 300, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":295
+  /* "vidcutter/libs/pympv/mpv.pyx":319
  * 
- *     @property
- *     def name(self):             # <<<<<<<<<<<<<<
- *         """mpv_event_name of the event id"""
- *         cdef const char* name_c
+ * def _errors(fn):
+ *     def wrapped(*k, **kw):             # <<<<<<<<<<<<<<
+ *         v = fn(*k, **kw)
+ *         if v < 0:
  */
 
   /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.name.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._errors.wrapped", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_v);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":302
- *         return _strdec(name_c)
+/* "vidcutter/libs/pympv/mpv.pyx":318
  * 
- *     cdef _init(self, mpv_event* event, ctx):             # <<<<<<<<<<<<<<
- *         cdef uint64_t ctxid = <uint64_t>id(ctx)
- *         self.id = event.event_id
+ * 
+ * def _errors(fn):             # <<<<<<<<<<<<<<
+ *     def wrapped(*k, **kw):
+ *         v = fn(*k, **kw)
  */
 
-static PyObject *__pyx_f_9vidcutter_4libs_3mpv_5Event__init(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, struct mpv_event *__pyx_v_event, PyObject *__pyx_v_ctx) {
-  uint64_t __pyx_v_ctxid;
-  PyObject *__pyx_v_userdata = NULL;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_4_errors(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_fn) {
+  struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *__pyx_cur_scope;
+  PyObject *__pyx_v_wrapped = 0;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  uint64_t __pyx_t_2;
-  enum mpv_event_id __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  int __pyx_t_7;
-  PyObject *__pyx_t_8 = NULL;
-  int __pyx_t_9;
-  int __pyx_t_10;
-  int __pyx_t_11;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_init", 0);
+  __Pyx_RefNannySetupContext("_errors", 0);
+  __pyx_cur_scope = (struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *)__pyx_tp_new_9vidcutter_4libs_3mpv___pyx_scope_struct___errors(__pyx_ptype_9vidcutter_4libs_3mpv___pyx_scope_struct___errors, __pyx_empty_tuple, NULL);
+  if (unlikely(!__pyx_cur_scope)) {
+    __pyx_cur_scope = ((struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *)Py_None);
+    __Pyx_INCREF(Py_None);
+    __PYX_ERR(0, 318, __pyx_L1_error)
+  } else {
+    __Pyx_GOTREF(__pyx_cur_scope);
+  }
+  __pyx_cur_scope->__pyx_v_fn = __pyx_v_fn;
+  __Pyx_INCREF(__pyx_cur_scope->__pyx_v_fn);
+  __Pyx_GIVEREF(__pyx_cur_scope->__pyx_v_fn);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":303
+  /* "vidcutter/libs/pympv/mpv.pyx":319
  * 
- *     cdef _init(self, mpv_event* event, ctx):
- *         cdef uint64_t ctxid = <uint64_t>id(ctx)             # <<<<<<<<<<<<<<
- *         self.id = event.event_id
- *         self.data = self._data(event)
+ * def _errors(fn):
+ *     def wrapped(*k, **kw):             # <<<<<<<<<<<<<<
+ *         v = fn(*k, **kw)
+ *         if v < 0:
  */
-  __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, __pyx_v_ctx); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 303, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_CyFunction_New(&__pyx_mdef_9vidcutter_4libs_3mpv_7_errors_1wrapped, 0, __pyx_n_s_errors_locals_wrapped, ((PyObject*)__pyx_cur_scope), __pyx_n_s_vidcutter_libs_mpv, __pyx_d, ((PyObject *)__pyx_codeobj__2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 319, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyInt_As_uint64_t(__pyx_t_1); if (unlikely((__pyx_t_2 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 303, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_ctxid = ((uint64_t)__pyx_t_2);
+  __pyx_v_wrapped = __pyx_t_1;
+  __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":304
- *     cdef _init(self, mpv_event* event, ctx):
- *         cdef uint64_t ctxid = <uint64_t>id(ctx)
- *         self.id = event.event_id             # <<<<<<<<<<<<<<
- *         self.data = self._data(event)
- *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)
+  /* "vidcutter/libs/pympv/mpv.pyx":323
+ *         if v < 0:
+ *             raise MPVError(v)
+ *     return wrapped             # <<<<<<<<<<<<<<
+ * 
+ * 
  */
-  __pyx_t_3 = __pyx_v_event->event_id;
-  __pyx_v_self->id = __pyx_t_3;
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_wrapped);
+  __pyx_r = __pyx_v_wrapped;
+  goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":305
- *         cdef uint64_t ctxid = <uint64_t>id(ctx)
- *         self.id = event.event_id
- *         self.data = self._data(event)             # <<<<<<<<<<<<<<
- *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)
- *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:
+  /* "vidcutter/libs/pympv/mpv.pyx":318
+ * 
+ * 
+ * def _errors(fn):             # <<<<<<<<<<<<<<
+ *     def wrapped(*k, **kw):
+ *         v = fn(*k, **kw)
  */
-  __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Event *)__pyx_v_self->__pyx_vtab)->_data(__pyx_v_self, __pyx_v_event); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 305, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->data);
-  __Pyx_DECREF(__pyx_v_self->data);
-  __pyx_v_self->data = __pyx_t_1;
-  __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":306
- *         self.id = event.event_id
- *         self.data = self._data(event)
- *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)             # <<<<<<<<<<<<<<
- *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:
- *             userdata.remove()
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._errors", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_wrapped);
+  __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "vidcutter/libs/pympv/mpv.pyx":329
+ *     code = None
+ * 
+ *     def __init__(self, e):             # <<<<<<<<<<<<<<
+ *         self.code = e
+ *         cdef const char* err_c
  */
-  __pyx_t_4 = __Pyx_GetItemInt(__pyx_v_9vidcutter_4libs_3mpv__reply_userdatas, __pyx_v_ctxid, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 306, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_get); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 306, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = __Pyx_PyInt_From_uint64_t(__pyx_v_event->reply_userdata); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 306, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_6 = NULL;
-  __pyx_t_7 = 0;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
-    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
-    if (likely(__pyx_t_6)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-      __Pyx_INCREF(__pyx_t_6);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_5, function);
-      __pyx_t_7 = 1;
-    }
-  }
-  #if CYTHON_FAST_PYCALL
-  if (PyFunction_Check(__pyx_t_5)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_4, Py_None};
-    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 306, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  } else
-  #endif
-  #if CYTHON_FAST_PYCCALL
-  if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_t_4, Py_None};
-    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_7, 2+__pyx_t_7); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 306, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  } else
-  #endif
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8MPVError_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_8MPVError_1__init__ = {"__init__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9vidcutter_4libs_3mpv_8MPVError_1__init__, METH_VARARGS|METH_KEYWORDS, 0};
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8MPVError_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_self = 0;
+  PyObject *__pyx_v_e = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
   {
-    __pyx_t_8 = PyTuple_New(2+__pyx_t_7); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 306, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    if (__pyx_t_6) {
-      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6); __pyx_t_6 = NULL;
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_e,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
+        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_e)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 329, __pyx_L3_error)
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 329, __pyx_L3_error)
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
     }
-    __Pyx_GIVEREF(__pyx_t_4);
-    PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_7, __pyx_t_4);
-    __Pyx_INCREF(Py_None);
-    __Pyx_GIVEREF(Py_None);
-    PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_7, Py_None);
-    __pyx_t_4 = 0;
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_8, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 306, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+    __pyx_v_self = values[0];
+    __pyx_v_e = values[1];
   }
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_v_userdata = __pyx_t_1;
-  __pyx_t_1 = 0;
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 329, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.MPVError.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8MPVError___init__(__pyx_self, __pyx_v_self, __pyx_v_e);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":307
- *         self.data = self._data(event)
- *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)
- *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:             # <<<<<<<<<<<<<<
- *             userdata.remove()
- *             if not userdata.observed and userdata.counter <= 0:
- */
-  __pyx_t_10 = (__pyx_v_userdata != Py_None);
-  __pyx_t_11 = (__pyx_t_10 != 0);
-  if (__pyx_t_11) {
-  } else {
-    __pyx_t_9 = __pyx_t_11;
-    goto __pyx_L4_bool_binop_done;
-  }
-  __pyx_t_11 = ((__pyx_v_self->id != MPV_EVENT_PROPERTY_CHANGE) != 0);
-  __pyx_t_9 = __pyx_t_11;
-  __pyx_L4_bool_binop_done:;
-  if (__pyx_t_9) {
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-    /* "vidcutter/libs/pympv/mpv.pyx":308
- *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)
- *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:
- *             userdata.remove()             # <<<<<<<<<<<<<<
- *             if not userdata.observed and userdata.counter <= 0:
- *                 del _reply_userdatas[ctxid][event.reply_userdata]
- */
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdata, __pyx_n_s_remove); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 308, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_8 = NULL;
-    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
-      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_5);
-      if (likely(__pyx_t_8)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-        __Pyx_INCREF(__pyx_t_8);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_5, function);
-      }
-    }
-    __pyx_t_1 = (__pyx_t_8) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_8) : __Pyx_PyObject_CallNoArg(__pyx_t_5);
-    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 308, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8MPVError___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_e) {
+  char const *__pyx_v_err_c;
+  int __pyx_v_e_i;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_t_1;
+  int __pyx_t_2;
+  int __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyObject *__pyx_t_7 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__init__", 0);
+  __Pyx_INCREF(__pyx_v_e);
 
-    /* "vidcutter/libs/pympv/mpv.pyx":309
- *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:
- *             userdata.remove()
- *             if not userdata.observed and userdata.counter <= 0:             # <<<<<<<<<<<<<<
- *                 del _reply_userdatas[ctxid][event.reply_userdata]
- *         if userdata is not None:
+  /* "vidcutter/libs/pympv/mpv.pyx":330
+ * 
+ *     def __init__(self, e):
+ *         self.code = e             # <<<<<<<<<<<<<<
+ *         cdef const char* err_c
+ *         cdef int e_i
  */
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdata, __pyx_n_s_observed); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 309, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_11 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_11 < 0)) __PYX_ERR(0, 309, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_t_10 = ((!__pyx_t_11) != 0);
-    if (__pyx_t_10) {
-    } else {
-      __pyx_t_9 = __pyx_t_10;
-      goto __pyx_L7_bool_binop_done;
-    }
-    __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdata, __pyx_n_s_counter); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 309, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_5 = PyObject_RichCompare(__pyx_t_1, __pyx_int_0, Py_LE); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 309, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_t_10 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_10 < 0)) __PYX_ERR(0, 309, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_9 = __pyx_t_10;
-    __pyx_L7_bool_binop_done:;
-    if (__pyx_t_9) {
+  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_code, __pyx_v_e) < 0) __PYX_ERR(0, 330, __pyx_L1_error)
 
-      /* "vidcutter/libs/pympv/mpv.pyx":310
- *             userdata.remove()
- *             if not userdata.observed and userdata.counter <= 0:
- *                 del _reply_userdatas[ctxid][event.reply_userdata]             # <<<<<<<<<<<<<<
- *         if userdata is not None:
- *             userdata = userdata.data
+  /* "vidcutter/libs/pympv/mpv.pyx":333
+ *         cdef const char* err_c
+ *         cdef int e_i
+ *         if not isinstance(e, basestring):             # <<<<<<<<<<<<<<
+ *             e_i = e
+ *             with nogil:
  */
-      __pyx_t_5 = __Pyx_GetItemInt(__pyx_v_9vidcutter_4libs_3mpv__reply_userdatas, __pyx_v_ctxid, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 310, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      if (unlikely(__Pyx_DelItemInt(__pyx_t_5, __pyx_v_event->reply_userdata, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 310, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_1 = __Pyx_PyBaseString_Check(__pyx_v_e); 
+  __pyx_t_2 = ((!(__pyx_t_1 != 0)) != 0);
+  if (__pyx_t_2) {
 
-      /* "vidcutter/libs/pympv/mpv.pyx":309
- *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:
- *             userdata.remove()
- *             if not userdata.observed and userdata.counter <= 0:             # <<<<<<<<<<<<<<
- *                 del _reply_userdatas[ctxid][event.reply_userdata]
- *         if userdata is not None:
+    /* "vidcutter/libs/pympv/mpv.pyx":334
+ *         cdef int e_i
+ *         if not isinstance(e, basestring):
+ *             e_i = e             # <<<<<<<<<<<<<<
+ *             with nogil:
+ *                 err_c = mpv_error_string(e_i)
  */
-    }
+    __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_v_e); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 334, __pyx_L1_error)
+    __pyx_v_e_i = __pyx_t_3;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":307
- *         self.data = self._data(event)
- *         userdata = _reply_userdatas[ctxid].get(event.reply_userdata, None)
- *         if userdata is not None and self.id != MPV_EVENT_PROPERTY_CHANGE:             # <<<<<<<<<<<<<<
- *             userdata.remove()
- *             if not userdata.observed and userdata.counter <= 0:
+    /* "vidcutter/libs/pympv/mpv.pyx":335
+ *         if not isinstance(e, basestring):
+ *             e_i = e
+ *             with nogil:             # <<<<<<<<<<<<<<
+ *                 err_c = mpv_error_string(e_i)
+ *             e = _strdec(err_c)
  */
-  }
+    {
+        #ifdef WITH_THREAD
+        PyThreadState *_save;
+        Py_UNBLOCK_THREADS
+        __Pyx_FastGIL_Remember();
+        #endif
+        /*try:*/ {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":311
- *             if not userdata.observed and userdata.counter <= 0:
- *                 del _reply_userdatas[ctxid][event.reply_userdata]
- *         if userdata is not None:             # <<<<<<<<<<<<<<
- *             userdata = userdata.data
- *         self.reply_userdata = userdata
+          /* "vidcutter/libs/pympv/mpv.pyx":336
+ *             e_i = e
+ *             with nogil:
+ *                 err_c = mpv_error_string(e_i)             # <<<<<<<<<<<<<<
+ *             e = _strdec(err_c)
+ *         Exception.__init__(self, e)
  */
-  __pyx_t_9 = (__pyx_v_userdata != Py_None);
-  __pyx_t_10 = (__pyx_t_9 != 0);
-  if (__pyx_t_10) {
+          __pyx_v_err_c = mpv_error_string(__pyx_v_e_i);
+        }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":312
- *                 del _reply_userdatas[ctxid][event.reply_userdata]
- *         if userdata is not None:
- *             userdata = userdata.data             # <<<<<<<<<<<<<<
- *         self.reply_userdata = userdata
- *         self.error = event.error
+        /* "vidcutter/libs/pympv/mpv.pyx":335
+ *         if not isinstance(e, basestring):
+ *             e_i = e
+ *             with nogil:             # <<<<<<<<<<<<<<
+ *                 err_c = mpv_error_string(e_i)
+ *             e = _strdec(err_c)
  */
-    __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdata, __pyx_n_s_data); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 312, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF_SET(__pyx_v_userdata, __pyx_t_5);
-    __pyx_t_5 = 0;
+        /*finally:*/ {
+          /*normal exit:*/{
+            #ifdef WITH_THREAD
+            __Pyx_FastGIL_Forget();
+            Py_BLOCK_THREADS
+            #endif
+            goto __pyx_L6;
+          }
+          __pyx_L6:;
+        }
+    }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":311
- *             if not userdata.observed and userdata.counter <= 0:
- *                 del _reply_userdatas[ctxid][event.reply_userdata]
- *         if userdata is not None:             # <<<<<<<<<<<<<<
- *             userdata = userdata.data
- *         self.reply_userdata = userdata
- */
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":313
- *         if userdata is not None:
- *             userdata = userdata.data
- *         self.reply_userdata = userdata             # <<<<<<<<<<<<<<
- *         self.error = event.error
- *         return self
+    /* "vidcutter/libs/pympv/mpv.pyx":337
+ *             with nogil:
+ *                 err_c = mpv_error_string(e_i)
+ *             e = _strdec(err_c)             # <<<<<<<<<<<<<<
+ *         Exception.__init__(self, e)
+ * 
  */
-  __Pyx_INCREF(__pyx_v_userdata);
-  __Pyx_GIVEREF(__pyx_v_userdata);
-  __Pyx_GOTREF(__pyx_v_self->reply_userdata);
-  __Pyx_DECREF(__pyx_v_self->reply_userdata);
-  __pyx_v_self->reply_userdata = __pyx_v_userdata;
+    __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_strdec); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 337, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_6 = __Pyx_PyBytes_FromString(__pyx_v_err_c); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 337, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_t_7 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
+      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_5);
+      if (likely(__pyx_t_7)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_7);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_5, function);
+      }
+    }
+    __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 337, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_DECREF_SET(__pyx_v_e, __pyx_t_4);
+    __pyx_t_4 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":314
- *             userdata = userdata.data
- *         self.reply_userdata = userdata
- *         self.error = event.error             # <<<<<<<<<<<<<<
- *         return self
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":333
+ *         cdef const char* err_c
+ *         cdef int e_i
+ *         if not isinstance(e, basestring):             # <<<<<<<<<<<<<<
+ *             e_i = e
+ *             with nogil:
  */
-  __pyx_t_7 = __pyx_v_event->error;
-  __pyx_v_self->error = __pyx_t_7;
+  }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":315
- *         self.reply_userdata = userdata
- *         self.error = event.error
- *         return self             # <<<<<<<<<<<<<<
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":338
+ *                 err_c = mpv_error_string(e_i)
+ *             e = _strdec(err_c)
+ *         Exception.__init__(self, e)             # <<<<<<<<<<<<<<
  * 
+ * class PyMPVError(Exception):
  */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(((PyObject *)__pyx_v_self));
-  __pyx_r = ((PyObject *)__pyx_v_self);
-  goto __pyx_L0;
+  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0])), __pyx_n_s_init); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 338, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_6 = NULL;
+  __pyx_t_3 = 0;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
+    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+    if (likely(__pyx_t_6)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+      __Pyx_INCREF(__pyx_t_6);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_5, function);
+      __pyx_t_3 = 1;
+    }
+  }
+  #if CYTHON_FAST_PYCALL
+  if (PyFunction_Check(__pyx_t_5)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_self, __pyx_v_e};
+    __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_3, 2+__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 338, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_GOTREF(__pyx_t_4);
+  } else
+  #endif
+  #if CYTHON_FAST_PYCCALL
+  if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_self, __pyx_v_e};
+    __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_3, 2+__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 338, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_GOTREF(__pyx_t_4);
+  } else
+  #endif
+  {
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 338, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    if (__pyx_t_6) {
+      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_6); __pyx_t_6 = NULL;
+    }
+    __Pyx_INCREF(__pyx_v_self);
+    __Pyx_GIVEREF(__pyx_v_self);
+    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_3, __pyx_v_self);
+    __Pyx_INCREF(__pyx_v_e);
+    __Pyx_GIVEREF(__pyx_v_e);
+    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_3, __pyx_v_e);
+    __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_7, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 338, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+  }
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":302
- *         return _strdec(name_c)
+  /* "vidcutter/libs/pympv/mpv.pyx":329
+ *     code = None
  * 
- *     cdef _init(self, mpv_event* event, ctx):             # <<<<<<<<<<<<<<
- *         cdef uint64_t ctxid = <uint64_t>id(ctx)
- *         self.id = event.event_id
+ *     def __init__(self, e):             # <<<<<<<<<<<<<<
+ *         self.code = e
+ *         cdef const char* err_c
  */
 
   /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Event._init", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.MPVError.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_userdata);
+  __Pyx_XDECREF(__pyx_v_e);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":258
- * cdef class Event(object):
- *     """Wraps: mpv_event"""
- *     cdef public mpv_event_id id             # <<<<<<<<<<<<<<
- *     cdef public int error
- *     cdef public object data, reply_userdata
+/* "vidcutter/libs/pympv/mpv.pyx":347
+ * 
+ * class _ReplyUserData(object):
+ *     def __init__(self, data):             # <<<<<<<<<<<<<<
+ *         self.counter = 0
+ *         self.data = data
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_2id_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_2id_1__get__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_14_ReplyUserData_1__init__ = {"__init__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_1__init__, METH_VARARGS|METH_KEYWORDS, 0};
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_self = 0;
+  PyObject *__pyx_v_data = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_2id___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_data,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
+        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 347, __pyx_L3_error)
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 347, __pyx_L3_error)
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_self = values[0];
+    __pyx_v_data = values[1];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 347, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("vidcutter.libs.mpv._ReplyUserData.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData___init__(__pyx_self, __pyx_v_self, __pyx_v_data);
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_2id___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_data) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__get__", 0);
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_enum__mpv_event_id(__pyx_v_self->id); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 258, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.id.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  __Pyx_RefNannySetupContext("__init__", 0);
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_2id_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_2id_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_2id_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+  /* "vidcutter/libs/pympv/mpv.pyx":348
+ * class _ReplyUserData(object):
+ *     def __init__(self, data):
+ *         self.counter = 0             # <<<<<<<<<<<<<<
+ *         self.data = data
+ *         self.observed = False
+ */
+  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_counter, __pyx_int_0) < 0) __PYX_ERR(0, 348, __pyx_L1_error)
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  /* "vidcutter/libs/pympv/mpv.pyx":349
+ *     def __init__(self, data):
+ *         self.counter = 0
+ *         self.data = data             # <<<<<<<<<<<<<<
+ *         self.observed = False
+ * 
+ */
+  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_data, __pyx_v_data) < 0) __PYX_ERR(0, 349, __pyx_L1_error)
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_2id_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  enum mpv_event_id __pyx_t_1;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __pyx_t_1 = ((enum mpv_event_id)__Pyx_PyInt_As_enum__mpv_event_id(__pyx_v_value)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 258, __pyx_L1_error)
-  __pyx_v_self->id = __pyx_t_1;
+  /* "vidcutter/libs/pympv/mpv.pyx":350
+ *         self.counter = 0
+ *         self.data = data
+ *         self.observed = False             # <<<<<<<<<<<<<<
+ * 
+ *     def add(self):
+ */
+  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_observed, Py_False) < 0) __PYX_ERR(0, 350, __pyx_L1_error)
+
+  /* "vidcutter/libs/pympv/mpv.pyx":347
+ * 
+ * class _ReplyUserData(object):
+ *     def __init__(self, data):             # <<<<<<<<<<<<<<
+ *         self.counter = 0
+ *         self.data = data
+ */
 
   /* function exit code */
-  __pyx_r = 0;
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.id.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = -1;
+  __Pyx_AddTraceback("vidcutter.libs.mpv._ReplyUserData.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
   __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":259
- *     """Wraps: mpv_event"""
- *     cdef public mpv_event_id id
- *     cdef public int error             # <<<<<<<<<<<<<<
- *     cdef public object data, reply_userdata
+/* "vidcutter/libs/pympv/mpv.pyx":352
+ *         self.observed = False
+ * 
+ *     def add(self):             # <<<<<<<<<<<<<<
+ *         self.counter += 1
  * 
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_5error_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_5error_1__get__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_3add(PyObject *__pyx_self, PyObject *__pyx_v_self); /*proto*/
+static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_14_ReplyUserData_3add = {"add", (PyCFunction)__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_3add, METH_O, 0};
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_3add(PyObject *__pyx_self, PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_5error___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("add (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData_2add(__pyx_self, ((PyObject *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_5error___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData_2add(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__get__", 0);
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->error); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 259, __pyx_L1_error)
+  __Pyx_RefNannySetupContext("add", 0);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":353
+ * 
+ *     def add(self):
+ *         self.counter += 1             # <<<<<<<<<<<<<<
+ * 
+ *     def remove(self):
+ */
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_counter); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 353, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
+  __pyx_t_2 = __Pyx_PyInt_AddObjC(__pyx_t_1, __pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 353, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_counter, __pyx_t_2) < 0) __PYX_ERR(0, 353, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":352
+ *         self.observed = False
+ * 
+ *     def add(self):             # <<<<<<<<<<<<<<
+ *         self.counter += 1
+ * 
+ */
 
   /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.error.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._ReplyUserData.add", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
@@ -7328,1181 +7931,1253 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_5error___get__(struct __p
   return __pyx_r;
 }
 
+/* "vidcutter/libs/pympv/mpv.pyx":355
+ *         self.counter += 1
+ * 
+ *     def remove(self):             # <<<<<<<<<<<<<<
+ *         self.counter -= 1
+ * 
+ */
+
 /* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_5error_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_5error_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_5remove(PyObject *__pyx_self, PyObject *__pyx_v_self); /*proto*/
+static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_14_ReplyUserData_5remove = {"remove", (PyCFunction)__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_5remove, METH_O, 0};
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_5remove(PyObject *__pyx_self, PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_5error_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+  __Pyx_RefNannySetupContext("remove (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData_4remove(__pyx_self, ((PyObject *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_5error_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData_4remove(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_value); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 259, __pyx_L1_error)
-  __pyx_v_self->error = __pyx_t_1;
+  __Pyx_RefNannySetupContext("remove", 0);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":356
+ * 
+ *     def remove(self):
+ *         self.counter -= 1             # <<<<<<<<<<<<<<
+ * 
+ * 
+ */
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_counter); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 356, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyInt_SubtractObjC(__pyx_t_1, __pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 356, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_counter, __pyx_t_2) < 0) __PYX_ERR(0, 356, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":355
+ *         self.counter += 1
+ * 
+ *     def remove(self):             # <<<<<<<<<<<<<<
+ *         self.counter -= 1
+ * 
+ */
 
   /* function exit code */
-  __pyx_r = 0;
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.error.__set__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = -1;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._ReplyUserData.remove", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
   __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":260
- *     cdef public mpv_event_id id
- *     cdef public int error
- *     cdef public object data, reply_userdata             # <<<<<<<<<<<<<<
+/* "vidcutter/libs/pympv/mpv.pyx":370
  * 
  *     @property
+ *     def api_version(self):             # <<<<<<<<<<<<<<
+ *         return _CAPI_MINOR, _CAPI_MAJOR, _CAPI_VERSION
+ * 
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_1__get__(PyObject *__pyx_v_self) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_11api_version_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_11api_version_1__get__(PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_4data___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_11api_version___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_4data___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_11api_version___get__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("__get__", 0);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":371
+ *     @property
+ *     def api_version(self):
+ *         return _CAPI_MINOR, _CAPI_MAJOR, _CAPI_VERSION             # <<<<<<<<<<<<<<
+ * 
+ *     @property
+ */
   __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->data);
-  __pyx_r = __pyx_v_self->data;
+  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_CAPI_MINOR); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 371, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_CAPI_MAJOR); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 371, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_PyInt_From_unsigned_long(__pyx_v_9vidcutter_4libs_3mpv__CAPI_VERSION); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 371, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 371, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_GIVEREF(__pyx_t_1);
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_2);
+  PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2);
+  __Pyx_GIVEREF(__pyx_t_3);
+  PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_3);
+  __pyx_t_1 = 0;
+  __pyx_t_2 = 0;
+  __pyx_t_3 = 0;
+  __pyx_r = __pyx_t_4;
+  __pyx_t_4 = 0;
   goto __pyx_L0;
 
+  /* "vidcutter/libs/pympv/mpv.pyx":370
+ * 
+ *     @property
+ *     def api_version(self):             # <<<<<<<<<<<<<<
+ *         return _CAPI_MINOR, _CAPI_MAJOR, _CAPI_VERSION
+ * 
+ */
+
   /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.api_version.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
+/* "vidcutter/libs/pympv/mpv.pyx":374
+ * 
+ *     @property
+ *     def name(self):             # <<<<<<<<<<<<<<
+ *         """Unique name for every context created.
+ * 
+ */
+
 /* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_4name_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_4name_1__get__(PyObject *__pyx_v_self) {
+  PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_4data_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self), ((PyObject *)__pyx_v_value));
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_4name___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_4data_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_4name___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
+  char const *__pyx_v_name;
+  PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __Pyx_INCREF(__pyx_v_value);
-  __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->data);
-  __Pyx_DECREF(__pyx_v_self->data);
-  __pyx_v_self->data = __pyx_v_value;
-
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_4data_5__del__(PyObject *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_4data_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__get__", 0);
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_4data_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__", 0);
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->data);
-  __Pyx_DECREF(__pyx_v_self->data);
-  __pyx_v_self->data = Py_None;
+  /* "vidcutter/libs/pympv/mpv.pyx":380
+ *         """
+ *         cdef const char* name
+ *         assert self._ctx             # <<<<<<<<<<<<<<
+ *         with nogil:
+ *             name = mpv_client_name(self._ctx)
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!Py_OptimizeFlag)) {
+    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
+      PyErr_SetNone(PyExc_AssertionError);
+      __PYX_ERR(0, 380, __pyx_L1_error)
+    }
+  }
+  #endif
 
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  /* "vidcutter/libs/pympv/mpv.pyx":381
+ *         cdef const char* name
+ *         assert self._ctx
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             name = mpv_client_name(self._ctx)
+ *         return _strdec(name)
+ */
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+        /* "vidcutter/libs/pympv/mpv.pyx":382
+ *         assert self._ctx
+ *         with nogil:
+ *             name = mpv_client_name(self._ctx)             # <<<<<<<<<<<<<<
+ *         return _strdec(name)
+ * 
+ */
+        __pyx_v_name = mpv_client_name(__pyx_v_self->_ctx);
+      }
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+      /* "vidcutter/libs/pympv/mpv.pyx":381
+ *         cdef const char* name
+ *         assert self._ctx
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             name = mpv_client_name(self._ctx)
+ *         return _strdec(name)
+ */
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
+      }
+  }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__", 0);
+  /* "vidcutter/libs/pympv/mpv.pyx":383
+ *         with nogil:
+ *             name = mpv_client_name(self._ctx)
+ *         return _strdec(name)             # <<<<<<<<<<<<<<
+ * 
+ *     @property
+ */
   __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_self->reply_userdata);
-  __pyx_r = __pyx_v_self->reply_userdata;
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 383, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_name); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 383, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_4)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_4);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 383, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
+  /* "vidcutter/libs/pympv/mpv.pyx":374
+ * 
+ *     @property
+ *     def name(self):             # <<<<<<<<<<<<<<
+ *         """Unique name for every context created.
+ * 
+ */
+
   /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.name.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_3__set__(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata_2__set__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self), ((PyObject *)__pyx_v_value));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata_2__set__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, PyObject *__pyx_v_value) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__set__", 0);
-  __Pyx_INCREF(__pyx_v_value);
-  __Pyx_GIVEREF(__pyx_v_value);
-  __Pyx_GOTREF(__pyx_v_self->reply_userdata);
-  __Pyx_DECREF(__pyx_v_self->reply_userdata);
-  __pyx_v_self->reply_userdata = __pyx_v_value;
-
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_5__del__(PyObject *__pyx_v_self); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_5Event_14reply_userdata_5__del__(PyObject *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata_4__del__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static int __pyx_pf_9vidcutter_4libs_3mpv_5Event_14reply_userdata_4__del__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__del__", 0);
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->reply_userdata);
-  __Pyx_DECREF(__pyx_v_self->reply_userdata);
-  __pyx_v_self->reply_userdata = Py_None;
-
-  /* function exit code */
-  __pyx_r = 0;
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     cdef tuple state
- *     cdef object _dict
+/* "vidcutter/libs/pympv/mpv.pyx":386
+ * 
+ *     @property
+ *     def time(self):             # <<<<<<<<<<<<<<
+ *         """Internal mpv client time.
+ * 
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_4time_1__get__(PyObject *__pyx_v_self); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_4time_1__get__(PyObject *__pyx_v_self) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event___reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_4time___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event___reduce_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self) {
-  PyObject *__pyx_v_state = 0;
-  PyObject *__pyx_v__dict = 0;
-  int __pyx_v_use_setstate;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_4time___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
+  int64_t __pyx_v_time;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  int __pyx_t_4;
-  int __pyx_t_5;
-  int __pyx_t_6;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
+  __Pyx_RefNannySetupContext("__get__", 0);
 
-  /* "(tree fragment)":5
- *     cdef object _dict
- *     cdef bint use_setstate
- *     state = (self.data, self.error, self.id, self.reply_userdata)             # <<<<<<<<<<<<<<
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:
- */
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_self->error); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 5, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyInt_From_enum__mpv_event_id(__pyx_v_self->id); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 5, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyTuple_New(4); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 5, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_INCREF(__pyx_v_self->data);
-  __Pyx_GIVEREF(__pyx_v_self->data);
-  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_self->data);
-  __Pyx_GIVEREF(__pyx_t_1);
-  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_2);
-  PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_t_2);
-  __Pyx_INCREF(__pyx_v_self->reply_userdata);
-  __Pyx_GIVEREF(__pyx_v_self->reply_userdata);
-  PyTuple_SET_ITEM(__pyx_t_3, 3, __pyx_v_self->reply_userdata);
-  __pyx_t_1 = 0;
-  __pyx_t_2 = 0;
-  __pyx_v_state = ((PyObject*)__pyx_t_3);
-  __pyx_t_3 = 0;
-
-  /* "(tree fragment)":6
- *     cdef bint use_setstate
- *     state = (self.data, self.error, self.id, self.reply_userdata)
- *     _dict = getattr(self, '__dict__', None)             # <<<<<<<<<<<<<<
- *     if _dict is not None:
- *         state += (_dict,)
- */
-  __pyx_t_3 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 6, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_v__dict = __pyx_t_3;
-  __pyx_t_3 = 0;
-
-  /* "(tree fragment)":7
- *     state = (self.data, self.error, self.id, self.reply_userdata)
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:             # <<<<<<<<<<<<<<
- *         state += (_dict,)
- *         use_setstate = True
- */
-  __pyx_t_4 = (__pyx_v__dict != Py_None);
-  __pyx_t_5 = (__pyx_t_4 != 0);
-  if (__pyx_t_5) {
-
-    /* "(tree fragment)":8
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:
- *         state += (_dict,)             # <<<<<<<<<<<<<<
- *         use_setstate = True
- *     else:
- */
-    __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 8, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_v__dict);
-    __Pyx_GIVEREF(__pyx_v__dict);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v__dict);
-    __pyx_t_2 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 8, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_2));
-    __pyx_t_2 = 0;
-
-    /* "(tree fragment)":9
- *     if _dict is not None:
- *         state += (_dict,)
- *         use_setstate = True             # <<<<<<<<<<<<<<
- *     else:
- *         use_setstate = self.data is not None or self.reply_userdata is not None
- */
-    __pyx_v_use_setstate = 1;
-
-    /* "(tree fragment)":7
- *     state = (self.data, self.error, self.id, self.reply_userdata)
- *     _dict = getattr(self, '__dict__', None)
- *     if _dict is not None:             # <<<<<<<<<<<<<<
- *         state += (_dict,)
- *         use_setstate = True
- */
-    goto __pyx_L3;
-  }
-
-  /* "(tree fragment)":11
- *         use_setstate = True
- *     else:
- *         use_setstate = self.data is not None or self.reply_userdata is not None             # <<<<<<<<<<<<<<
- *     if use_setstate:
- *         return __pyx_unpickle_Event, (type(self), 0xda38c25, None), state
+  /* "vidcutter/libs/pympv/mpv.pyx":394
+ *         """
+ *         cdef int64_t time
+ *         assert self._ctx             # <<<<<<<<<<<<<<
+ *         with nogil:
+ *             time = mpv_get_time_us(self._ctx)
  */
-  /*else*/ {
-    __pyx_t_4 = (__pyx_v_self->data != Py_None);
-    __pyx_t_6 = (__pyx_t_4 != 0);
-    if (!__pyx_t_6) {
-    } else {
-      __pyx_t_5 = __pyx_t_6;
-      goto __pyx_L4_bool_binop_done;
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!Py_OptimizeFlag)) {
+    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
+      PyErr_SetNone(PyExc_AssertionError);
+      __PYX_ERR(0, 394, __pyx_L1_error)
     }
-    __pyx_t_6 = (__pyx_v_self->reply_userdata != Py_None);
-    __pyx_t_4 = (__pyx_t_6 != 0);
-    __pyx_t_5 = __pyx_t_4;
-    __pyx_L4_bool_binop_done:;
-    __pyx_v_use_setstate = __pyx_t_5;
   }
-  __pyx_L3:;
+  #endif
 
-  /* "(tree fragment)":12
- *     else:
- *         use_setstate = self.data is not None or self.reply_userdata is not None
- *     if use_setstate:             # <<<<<<<<<<<<<<
- *         return __pyx_unpickle_Event, (type(self), 0xda38c25, None), state
- *     else:
+  /* "vidcutter/libs/pympv/mpv.pyx":395
+ *         cdef int64_t time
+ *         assert self._ctx
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             time = mpv_get_time_us(self._ctx)
+ *         return time
  */
-  __pyx_t_5 = (__pyx_v_use_setstate != 0);
-  if (__pyx_t_5) {
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
 
-    /* "(tree fragment)":13
- *         use_setstate = self.data is not None or self.reply_userdata is not None
- *     if use_setstate:
- *         return __pyx_unpickle_Event, (type(self), 0xda38c25, None), state             # <<<<<<<<<<<<<<
- *     else:
- *         return __pyx_unpickle_Event, (type(self), 0xda38c25, state)
+        /* "vidcutter/libs/pympv/mpv.pyx":396
+ *         assert self._ctx
+ *         with nogil:
+ *             time = mpv_get_time_us(self._ctx)             # <<<<<<<<<<<<<<
+ *         return time
+ * 
  */
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_pyx_unpickle_Event); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 13, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 13, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_INCREF(__pyx_int_228822053);
-    __Pyx_GIVEREF(__pyx_int_228822053);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_int_228822053);
-    __Pyx_INCREF(Py_None);
-    __Pyx_GIVEREF(Py_None);
-    PyTuple_SET_ITEM(__pyx_t_3, 2, Py_None);
-    __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_GIVEREF(__pyx_t_2);
-    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_2);
-    __Pyx_GIVEREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3);
-    __Pyx_INCREF(__pyx_v_state);
-    __Pyx_GIVEREF(__pyx_v_state);
-    PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state);
-    __pyx_t_2 = 0;
-    __pyx_t_3 = 0;
-    __pyx_r = __pyx_t_1;
-    __pyx_t_1 = 0;
-    goto __pyx_L0;
+        __pyx_v_time = mpv_get_time_us(__pyx_v_self->_ctx);
+      }
 
-    /* "(tree fragment)":12
- *     else:
- *         use_setstate = self.data is not None or self.reply_userdata is not None
- *     if use_setstate:             # <<<<<<<<<<<<<<
- *         return __pyx_unpickle_Event, (type(self), 0xda38c25, None), state
- *     else:
+      /* "vidcutter/libs/pympv/mpv.pyx":395
+ *         cdef int64_t time
+ *         assert self._ctx
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             time = mpv_get_time_us(self._ctx)
+ *         return time
  */
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
+      }
   }
 
-  /* "(tree fragment)":15
- *         return __pyx_unpickle_Event, (type(self), 0xda38c25, None), state
- *     else:
- *         return __pyx_unpickle_Event, (type(self), 0xda38c25, state)             # <<<<<<<<<<<<<<
- * def __setstate_cython__(self, __pyx_state):
- *     __pyx_unpickle_Event__set_state(self, __pyx_state)
+  /* "vidcutter/libs/pympv/mpv.pyx":397
+ *         with nogil:
+ *             time = mpv_get_time_us(self._ctx)
+ *         return time             # <<<<<<<<<<<<<<
+ * 
+ *     # def suspend(self):
  */
-  /*else*/ {
-    __Pyx_XDECREF(__pyx_r);
-    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_pyx_unpickle_Event); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(1, 15, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    PyTuple_SET_ITEM(__pyx_t_3, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
-    __Pyx_INCREF(__pyx_int_228822053);
-    __Pyx_GIVEREF(__pyx_int_228822053);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_int_228822053);
-    __Pyx_INCREF(__pyx_v_state);
-    __Pyx_GIVEREF(__pyx_v_state);
-    PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_state);
-    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(1, 15, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_GIVEREF(__pyx_t_1);
-    PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
-    __Pyx_GIVEREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3);
-    __pyx_t_1 = 0;
-    __pyx_t_3 = 0;
-    __pyx_r = __pyx_t_2;
-    __pyx_t_2 = 0;
-    goto __pyx_L0;
-  }
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_v_time); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 397, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
 
-  /* "(tree fragment)":1
- * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     cdef tuple state
- *     cdef object _dict
+  /* "vidcutter/libs/pympv/mpv.pyx":386
+ * 
+ *     @property
+ *     def time(self):             # <<<<<<<<<<<<<<
+ *         """Internal mpv client time.
+ * 
  */
 
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.time.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_state);
-  __Pyx_XDECREF(__pyx_v__dict);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "(tree fragment)":16
- *     else:
- *         return __pyx_unpickle_Event, (type(self), 0xda38c25, state)
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     __pyx_unpickle_Event__set_state(self, __pyx_state)
+/* "vidcutter/libs/pympv/mpv.pyx":412
+ * 
+ *     @_errors
+ *     def request_event(self, event, enable):             # <<<<<<<<<<<<<<
+ *         """Enable or disable a given event.
+ * 
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5Event_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_1request_event(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_request_event[] = "Enable or disable a given event.\n\n        Arguments:\n        event - See Events\n        enable - True to enable, False to disable\n\n        Wraps: mpv_request_event\n        ";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_1request_event(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_event = 0;
+  PyObject *__pyx_v_enable = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_5Event_2__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
+  __Pyx_RefNannySetupContext("request_event (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_event,&__pyx_n_s_enable,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_event)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
+        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_enable)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("request_event", 1, 2, 2, 1); __PYX_ERR(0, 412, __pyx_L3_error)
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "request_event") < 0)) __PYX_ERR(0, 412, __pyx_L3_error)
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_event = values[0];
+    __pyx_v_enable = values[1];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("request_event", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 412, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.request_event", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_request_event(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_event, __pyx_v_enable);
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_5Event_2__setstate_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_Event *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_request_event(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_event, PyObject *__pyx_v_enable) {
+  int __pyx_v_enable_i;
+  int __pyx_v_err;
+  enum mpv_event_id __pyx_v_event_id;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
+  int __pyx_t_1;
+  int __pyx_t_2;
+  enum mpv_event_id __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
+  __Pyx_RefNannySetupContext("request_event", 0);
 
-  /* "(tree fragment)":17
- *         return __pyx_unpickle_Event, (type(self), 0xda38c25, state)
- * def __setstate_cython__(self, __pyx_state):
- *     __pyx_unpickle_Event__set_state(self, __pyx_state)             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":421
+ *         Wraps: mpv_request_event
+ *         """
+ *         assert self._ctx             # <<<<<<<<<<<<<<
+ *         cdef int enable_i = 1 if enable else 0
+ *         cdef int err
  */
-  if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error)
-  __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_Event__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!Py_OptimizeFlag)) {
+    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
+      PyErr_SetNone(PyExc_AssertionError);
+      __PYX_ERR(0, 421, __pyx_L1_error)
+    }
+  }
+  #endif
 
-  /* "(tree fragment)":16
- *     else:
- *         return __pyx_unpickle_Event, (type(self), 0xda38c25, state)
- * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     __pyx_unpickle_Event__set_state(self, __pyx_state)
+  /* "vidcutter/libs/pympv/mpv.pyx":422
+ *         """
+ *         assert self._ctx
+ *         cdef int enable_i = 1 if enable else 0             # <<<<<<<<<<<<<<
+ *         cdef int err
+ *         cdef mpv_event_id event_id = event
  */
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_enable); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 422, __pyx_L1_error)
+  if (__pyx_t_2) {
+    __pyx_t_1 = 1;
+  } else {
+    __pyx_t_1 = 0;
+  }
+  __pyx_v_enable_i = __pyx_t_1;
 
-  /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Event.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  /* "vidcutter/libs/pympv/mpv.pyx":424
+ *         cdef int enable_i = 1 if enable else 0
+ *         cdef int err
+ *         cdef mpv_event_id event_id = event             # <<<<<<<<<<<<<<
+ *         with nogil:
+ *             err = mpv_request_event(self._ctx, event_id, enable_i)
+ */
+  __pyx_t_3 = ((enum mpv_event_id)__Pyx_PyInt_As_enum__mpv_event_id(__pyx_v_event)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 424, __pyx_L1_error)
+  __pyx_v_event_id = __pyx_t_3;
 
-/* "vidcutter/libs/pympv/mpv.pyx":318
+  /* "vidcutter/libs/pympv/mpv.pyx":425
+ *         cdef int err
+ *         cdef mpv_event_id event_id = event
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_request_event(self._ctx, event_id, enable_i)
+ *         return err
+ */
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
+
+        /* "vidcutter/libs/pympv/mpv.pyx":426
+ *         cdef mpv_event_id event_id = event
+ *         with nogil:
+ *             err = mpv_request_event(self._ctx, event_id, enable_i)             # <<<<<<<<<<<<<<
+ *         return err
  * 
+ */
+        __pyx_v_err = mpv_request_event(__pyx_v_self->_ctx, __pyx_v_event_id, __pyx_v_enable_i);
+      }
+
+      /* "vidcutter/libs/pympv/mpv.pyx":425
+ *         cdef int err
+ *         cdef mpv_event_id event_id = event
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_request_event(self._ctx, event_id, enable_i)
+ *         return err
+ */
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
+      }
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":427
+ *         with nogil:
+ *             err = mpv_request_event(self._ctx, event_id, enable_i)
+ *         return err             # <<<<<<<<<<<<<<
  * 
- * def _errors(fn):             # <<<<<<<<<<<<<<
- *     def wrapped(*k, **kw):
- *         v = fn(*k, **kw)
+ *     @_errors
  */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 427, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_r = __pyx_t_4;
+  __pyx_t_4 = 0;
+  goto __pyx_L0;
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5_errors(PyObject *__pyx_self, PyObject *__pyx_v_fn); /*proto*/
-static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_5_errors = {"_errors", (PyCFunction)__pyx_pw_9vidcutter_4libs_3mpv_5_errors, METH_O, 0};
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_5_errors(PyObject *__pyx_self, PyObject *__pyx_v_fn) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_errors (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_4_errors(__pyx_self, ((PyObject *)__pyx_v_fn));
+  /* "vidcutter/libs/pympv/mpv.pyx":412
+ * 
+ *     @_errors
+ *     def request_event(self, event, enable):             # <<<<<<<<<<<<<<
+ *         """Enable or disable a given event.
+ * 
+ */
 
   /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.request_event", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":319
+/* "vidcutter/libs/pympv/mpv.pyx":430
  * 
- * def _errors(fn):
- *     def wrapped(*k, **kw):             # <<<<<<<<<<<<<<
- *         v = fn(*k, **kw)
- *         if v < 0:
+ *     @_errors
+ *     def set_log_level(self, loglevel):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_request_log_messages"""
+ *         assert self._ctx
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7_errors_1wrapped(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_7_errors_1wrapped = {"wrapped", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9vidcutter_4libs_3mpv_7_errors_1wrapped, METH_VARARGS|METH_KEYWORDS, 0};
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7_errors_1wrapped(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_k = 0;
-  PyObject *__pyx_v_kw = 0;
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_3set_log_level(PyObject *__pyx_v_self, PyObject *__pyx_v_loglevel); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_2set_log_level[] = "Wraps: mpv_request_log_messages";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_3set_log_level(PyObject *__pyx_v_self, PyObject *__pyx_v_loglevel) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("wrapped (wrapper)", 0);
-  if (unlikely(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "wrapped", 1))) return NULL;
-  if (unlikely(__pyx_kwds)) {
-    __pyx_v_kw = PyDict_Copy(__pyx_kwds); if (unlikely(!__pyx_v_kw)) return NULL;
-    __Pyx_GOTREF(__pyx_v_kw);
-  } else {
-    __pyx_v_kw = NULL;
-  }
-  __Pyx_INCREF(__pyx_args);
-  __pyx_v_k = __pyx_args;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7_errors_wrapped(__pyx_self, __pyx_v_k, __pyx_v_kw);
+  __Pyx_RefNannySetupContext("set_log_level (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_2set_log_level(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_loglevel));
 
   /* function exit code */
-  __Pyx_XDECREF(__pyx_v_k);
-  __Pyx_XDECREF(__pyx_v_kw);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7_errors_wrapped(PyObject *__pyx_self, PyObject *__pyx_v_k, PyObject *__pyx_v_kw) {
-  struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *__pyx_cur_scope;
-  struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *__pyx_outer_scope;
-  PyObject *__pyx_v_v = NULL;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_2set_log_level(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_loglevel) {
+  char const *__pyx_v_loglevel_c;
+  int __pyx_v_err;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  int __pyx_t_2;
+  PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
+  char const *__pyx_t_4;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("wrapped", 0);
-  __pyx_outer_scope = (struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *) __Pyx_CyFunction_GetClosure(__pyx_self);
-  __pyx_cur_scope = __pyx_outer_scope;
+  __Pyx_RefNannySetupContext("set_log_level", 0);
+  __Pyx_INCREF(__pyx_v_loglevel);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":320
- * def _errors(fn):
- *     def wrapped(*k, **kw):
- *         v = fn(*k, **kw)             # <<<<<<<<<<<<<<
- *         if v < 0:
- *             raise MPVError(v)
+  /* "vidcutter/libs/pympv/mpv.pyx":432
+ *     def set_log_level(self, loglevel):
+ *         """Wraps: mpv_request_log_messages"""
+ *         assert self._ctx             # <<<<<<<<<<<<<<
+ *         loglevel = _strenc(loglevel)
+ *         cdef const char* loglevel_c = loglevel
  */
-  if (unlikely(!__pyx_cur_scope->__pyx_v_fn)) { __Pyx_RaiseClosureNameError("fn"); __PYX_ERR(0, 320, __pyx_L1_error) }
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_cur_scope->__pyx_v_fn, __pyx_v_k, __pyx_v_kw); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 320, __pyx_L1_error)
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!Py_OptimizeFlag)) {
+    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
+      PyErr_SetNone(PyExc_AssertionError);
+      __PYX_ERR(0, 432, __pyx_L1_error)
+    }
+  }
+  #endif
+
+  /* "vidcutter/libs/pympv/mpv.pyx":433
+ *         """Wraps: mpv_request_log_messages"""
+ *         assert self._ctx
+ *         loglevel = _strenc(loglevel)             # <<<<<<<<<<<<<<
+ *         cdef const char* loglevel_c = loglevel
+ *         cdef int err
+ */
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 433, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_3)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_loglevel) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_loglevel);
+  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 433, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_v = __pyx_t_1;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF_SET(__pyx_v_loglevel, __pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":321
- *     def wrapped(*k, **kw):
- *         v = fn(*k, **kw)
- *         if v < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(v)
- *     return wrapped
+  /* "vidcutter/libs/pympv/mpv.pyx":434
+ *         assert self._ctx
+ *         loglevel = _strenc(loglevel)
+ *         cdef const char* loglevel_c = loglevel             # <<<<<<<<<<<<<<
+ *         cdef int err
+ *         with nogil:
  */
-  __pyx_t_1 = PyObject_RichCompare(__pyx_v_v, __pyx_int_0, Py_LT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 321, __pyx_L1_error)
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 321, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (unlikely(__pyx_t_2)) {
+  __pyx_t_4 = __Pyx_PyObject_AsString(__pyx_v_loglevel); if (unlikely((!__pyx_t_4) && PyErr_Occurred())) __PYX_ERR(0, 434, __pyx_L1_error)
+  __pyx_v_loglevel_c = __pyx_t_4;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":322
- *         v = fn(*k, **kw)
- *         if v < 0:
- *             raise MPVError(v)             # <<<<<<<<<<<<<<
- *     return wrapped
+  /* "vidcutter/libs/pympv/mpv.pyx":436
+ *         cdef const char* loglevel_c = loglevel
+ *         cdef int err
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_request_log_messages(self._ctx, loglevel_c)
+ *         return err
+ */
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
+
+        /* "vidcutter/libs/pympv/mpv.pyx":437
+ *         cdef int err
+ *         with nogil:
+ *             err = mpv_request_log_messages(self._ctx, loglevel_c)             # <<<<<<<<<<<<<<
+ *         return err
  * 
  */
-    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 322, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-      if (likely(__pyx_t_4)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-        __Pyx_INCREF(__pyx_t_4);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_3, function);
+        __pyx_v_err = mpv_request_log_messages(__pyx_v_self->_ctx, __pyx_v_loglevel_c);
       }
-    }
-    __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_v) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_v);
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 322, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __PYX_ERR(0, 322, __pyx_L1_error)
 
-    /* "vidcutter/libs/pympv/mpv.pyx":321
- *     def wrapped(*k, **kw):
- *         v = fn(*k, **kw)
- *         if v < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(v)
- *     return wrapped
+      /* "vidcutter/libs/pympv/mpv.pyx":436
+ *         cdef const char* loglevel_c = loglevel
+ *         cdef int err
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_request_log_messages(self._ctx, loglevel_c)
+ *         return err
  */
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
+      }
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":319
+  /* "vidcutter/libs/pympv/mpv.pyx":438
+ *         with nogil:
+ *             err = mpv_request_log_messages(self._ctx, loglevel_c)
+ *         return err             # <<<<<<<<<<<<<<
  * 
- * def _errors(fn):
- *     def wrapped(*k, **kw):             # <<<<<<<<<<<<<<
- *         v = fn(*k, **kw)
- *         if v < 0:
+ *     @_errors
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 438, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":430
+ * 
+ *     @_errors
+ *     def set_log_level(self, loglevel):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_request_log_messages"""
+ *         assert self._ctx
  */
 
   /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv._errors.wrapped", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_log_level", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_v);
+  __Pyx_XDECREF(__pyx_v_loglevel);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":318
- * 
+/* "vidcutter/libs/pympv/mpv.pyx":441
  * 
- * def _errors(fn):             # <<<<<<<<<<<<<<
- *     def wrapped(*k, **kw):
- *         v = fn(*k, **kw)
+ *     @_errors
+ *     def load_config(self, filename):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_load_config_file"""
+ *         assert self._ctx
  */
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_4_errors(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_fn) {
-  struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *__pyx_cur_scope;
-  PyObject *__pyx_v_wrapped = 0;
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_5load_config(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_4load_config[] = "Wraps: mpv_load_config_file";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_5load_config(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("load_config (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_4load_config(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_filename));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_4load_config(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_filename) {
+  char const *__pyx_v__filename;
+  int __pyx_v_err;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  char const *__pyx_t_4;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_errors", 0);
-  __pyx_cur_scope = (struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *)__pyx_tp_new_9vidcutter_4libs_3mpv___pyx_scope_struct___errors(__pyx_ptype_9vidcutter_4libs_3mpv___pyx_scope_struct___errors, __pyx_empty_tuple, NULL);
-  if (unlikely(!__pyx_cur_scope)) {
-    __pyx_cur_scope = ((struct __pyx_obj_9vidcutter_4libs_3mpv___pyx_scope_struct___errors *)Py_None);
-    __Pyx_INCREF(Py_None);
-    __PYX_ERR(0, 318, __pyx_L1_error)
-  } else {
-    __Pyx_GOTREF(__pyx_cur_scope);
+  __Pyx_RefNannySetupContext("load_config", 0);
+  __Pyx_INCREF(__pyx_v_filename);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":443
+ *     def load_config(self, filename):
+ *         """Wraps: mpv_load_config_file"""
+ *         assert self._ctx             # <<<<<<<<<<<<<<
+ *         filename = _strenc(filename)
+ *         cdef const char* _filename = filename
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!Py_OptimizeFlag)) {
+    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
+      PyErr_SetNone(PyExc_AssertionError);
+      __PYX_ERR(0, 443, __pyx_L1_error)
+    }
   }
-  __pyx_cur_scope->__pyx_v_fn = __pyx_v_fn;
-  __Pyx_INCREF(__pyx_cur_scope->__pyx_v_fn);
-  __Pyx_GIVEREF(__pyx_cur_scope->__pyx_v_fn);
+  #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":319
- * 
- * def _errors(fn):
- *     def wrapped(*k, **kw):             # <<<<<<<<<<<<<<
- *         v = fn(*k, **kw)
- *         if v < 0:
+  /* "vidcutter/libs/pympv/mpv.pyx":444
+ *         """Wraps: mpv_load_config_file"""
+ *         assert self._ctx
+ *         filename = _strenc(filename)             # <<<<<<<<<<<<<<
+ *         cdef const char* _filename = filename
+ *         cdef int err
  */
-  __pyx_t_1 = __Pyx_CyFunction_New(&__pyx_mdef_9vidcutter_4libs_3mpv_7_errors_1wrapped, 0, __pyx_n_s_errors_locals_wrapped, ((PyObject*)__pyx_cur_scope), __pyx_n_s_vidcutter_libs_mpv, __pyx_d, ((PyObject *)__pyx_codeobj__2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 319, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 444, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_3)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_filename);
+  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 444, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_wrapped = __pyx_t_1;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF_SET(__pyx_v_filename, __pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":323
- *         if v < 0:
- *             raise MPVError(v)
- *     return wrapped             # <<<<<<<<<<<<<<
- * 
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":445
+ *         assert self._ctx
+ *         filename = _strenc(filename)
+ *         cdef const char* _filename = filename             # <<<<<<<<<<<<<<
+ *         cdef int err
+ *         with nogil:
+ */
+  __pyx_t_4 = __Pyx_PyObject_AsString(__pyx_v_filename); if (unlikely((!__pyx_t_4) && PyErr_Occurred())) __PYX_ERR(0, 445, __pyx_L1_error)
+  __pyx_v__filename = __pyx_t_4;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":447
+ *         cdef const char* _filename = filename
+ *         cdef int err
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_load_config_file(self._ctx, _filename)
+ *         return err
+ */
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
+
+        /* "vidcutter/libs/pympv/mpv.pyx":448
+ *         cdef int err
+ *         with nogil:
+ *             err = mpv_load_config_file(self._ctx, _filename)             # <<<<<<<<<<<<<<
+ *         return err
+ * 
+ */
+        __pyx_v_err = mpv_load_config_file(__pyx_v_self->_ctx, __pyx_v__filename);
+      }
+
+      /* "vidcutter/libs/pympv/mpv.pyx":447
+ *         cdef const char* _filename = filename
+ *         cdef int err
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_load_config_file(self._ctx, _filename)
+ *         return err
+ */
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
+      }
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":449
+ *         with nogil:
+ *             err = mpv_load_config_file(self._ctx, _filename)
+ *         return err             # <<<<<<<<<<<<<<
+ * 
+ *     def _format_for(self, value):
  */
   __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_wrapped);
-  __pyx_r = __pyx_v_wrapped;
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 449, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":318
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":441
  * 
- * def _errors(fn):             # <<<<<<<<<<<<<<
- *     def wrapped(*k, **kw):
- *         v = fn(*k, **kw)
+ *     @_errors
+ *     def load_config(self, filename):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_load_config_file"""
+ *         assert self._ctx
  */
 
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv._errors", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.load_config", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_wrapped);
-  __Pyx_DECREF(((PyObject *)__pyx_cur_scope));
+  __Pyx_XDECREF(__pyx_v_filename);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":329
- *     code = None
+/* "vidcutter/libs/pympv/mpv.pyx":451
+ *         return err
  * 
- *     def __init__(self, e):             # <<<<<<<<<<<<<<
- *         self.code = e
- *         cdef const char* err_c
+ *     def _format_for(self, value):             # <<<<<<<<<<<<<<
+ *         if isinstance(value, basestring):
+ *             return MPV_FORMAT_STRING
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8MPVError_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_8MPVError_1__init__ = {"__init__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9vidcutter_4libs_3mpv_8MPVError_1__init__, METH_VARARGS|METH_KEYWORDS, 0};
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_8MPVError_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_self = 0;
-  PyObject *__pyx_v_e = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_7_format_for(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_7_format_for(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_e,0};
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_e)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 329, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 329, __pyx_L3_error)
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_self = values[0];
-    __pyx_v_e = values[1];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 329, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.MPVError.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_8MPVError___init__(__pyx_self, __pyx_v_self, __pyx_v_e);
+  __Pyx_RefNannySetupContext("_format_for (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_6_format_for(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_value));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_8MPVError___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_e) {
-  char const *__pyx_v_err_c;
-  int __pyx_v_e_i;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_6_format_for(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_value) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
   int __pyx_t_2;
-  int __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  PyObject *__pyx_t_7 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_t_4;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__init__", 0);
-  __Pyx_INCREF(__pyx_v_e);
+  __Pyx_RefNannySetupContext("_format_for", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":330
+  /* "vidcutter/libs/pympv/mpv.pyx":452
  * 
- *     def __init__(self, e):
- *         self.code = e             # <<<<<<<<<<<<<<
- *         cdef const char* err_c
- *         cdef int e_i
- */
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_code, __pyx_v_e) < 0) __PYX_ERR(0, 330, __pyx_L1_error)
-
-  /* "vidcutter/libs/pympv/mpv.pyx":333
- *         cdef const char* err_c
- *         cdef int e_i
- *         if not isinstance(e, basestring):             # <<<<<<<<<<<<<<
- *             e_i = e
- *             with nogil:
+ *     def _format_for(self, value):
+ *         if isinstance(value, basestring):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_STRING
+ *         elif isinstance(value, bool):
  */
-  __pyx_t_1 = __Pyx_PyBaseString_Check(__pyx_v_e); 
-  __pyx_t_2 = ((!(__pyx_t_1 != 0)) != 0);
+  __pyx_t_1 = __Pyx_PyBaseString_Check(__pyx_v_value); 
+  __pyx_t_2 = (__pyx_t_1 != 0);
   if (__pyx_t_2) {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":334
- *         cdef int e_i
- *         if not isinstance(e, basestring):
- *             e_i = e             # <<<<<<<<<<<<<<
- *             with nogil:
- *                 err_c = mpv_error_string(e_i)
+    /* "vidcutter/libs/pympv/mpv.pyx":453
+ *     def _format_for(self, value):
+ *         if isinstance(value, basestring):
+ *             return MPV_FORMAT_STRING             # <<<<<<<<<<<<<<
+ *         elif isinstance(value, bool):
+ *             return MPV_FORMAT_FLAG
  */
-    __pyx_t_3 = __Pyx_PyInt_As_int(__pyx_v_e); if (unlikely((__pyx_t_3 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 334, __pyx_L1_error)
-    __pyx_v_e_i = __pyx_t_3;
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_STRING); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 453, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_r = __pyx_t_3;
+    __pyx_t_3 = 0;
+    goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":335
- *         if not isinstance(e, basestring):
- *             e_i = e
- *             with nogil:             # <<<<<<<<<<<<<<
- *                 err_c = mpv_error_string(e_i)
- *             e = _strdec(err_c)
+    /* "vidcutter/libs/pympv/mpv.pyx":452
+ * 
+ *     def _format_for(self, value):
+ *         if isinstance(value, basestring):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_STRING
+ *         elif isinstance(value, bool):
  */
-    {
-        #ifdef WITH_THREAD
-        PyThreadState *_save;
-        Py_UNBLOCK_THREADS
-        __Pyx_FastGIL_Remember();
-        #endif
-        /*try:*/ {
+  }
 
-          /* "vidcutter/libs/pympv/mpv.pyx":336
- *             e_i = e
- *             with nogil:
- *                 err_c = mpv_error_string(e_i)             # <<<<<<<<<<<<<<
- *             e = _strdec(err_c)
- *         Exception.__init__(self, e)
+  /* "vidcutter/libs/pympv/mpv.pyx":454
+ *         if isinstance(value, basestring):
+ *             return MPV_FORMAT_STRING
+ *         elif isinstance(value, bool):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_FLAG
+ *         elif isinstance(value, int):
  */
-          __pyx_v_err_c = mpv_error_string(__pyx_v_e_i);
-        }
+  __pyx_t_3 = ((PyObject*)&PyBool_Type);
+  __Pyx_INCREF(__pyx_t_3);
+  __pyx_t_2 = PyObject_IsInstance(__pyx_v_value, __pyx_t_3); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(0, 454, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_1 = (__pyx_t_2 != 0);
+  if (__pyx_t_1) {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":335
- *         if not isinstance(e, basestring):
- *             e_i = e
- *             with nogil:             # <<<<<<<<<<<<<<
- *                 err_c = mpv_error_string(e_i)
- *             e = _strdec(err_c)
+    /* "vidcutter/libs/pympv/mpv.pyx":455
+ *             return MPV_FORMAT_STRING
+ *         elif isinstance(value, bool):
+ *             return MPV_FORMAT_FLAG             # <<<<<<<<<<<<<<
+ *         elif isinstance(value, int):
+ *             return MPV_FORMAT_INT64
  */
-        /*finally:*/ {
-          /*normal exit:*/{
-            #ifdef WITH_THREAD
-            __Pyx_FastGIL_Forget();
-            Py_BLOCK_THREADS
-            #endif
-            goto __pyx_L6;
-          }
-          __pyx_L6:;
-        }
-    }
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_FLAG); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 455, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_r = __pyx_t_3;
+    __pyx_t_3 = 0;
+    goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":337
- *             with nogil:
- *                 err_c = mpv_error_string(e_i)
- *             e = _strdec(err_c)             # <<<<<<<<<<<<<<
- *         Exception.__init__(self, e)
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":454
+ *         if isinstance(value, basestring):
+ *             return MPV_FORMAT_STRING
+ *         elif isinstance(value, bool):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_FLAG
+ *         elif isinstance(value, int):
  */
-    __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_strdec); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 337, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_6 = __Pyx_PyBytes_FromString(__pyx_v_err_c); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 337, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_t_7 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
-      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_5);
-      if (likely(__pyx_t_7)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-        __Pyx_INCREF(__pyx_t_7);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_5, function);
-      }
-    }
-    __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_7, __pyx_t_6) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_6);
-    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 337, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_DECREF_SET(__pyx_v_e, __pyx_t_4);
-    __pyx_t_4 = 0;
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":333
- *         cdef const char* err_c
- *         cdef int e_i
- *         if not isinstance(e, basestring):             # <<<<<<<<<<<<<<
- *             e_i = e
- *             with nogil:
+  /* "vidcutter/libs/pympv/mpv.pyx":456
+ *         elif isinstance(value, bool):
+ *             return MPV_FORMAT_FLAG
+ *         elif isinstance(value, int):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_INT64
+ *         elif isinstance(value, float):
+ */
+  __pyx_t_1 = PyInt_Check(__pyx_v_value); 
+  __pyx_t_2 = (__pyx_t_1 != 0);
+  if (__pyx_t_2) {
+
+    /* "vidcutter/libs/pympv/mpv.pyx":457
+ *             return MPV_FORMAT_FLAG
+ *         elif isinstance(value, int):
+ *             return MPV_FORMAT_INT64             # <<<<<<<<<<<<<<
+ *         elif isinstance(value, float):
+ *             return MPV_FORMAT_DOUBLE
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_INT64); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 457, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_r = __pyx_t_3;
+    __pyx_t_3 = 0;
+    goto __pyx_L0;
+
+    /* "vidcutter/libs/pympv/mpv.pyx":456
+ *         elif isinstance(value, bool):
+ *             return MPV_FORMAT_FLAG
+ *         elif isinstance(value, int):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_INT64
+ *         elif isinstance(value, float):
  */
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":338
- *                 err_c = mpv_error_string(e_i)
- *             e = _strdec(err_c)
- *         Exception.__init__(self, e)             # <<<<<<<<<<<<<<
- * 
- * class PyMPVError(Exception):
+  /* "vidcutter/libs/pympv/mpv.pyx":458
+ *         elif isinstance(value, int):
+ *             return MPV_FORMAT_INT64
+ *         elif isinstance(value, float):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_DOUBLE
+ *         elif isinstance(value, (tuple, list)):
+ */
+  __pyx_t_2 = PyFloat_Check(__pyx_v_value); 
+  __pyx_t_1 = (__pyx_t_2 != 0);
+  if (__pyx_t_1) {
+
+    /* "vidcutter/libs/pympv/mpv.pyx":459
+ *             return MPV_FORMAT_INT64
+ *         elif isinstance(value, float):
+ *             return MPV_FORMAT_DOUBLE             # <<<<<<<<<<<<<<
+ *         elif isinstance(value, (tuple, list)):
+ *             return MPV_FORMAT_NODE_ARRAY
+ */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_DOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 459, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_r = __pyx_t_3;
+    __pyx_t_3 = 0;
+    goto __pyx_L0;
+
+    /* "vidcutter/libs/pympv/mpv.pyx":458
+ *         elif isinstance(value, int):
+ *             return MPV_FORMAT_INT64
+ *         elif isinstance(value, float):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_DOUBLE
+ *         elif isinstance(value, (tuple, list)):
  */
-  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)(&((PyTypeObject*)PyExc_Exception)[0])), __pyx_n_s_init); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 338, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_6 = NULL;
-  __pyx_t_3 = 0;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
-    __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
-    if (likely(__pyx_t_6)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-      __Pyx_INCREF(__pyx_t_6);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_5, function);
-      __pyx_t_3 = 1;
-    }
   }
-  #if CYTHON_FAST_PYCALL
-  if (PyFunction_Check(__pyx_t_5)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_self, __pyx_v_e};
-    __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_3, 2+__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 338, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_GOTREF(__pyx_t_4);
-  } else
-  #endif
-  #if CYTHON_FAST_PYCCALL
-  if (__Pyx_PyFastCFunction_Check(__pyx_t_5)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_6, __pyx_v_self, __pyx_v_e};
-    __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_5, __pyx_temp+1-__pyx_t_3, 2+__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 338, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_GOTREF(__pyx_t_4);
-  } else
-  #endif
-  {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 338, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    if (__pyx_t_6) {
-      __Pyx_GIVEREF(__pyx_t_6); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_6); __pyx_t_6 = NULL;
-    }
-    __Pyx_INCREF(__pyx_v_self);
-    __Pyx_GIVEREF(__pyx_v_self);
-    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_3, __pyx_v_self);
-    __Pyx_INCREF(__pyx_v_e);
-    __Pyx_GIVEREF(__pyx_v_e);
-    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_3, __pyx_v_e);
-    __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_5, __pyx_t_7, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 338, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":460
+ *         elif isinstance(value, float):
+ *             return MPV_FORMAT_DOUBLE
+ *         elif isinstance(value, (tuple, list)):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_NODE_ARRAY
+ *         elif isinstance(value, dict):
+ */
+  __pyx_t_2 = PyTuple_Check(__pyx_v_value); 
+  __pyx_t_4 = (__pyx_t_2 != 0);
+  if (!__pyx_t_4) {
+  } else {
+    __pyx_t_1 = __pyx_t_4;
+    goto __pyx_L4_bool_binop_done;
   }
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyList_Check(__pyx_v_value); 
+  __pyx_t_2 = (__pyx_t_4 != 0);
+  __pyx_t_1 = __pyx_t_2;
+  __pyx_L4_bool_binop_done:;
+  __pyx_t_2 = (__pyx_t_1 != 0);
+  if (__pyx_t_2) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":329
- *     code = None
- * 
- *     def __init__(self, e):             # <<<<<<<<<<<<<<
- *         self.code = e
- *         cdef const char* err_c
+    /* "vidcutter/libs/pympv/mpv.pyx":461
+ *             return MPV_FORMAT_DOUBLE
+ *         elif isinstance(value, (tuple, list)):
+ *             return MPV_FORMAT_NODE_ARRAY             # <<<<<<<<<<<<<<
+ *         elif isinstance(value, dict):
+ *             return MPV_FORMAT_NODE_MAP
  */
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_NODE_ARRAY); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 461, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_r = __pyx_t_3;
+    __pyx_t_3 = 0;
+    goto __pyx_L0;
 
-  /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.MPVError.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_e);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":460
+ *         elif isinstance(value, float):
+ *             return MPV_FORMAT_DOUBLE
+ *         elif isinstance(value, (tuple, list)):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_NODE_ARRAY
+ *         elif isinstance(value, dict):
+ */
+  }
 
-/* "vidcutter/libs/pympv/mpv.pyx":347
- * 
- * class _ReplyUserData(object):
- *     def __init__(self, data):             # <<<<<<<<<<<<<<
- *         self.counter = 0
- *         self.data = data
+  /* "vidcutter/libs/pympv/mpv.pyx":462
+ *         elif isinstance(value, (tuple, list)):
+ *             return MPV_FORMAT_NODE_ARRAY
+ *         elif isinstance(value, dict):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_NODE_MAP
+ *         return MPV_FORMAT_NONE
  */
+  __pyx_t_2 = PyDict_Check(__pyx_v_value); 
+  __pyx_t_1 = (__pyx_t_2 != 0);
+  if (__pyx_t_1) {
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_14_ReplyUserData_1__init__ = {"__init__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_1__init__, METH_VARARGS|METH_KEYWORDS, 0};
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_1__init__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_self = 0;
-  PyObject *__pyx_v_data = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_data,0};
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, 1); __PYX_ERR(0, 347, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 347, __pyx_L3_error)
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_self = values[0];
-    __pyx_v_data = values[1];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__init__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 347, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv._ReplyUserData.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData___init__(__pyx_self, __pyx_v_self, __pyx_v_data);
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData___init__(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self, PyObject *__pyx_v_data) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__init__", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":348
- * class _ReplyUserData(object):
- *     def __init__(self, data):
- *         self.counter = 0             # <<<<<<<<<<<<<<
- *         self.data = data
- *         self.observed = False
+    /* "vidcutter/libs/pympv/mpv.pyx":463
+ *             return MPV_FORMAT_NODE_ARRAY
+ *         elif isinstance(value, dict):
+ *             return MPV_FORMAT_NODE_MAP             # <<<<<<<<<<<<<<
+ *         return MPV_FORMAT_NONE
+ * 
  */
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_counter, __pyx_int_0) < 0) __PYX_ERR(0, 348, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_NODE_MAP); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 463, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_r = __pyx_t_3;
+    __pyx_t_3 = 0;
+    goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":349
- *     def __init__(self, data):
- *         self.counter = 0
- *         self.data = data             # <<<<<<<<<<<<<<
- *         self.observed = False
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":462
+ *         elif isinstance(value, (tuple, list)):
+ *             return MPV_FORMAT_NODE_ARRAY
+ *         elif isinstance(value, dict):             # <<<<<<<<<<<<<<
+ *             return MPV_FORMAT_NODE_MAP
+ *         return MPV_FORMAT_NONE
  */
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_data, __pyx_v_data) < 0) __PYX_ERR(0, 349, __pyx_L1_error)
+  }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":350
- *         self.counter = 0
- *         self.data = data
- *         self.observed = False             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":464
+ *         elif isinstance(value, dict):
+ *             return MPV_FORMAT_NODE_MAP
+ *         return MPV_FORMAT_NONE             # <<<<<<<<<<<<<<
  * 
- *     def add(self):
+ *     cdef mpv_node_list* _prep_node_list(self, values):
  */
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_observed, Py_False) < 0) __PYX_ERR(0, 350, __pyx_L1_error)
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_NONE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 464, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_r = __pyx_t_3;
+  __pyx_t_3 = 0;
+  goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":347
+  /* "vidcutter/libs/pympv/mpv.pyx":451
+ *         return err
  * 
- * class _ReplyUserData(object):
- *     def __init__(self, data):             # <<<<<<<<<<<<<<
- *         self.counter = 0
- *         self.data = data
+ *     def _format_for(self, value):             # <<<<<<<<<<<<<<
+ *         if isinstance(value, basestring):
+ *             return MPV_FORMAT_STRING
  */
 
   /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv._ReplyUserData.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context._format_for", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
@@ -8510,1160 +9185,1186 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData___init__(CYTHON
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":352
- *         self.observed = False
- * 
- *     def add(self):             # <<<<<<<<<<<<<<
- *         self.counter += 1
+/* "vidcutter/libs/pympv/mpv.pyx":466
+ *         return MPV_FORMAT_NONE
  * 
+ *     cdef mpv_node_list* _prep_node_list(self, values):             # <<<<<<<<<<<<<<
+ *         cdef mpv_node node
+ *         cdef mpv_format format
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_3add(PyObject *__pyx_self, PyObject *__pyx_v_self); /*proto*/
-static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_14_ReplyUserData_3add = {"add", (PyCFunction)__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_3add, METH_O, 0};
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_3add(PyObject *__pyx_self, PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("add (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData_2add(__pyx_self, ((PyObject *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData_2add(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
+static struct mpv_node_list *__pyx_f_9vidcutter_4libs_3mpv_7Context__prep_node_list(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_values) {
+  struct mpv_node __pyx_v_node;
+  enum mpv_format __pyx_v_format;
+  struct mpv_node_list *__pyx_v_node_list;
+  PyObject *__pyx_v_i = NULL;
+  PyObject *__pyx_v_value = NULL;
+  struct mpv_node_list *__pyx_r;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
+  Py_ssize_t __pyx_t_1;
+  int __pyx_t_2;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *(*__pyx_t_5)(PyObject *);
+  PyObject *__pyx_t_6 = NULL;
+  PyObject *__pyx_t_7 = NULL;
+  PyObject *__pyx_t_8 = NULL;
+  enum mpv_format __pyx_t_9;
+  Py_ssize_t __pyx_t_10;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("add", 0);
+  __Pyx_RefNannySetupContext("_prep_node_list", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":353
- * 
- *     def add(self):
- *         self.counter += 1             # <<<<<<<<<<<<<<
- * 
- *     def remove(self):
+  /* "vidcutter/libs/pympv/mpv.pyx":469
+ *         cdef mpv_node node
+ *         cdef mpv_format format
+ *         cdef mpv_node_list* node_list = <mpv_node_list*>malloc(sizeof(mpv_node_list))             # <<<<<<<<<<<<<<
+ *         node_list.num = len(values)
+ *         node_list.values = NULL
  */
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_counter); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 353, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyInt_AddObjC(__pyx_t_1, __pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 353, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_counter, __pyx_t_2) < 0) __PYX_ERR(0, 353, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_v_node_list = ((struct mpv_node_list *)malloc((sizeof(struct mpv_node_list))));
 
-  /* "vidcutter/libs/pympv/mpv.pyx":352
- *         self.observed = False
- * 
- *     def add(self):             # <<<<<<<<<<<<<<
- *         self.counter += 1
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":470
+ *         cdef mpv_format format
+ *         cdef mpv_node_list* node_list = <mpv_node_list*>malloc(sizeof(mpv_node_list))
+ *         node_list.num = len(values)             # <<<<<<<<<<<<<<
+ *         node_list.values = NULL
+ *         node_list.keys = NULL
  */
+  __pyx_t_1 = PyObject_Length(__pyx_v_values); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 470, __pyx_L1_error)
+  __pyx_v_node_list->num = __pyx_t_1;
 
-  /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_AddTraceback("vidcutter.libs.mpv._ReplyUserData.add", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "vidcutter/libs/pympv/mpv.pyx":355
- *         self.counter += 1
- * 
- *     def remove(self):             # <<<<<<<<<<<<<<
- *         self.counter -= 1
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":471
+ *         cdef mpv_node_list* node_list = <mpv_node_list*>malloc(sizeof(mpv_node_list))
+ *         node_list.num = len(values)
+ *         node_list.values = NULL             # <<<<<<<<<<<<<<
+ *         node_list.keys = NULL
+ *         if node_list.num:
  */
+  __pyx_v_node_list->values = NULL;
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_5remove(PyObject *__pyx_self, PyObject *__pyx_v_self); /*proto*/
-static PyMethodDef __pyx_mdef_9vidcutter_4libs_3mpv_14_ReplyUserData_5remove = {"remove", (PyCFunction)__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_5remove, METH_O, 0};
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_14_ReplyUserData_5remove(PyObject *__pyx_self, PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("remove (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData_4remove(__pyx_self, ((PyObject *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  /* "vidcutter/libs/pympv/mpv.pyx":472
+ *         node_list.num = len(values)
+ *         node_list.values = NULL
+ *         node_list.keys = NULL             # <<<<<<<<<<<<<<
+ *         if node_list.num:
+ *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
+ */
+  __pyx_v_node_list->keys = NULL;
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_14_ReplyUserData_4remove(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("remove", 0);
+  /* "vidcutter/libs/pympv/mpv.pyx":473
+ *         node_list.values = NULL
+ *         node_list.keys = NULL
+ *         if node_list.num:             # <<<<<<<<<<<<<<
+ *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
+ *         for i, value in enumerate(values):
+ */
+  __pyx_t_2 = (__pyx_v_node_list->num != 0);
+  if (__pyx_t_2) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":356
- * 
- *     def remove(self):
- *         self.counter -= 1             # <<<<<<<<<<<<<<
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":474
+ *         node_list.keys = NULL
+ *         if node_list.num:
+ *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))             # <<<<<<<<<<<<<<
+ *         for i, value in enumerate(values):
+ *             format = self._format_for(value)
+ */
+    __pyx_v_node_list->values = ((struct mpv_node *)malloc((__pyx_v_node_list->num * (sizeof(struct mpv_node)))));
+
+    /* "vidcutter/libs/pympv/mpv.pyx":473
+ *         node_list.values = NULL
+ *         node_list.keys = NULL
+ *         if node_list.num:             # <<<<<<<<<<<<<<
+ *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
+ *         for i, value in enumerate(values):
+ */
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":475
+ *         if node_list.num:
+ *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
+ *         for i, value in enumerate(values):             # <<<<<<<<<<<<<<
+ *             format = self._format_for(value)
+ *             node = self._prep_native_value(value, format)
+ */
+  __Pyx_INCREF(__pyx_int_0);
+  __pyx_t_3 = __pyx_int_0;
+  if (likely(PyList_CheckExact(__pyx_v_values)) || PyTuple_CheckExact(__pyx_v_values)) {
+    __pyx_t_4 = __pyx_v_values; __Pyx_INCREF(__pyx_t_4); __pyx_t_1 = 0;
+    __pyx_t_5 = NULL;
+  } else {
+    __pyx_t_1 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_values); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 475, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 475, __pyx_L1_error)
+  }
+  for (;;) {
+    if (likely(!__pyx_t_5)) {
+      if (likely(PyList_CheckExact(__pyx_t_4))) {
+        if (__pyx_t_1 >= PyList_GET_SIZE(__pyx_t_4)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_6 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_1); __Pyx_INCREF(__pyx_t_6); __pyx_t_1++; if (unlikely(0 < 0)) __PYX_ERR(0, 475, __pyx_L1_error)
+        #else
+        __pyx_t_6 = PySequence_ITEM(__pyx_t_4, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 475, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_6);
+        #endif
+      } else {
+        if (__pyx_t_1 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_1); __Pyx_INCREF(__pyx_t_6); __pyx_t_1++; if (unlikely(0 < 0)) __PYX_ERR(0, 475, __pyx_L1_error)
+        #else
+        __pyx_t_6 = PySequence_ITEM(__pyx_t_4, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 475, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_6);
+        #endif
+      }
+    } else {
+      __pyx_t_6 = __pyx_t_5(__pyx_t_4);
+      if (unlikely(!__pyx_t_6)) {
+        PyObject* exc_type = PyErr_Occurred();
+        if (exc_type) {
+          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+          else __PYX_ERR(0, 475, __pyx_L1_error)
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_6);
+    }
+    __Pyx_XDECREF_SET(__pyx_v_value, __pyx_t_6);
+    __pyx_t_6 = 0;
+    __Pyx_INCREF(__pyx_t_3);
+    __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_3);
+    __pyx_t_6 = __Pyx_PyInt_AddObjC(__pyx_t_3, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 475, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_3);
+    __pyx_t_3 = __pyx_t_6;
+    __pyx_t_6 = 0;
+
+    /* "vidcutter/libs/pympv/mpv.pyx":476
+ *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
+ *         for i, value in enumerate(values):
+ *             format = self._format_for(value)             # <<<<<<<<<<<<<<
+ *             node = self._prep_native_value(value, format)
+ *             node_list.values[i] = node
+ */
+    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_format_for); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 476, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_8 = NULL;
+    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
+      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7);
+      if (likely(__pyx_t_8)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
+        __Pyx_INCREF(__pyx_t_8);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_7, function);
+      }
+    }
+    __pyx_t_6 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_value) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_value);
+    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 476, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __pyx_t_9 = ((enum mpv_format)__Pyx_PyInt_As_enum__mpv_format(__pyx_t_6)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 476, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __pyx_v_format = __pyx_t_9;
+
+    /* "vidcutter/libs/pympv/mpv.pyx":477
+ *         for i, value in enumerate(values):
+ *             format = self._format_for(value)
+ *             node = self._prep_native_value(value, format)             # <<<<<<<<<<<<<<
+ *             node_list.values[i] = node
+ *         return node_list
+ */
+    __pyx_t_6 = __Pyx_PyInt_From_enum__mpv_format(__pyx_v_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 477, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __pyx_v_node = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_native_value(__pyx_v_self, __pyx_v_value, __pyx_t_6);
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+
+    /* "vidcutter/libs/pympv/mpv.pyx":478
+ *             format = self._format_for(value)
+ *             node = self._prep_native_value(value, format)
+ *             node_list.values[i] = node             # <<<<<<<<<<<<<<
+ *         return node_list
  * 
  */
-  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_self, __pyx_n_s_counter); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 356, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyInt_SubtractObjC(__pyx_t_1, __pyx_int_1, 1, 1, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 356, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_self, __pyx_n_s_counter, __pyx_t_2) < 0) __PYX_ERR(0, 356, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_t_10 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_10 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 478, __pyx_L1_error)
+    (__pyx_v_node_list->values[__pyx_t_10]) = __pyx_v_node;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":355
- *         self.counter += 1
+    /* "vidcutter/libs/pympv/mpv.pyx":475
+ *         if node_list.num:
+ *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
+ *         for i, value in enumerate(values):             # <<<<<<<<<<<<<<
+ *             format = self._format_for(value)
+ *             node = self._prep_native_value(value, format)
+ */
+  }
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":479
+ *             node = self._prep_native_value(value, format)
+ *             node_list.values[i] = node
+ *         return node_list             # <<<<<<<<<<<<<<
  * 
- *     def remove(self):             # <<<<<<<<<<<<<<
- *         self.counter -= 1
+ *     cdef mpv_node_list* _prep_node_map(self, map):
+ */
+  __pyx_r = __pyx_v_node_list;
+  goto __pyx_L0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":466
+ *         return MPV_FORMAT_NONE
  * 
+ *     cdef mpv_node_list* _prep_node_list(self, values):             # <<<<<<<<<<<<<<
+ *         cdef mpv_node node
+ *         cdef mpv_format format
  */
 
   /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_AddTraceback("vidcutter.libs.mpv._ReplyUserData.remove", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_WriteUnraisable("vidcutter.libs.mpv.Context._prep_node_list", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
+  __pyx_r = 0;
   __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_XDECREF(__pyx_v_i);
+  __Pyx_XDECREF(__pyx_v_value);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":370
- * 
- *     @property
- *     def api_version(self):             # <<<<<<<<<<<<<<
- *         return _CAPI_MINOR, _CAPI_MAJOR, _CAPI_VERSION
+/* "vidcutter/libs/pympv/mpv.pyx":481
+ *         return node_list
  * 
+ *     cdef mpv_node_list* _prep_node_map(self, map):             # <<<<<<<<<<<<<<
+ *         cdef char* ckey
+ *         cdef mpv_node_list* list
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_11api_version_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_11api_version_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_11api_version___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_11api_version___get__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
+static struct mpv_node_list *__pyx_f_9vidcutter_4libs_3mpv_7Context__prep_node_map(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_map) {
+  char *__pyx_v_ckey;
+  struct mpv_node_list *__pyx_v_list;
+  PyObject *__pyx_v_keys = NULL;
+  PyObject *__pyx_v_i = NULL;
+  PyObject *__pyx_v_key = NULL;
+  struct mpv_node_list *__pyx_r;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
+  Py_ssize_t __pyx_t_4;
+  int __pyx_t_5;
+  PyObject *(*__pyx_t_6)(PyObject *);
+  PyObject *__pyx_t_7 = NULL;
+  PyObject *__pyx_t_8 = NULL;
+  char *__pyx_t_9;
+  Py_ssize_t __pyx_t_10;
+  Py_ssize_t __pyx_t_11;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__get__", 0);
+  __Pyx_RefNannySetupContext("_prep_node_map", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":371
- *     @property
- *     def api_version(self):
- *         return _CAPI_MINOR, _CAPI_MAJOR, _CAPI_VERSION             # <<<<<<<<<<<<<<
- * 
- *     @property
+  /* "vidcutter/libs/pympv/mpv.pyx":484
+ *         cdef char* ckey
+ *         cdef mpv_node_list* list
+ *         list = self._prep_node_list(map.values())             # <<<<<<<<<<<<<<
+ *         keys = map.keys()
+ *         if not len(keys):
  */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_CAPI_MINOR); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 371, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_CAPI_MAJOR); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 371, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_map, __pyx_n_s_values); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 484, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyInt_From_unsigned_long(__pyx_v_9vidcutter_4libs_3mpv__CAPI_VERSION); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 371, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = PyTuple_New(3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 371, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_GIVEREF(__pyx_t_1);
-  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_2);
-  PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_2);
-  __Pyx_GIVEREF(__pyx_t_3);
-  PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_t_3);
-  __pyx_t_1 = 0;
-  __pyx_t_2 = 0;
-  __pyx_t_3 = 0;
-  __pyx_r = __pyx_t_4;
-  __pyx_t_4 = 0;
-  goto __pyx_L0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":370
- * 
- *     @property
- *     def api_version(self):             # <<<<<<<<<<<<<<
- *         return _CAPI_MINOR, _CAPI_MAJOR, _CAPI_VERSION
- * 
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.api_version.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "vidcutter/libs/pympv/mpv.pyx":374
- * 
- *     @property
- *     def name(self):             # <<<<<<<<<<<<<<
- *         """Unique name for every context created.
- * 
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_4name_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_4name_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_4name___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_4name___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  char const *__pyx_v_name;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__get__", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":380
- *         """
- *         cdef const char* name
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         with nogil:
- *             name = mpv_client_name(self._ctx)
- */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 380, __pyx_L1_error)
+  __pyx_t_3 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_3)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  #endif
-
-  /* "vidcutter/libs/pympv/mpv.pyx":381
- *         cdef const char* name
- *         assert self._ctx
- *         with nogil:             # <<<<<<<<<<<<<<
- *             name = mpv_client_name(self._ctx)
- *         return _strdec(name)
- */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
-
-        /* "vidcutter/libs/pympv/mpv.pyx":382
- *         assert self._ctx
- *         with nogil:
- *             name = mpv_client_name(self._ctx)             # <<<<<<<<<<<<<<
- *         return _strdec(name)
- * 
- */
-        __pyx_v_name = mpv_client_name(__pyx_v_self->_ctx);
-      }
-
-      /* "vidcutter/libs/pympv/mpv.pyx":381
- *         cdef const char* name
- *         assert self._ctx
- *         with nogil:             # <<<<<<<<<<<<<<
- *             name = mpv_client_name(self._ctx)
- *         return _strdec(name)
- */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
-  }
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 484, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_v_list = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_node_list(__pyx_v_self, __pyx_t_1);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":383
- *         with nogil:
- *             name = mpv_client_name(self._ctx)
- *         return _strdec(name)             # <<<<<<<<<<<<<<
- * 
- *     @property
+  /* "vidcutter/libs/pympv/mpv.pyx":485
+ *         cdef mpv_node_list* list
+ *         list = self._prep_node_list(map.values())
+ *         keys = map.keys()             # <<<<<<<<<<<<<<
+ *         if not len(keys):
+ *             return list
  */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strdec); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 383, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_map, __pyx_n_s_keys); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 485, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyBytes_FromString(__pyx_v_name); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 383, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_4)) {
+  __pyx_t_3 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_3)) {
       PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_4);
+      __Pyx_INCREF(__pyx_t_3);
       __Pyx_INCREF(function);
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_4, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 383, __pyx_L1_error)
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 485, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_r = __pyx_t_1;
+  __pyx_v_keys = __pyx_t_1;
   __pyx_t_1 = 0;
-  goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":374
- * 
- *     @property
- *     def name(self):             # <<<<<<<<<<<<<<
- *         """Unique name for every context created.
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":486
+ *         list = self._prep_node_list(map.values())
+ *         keys = map.keys()
+ *         if not len(keys):             # <<<<<<<<<<<<<<
+ *             return list
+ *         list.keys = <char**>malloc(list.num)
  */
+  __pyx_t_4 = PyObject_Length(__pyx_v_keys); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-1))) __PYX_ERR(0, 486, __pyx_L1_error)
+  __pyx_t_5 = ((!(__pyx_t_4 != 0)) != 0);
+  if (__pyx_t_5) {
 
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.name.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "vidcutter/libs/pympv/mpv.pyx":386
- * 
- *     @property
- *     def time(self):             # <<<<<<<<<<<<<<
- *         """Internal mpv client time.
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":487
+ *         keys = map.keys()
+ *         if not len(keys):
+ *             return list             # <<<<<<<<<<<<<<
+ *         list.keys = <char**>malloc(list.num)
+ *         for i, key in enumerate(keys):
  */
+    __pyx_r = __pyx_v_list;
+    goto __pyx_L0;
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_4time_1__get__(PyObject *__pyx_v_self); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_4time_1__get__(PyObject *__pyx_v_self) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__get__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_4time___get__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
+    /* "vidcutter/libs/pympv/mpv.pyx":486
+ *         list = self._prep_node_list(map.values())
+ *         keys = map.keys()
+ *         if not len(keys):             # <<<<<<<<<<<<<<
+ *             return list
+ *         list.keys = <char**>malloc(list.num)
+ */
+  }
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  /* "vidcutter/libs/pympv/mpv.pyx":488
+ *         if not len(keys):
+ *             return list
+ *         list.keys = <char**>malloc(list.num)             # <<<<<<<<<<<<<<
+ *         for i, key in enumerate(keys):
+ *             key = _strenc(key)
+ */
+  __pyx_v_list->keys = ((char **)malloc(__pyx_v_list->num));
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_4time___get__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  int64_t __pyx_v_time;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__get__", 0);
+  /* "vidcutter/libs/pympv/mpv.pyx":489
+ *             return list
+ *         list.keys = <char**>malloc(list.num)
+ *         for i, key in enumerate(keys):             # <<<<<<<<<<<<<<
+ *             key = _strenc(key)
+ *             ckey = key
+ */
+  __Pyx_INCREF(__pyx_int_0);
+  __pyx_t_1 = __pyx_int_0;
+  if (likely(PyList_CheckExact(__pyx_v_keys)) || PyTuple_CheckExact(__pyx_v_keys)) {
+    __pyx_t_2 = __pyx_v_keys; __Pyx_INCREF(__pyx_t_2); __pyx_t_4 = 0;
+    __pyx_t_6 = NULL;
+  } else {
+    __pyx_t_4 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_keys); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 489, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_6 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 489, __pyx_L1_error)
+  }
+  for (;;) {
+    if (likely(!__pyx_t_6)) {
+      if (likely(PyList_CheckExact(__pyx_t_2))) {
+        if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_2)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_3 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_4); __Pyx_INCREF(__pyx_t_3); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 489, __pyx_L1_error)
+        #else
+        __pyx_t_3 = PySequence_ITEM(__pyx_t_2, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 489, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        #endif
+      } else {
+        if (__pyx_t_4 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_4); __Pyx_INCREF(__pyx_t_3); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 489, __pyx_L1_error)
+        #else
+        __pyx_t_3 = PySequence_ITEM(__pyx_t_2, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 489, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        #endif
+      }
+    } else {
+      __pyx_t_3 = __pyx_t_6(__pyx_t_2);
+      if (unlikely(!__pyx_t_3)) {
+        PyObject* exc_type = PyErr_Occurred();
+        if (exc_type) {
+          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+          else __PYX_ERR(0, 489, __pyx_L1_error)
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_3);
+    }
+    __Pyx_XDECREF_SET(__pyx_v_key, __pyx_t_3);
+    __pyx_t_3 = 0;
+    __Pyx_INCREF(__pyx_t_1);
+    __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_1);
+    __pyx_t_3 = __Pyx_PyInt_AddObjC(__pyx_t_1, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 489, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_1);
+    __pyx_t_1 = __pyx_t_3;
+    __pyx_t_3 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":394
- *         """
- *         cdef int64_t time
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         with nogil:
- *             time = mpv_get_time_us(self._ctx)
+    /* "vidcutter/libs/pympv/mpv.pyx":490
+ *         list.keys = <char**>malloc(list.num)
+ *         for i, key in enumerate(keys):
+ *             key = _strenc(key)             # <<<<<<<<<<<<<<
+ *             ckey = key
+ *             list.keys[i] = <char*>malloc(len(key) + 1)
  */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 394, __pyx_L1_error)
+    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_strenc); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 490, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_8 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) {
+      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7);
+      if (likely(__pyx_t_8)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
+        __Pyx_INCREF(__pyx_t_8);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_7, function);
+      }
     }
-  }
-  #endif
+    __pyx_t_3 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_key) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_key);
+    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 490, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_DECREF_SET(__pyx_v_key, __pyx_t_3);
+    __pyx_t_3 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":395
- *         cdef int64_t time
- *         assert self._ctx
- *         with nogil:             # <<<<<<<<<<<<<<
- *             time = mpv_get_time_us(self._ctx)
- *         return time
+    /* "vidcutter/libs/pympv/mpv.pyx":491
+ *         for i, key in enumerate(keys):
+ *             key = _strenc(key)
+ *             ckey = key             # <<<<<<<<<<<<<<
+ *             list.keys[i] = <char*>malloc(len(key) + 1)
+ *             strcpy(list.keys[i], ckey)
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+    __pyx_t_9 = __Pyx_PyObject_AsWritableString(__pyx_v_key); if (unlikely((!__pyx_t_9) && PyErr_Occurred())) __PYX_ERR(0, 491, __pyx_L1_error)
+    __pyx_v_ckey = __pyx_t_9;
 
-        /* "vidcutter/libs/pympv/mpv.pyx":396
- *         assert self._ctx
- *         with nogil:
- *             time = mpv_get_time_us(self._ctx)             # <<<<<<<<<<<<<<
- *         return time
+    /* "vidcutter/libs/pympv/mpv.pyx":492
+ *             key = _strenc(key)
+ *             ckey = key
+ *             list.keys[i] = <char*>malloc(len(key) + 1)             # <<<<<<<<<<<<<<
+ *             strcpy(list.keys[i], ckey)
+ *         return list
+ */
+    __pyx_t_10 = PyObject_Length(__pyx_v_key); if (unlikely(__pyx_t_10 == ((Py_ssize_t)-1))) __PYX_ERR(0, 492, __pyx_L1_error)
+    __pyx_t_11 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_11 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 492, __pyx_L1_error)
+    (__pyx_v_list->keys[__pyx_t_11]) = ((char *)malloc((__pyx_t_10 + 1)));
+
+    /* "vidcutter/libs/pympv/mpv.pyx":493
+ *             ckey = key
+ *             list.keys[i] = <char*>malloc(len(key) + 1)
+ *             strcpy(list.keys[i], ckey)             # <<<<<<<<<<<<<<
+ *         return list
  * 
  */
-        __pyx_v_time = mpv_get_time_us(__pyx_v_self->_ctx);
-      }
+    __pyx_t_10 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_10 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 493, __pyx_L1_error)
+    (void)(strcpy((__pyx_v_list->keys[__pyx_t_10]), __pyx_v_ckey));
 
-      /* "vidcutter/libs/pympv/mpv.pyx":395
- *         cdef int64_t time
- *         assert self._ctx
- *         with nogil:             # <<<<<<<<<<<<<<
- *             time = mpv_get_time_us(self._ctx)
- *         return time
+    /* "vidcutter/libs/pympv/mpv.pyx":489
+ *             return list
+ *         list.keys = <char**>malloc(list.num)
+ *         for i, key in enumerate(keys):             # <<<<<<<<<<<<<<
+ *             key = _strenc(key)
+ *             ckey = key
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
   }
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":397
- *         with nogil:
- *             time = mpv_get_time_us(self._ctx)
- *         return time             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":494
+ *             list.keys[i] = <char*>malloc(len(key) + 1)
+ *             strcpy(list.keys[i], ckey)
+ *         return list             # <<<<<<<<<<<<<<
  * 
- *     def suspend(self):
+ *     cdef mpv_node _prep_native_value(self, value, format):
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int64_t(__pyx_v_time); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 397, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
+  __pyx_r = __pyx_v_list;
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":386
- * 
- *     @property
- *     def time(self):             # <<<<<<<<<<<<<<
- *         """Internal mpv client time.
+  /* "vidcutter/libs/pympv/mpv.pyx":481
+ *         return node_list
  * 
+ *     cdef mpv_node_list* _prep_node_map(self, map):             # <<<<<<<<<<<<<<
+ *         cdef char* ckey
+ *         cdef mpv_node_list* list
  */
 
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.time.__get__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_WriteUnraisable("vidcutter.libs.mpv.Context._prep_node_map", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
+  __pyx_r = 0;
   __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_XDECREF(__pyx_v_keys);
+  __Pyx_XDECREF(__pyx_v_i);
+  __Pyx_XDECREF(__pyx_v_key);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":399
- *         return time
+/* "vidcutter/libs/pympv/mpv.pyx":496
+ *         return list
  * 
- *     def suspend(self):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_suspend"""
- *         assert self._ctx
+ *     cdef mpv_node _prep_native_value(self, value, format):             # <<<<<<<<<<<<<<
+ *         cdef mpv_node node
+ *         node.format = format
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_1suspend(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_suspend[] = "Wraps: mpv_suspend";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_1suspend(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("suspend (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_suspend(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_suspend(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
+static struct mpv_node __pyx_f_9vidcutter_4libs_3mpv_7Context__prep_native_value(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_value, PyObject *__pyx_v_format) {
+  struct mpv_node __pyx_v_node;
+  struct mpv_node __pyx_r;
   __Pyx_RefNannyDeclarations
+  enum mpv_format __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_t_4;
+  PyObject *__pyx_t_5 = NULL;
+  Py_ssize_t __pyx_t_6;
+  char const *__pyx_t_7;
+  int __pyx_t_8;
+  int64_t __pyx_t_9;
+  double __pyx_t_10;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("suspend", 0);
+  __Pyx_RefNannySetupContext("_prep_native_value", 0);
+  __Pyx_INCREF(__pyx_v_value);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":401
- *     def suspend(self):
- *         """Wraps: mpv_suspend"""
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         with nogil:
- *             mpv_suspend(self._ctx)
+  /* "vidcutter/libs/pympv/mpv.pyx":498
+ *     cdef mpv_node _prep_native_value(self, value, format):
+ *         cdef mpv_node node
+ *         node.format = format             # <<<<<<<<<<<<<<
+ *         if format == MPV_FORMAT_STRING:
+ *             value = _strenc(value)
  */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 401, __pyx_L1_error)
-    }
-  }
-  #endif
-
-  /* "vidcutter/libs/pympv/mpv.pyx":402
- *         """Wraps: mpv_suspend"""
- *         assert self._ctx
- *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_suspend(self._ctx)
- * 
- */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+  __pyx_t_1 = ((enum mpv_format)__Pyx_PyInt_As_enum__mpv_format(__pyx_v_format)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 498, __pyx_L1_error)
+  __pyx_v_node.format = __pyx_t_1;
 
-        /* "vidcutter/libs/pympv/mpv.pyx":403
- *         assert self._ctx
- *         with nogil:
- *             mpv_suspend(self._ctx)             # <<<<<<<<<<<<<<
- * 
- *     def resume(self):
+  /* "vidcutter/libs/pympv/mpv.pyx":499
+ *         cdef mpv_node node
+ *         node.format = format
+ *         if format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
+ *             value = _strenc(value)
+ *             node.u.string = <char*>malloc(len(value) + 1)
  */
-        mpv_suspend(__pyx_v_self->_ctx);
-      }
+  __pyx_t_2 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_STRING); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 499, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_RichCompare(__pyx_v_format, __pyx_t_2, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 499, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 499, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (__pyx_t_4) {
 
-      /* "vidcutter/libs/pympv/mpv.pyx":402
- *         """Wraps: mpv_suspend"""
- *         assert self._ctx
- *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_suspend(self._ctx)
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":500
+ *         node.format = format
+ *         if format == MPV_FORMAT_STRING:
+ *             value = _strenc(value)             # <<<<<<<<<<<<<<
+ *             node.u.string = <char*>malloc(len(value) + 1)
+ *             strcpy(node.u.string, value)
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 500, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_5 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
       }
-  }
+    }
+    __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_5, __pyx_v_value) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_value);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 500, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_DECREF_SET(__pyx_v_value, __pyx_t_3);
+    __pyx_t_3 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":399
- *         return time
- * 
- *     def suspend(self):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_suspend"""
- *         assert self._ctx
+    /* "vidcutter/libs/pympv/mpv.pyx":501
+ *         if format == MPV_FORMAT_STRING:
+ *             value = _strenc(value)
+ *             node.u.string = <char*>malloc(len(value) + 1)             # <<<<<<<<<<<<<<
+ *             strcpy(node.u.string, value)
+ *         elif format == MPV_FORMAT_FLAG:
  */
+    __pyx_t_6 = PyObject_Length(__pyx_v_value); if (unlikely(__pyx_t_6 == ((Py_ssize_t)-1))) __PYX_ERR(0, 501, __pyx_L1_error)
+    __pyx_v_node.u.string = ((char *)malloc((__pyx_t_6 + 1)));
 
-  /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.suspend", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "vidcutter/libs/pympv/mpv.pyx":405
- *             mpv_suspend(self._ctx)
- * 
- *     def resume(self):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_resume"""
- *         assert self._ctx
+    /* "vidcutter/libs/pympv/mpv.pyx":502
+ *             value = _strenc(value)
+ *             node.u.string = <char*>malloc(len(value) + 1)
+ *             strcpy(node.u.string, value)             # <<<<<<<<<<<<<<
+ *         elif format == MPV_FORMAT_FLAG:
+ *             node.u.flag = 1 if value else 0
  */
+    __pyx_t_7 = __Pyx_PyObject_AsString(__pyx_v_value); if (unlikely((!__pyx_t_7) && PyErr_Occurred())) __PYX_ERR(0, 502, __pyx_L1_error)
+    (void)(strcpy(__pyx_v_node.u.string, __pyx_t_7));
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_3resume(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_2resume[] = "Wraps: mpv_resume";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_3resume(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("resume (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_2resume(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":499
+ *         cdef mpv_node node
+ *         node.format = format
+ *         if format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
+ *             value = _strenc(value)
+ *             node.u.string = <char*>malloc(len(value) + 1)
+ */
+    goto __pyx_L3;
+  }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_2resume(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("resume", 0);
+  /* "vidcutter/libs/pympv/mpv.pyx":503
+ *             node.u.string = <char*>malloc(len(value) + 1)
+ *             strcpy(node.u.string, value)
+ *         elif format == MPV_FORMAT_FLAG:             # <<<<<<<<<<<<<<
+ *             node.u.flag = 1 if value else 0
+ *         elif format == MPV_FORMAT_INT64:
+ */
+  __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_FLAG); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 503, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_2 = PyObject_RichCompare(__pyx_v_format, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 503, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 503, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (__pyx_t_4) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":407
- *     def resume(self):
- *         """Wraps: mpv_resume"""
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         with nogil:
- *             mpv_resume(self._ctx)
+    /* "vidcutter/libs/pympv/mpv.pyx":504
+ *             strcpy(node.u.string, value)
+ *         elif format == MPV_FORMAT_FLAG:
+ *             node.u.flag = 1 if value else 0             # <<<<<<<<<<<<<<
+ *         elif format == MPV_FORMAT_INT64:
+ *             node.u.int64 = value
  */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 407, __pyx_L1_error)
+    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_value); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 504, __pyx_L1_error)
+    if (__pyx_t_4) {
+      __pyx_t_8 = 1;
+    } else {
+      __pyx_t_8 = 0;
     }
+    __pyx_v_node.u.flag = __pyx_t_8;
+
+    /* "vidcutter/libs/pympv/mpv.pyx":503
+ *             node.u.string = <char*>malloc(len(value) + 1)
+ *             strcpy(node.u.string, value)
+ *         elif format == MPV_FORMAT_FLAG:             # <<<<<<<<<<<<<<
+ *             node.u.flag = 1 if value else 0
+ *         elif format == MPV_FORMAT_INT64:
+ */
+    goto __pyx_L3;
   }
-  #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":408
- *         """Wraps: mpv_resume"""
- *         assert self._ctx
- *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_resume(self._ctx)
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":505
+ *         elif format == MPV_FORMAT_FLAG:
+ *             node.u.flag = 1 if value else 0
+ *         elif format == MPV_FORMAT_INT64:             # <<<<<<<<<<<<<<
+ *             node.u.int64 = value
+ *         elif format == MPV_FORMAT_DOUBLE:
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+  __pyx_t_2 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_INT64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 505, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_RichCompare(__pyx_v_format, __pyx_t_2, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 505, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 505, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (__pyx_t_4) {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":409
- *         assert self._ctx
- *         with nogil:
- *             mpv_resume(self._ctx)             # <<<<<<<<<<<<<<
- * 
- *     @_errors
+    /* "vidcutter/libs/pympv/mpv.pyx":506
+ *             node.u.flag = 1 if value else 0
+ *         elif format == MPV_FORMAT_INT64:
+ *             node.u.int64 = value             # <<<<<<<<<<<<<<
+ *         elif format == MPV_FORMAT_DOUBLE:
+ *             node.u.double_ = value
  */
-        mpv_resume(__pyx_v_self->_ctx);
-      }
+    __pyx_t_9 = __Pyx_PyInt_As_int64_t(__pyx_v_value); if (unlikely((__pyx_t_9 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 506, __pyx_L1_error)
+    __pyx_v_node.u.int64 = __pyx_t_9;
 
-      /* "vidcutter/libs/pympv/mpv.pyx":408
- *         """Wraps: mpv_resume"""
- *         assert self._ctx
- *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_resume(self._ctx)
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":505
+ *         elif format == MPV_FORMAT_FLAG:
+ *             node.u.flag = 1 if value else 0
+ *         elif format == MPV_FORMAT_INT64:             # <<<<<<<<<<<<<<
+ *             node.u.int64 = value
+ *         elif format == MPV_FORMAT_DOUBLE:
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
+    goto __pyx_L3;
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":405
- *             mpv_suspend(self._ctx)
- * 
- *     def resume(self):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_resume"""
- *         assert self._ctx
+  /* "vidcutter/libs/pympv/mpv.pyx":507
+ *         elif format == MPV_FORMAT_INT64:
+ *             node.u.int64 = value
+ *         elif format == MPV_FORMAT_DOUBLE:             # <<<<<<<<<<<<<<
+ *             node.u.double_ = value
+ *         elif format == MPV_FORMAT_NODE_ARRAY:
  */
+  __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_DOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 507, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_2 = PyObject_RichCompare(__pyx_v_format, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 507, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 507, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (__pyx_t_4) {
 
-  /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.resume", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":508
+ *             node.u.int64 = value
+ *         elif format == MPV_FORMAT_DOUBLE:
+ *             node.u.double_ = value             # <<<<<<<<<<<<<<
+ *         elif format == MPV_FORMAT_NODE_ARRAY:
+ *             node.u.list = self._prep_node_list(value)
+ */
+    __pyx_t_10 = __pyx_PyFloat_AsDouble(__pyx_v_value); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 508, __pyx_L1_error)
+    __pyx_v_node.u.double_ = __pyx_t_10;
 
-/* "vidcutter/libs/pympv/mpv.pyx":412
- * 
- *     @_errors
- *     def request_event(self, event, enable):             # <<<<<<<<<<<<<<
- *         """Enable or disable a given event.
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":507
+ *         elif format == MPV_FORMAT_INT64:
+ *             node.u.int64 = value
+ *         elif format == MPV_FORMAT_DOUBLE:             # <<<<<<<<<<<<<<
+ *             node.u.double_ = value
+ *         elif format == MPV_FORMAT_NODE_ARRAY:
  */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_5request_event(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_4request_event[] = "Enable or disable a given event.\n\n        Arguments:\n        event - See Events\n        enable - True to enable, False to disable\n\n        Wraps: mpv_request_event\n        ";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_5request_event(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_event = 0;
-  PyObject *__pyx_v_enable = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("request_event (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_event,&__pyx_n_s_enable,0};
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_event)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_enable)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("request_event", 1, 2, 2, 1); __PYX_ERR(0, 412, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "request_event") < 0)) __PYX_ERR(0, 412, __pyx_L3_error)
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_event = values[0];
-    __pyx_v_enable = values[1];
+    goto __pyx_L3;
   }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("request_event", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 412, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.request_event", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_4request_event(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_event, __pyx_v_enable);
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_4request_event(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_event, PyObject *__pyx_v_enable) {
-  int __pyx_v_enable_i;
-  int __pyx_v_err;
-  enum mpv_event_id __pyx_v_event_id;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  int __pyx_t_2;
-  enum mpv_event_id __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("request_event", 0);
+  /* "vidcutter/libs/pympv/mpv.pyx":509
+ *         elif format == MPV_FORMAT_DOUBLE:
+ *             node.u.double_ = value
+ *         elif format == MPV_FORMAT_NODE_ARRAY:             # <<<<<<<<<<<<<<
+ *             node.u.list = self._prep_node_list(value)
+ *         elif format == MPV_FORMAT_NODE_MAP:
+ */
+  __pyx_t_2 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_NODE_ARRAY); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 509, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_RichCompare(__pyx_v_format, __pyx_t_2, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 509, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 509, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (__pyx_t_4) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":421
- *         Wraps: mpv_request_event
- *         """
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         cdef int enable_i = 1 if enable else 0
- *         cdef int err
+    /* "vidcutter/libs/pympv/mpv.pyx":510
+ *             node.u.double_ = value
+ *         elif format == MPV_FORMAT_NODE_ARRAY:
+ *             node.u.list = self._prep_node_list(value)             # <<<<<<<<<<<<<<
+ *         elif format == MPV_FORMAT_NODE_MAP:
+ *             node.u.list = self._prep_node_map(value)
  */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 421, __pyx_L1_error)
-    }
-  }
-  #endif
+    __pyx_v_node.u.list = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_node_list(__pyx_v_self, __pyx_v_value);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":422
- *         """
- *         assert self._ctx
- *         cdef int enable_i = 1 if enable else 0             # <<<<<<<<<<<<<<
- *         cdef int err
- *         cdef mpv_event_id event_id = event
+    /* "vidcutter/libs/pympv/mpv.pyx":509
+ *         elif format == MPV_FORMAT_DOUBLE:
+ *             node.u.double_ = value
+ *         elif format == MPV_FORMAT_NODE_ARRAY:             # <<<<<<<<<<<<<<
+ *             node.u.list = self._prep_node_list(value)
+ *         elif format == MPV_FORMAT_NODE_MAP:
  */
-  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_enable); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 422, __pyx_L1_error)
-  if (__pyx_t_2) {
-    __pyx_t_1 = 1;
-  } else {
-    __pyx_t_1 = 0;
+    goto __pyx_L3;
   }
-  __pyx_v_enable_i = __pyx_t_1;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":424
- *         cdef int enable_i = 1 if enable else 0
- *         cdef int err
- *         cdef mpv_event_id event_id = event             # <<<<<<<<<<<<<<
- *         with nogil:
- *             err = mpv_request_event(self._ctx, event_id, enable_i)
+  /* "vidcutter/libs/pympv/mpv.pyx":511
+ *         elif format == MPV_FORMAT_NODE_ARRAY:
+ *             node.u.list = self._prep_node_list(value)
+ *         elif format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
+ *             node.u.list = self._prep_node_map(value)
+ *         else:
  */
-  __pyx_t_3 = ((enum mpv_event_id)__Pyx_PyInt_As_enum__mpv_event_id(__pyx_v_event)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 424, __pyx_L1_error)
-  __pyx_v_event_id = __pyx_t_3;
+  __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_NODE_MAP); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 511, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_2 = PyObject_RichCompare(__pyx_v_format, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 511, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 511, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (__pyx_t_4) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":425
- *         cdef int err
- *         cdef mpv_event_id event_id = event
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_request_event(self._ctx, event_id, enable_i)
- *         return err
+    /* "vidcutter/libs/pympv/mpv.pyx":512
+ *             node.u.list = self._prep_node_list(value)
+ *         elif format == MPV_FORMAT_NODE_MAP:
+ *             node.u.list = self._prep_node_map(value)             # <<<<<<<<<<<<<<
+ *         else:
+ *             node.format = MPV_FORMAT_NONE
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+    __pyx_v_node.u.list = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_node_map(__pyx_v_self, __pyx_v_value);
 
-        /* "vidcutter/libs/pympv/mpv.pyx":426
- *         cdef mpv_event_id event_id = event
- *         with nogil:
- *             err = mpv_request_event(self._ctx, event_id, enable_i)             # <<<<<<<<<<<<<<
- *         return err
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":511
+ *         elif format == MPV_FORMAT_NODE_ARRAY:
+ *             node.u.list = self._prep_node_list(value)
+ *         elif format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
+ *             node.u.list = self._prep_node_map(value)
+ *         else:
  */
-        __pyx_v_err = mpv_request_event(__pyx_v_self->_ctx, __pyx_v_event_id, __pyx_v_enable_i);
-      }
+    goto __pyx_L3;
+  }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":425
- *         cdef int err
- *         cdef mpv_event_id event_id = event
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_request_event(self._ctx, event_id, enable_i)
- *         return err
+  /* "vidcutter/libs/pympv/mpv.pyx":514
+ *             node.u.list = self._prep_node_map(value)
+ *         else:
+ *             node.format = MPV_FORMAT_NONE             # <<<<<<<<<<<<<<
+ *         return node
+ * 
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
+  /*else*/ {
+    __pyx_v_node.format = MPV_FORMAT_NONE;
   }
+  __pyx_L3:;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":427
- *         with nogil:
- *             err = mpv_request_event(self._ctx, event_id, enable_i)
- *         return err             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":515
+ *         else:
+ *             node.format = MPV_FORMAT_NONE
+ *         return node             # <<<<<<<<<<<<<<
  * 
- *     @_errors
+ *     cdef _free_native_value(self, mpv_node node):
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 427, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_r = __pyx_t_4;
-  __pyx_t_4 = 0;
+  __pyx_r = __pyx_v_node;
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":412
- * 
- *     @_errors
- *     def request_event(self, event, enable):             # <<<<<<<<<<<<<<
- *         """Enable or disable a given event.
+  /* "vidcutter/libs/pympv/mpv.pyx":496
+ *         return list
  * 
+ *     cdef mpv_node _prep_native_value(self, value, format):             # <<<<<<<<<<<<<<
+ *         cdef mpv_node node
+ *         node.format = format
  */
 
   /* function exit code */
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.request_event", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_WriteUnraisable("vidcutter.libs.mpv.Context._prep_native_value", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
+  __Pyx_pretend_to_initialize(&__pyx_r);
   __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_XDECREF(__pyx_v_value);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":430
+/* "vidcutter/libs/pympv/mpv.pyx":517
+ *         return node
  * 
- *     @_errors
- *     def set_log_level(self, loglevel):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_request_log_messages"""
- *         assert self._ctx
+ *     cdef _free_native_value(self, mpv_node node):             # <<<<<<<<<<<<<<
+ *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):
+ *             for i in range(node.u.list.num):
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_7set_log_level(PyObject *__pyx_v_self, PyObject *__pyx_v_loglevel); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_6set_log_level[] = "Wraps: mpv_request_log_messages";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_7set_log_level(PyObject *__pyx_v_self, PyObject *__pyx_v_loglevel) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("set_log_level (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_6set_log_level(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_loglevel));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_6set_log_level(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_loglevel) {
-  char const *__pyx_v_loglevel_c;
-  int __pyx_v_err;
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv_7Context__free_native_value(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, struct mpv_node __pyx_v_node) {
+  int __pyx_v_i;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  char const *__pyx_t_4;
+  int __pyx_t_1;
+  int __pyx_t_2;
+  int __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
+  int __pyx_t_5;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("set_log_level", 0);
-  __Pyx_INCREF(__pyx_v_loglevel);
+  __Pyx_RefNannySetupContext("_free_native_value", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":432
- *     def set_log_level(self, loglevel):
- *         """Wraps: mpv_request_log_messages"""
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         loglevel = _strenc(loglevel)
- *         cdef const char* loglevel_c = loglevel
+  /* "vidcutter/libs/pympv/mpv.pyx":518
+ * 
+ *     cdef _free_native_value(self, mpv_node node):
+ *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):             # <<<<<<<<<<<<<<
+ *             for i in range(node.u.list.num):
+ *                 self._free_native_value(node.u.list.values[i])
  */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 432, __pyx_L1_error)
-    }
-  }
-  #endif
+  switch (__pyx_v_node.format) {
+    case MPV_FORMAT_NODE_ARRAY:
+    case MPV_FORMAT_NODE_MAP:
 
-  /* "vidcutter/libs/pympv/mpv.pyx":433
- *         """Wraps: mpv_request_log_messages"""
- *         assert self._ctx
- *         loglevel = _strenc(loglevel)             # <<<<<<<<<<<<<<
- *         cdef const char* loglevel_c = loglevel
- *         cdef int err
+    /* "vidcutter/libs/pympv/mpv.pyx":519
+ *     cdef _free_native_value(self, mpv_node node):
+ *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):
+ *             for i in range(node.u.list.num):             # <<<<<<<<<<<<<<
+ *                 self._free_native_value(node.u.list.values[i])
+ *             free(node.u.list.values)
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 433, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_3)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
+    __pyx_t_1 = __pyx_v_node.u.list->num;
+    __pyx_t_2 = __pyx_t_1;
+    for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
+      __pyx_v_i = __pyx_t_3;
+
+      /* "vidcutter/libs/pympv/mpv.pyx":520
+ *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):
+ *             for i in range(node.u.list.num):
+ *                 self._free_native_value(node.u.list.values[i])             # <<<<<<<<<<<<<<
+ *             free(node.u.list.values)
+ *             if node.format == MPV_FORMAT_NODE_MAP:
+ */
+      __pyx_t_4 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, (__pyx_v_node.u.list->values[__pyx_v_i])); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 520, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     }
-  }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_loglevel) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_loglevel);
-  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 433, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF_SET(__pyx_v_loglevel, __pyx_t_1);
-  __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":434
- *         assert self._ctx
- *         loglevel = _strenc(loglevel)
- *         cdef const char* loglevel_c = loglevel             # <<<<<<<<<<<<<<
- *         cdef int err
- *         with nogil:
+    /* "vidcutter/libs/pympv/mpv.pyx":521
+ *             for i in range(node.u.list.num):
+ *                 self._free_native_value(node.u.list.values[i])
+ *             free(node.u.list.values)             # <<<<<<<<<<<<<<
+ *             if node.format == MPV_FORMAT_NODE_MAP:
+ *                 for i in range(node.u.list.num):
  */
-  __pyx_t_4 = __Pyx_PyObject_AsString(__pyx_v_loglevel); if (unlikely((!__pyx_t_4) && PyErr_Occurred())) __PYX_ERR(0, 434, __pyx_L1_error)
-  __pyx_v_loglevel_c = __pyx_t_4;
+    free(__pyx_v_node.u.list->values);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":436
- *         cdef const char* loglevel_c = loglevel
- *         cdef int err
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_request_log_messages(self._ctx, loglevel_c)
- *         return err
+    /* "vidcutter/libs/pympv/mpv.pyx":522
+ *                 self._free_native_value(node.u.list.values[i])
+ *             free(node.u.list.values)
+ *             if node.format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
+ *                 for i in range(node.u.list.num):
+ *                     free(node.u.list.keys[i])
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+    __pyx_t_5 = ((__pyx_v_node.format == MPV_FORMAT_NODE_MAP) != 0);
+    if (__pyx_t_5) {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":437
- *         cdef int err
- *         with nogil:
- *             err = mpv_request_log_messages(self._ctx, loglevel_c)             # <<<<<<<<<<<<<<
- *         return err
- * 
+      /* "vidcutter/libs/pympv/mpv.pyx":523
+ *             free(node.u.list.values)
+ *             if node.format == MPV_FORMAT_NODE_MAP:
+ *                 for i in range(node.u.list.num):             # <<<<<<<<<<<<<<
+ *                     free(node.u.list.keys[i])
+ *                 free(node.u.list.keys)
  */
-        __pyx_v_err = mpv_request_log_messages(__pyx_v_self->_ctx, __pyx_v_loglevel_c);
-      }
+      __pyx_t_1 = __pyx_v_node.u.list->num;
+      __pyx_t_2 = __pyx_t_1;
+      for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
+        __pyx_v_i = __pyx_t_3;
 
-      /* "vidcutter/libs/pympv/mpv.pyx":436
- *         cdef const char* loglevel_c = loglevel
- *         cdef int err
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_request_log_messages(self._ctx, loglevel_c)
- *         return err
+        /* "vidcutter/libs/pympv/mpv.pyx":524
+ *             if node.format == MPV_FORMAT_NODE_MAP:
+ *                 for i in range(node.u.list.num):
+ *                     free(node.u.list.keys[i])             # <<<<<<<<<<<<<<
+ *                 free(node.u.list.keys)
+ *             free(node.u.list)
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
+        free((__pyx_v_node.u.list->keys[__pyx_v_i]));
       }
-  }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":438
- *         with nogil:
- *             err = mpv_request_log_messages(self._ctx, loglevel_c)
- *         return err             # <<<<<<<<<<<<<<
- * 
- *     @_errors
+      /* "vidcutter/libs/pympv/mpv.pyx":525
+ *                 for i in range(node.u.list.num):
+ *                     free(node.u.list.keys[i])
+ *                 free(node.u.list.keys)             # <<<<<<<<<<<<<<
+ *             free(node.u.list)
+ *         elif node.format == MPV_FORMAT_STRING:
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 438, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
+      free(__pyx_v_node.u.list->keys);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":430
- * 
- *     @_errors
- *     def set_log_level(self, loglevel):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_request_log_messages"""
- *         assert self._ctx
+      /* "vidcutter/libs/pympv/mpv.pyx":522
+ *                 self._free_native_value(node.u.list.values[i])
+ *             free(node.u.list.values)
+ *             if node.format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
+ *                 for i in range(node.u.list.num):
+ *                     free(node.u.list.keys[i])
  */
+    }
 
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_log_level", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_loglevel);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":526
+ *                     free(node.u.list.keys[i])
+ *                 free(node.u.list.keys)
+ *             free(node.u.list)             # <<<<<<<<<<<<<<
+ *         elif node.format == MPV_FORMAT_STRING:
+ *             free(node.u.string)
+ */
+    free(__pyx_v_node.u.list);
 
-/* "vidcutter/libs/pympv/mpv.pyx":441
+    /* "vidcutter/libs/pympv/mpv.pyx":518
  * 
- *     @_errors
- *     def load_config(self, filename):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_load_config_file"""
- *         assert self._ctx
+ *     cdef _free_native_value(self, mpv_node node):
+ *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):             # <<<<<<<<<<<<<<
+ *             for i in range(node.u.list.num):
+ *                 self._free_native_value(node.u.list.values[i])
  */
+    break;
+    case MPV_FORMAT_STRING:
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_9load_config(PyObject *__pyx_v_self, PyObject *__pyx_v_filename); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_8load_config[] = "Wraps: mpv_load_config_file";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_9load_config(PyObject *__pyx_v_self, PyObject *__pyx_v_filename) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("load_config (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_8load_config(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_filename));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_8load_config(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_filename) {
-  char const *__pyx_v__filename;
+    /* "vidcutter/libs/pympv/mpv.pyx":528
+ *             free(node.u.list)
+ *         elif node.format == MPV_FORMAT_STRING:
+ *             free(node.u.string)             # <<<<<<<<<<<<<<
+ * 
+ *     def command(self, *cmdlist, asynchronous=False, data=None):
+ */
+    free(__pyx_v_node.u.string);
+
+    /* "vidcutter/libs/pympv/mpv.pyx":527
+ *                 free(node.u.list.keys)
+ *             free(node.u.list)
+ *         elif node.format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
+ *             free(node.u.string)
+ * 
+ */
+    break;
+    default: break;
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":517
+ *         return node
+ * 
+ *     cdef _free_native_value(self, mpv_node node):             # <<<<<<<<<<<<<<
+ *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):
+ *             for i in range(node.u.list.num):
+ */
+
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context._free_native_value", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "vidcutter/libs/pympv/mpv.pyx":530
+ *             free(node.u.string)
+ * 
+ *     def command(self, *cmdlist, asynchronous=False, data=None):             # <<<<<<<<<<<<<<
+ *         """Send a command to mpv.
+ * 
+ */
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_9command(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_8command[] = "Send a command to mpv.\n\n        Non-async success returns the command's response data, otherwise None\n\n        Arguments:\n        Accepts parameters as args\n\n        Keyword Arguments:\n        asynchronous: True will return right away, status comes in as MPV_EVENT_COMMAND_REPLY\n        data: Only valid if async, gets sent back as reply_userdata in the Event\n\n        Wraps: mpv_command_node and mpv_command_node_async\n        ";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_9command(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_asynchronous = 0;
+  PyObject *__pyx_v_data = 0;
+  PyObject *__pyx_v_cmdlist = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("command (wrapper)", 0);
+  if (PyTuple_GET_SIZE(__pyx_args) > 0) {
+    __pyx_v_cmdlist = PyTuple_GetSlice(__pyx_args, 0, PyTuple_GET_SIZE(__pyx_args));
+    if (unlikely(!__pyx_v_cmdlist)) {
+      __Pyx_RefNannyFinishContext();
+      return NULL;
+    }
+    __Pyx_GOTREF(__pyx_v_cmdlist);
+  } else {
+    __pyx_v_cmdlist = __pyx_empty_tuple; __Pyx_INCREF(__pyx_empty_tuple);
+  }
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_asynchronous,&__pyx_n_s_data,0};
+    PyObject* values[2] = {0,0};
+    values[0] = ((PyObject *)Py_False);
+    values[1] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        default:
+        case  0: break;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      if (kw_args > 0 && likely(kw_args <= 2)) {
+        Py_ssize_t index;
+        for (index = 0; index < 2 && kw_args > 0; index++) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, *__pyx_pyargnames[index]);
+          if (value) { values[index] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, 0, "command") < 0)) __PYX_ERR(0, 530, __pyx_L3_error)
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) < 0) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+    }
+    __pyx_v_asynchronous = values[0];
+    __pyx_v_data = values[1];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("command", 0, 0, 0, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 530, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_DECREF(__pyx_v_cmdlist); __pyx_v_cmdlist = 0;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.command", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_8command(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_asynchronous, __pyx_v_data, __pyx_v_cmdlist);
+
+  /* function exit code */
+  __Pyx_XDECREF(__pyx_v_cmdlist);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_8command(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_asynchronous, PyObject *__pyx_v_data, PyObject *__pyx_v_cmdlist) {
+  struct mpv_node __pyx_v_node;
+  struct mpv_node __pyx_v_noderesult;
   int __pyx_v_err;
+  uint64_t __pyx_v_data_id;
+  PyObject *__pyx_v_result = NULL;
+  PyObject *__pyx_v_userdatas = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  char const *__pyx_t_4;
+  uint64_t __pyx_t_4;
+  int __pyx_t_5;
+  int __pyx_t_6;
+  int __pyx_t_7;
+  int __pyx_t_8;
+  char const *__pyx_t_9;
+  PyObject *__pyx_t_10 = NULL;
+  PyObject *__pyx_t_11 = NULL;
+  PyObject *__pyx_t_12 = NULL;
+  PyObject *__pyx_t_13 = NULL;
+  PyObject *__pyx_t_14 = NULL;
+  PyObject *__pyx_t_15 = NULL;
+  PyObject *__pyx_t_16 = NULL;
+  PyObject *__pyx_t_17 = NULL;
+  char const *__pyx_t_18;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("load_config", 0);
-  __Pyx_INCREF(__pyx_v_filename);
+  __Pyx_RefNannySetupContext("command", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":443
- *     def load_config(self, filename):
- *         """Wraps: mpv_load_config_file"""
+  /* "vidcutter/libs/pympv/mpv.pyx":544
+ *         Wraps: mpv_command_node and mpv_command_node_async
+ *         """
  *         assert self._ctx             # <<<<<<<<<<<<<<
- *         filename = _strenc(filename)
- *         cdef const char* _filename = filename
+ *         cdef mpv_node node = self._prep_native_value(cmdlist, self._format_for(cmdlist))
+ *         cdef mpv_node noderesult
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
   if (unlikely(!Py_OptimizeFlag)) {
     if (unlikely(!(__pyx_v_self->_ctx != 0))) {
       PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 443, __pyx_L1_error)
+      __PYX_ERR(0, 544, __pyx_L1_error)
     }
   }
   #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":444
- *         """Wraps: mpv_load_config_file"""
+  /* "vidcutter/libs/pympv/mpv.pyx":545
+ *         """
  *         assert self._ctx
- *         filename = _strenc(filename)             # <<<<<<<<<<<<<<
- *         cdef const char* _filename = filename
+ *         cdef mpv_node node = self._prep_native_value(cmdlist, self._format_for(cmdlist))             # <<<<<<<<<<<<<<
+ *         cdef mpv_node noderesult
  *         cdef int err
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 444, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_format_for); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 545, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
     __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
     if (likely(__pyx_t_3)) {
       PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
@@ -9672,679 +10373,724 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_8load_config(struct __p
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_filename) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_filename);
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_cmdlist) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_cmdlist);
   __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 444, __pyx_L1_error)
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 545, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF_SET(__pyx_v_filename, __pyx_t_1);
-  __pyx_t_1 = 0;
+  __pyx_v_node = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_native_value(__pyx_v_self, __pyx_v_cmdlist, __pyx_t_1);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":445
- *         assert self._ctx
- *         filename = _strenc(filename)
- *         cdef const char* _filename = filename             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":549
  *         cdef int err
- *         with nogil:
+ *         cdef uint64_t data_id
+ *         result = None             # <<<<<<<<<<<<<<
+ *         try:
+ *             data_id = id(data)
  */
-  __pyx_t_4 = __Pyx_PyObject_AsString(__pyx_v_filename); if (unlikely((!__pyx_t_4) && PyErr_Occurred())) __PYX_ERR(0, 445, __pyx_L1_error)
-  __pyx_v__filename = __pyx_t_4;
+  __Pyx_INCREF(Py_None);
+  __pyx_v_result = Py_None;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":447
- *         cdef const char* _filename = filename
- *         cdef int err
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_load_config_file(self._ctx, _filename)
- *         return err
+  /* "vidcutter/libs/pympv/mpv.pyx":550
+ *         cdef uint64_t data_id
+ *         result = None
+ *         try:             # <<<<<<<<<<<<<<
+ *             data_id = id(data)
+ *             if not asynchronous:
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+  /*try:*/ {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":448
- *         cdef int err
- *         with nogil:
- *             err = mpv_load_config_file(self._ctx, _filename)             # <<<<<<<<<<<<<<
- *         return err
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":551
+ *         result = None
+ *         try:
+ *             data_id = id(data)             # <<<<<<<<<<<<<<
+ *             if not asynchronous:
+ *                 with nogil:
  */
-        __pyx_v_err = mpv_load_config_file(__pyx_v_self->_ctx, __pyx_v__filename);
-      }
+    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, __pyx_v_data); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 551, __pyx_L4_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = __Pyx_PyInt_As_uint64_t(__pyx_t_1); if (unlikely((__pyx_t_4 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 551, __pyx_L4_error)
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __pyx_v_data_id = __pyx_t_4;
 
-      /* "vidcutter/libs/pympv/mpv.pyx":447
- *         cdef const char* _filename = filename
- *         cdef int err
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_load_config_file(self._ctx, _filename)
- *         return err
+    /* "vidcutter/libs/pympv/mpv.pyx":552
+ *         try:
+ *             data_id = id(data)
+ *             if not asynchronous:             # <<<<<<<<<<<<<<
+ *                 with nogil:
+ *                     err = mpv_command_node(self._ctx, &node, &noderesult)
  */
-      /*finally:*/ {
-        /*normal exit:*/{
+    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_asynchronous); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 552, __pyx_L4_error)
+    __pyx_t_6 = ((!__pyx_t_5) != 0);
+    if (__pyx_t_6) {
+
+      /* "vidcutter/libs/pympv/mpv.pyx":553
+ *             data_id = id(data)
+ *             if not asynchronous:
+ *                 with nogil:             # <<<<<<<<<<<<<<
+ *                     err = mpv_command_node(self._ctx, &node, &noderesult)
+ *                 try:
+ */
+      {
           #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
+          PyThreadState *_save;
+          Py_UNBLOCK_THREADS
+          __Pyx_FastGIL_Remember();
           #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
-  }
+          /*try:*/ {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":449
- *         with nogil:
- *             err = mpv_load_config_file(self._ctx, _filename)
- *         return err             # <<<<<<<<<<<<<<
- * 
- *     def _format_for(self, value):
+            /* "vidcutter/libs/pympv/mpv.pyx":554
+ *             if not asynchronous:
+ *                 with nogil:
+ *                     err = mpv_command_node(self._ctx, &node, &noderesult)             # <<<<<<<<<<<<<<
+ *                 try:
+ *                     result = _convert_node_value(noderesult) if err >= 0 else None
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 449, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
+            __pyx_v_err = mpv_command_node(__pyx_v_self->_ctx, (&__pyx_v_node), (&__pyx_v_noderesult));
+          }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":441
- * 
- *     @_errors
- *     def load_config(self, filename):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_load_config_file"""
- *         assert self._ctx
+          /* "vidcutter/libs/pympv/mpv.pyx":553
+ *             data_id = id(data)
+ *             if not asynchronous:
+ *                 with nogil:             # <<<<<<<<<<<<<<
+ *                     err = mpv_command_node(self._ctx, &node, &noderesult)
+ *                 try:
  */
+          /*finally:*/ {
+            /*normal exit:*/{
+              #ifdef WITH_THREAD
+              __Pyx_FastGIL_Forget();
+              Py_BLOCK_THREADS
+              #endif
+              goto __pyx_L9;
+            }
+            __pyx_L9:;
+          }
+      }
 
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.load_config", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_filename);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "vidcutter/libs/pympv/mpv.pyx":451
- *         return err
- * 
- *     def _format_for(self, value):             # <<<<<<<<<<<<<<
- *         if isinstance(value, basestring):
- *             return MPV_FORMAT_STRING
+      /* "vidcutter/libs/pympv/mpv.pyx":555
+ *                 with nogil:
+ *                     err = mpv_command_node(self._ctx, &node, &noderesult)
+ *                 try:             # <<<<<<<<<<<<<<
+ *                     result = _convert_node_value(noderesult) if err >= 0 else None
+ *                 finally:
  */
+      /*try:*/ {
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_11_format_for(PyObject *__pyx_v_self, PyObject *__pyx_v_value); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_11_format_for(PyObject *__pyx_v_self, PyObject *__pyx_v_value) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_format_for (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_10_format_for(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_value));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_10_format_for(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_value) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  int __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
-  int __pyx_t_4;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_format_for", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":452
- * 
- *     def _format_for(self, value):
- *         if isinstance(value, basestring):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_STRING
- *         elif isinstance(value, bool):
+        /* "vidcutter/libs/pympv/mpv.pyx":556
+ *                     err = mpv_command_node(self._ctx, &node, &noderesult)
+ *                 try:
+ *                     result = _convert_node_value(noderesult) if err >= 0 else None             # <<<<<<<<<<<<<<
+ *                 finally:
+ *                     with nogil:
  */
-  __pyx_t_1 = __Pyx_PyBaseString_Check(__pyx_v_value); 
-  __pyx_t_2 = (__pyx_t_1 != 0);
-  if (__pyx_t_2) {
+        if (((__pyx_v_err >= 0) != 0)) {
+          __pyx_t_2 = __pyx_f_9vidcutter_4libs_3mpv__convert_node_value(__pyx_v_noderesult); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 556, __pyx_L11_error)
+          __Pyx_GOTREF(__pyx_t_2);
+          __pyx_t_1 = __pyx_t_2;
+          __pyx_t_2 = 0;
+        } else {
+          __Pyx_INCREF(Py_None);
+          __pyx_t_1 = Py_None;
+        }
+        __Pyx_DECREF_SET(__pyx_v_result, __pyx_t_1);
+        __pyx_t_1 = 0;
+      }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":453
- *     def _format_for(self, value):
- *         if isinstance(value, basestring):
- *             return MPV_FORMAT_STRING             # <<<<<<<<<<<<<<
- *         elif isinstance(value, bool):
- *             return MPV_FORMAT_FLAG
+      /* "vidcutter/libs/pympv/mpv.pyx":558
+ *                     result = _convert_node_value(noderesult) if err >= 0 else None
+ *                 finally:
+ *                     with nogil:             # <<<<<<<<<<<<<<
+ *                         mpv_free_node_contents(&noderesult)
+ *             else:
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_STRING); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 453, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_r = __pyx_t_3;
-    __pyx_t_3 = 0;
-    goto __pyx_L0;
+      /*finally:*/ {
+        /*normal exit:*/{
+          {
+              #ifdef WITH_THREAD
+              PyThreadState *_save;
+              Py_UNBLOCK_THREADS
+              __Pyx_FastGIL_Remember();
+              #endif
+              /*try:*/ {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":452
- * 
- *     def _format_for(self, value):
- *         if isinstance(value, basestring):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_STRING
- *         elif isinstance(value, bool):
+                /* "vidcutter/libs/pympv/mpv.pyx":559
+ *                 finally:
+ *                     with nogil:
+ *                         mpv_free_node_contents(&noderesult)             # <<<<<<<<<<<<<<
+ *             else:
+ *                 userdatas = self.reply_userdata.get(data_id, None)
  */
-  }
+                mpv_free_node_contents((&__pyx_v_noderesult));
+              }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":454
- *         if isinstance(value, basestring):
- *             return MPV_FORMAT_STRING
- *         elif isinstance(value, bool):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_FLAG
- *         elif isinstance(value, int):
+              /* "vidcutter/libs/pympv/mpv.pyx":558
+ *                     result = _convert_node_value(noderesult) if err >= 0 else None
+ *                 finally:
+ *                     with nogil:             # <<<<<<<<<<<<<<
+ *                         mpv_free_node_contents(&noderesult)
+ *             else:
  */
-  __pyx_t_3 = ((PyObject*)&PyBool_Type);
-  __Pyx_INCREF(__pyx_t_3);
-  __pyx_t_2 = PyObject_IsInstance(__pyx_v_value, __pyx_t_3); if (unlikely(__pyx_t_2 == ((int)-1))) __PYX_ERR(0, 454, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_1 = (__pyx_t_2 != 0);
-  if (__pyx_t_1) {
+              /*finally:*/ {
+                /*normal exit:*/{
+                  #ifdef WITH_THREAD
+                  __Pyx_FastGIL_Forget();
+                  Py_BLOCK_THREADS
+                  #endif
+                  goto __pyx_L15;
+                }
+                __pyx_L15:;
+              }
+          }
+          goto __pyx_L12;
+        }
+        __pyx_L11_error:;
+        /*exception exit:*/{
+          __Pyx_PyThreadState_declare
+          __Pyx_PyThreadState_assign
+          __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0;
+          __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+          __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+          __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+          if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15);
+          if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12) < 0)) __Pyx_ErrFetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
+          __Pyx_XGOTREF(__pyx_t_10);
+          __Pyx_XGOTREF(__pyx_t_11);
+          __Pyx_XGOTREF(__pyx_t_12);
+          __Pyx_XGOTREF(__pyx_t_13);
+          __Pyx_XGOTREF(__pyx_t_14);
+          __Pyx_XGOTREF(__pyx_t_15);
+          __pyx_t_7 = __pyx_lineno; __pyx_t_8 = __pyx_clineno; __pyx_t_9 = __pyx_filename;
+          {
+            {
+                #ifdef WITH_THREAD
+                PyThreadState *_save;
+                Py_UNBLOCK_THREADS
+                __Pyx_FastGIL_Remember();
+                #endif
+                /*try:*/ {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":455
- *             return MPV_FORMAT_STRING
- *         elif isinstance(value, bool):
- *             return MPV_FORMAT_FLAG             # <<<<<<<<<<<<<<
- *         elif isinstance(value, int):
- *             return MPV_FORMAT_INT64
+                  /* "vidcutter/libs/pympv/mpv.pyx":559
+ *                 finally:
+ *                     with nogil:
+ *                         mpv_free_node_contents(&noderesult)             # <<<<<<<<<<<<<<
+ *             else:
+ *                 userdatas = self.reply_userdata.get(data_id, None)
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_FLAG); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 455, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_r = __pyx_t_3;
-    __pyx_t_3 = 0;
-    goto __pyx_L0;
+                  mpv_free_node_contents((&__pyx_v_noderesult));
+                }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":454
- *         if isinstance(value, basestring):
- *             return MPV_FORMAT_STRING
- *         elif isinstance(value, bool):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_FLAG
- *         elif isinstance(value, int):
+                /* "vidcutter/libs/pympv/mpv.pyx":558
+ *                     result = _convert_node_value(noderesult) if err >= 0 else None
+ *                 finally:
+ *                     with nogil:             # <<<<<<<<<<<<<<
+ *                         mpv_free_node_contents(&noderesult)
+ *             else:
  */
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":456
- *         elif isinstance(value, bool):
- *             return MPV_FORMAT_FLAG
- *         elif isinstance(value, int):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_INT64
- *         elif isinstance(value, float):
- */
-  __pyx_t_1 = PyInt_Check(__pyx_v_value); 
-  __pyx_t_2 = (__pyx_t_1 != 0);
-  if (__pyx_t_2) {
+                /*finally:*/ {
+                  /*normal exit:*/{
+                    #ifdef WITH_THREAD
+                    __Pyx_FastGIL_Forget();
+                    Py_BLOCK_THREADS
+                    #endif
+                    goto __pyx_L20;
+                  }
+                  __pyx_L20:;
+                }
+            }
+          }
+          if (PY_MAJOR_VERSION >= 3) {
+            __Pyx_XGIVEREF(__pyx_t_13);
+            __Pyx_XGIVEREF(__pyx_t_14);
+            __Pyx_XGIVEREF(__pyx_t_15);
+            __Pyx_ExceptionReset(__pyx_t_13, __pyx_t_14, __pyx_t_15);
+          }
+          __Pyx_XGIVEREF(__pyx_t_10);
+          __Pyx_XGIVEREF(__pyx_t_11);
+          __Pyx_XGIVEREF(__pyx_t_12);
+          __Pyx_ErrRestore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
+          __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0;
+          __pyx_lineno = __pyx_t_7; __pyx_clineno = __pyx_t_8; __pyx_filename = __pyx_t_9;
+          goto __pyx_L4_error;
+        }
+        __pyx_L12:;
+      }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":457
- *             return MPV_FORMAT_FLAG
- *         elif isinstance(value, int):
- *             return MPV_FORMAT_INT64             # <<<<<<<<<<<<<<
- *         elif isinstance(value, float):
- *             return MPV_FORMAT_DOUBLE
+      /* "vidcutter/libs/pympv/mpv.pyx":552
+ *         try:
+ *             data_id = id(data)
+ *             if not asynchronous:             # <<<<<<<<<<<<<<
+ *                 with nogil:
+ *                     err = mpv_command_node(self._ctx, &node, &noderesult)
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_INT64); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 457, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_r = __pyx_t_3;
-    __pyx_t_3 = 0;
-    goto __pyx_L0;
+      goto __pyx_L6;
+    }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":456
- *         elif isinstance(value, bool):
- *             return MPV_FORMAT_FLAG
- *         elif isinstance(value, int):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_INT64
- *         elif isinstance(value, float):
+    /* "vidcutter/libs/pympv/mpv.pyx":561
+ *                         mpv_free_node_contents(&noderesult)
+ *             else:
+ *                 userdatas = self.reply_userdata.get(data_id, None)             # <<<<<<<<<<<<<<
+ *                 if userdatas is None:
+ *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
  */
-  }
+    /*else*/ {
+      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->reply_userdata, __pyx_n_s_get); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 561, __pyx_L4_error)
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_3 = __Pyx_PyInt_From_uint64_t(__pyx_v_data_id); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 561, __pyx_L4_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_16 = NULL;
+      __pyx_t_8 = 0;
+      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+        __pyx_t_16 = PyMethod_GET_SELF(__pyx_t_2);
+        if (likely(__pyx_t_16)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+          __Pyx_INCREF(__pyx_t_16);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_2, function);
+          __pyx_t_8 = 1;
+        }
+      }
+      #if CYTHON_FAST_PYCALL
+      if (PyFunction_Check(__pyx_t_2)) {
+        PyObject *__pyx_temp[3] = {__pyx_t_16, __pyx_t_3, Py_None};
+        __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 561, __pyx_L4_error)
+        __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
+        __Pyx_GOTREF(__pyx_t_1);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      } else
+      #endif
+      #if CYTHON_FAST_PYCCALL
+      if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
+        PyObject *__pyx_temp[3] = {__pyx_t_16, __pyx_t_3, Py_None};
+        __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 561, __pyx_L4_error)
+        __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
+        __Pyx_GOTREF(__pyx_t_1);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      } else
+      #endif
+      {
+        __pyx_t_17 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 561, __pyx_L4_error)
+        __Pyx_GOTREF(__pyx_t_17);
+        if (__pyx_t_16) {
+          __Pyx_GIVEREF(__pyx_t_16); PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_16); __pyx_t_16 = NULL;
+        }
+        __Pyx_GIVEREF(__pyx_t_3);
+        PyTuple_SET_ITEM(__pyx_t_17, 0+__pyx_t_8, __pyx_t_3);
+        __Pyx_INCREF(Py_None);
+        __Pyx_GIVEREF(Py_None);
+        PyTuple_SET_ITEM(__pyx_t_17, 1+__pyx_t_8, Py_None);
+        __pyx_t_3 = 0;
+        __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_17, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 561, __pyx_L4_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
+      }
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      __pyx_v_userdatas = __pyx_t_1;
+      __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":458
- *         elif isinstance(value, int):
- *             return MPV_FORMAT_INT64
- *         elif isinstance(value, float):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_DOUBLE
- *         elif isinstance(value, (tuple, list)):
+      /* "vidcutter/libs/pympv/mpv.pyx":562
+ *             else:
+ *                 userdatas = self.reply_userdata.get(data_id, None)
+ *                 if userdatas is None:             # <<<<<<<<<<<<<<
+ *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
+ *                 userdatas.add()
  */
-  __pyx_t_2 = PyFloat_Check(__pyx_v_value); 
-  __pyx_t_1 = (__pyx_t_2 != 0);
-  if (__pyx_t_1) {
+      __pyx_t_6 = (__pyx_v_userdatas == Py_None);
+      __pyx_t_5 = (__pyx_t_6 != 0);
+      if (__pyx_t_5) {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":459
- *             return MPV_FORMAT_INT64
- *         elif isinstance(value, float):
- *             return MPV_FORMAT_DOUBLE             # <<<<<<<<<<<<<<
- *         elif isinstance(value, (tuple, list)):
- *             return MPV_FORMAT_NODE_ARRAY
+        /* "vidcutter/libs/pympv/mpv.pyx":563
+ *                 userdatas = self.reply_userdata.get(data_id, None)
+ *                 if userdatas is None:
+ *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)             # <<<<<<<<<<<<<<
+ *                 userdatas.add()
+ *                 with nogil:
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_DOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 459, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_r = __pyx_t_3;
-    __pyx_t_3 = 0;
-    goto __pyx_L0;
+        __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_ReplyUserData); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 563, __pyx_L4_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        __pyx_t_17 = NULL;
+        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+          __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_2);
+          if (likely(__pyx_t_17)) {
+            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+            __Pyx_INCREF(__pyx_t_17);
+            __Pyx_INCREF(function);
+            __Pyx_DECREF_SET(__pyx_t_2, function);
+          }
+        }
+        __pyx_t_1 = (__pyx_t_17) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_17, __pyx_v_data) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_data);
+        __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
+        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 563, __pyx_L4_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+        if (unlikely(__Pyx_SetItemInt(__pyx_v_9vidcutter_4libs_3mpv__reply_userdatas, __pyx_v_data_id, __pyx_t_1, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 563, __pyx_L4_error)
+        __Pyx_INCREF(__pyx_t_1);
+        __Pyx_DECREF_SET(__pyx_v_userdatas, __pyx_t_1);
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":458
- *         elif isinstance(value, int):
- *             return MPV_FORMAT_INT64
- *         elif isinstance(value, float):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_DOUBLE
- *         elif isinstance(value, (tuple, list)):
+        /* "vidcutter/libs/pympv/mpv.pyx":562
+ *             else:
+ *                 userdatas = self.reply_userdata.get(data_id, None)
+ *                 if userdatas is None:             # <<<<<<<<<<<<<<
+ *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
+ *                 userdatas.add()
  */
-  }
+      }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":460
- *         elif isinstance(value, float):
- *             return MPV_FORMAT_DOUBLE
- *         elif isinstance(value, (tuple, list)):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_NODE_ARRAY
- *         elif isinstance(value, dict):
+      /* "vidcutter/libs/pympv/mpv.pyx":564
+ *                 if userdatas is None:
+ *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
+ *                 userdatas.add()             # <<<<<<<<<<<<<<
+ *                 with nogil:
+ *                     err = mpv_command_node_async(self._ctx, data_id, &node)
  */
-  __pyx_t_2 = PyTuple_Check(__pyx_v_value); 
-  __pyx_t_4 = (__pyx_t_2 != 0);
-  if (!__pyx_t_4) {
-  } else {
-    __pyx_t_1 = __pyx_t_4;
-    goto __pyx_L4_bool_binop_done;
-  }
-  __pyx_t_4 = PyList_Check(__pyx_v_value); 
-  __pyx_t_2 = (__pyx_t_4 != 0);
-  __pyx_t_1 = __pyx_t_2;
-  __pyx_L4_bool_binop_done:;
-  __pyx_t_2 = (__pyx_t_1 != 0);
-  if (__pyx_t_2) {
+      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdatas, __pyx_n_s_add); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 564, __pyx_L4_error)
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_17 = NULL;
+      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+        __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_2);
+        if (likely(__pyx_t_17)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+          __Pyx_INCREF(__pyx_t_17);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_2, function);
+        }
+      }
+      __pyx_t_1 = (__pyx_t_17) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_17) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
+      __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
+      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 564, __pyx_L4_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":461
- *             return MPV_FORMAT_DOUBLE
- *         elif isinstance(value, (tuple, list)):
- *             return MPV_FORMAT_NODE_ARRAY             # <<<<<<<<<<<<<<
- *         elif isinstance(value, dict):
- *             return MPV_FORMAT_NODE_MAP
+      /* "vidcutter/libs/pympv/mpv.pyx":565
+ *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
+ *                 userdatas.add()
+ *                 with nogil:             # <<<<<<<<<<<<<<
+ *                     err = mpv_command_node_async(self._ctx, data_id, &node)
+ *         finally:
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_NODE_ARRAY); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 461, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_r = __pyx_t_3;
-    __pyx_t_3 = 0;
-    goto __pyx_L0;
+      {
+          #ifdef WITH_THREAD
+          PyThreadState *_save;
+          Py_UNBLOCK_THREADS
+          __Pyx_FastGIL_Remember();
+          #endif
+          /*try:*/ {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":460
- *         elif isinstance(value, float):
- *             return MPV_FORMAT_DOUBLE
- *         elif isinstance(value, (tuple, list)):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_NODE_ARRAY
- *         elif isinstance(value, dict):
+            /* "vidcutter/libs/pympv/mpv.pyx":566
+ *                 userdatas.add()
+ *                 with nogil:
+ *                     err = mpv_command_node_async(self._ctx, data_id, &node)             # <<<<<<<<<<<<<<
+ *         finally:
+ *             self._free_native_value(node)
+ */
+            __pyx_v_err = mpv_command_node_async(__pyx_v_self->_ctx, __pyx_v_data_id, (&__pyx_v_node));
+          }
+
+          /* "vidcutter/libs/pympv/mpv.pyx":565
+ *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
+ *                 userdatas.add()
+ *                 with nogil:             # <<<<<<<<<<<<<<
+ *                     err = mpv_command_node_async(self._ctx, data_id, &node)
+ *         finally:
  */
+          /*finally:*/ {
+            /*normal exit:*/{
+              #ifdef WITH_THREAD
+              __Pyx_FastGIL_Forget();
+              Py_BLOCK_THREADS
+              #endif
+              goto __pyx_L24;
+            }
+            __pyx_L24:;
+          }
+      }
+    }
+    __pyx_L6:;
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":462
- *         elif isinstance(value, (tuple, list)):
- *             return MPV_FORMAT_NODE_ARRAY
- *         elif isinstance(value, dict):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_NODE_MAP
- *         return MPV_FORMAT_NONE
+  /* "vidcutter/libs/pympv/mpv.pyx":568
+ *                     err = mpv_command_node_async(self._ctx, data_id, &node)
+ *         finally:
+ *             self._free_native_value(node)             # <<<<<<<<<<<<<<
+ *         if err < 0:
+ *             raise MPVError(err)
  */
-  __pyx_t_2 = PyDict_Check(__pyx_v_value); 
-  __pyx_t_1 = (__pyx_t_2 != 0);
-  if (__pyx_t_1) {
+  /*finally:*/ {
+    /*normal exit:*/{
+      __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 568, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      goto __pyx_L5;
+    }
+    __pyx_L4_error:;
+    /*exception exit:*/{
+      __Pyx_PyThreadState_declare
+      __Pyx_PyThreadState_assign
+      __pyx_t_15 = 0; __pyx_t_14 = 0; __pyx_t_13 = 0; __pyx_t_12 = 0; __pyx_t_11 = 0; __pyx_t_10 = 0;
+      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
+      __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
+      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
+      if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_15, &__pyx_t_14, &__pyx_t_13) < 0)) __Pyx_ErrFetch(&__pyx_t_15, &__pyx_t_14, &__pyx_t_13);
+      __Pyx_XGOTREF(__pyx_t_15);
+      __Pyx_XGOTREF(__pyx_t_14);
+      __Pyx_XGOTREF(__pyx_t_13);
+      __Pyx_XGOTREF(__pyx_t_12);
+      __Pyx_XGOTREF(__pyx_t_11);
+      __Pyx_XGOTREF(__pyx_t_10);
+      __pyx_t_8 = __pyx_lineno; __pyx_t_7 = __pyx_clineno; __pyx_t_18 = __pyx_filename;
+      {
+        __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 568, __pyx_L26_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      }
+      if (PY_MAJOR_VERSION >= 3) {
+        __Pyx_XGIVEREF(__pyx_t_12);
+        __Pyx_XGIVEREF(__pyx_t_11);
+        __Pyx_XGIVEREF(__pyx_t_10);
+        __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_11, __pyx_t_10);
+      }
+      __Pyx_XGIVEREF(__pyx_t_15);
+      __Pyx_XGIVEREF(__pyx_t_14);
+      __Pyx_XGIVEREF(__pyx_t_13);
+      __Pyx_ErrRestore(__pyx_t_15, __pyx_t_14, __pyx_t_13);
+      __pyx_t_15 = 0; __pyx_t_14 = 0; __pyx_t_13 = 0; __pyx_t_12 = 0; __pyx_t_11 = 0; __pyx_t_10 = 0;
+      __pyx_lineno = __pyx_t_8; __pyx_clineno = __pyx_t_7; __pyx_filename = __pyx_t_18;
+      goto __pyx_L1_error;
+      __pyx_L26_error:;
+      if (PY_MAJOR_VERSION >= 3) {
+        __Pyx_XGIVEREF(__pyx_t_12);
+        __Pyx_XGIVEREF(__pyx_t_11);
+        __Pyx_XGIVEREF(__pyx_t_10);
+        __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_11, __pyx_t_10);
+      }
+      __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
+      __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
+      __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
+      __pyx_t_12 = 0; __pyx_t_11 = 0; __pyx_t_10 = 0;
+      goto __pyx_L1_error;
+    }
+    __pyx_L5:;
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":463
- *             return MPV_FORMAT_NODE_ARRAY
- *         elif isinstance(value, dict):
- *             return MPV_FORMAT_NODE_MAP             # <<<<<<<<<<<<<<
- *         return MPV_FORMAT_NONE
+  /* "vidcutter/libs/pympv/mpv.pyx":569
+ *         finally:
+ *             self._free_native_value(node)
+ *         if err < 0:             # <<<<<<<<<<<<<<
+ *             raise MPVError(err)
+ *         return result
+ */
+  __pyx_t_5 = ((__pyx_v_err < 0) != 0);
+  if (unlikely(__pyx_t_5)) {
+
+    /* "vidcutter/libs/pympv/mpv.pyx":570
+ *             self._free_native_value(node)
+ *         if err < 0:
+ *             raise MPVError(err)             # <<<<<<<<<<<<<<
+ *         return result
  * 
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_NODE_MAP); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 463, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_r = __pyx_t_3;
-    __pyx_t_3 = 0;
-    goto __pyx_L0;
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 570, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_17 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 570, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_17);
+    __pyx_t_3 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_3)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_t_17) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_17);
+    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 570, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 570, __pyx_L1_error)
 
-    /* "vidcutter/libs/pympv/mpv.pyx":462
- *         elif isinstance(value, (tuple, list)):
- *             return MPV_FORMAT_NODE_ARRAY
- *         elif isinstance(value, dict):             # <<<<<<<<<<<<<<
- *             return MPV_FORMAT_NODE_MAP
- *         return MPV_FORMAT_NONE
+    /* "vidcutter/libs/pympv/mpv.pyx":569
+ *         finally:
+ *             self._free_native_value(node)
+ *         if err < 0:             # <<<<<<<<<<<<<<
+ *             raise MPVError(err)
+ *         return result
  */
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":464
- *         elif isinstance(value, dict):
- *             return MPV_FORMAT_NODE_MAP
- *         return MPV_FORMAT_NONE             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":571
+ *         if err < 0:
+ *             raise MPVError(err)
+ *         return result             # <<<<<<<<<<<<<<
  * 
- *     cdef mpv_node_list* _prep_node_list(self, values):
+ *     @_errors
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_NONE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 464, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_r = __pyx_t_3;
-  __pyx_t_3 = 0;
+  __Pyx_INCREF(__pyx_v_result);
+  __pyx_r = __pyx_v_result;
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":451
- *         return err
+  /* "vidcutter/libs/pympv/mpv.pyx":530
+ *             free(node.u.string)
+ * 
+ *     def command(self, *cmdlist, asynchronous=False, data=None):             # <<<<<<<<<<<<<<
+ *         """Send a command to mpv.
  * 
- *     def _format_for(self, value):             # <<<<<<<<<<<<<<
- *         if isinstance(value, basestring):
- *             return MPV_FORMAT_STRING
  */
 
   /* function exit code */
   __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context._format_for", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_16);
+  __Pyx_XDECREF(__pyx_t_17);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.command", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_result);
+  __Pyx_XDECREF(__pyx_v_userdatas);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":466
- *         return MPV_FORMAT_NONE
+/* "vidcutter/libs/pympv/mpv.pyx":574
+ * 
+ *     @_errors
+ *     def get_property_async(self, prop, data=None):             # <<<<<<<<<<<<<<
+ *         """Gets the value of a property asynchronously.
  * 
- *     cdef mpv_node_list* _prep_node_list(self, values):             # <<<<<<<<<<<<<<
- *         cdef mpv_node node
- *         cdef mpv_format format
  */
 
-static struct mpv_node_list *__pyx_f_9vidcutter_4libs_3mpv_7Context__prep_node_list(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_values) {
-  struct mpv_node __pyx_v_node;
-  enum mpv_format __pyx_v_format;
-  struct mpv_node_list *__pyx_v_node_list;
-  PyObject *__pyx_v_i = NULL;
-  PyObject *__pyx_v_value = NULL;
-  struct mpv_node_list *__pyx_r;
-  __Pyx_RefNannyDeclarations
-  Py_ssize_t __pyx_t_1;
-  int __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *(*__pyx_t_5)(PyObject *);
-  PyObject *__pyx_t_6 = NULL;
-  PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
-  enum mpv_format __pyx_t_9;
-  Py_ssize_t __pyx_t_10;
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_11get_property_async(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_10get_property_async[] = "Gets the value of a property asynchronously.\n\n        Arguments:\n        prop: Property to get the value of.\n\n        Keyword arguments:\n        data: Value to be passed into the reply_userdata of the response event.\n        Wraps: mpv_get_property_async";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_11get_property_async(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_prop = 0;
+  PyObject *__pyx_v_data = 0;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_prep_node_list", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":469
- *         cdef mpv_node node
- *         cdef mpv_format format
- *         cdef mpv_node_list* node_list = <mpv_node_list*>malloc(sizeof(mpv_node_list))             # <<<<<<<<<<<<<<
- *         node_list.num = len(values)
- *         node_list.values = NULL
- */
-  __pyx_v_node_list = ((struct mpv_node_list *)malloc((sizeof(struct mpv_node_list))));
-
-  /* "vidcutter/libs/pympv/mpv.pyx":470
- *         cdef mpv_format format
- *         cdef mpv_node_list* node_list = <mpv_node_list*>malloc(sizeof(mpv_node_list))
- *         node_list.num = len(values)             # <<<<<<<<<<<<<<
- *         node_list.values = NULL
- *         node_list.keys = NULL
- */
-  __pyx_t_1 = PyObject_Length(__pyx_v_values); if (unlikely(__pyx_t_1 == ((Py_ssize_t)-1))) __PYX_ERR(0, 470, __pyx_L1_error)
-  __pyx_v_node_list->num = __pyx_t_1;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":471
- *         cdef mpv_node_list* node_list = <mpv_node_list*>malloc(sizeof(mpv_node_list))
- *         node_list.num = len(values)
- *         node_list.values = NULL             # <<<<<<<<<<<<<<
- *         node_list.keys = NULL
- *         if node_list.num:
- */
-  __pyx_v_node_list->values = NULL;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":472
- *         node_list.num = len(values)
- *         node_list.values = NULL
- *         node_list.keys = NULL             # <<<<<<<<<<<<<<
- *         if node_list.num:
- *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
- */
-  __pyx_v_node_list->keys = NULL;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":473
- *         node_list.values = NULL
- *         node_list.keys = NULL
- *         if node_list.num:             # <<<<<<<<<<<<<<
- *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
- *         for i, value in enumerate(values):
- */
-  __pyx_t_2 = (__pyx_v_node_list->num != 0);
-  if (__pyx_t_2) {
-
-    /* "vidcutter/libs/pympv/mpv.pyx":474
- *         node_list.keys = NULL
- *         if node_list.num:
- *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))             # <<<<<<<<<<<<<<
- *         for i, value in enumerate(values):
- *             format = self._format_for(value)
- */
-    __pyx_v_node_list->values = ((struct mpv_node *)malloc((__pyx_v_node_list->num * (sizeof(struct mpv_node)))));
-
-    /* "vidcutter/libs/pympv/mpv.pyx":473
- *         node_list.values = NULL
- *         node_list.keys = NULL
- *         if node_list.num:             # <<<<<<<<<<<<<<
- *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
- *         for i, value in enumerate(values):
- */
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":475
- *         if node_list.num:
- *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
- *         for i, value in enumerate(values):             # <<<<<<<<<<<<<<
- *             format = self._format_for(value)
- *             node = self._prep_native_value(value, format)
- */
-  __Pyx_INCREF(__pyx_int_0);
-  __pyx_t_3 = __pyx_int_0;
-  if (likely(PyList_CheckExact(__pyx_v_values)) || PyTuple_CheckExact(__pyx_v_values)) {
-    __pyx_t_4 = __pyx_v_values; __Pyx_INCREF(__pyx_t_4); __pyx_t_1 = 0;
-    __pyx_t_5 = NULL;
-  } else {
-    __pyx_t_1 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_v_values); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 475, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 475, __pyx_L1_error)
-  }
-  for (;;) {
-    if (likely(!__pyx_t_5)) {
-      if (likely(PyList_CheckExact(__pyx_t_4))) {
-        if (__pyx_t_1 >= PyList_GET_SIZE(__pyx_t_4)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_6 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_1); __Pyx_INCREF(__pyx_t_6); __pyx_t_1++; if (unlikely(0 < 0)) __PYX_ERR(0, 475, __pyx_L1_error)
-        #else
-        __pyx_t_6 = PySequence_ITEM(__pyx_t_4, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 475, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        #endif
-      } else {
-        if (__pyx_t_1 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_6 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_1); __Pyx_INCREF(__pyx_t_6); __pyx_t_1++; if (unlikely(0 < 0)) __PYX_ERR(0, 475, __pyx_L1_error)
-        #else
-        __pyx_t_6 = PySequence_ITEM(__pyx_t_4, __pyx_t_1); __pyx_t_1++; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 475, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_6);
-        #endif
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("get_property_async (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_data,0};
+    PyObject* values[2] = {0,0};
+    values[1] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
       }
-    } else {
-      __pyx_t_6 = __pyx_t_5(__pyx_t_4);
-      if (unlikely(!__pyx_t_6)) {
-        PyObject* exc_type = PyErr_Occurred();
-        if (exc_type) {
-          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else __PYX_ERR(0, 475, __pyx_L1_error)
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_prop)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data);
+          if (value) { values[1] = value; kw_args--; }
         }
-        break;
       }
-      __Pyx_GOTREF(__pyx_t_6);
-    }
-    __Pyx_XDECREF_SET(__pyx_v_value, __pyx_t_6);
-    __pyx_t_6 = 0;
-    __Pyx_INCREF(__pyx_t_3);
-    __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_3);
-    __pyx_t_6 = __Pyx_PyInt_AddObjC(__pyx_t_3, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 475, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_DECREF(__pyx_t_3);
-    __pyx_t_3 = __pyx_t_6;
-    __pyx_t_6 = 0;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":476
- *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
- *         for i, value in enumerate(values):
- *             format = self._format_for(value)             # <<<<<<<<<<<<<<
- *             node = self._prep_native_value(value, format)
- *             node_list.values[i] = node
- */
-    __pyx_t_7 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_format_for); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 476, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_8 = NULL;
-    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_7))) {
-      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7);
-      if (likely(__pyx_t_8)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
-        __Pyx_INCREF(__pyx_t_8);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_7, function);
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "get_property_async") < 0)) __PYX_ERR(0, 574, __pyx_L3_error)
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
       }
     }
-    __pyx_t_6 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_value) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_value);
-    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 476, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __pyx_t_9 = ((enum mpv_format)__Pyx_PyInt_As_enum__mpv_format(__pyx_t_6)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 476, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __pyx_v_format = __pyx_t_9;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":477
- *         for i, value in enumerate(values):
- *             format = self._format_for(value)
- *             node = self._prep_native_value(value, format)             # <<<<<<<<<<<<<<
- *             node_list.values[i] = node
- *         return node_list
- */
-    __pyx_t_6 = __Pyx_PyInt_From_enum__mpv_format(__pyx_v_format); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 477, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_6);
-    __pyx_v_node = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_native_value(__pyx_v_self, __pyx_v_value, __pyx_t_6);
-    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":478
- *             format = self._format_for(value)
- *             node = self._prep_native_value(value, format)
- *             node_list.values[i] = node             # <<<<<<<<<<<<<<
- *         return node_list
- * 
- */
-    __pyx_t_10 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_10 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 478, __pyx_L1_error)
-    (__pyx_v_node_list->values[__pyx_t_10]) = __pyx_v_node;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":475
- *         if node_list.num:
- *             node_list.values = <mpv_node*>malloc(node_list.num * sizeof(mpv_node))
- *         for i, value in enumerate(values):             # <<<<<<<<<<<<<<
- *             format = self._format_for(value)
- *             node = self._prep_native_value(value, format)
- */
+    __pyx_v_prop = values[0];
+    __pyx_v_data = values[1];
   }
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":479
- *             node = self._prep_native_value(value, format)
- *             node_list.values[i] = node
- *         return node_list             # <<<<<<<<<<<<<<
- * 
- *     cdef mpv_node_list* _prep_node_map(self, map):
- */
-  __pyx_r = __pyx_v_node_list;
-  goto __pyx_L0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":466
- *         return MPV_FORMAT_NONE
- * 
- *     cdef mpv_node_list* _prep_node_list(self, values):             # <<<<<<<<<<<<<<
- *         cdef mpv_node node
- *         cdef mpv_format format
- */
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("get_property_async", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 574, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.get_property_async", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_10get_property_async(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_data);
 
   /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_WriteUnraisable("vidcutter.libs.mpv.Context._prep_node_list", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_i);
-  __Pyx_XDECREF(__pyx_v_value);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":481
- *         return node_list
- * 
- *     cdef mpv_node_list* _prep_node_map(self, map):             # <<<<<<<<<<<<<<
- *         cdef char* ckey
- *         cdef mpv_node_list* list
- */
-
-static struct mpv_node_list *__pyx_f_9vidcutter_4libs_3mpv_7Context__prep_node_map(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_map) {
-  char *__pyx_v_ckey;
-  struct mpv_node_list *__pyx_v_list;
-  PyObject *__pyx_v_keys = NULL;
-  PyObject *__pyx_v_i = NULL;
-  PyObject *__pyx_v_key = NULL;
-  struct mpv_node_list *__pyx_r;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_10get_property_async(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data) {
+  uint64_t __pyx_v_id_data;
+  PyObject *__pyx_v_userdatas = NULL;
+  char const *__pyx_v_prop_c;
+  int __pyx_v_err;
+  PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  Py_ssize_t __pyx_t_4;
-  int __pyx_t_5;
-  PyObject *(*__pyx_t_6)(PyObject *);
+  Py_hash_t __pyx_t_4;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_t_6;
   PyObject *__pyx_t_7 = NULL;
-  PyObject *__pyx_t_8 = NULL;
-  char *__pyx_t_9;
-  Py_ssize_t __pyx_t_10;
-  Py_ssize_t __pyx_t_11;
+  int __pyx_t_8;
+  int __pyx_t_9;
+  char const *__pyx_t_10;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_prep_node_map", 0);
+  __Pyx_RefNannySetupContext("get_property_async", 0);
+  __Pyx_INCREF(__pyx_v_prop);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":484
- *         cdef char* ckey
- *         cdef mpv_node_list* list
- *         list = self._prep_node_list(map.values())             # <<<<<<<<<<<<<<
- *         keys = map.keys()
- *         if not len(keys):
+  /* "vidcutter/libs/pympv/mpv.pyx":583
+ *         data: Value to be passed into the reply_userdata of the response event.
+ *         Wraps: mpv_get_property_async"""
+ *         assert self._ctx             # <<<<<<<<<<<<<<
+ *         prop = _strenc(prop)
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
  */
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_map, __pyx_n_s_values); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 484, __pyx_L1_error)
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!Py_OptimizeFlag)) {
+    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
+      PyErr_SetNone(PyExc_AssertionError);
+      __PYX_ERR(0, 583, __pyx_L1_error)
+    }
+  }
+  #endif
+
+  /* "vidcutter/libs/pympv/mpv.pyx":584
+ *         Wraps: mpv_get_property_async"""
+ *         assert self._ctx
+ *         prop = _strenc(prop)             # <<<<<<<<<<<<<<
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ */
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 584, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
     __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
     if (likely(__pyx_t_3)) {
       PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
@@ -10353,223 +11099,234 @@ static struct mpv_node_list *__pyx_f_9vidcutter_4libs_3mpv_7Context__prep_node_m
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_prop) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_prop);
   __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 484, __pyx_L1_error)
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 584, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_v_list = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_node_list(__pyx_v_self, __pyx_t_1);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF_SET(__pyx_v_prop, __pyx_t_1);
+  __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":485
- *         cdef mpv_node_list* list
- *         list = self._prep_node_list(map.values())
- *         keys = map.keys()             # <<<<<<<<<<<<<<
- *         if not len(keys):
- *             return list
+  /* "vidcutter/libs/pympv/mpv.pyx":585
+ *         assert self._ctx
+ *         prop = _strenc(prop)
+ *         cdef uint64_t id_data = <uint64_t>hash(data)             # <<<<<<<<<<<<<<
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is None:
  */
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_map, __pyx_n_s_keys); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 485, __pyx_L1_error)
+  __pyx_t_4 = PyObject_Hash(__pyx_v_data); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 585, __pyx_L1_error)
+  __pyx_v_id_data = ((uint64_t)__pyx_t_4);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":586
+ *         prop = _strenc(prop)
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)             # <<<<<<<<<<<<<<
+ *         if userdatas is None:
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+ */
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->reply_userdata, __pyx_n_s_get); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 586, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = NULL;
+  __pyx_t_3 = __Pyx_PyInt_From_uint64_t(__pyx_v_id_data); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 586, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_5 = NULL;
+  __pyx_t_6 = 0;
   if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_3)) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_5)) {
       PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_5);
       __Pyx_INCREF(function);
       __Pyx_DECREF_SET(__pyx_t_2, function);
+      __pyx_t_6 = 1;
     }
   }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 485, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
+  #if CYTHON_FAST_PYCALL
+  if (PyFunction_Check(__pyx_t_2)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, Py_None};
+    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 586, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  } else
+  #endif
+  #if CYTHON_FAST_PYCCALL
+  if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, Py_None};
+    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 586, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  } else
+  #endif
+  {
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 586, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    if (__pyx_t_5) {
+      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
+    }
+    __Pyx_GIVEREF(__pyx_t_3);
+    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_t_3);
+    __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(Py_None);
+    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, Py_None);
+    __pyx_t_3 = 0;
+    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 586, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+  }
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_v_keys = __pyx_t_1;
+  __pyx_v_userdatas = __pyx_t_1;
   __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":486
- *         list = self._prep_node_list(map.values())
- *         keys = map.keys()
- *         if not len(keys):             # <<<<<<<<<<<<<<
- *             return list
- *         list.keys = <char**>malloc(list.num)
+  /* "vidcutter/libs/pympv/mpv.pyx":587
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is None:             # <<<<<<<<<<<<<<
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+ *         userdatas.add()
  */
-  __pyx_t_4 = PyObject_Length(__pyx_v_keys); if (unlikely(__pyx_t_4 == ((Py_ssize_t)-1))) __PYX_ERR(0, 486, __pyx_L1_error)
-  __pyx_t_5 = ((!(__pyx_t_4 != 0)) != 0);
-  if (__pyx_t_5) {
+  __pyx_t_8 = (__pyx_v_userdatas == Py_None);
+  __pyx_t_9 = (__pyx_t_8 != 0);
+  if (__pyx_t_9) {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":487
- *         keys = map.keys()
- *         if not len(keys):
- *             return list             # <<<<<<<<<<<<<<
- *         list.keys = <char**>malloc(list.num)
- *         for i, key in enumerate(keys):
+    /* "vidcutter/libs/pympv/mpv.pyx":588
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is None:
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)             # <<<<<<<<<<<<<<
+ *         userdatas.add()
+ *         cdef const char* prop_c = prop
  */
-    __pyx_r = __pyx_v_list;
-    goto __pyx_L0;
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_ReplyUserData); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 588, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_7 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_7)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_7);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_7, __pyx_v_data) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_data);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 588, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    if (unlikely(__Pyx_SetItemInt(__pyx_v_self->reply_userdata, __pyx_v_id_data, __pyx_t_1, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 588, __pyx_L1_error)
+    __Pyx_INCREF(__pyx_t_1);
+    __Pyx_DECREF_SET(__pyx_v_userdatas, __pyx_t_1);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":486
- *         list = self._prep_node_list(map.values())
- *         keys = map.keys()
- *         if not len(keys):             # <<<<<<<<<<<<<<
- *             return list
- *         list.keys = <char**>malloc(list.num)
+    /* "vidcutter/libs/pympv/mpv.pyx":587
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is None:             # <<<<<<<<<<<<<<
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+ *         userdatas.add()
  */
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":488
- *         if not len(keys):
- *             return list
- *         list.keys = <char**>malloc(list.num)             # <<<<<<<<<<<<<<
- *         for i, key in enumerate(keys):
- *             key = _strenc(key)
+  /* "vidcutter/libs/pympv/mpv.pyx":589
+ *         if userdatas is None:
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+ *         userdatas.add()             # <<<<<<<<<<<<<<
+ *         cdef const char* prop_c = prop
+ *         with nogil:
  */
-  __pyx_v_list->keys = ((char **)malloc(__pyx_v_list->num));
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdatas, __pyx_n_s_add); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 589, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_7 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_7)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_7);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 589, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":489
- *             return list
- *         list.keys = <char**>malloc(list.num)
- *         for i, key in enumerate(keys):             # <<<<<<<<<<<<<<
- *             key = _strenc(key)
- *             ckey = key
+  /* "vidcutter/libs/pympv/mpv.pyx":590
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+ *         userdatas.add()
+ *         cdef const char* prop_c = prop             # <<<<<<<<<<<<<<
+ *         with nogil:
+ *             err = mpv_get_property_async(
  */
-  __Pyx_INCREF(__pyx_int_0);
-  __pyx_t_1 = __pyx_int_0;
-  if (likely(PyList_CheckExact(__pyx_v_keys)) || PyTuple_CheckExact(__pyx_v_keys)) {
-    __pyx_t_2 = __pyx_v_keys; __Pyx_INCREF(__pyx_t_2); __pyx_t_4 = 0;
-    __pyx_t_6 = NULL;
-  } else {
-    __pyx_t_4 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_keys); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 489, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_6 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 489, __pyx_L1_error)
-  }
-  for (;;) {
-    if (likely(!__pyx_t_6)) {
-      if (likely(PyList_CheckExact(__pyx_t_2))) {
-        if (__pyx_t_4 >= PyList_GET_SIZE(__pyx_t_2)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_3 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_4); __Pyx_INCREF(__pyx_t_3); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 489, __pyx_L1_error)
-        #else
-        __pyx_t_3 = PySequence_ITEM(__pyx_t_2, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 489, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        #endif
-      } else {
-        if (__pyx_t_4 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_4); __Pyx_INCREF(__pyx_t_3); __pyx_t_4++; if (unlikely(0 < 0)) __PYX_ERR(0, 489, __pyx_L1_error)
-        #else
-        __pyx_t_3 = PySequence_ITEM(__pyx_t_2, __pyx_t_4); __pyx_t_4++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 489, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        #endif
-      }
-    } else {
-      __pyx_t_3 = __pyx_t_6(__pyx_t_2);
-      if (unlikely(!__pyx_t_3)) {
-        PyObject* exc_type = PyErr_Occurred();
-        if (exc_type) {
-          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else __PYX_ERR(0, 489, __pyx_L1_error)
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_3);
-    }
-    __Pyx_XDECREF_SET(__pyx_v_key, __pyx_t_3);
-    __pyx_t_3 = 0;
-    __Pyx_INCREF(__pyx_t_1);
-    __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_1);
-    __pyx_t_3 = __Pyx_PyInt_AddObjC(__pyx_t_1, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 489, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_1);
-    __pyx_t_1 = __pyx_t_3;
-    __pyx_t_3 = 0;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":490
- *         list.keys = <char**>malloc(list.num)
- *         for i, key in enumerate(keys):
- *             key = _strenc(key)             # <<<<<<<<<<<<<<
- *             ckey = key
- *             list.keys[i] = <char*>malloc(len(key) + 1)
- */
-    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_strenc); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 490, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_8 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) {
-      __pyx_t_8 = PyMethod_GET_SELF(__pyx_t_7);
-      if (likely(__pyx_t_8)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
-        __Pyx_INCREF(__pyx_t_8);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_7, function);
-      }
-    }
-    __pyx_t_3 = (__pyx_t_8) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_8, __pyx_v_key) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_v_key);
-    __Pyx_XDECREF(__pyx_t_8); __pyx_t_8 = 0;
-    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 490, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __Pyx_DECREF_SET(__pyx_v_key, __pyx_t_3);
-    __pyx_t_3 = 0;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":491
- *         for i, key in enumerate(keys):
- *             key = _strenc(key)
- *             ckey = key             # <<<<<<<<<<<<<<
- *             list.keys[i] = <char*>malloc(len(key) + 1)
- *             strcpy(list.keys[i], ckey)
- */
-    __pyx_t_9 = __Pyx_PyObject_AsWritableString(__pyx_v_key); if (unlikely((!__pyx_t_9) && PyErr_Occurred())) __PYX_ERR(0, 491, __pyx_L1_error)
-    __pyx_v_ckey = __pyx_t_9;
+  __pyx_t_10 = __Pyx_PyObject_AsString(__pyx_v_prop); if (unlikely((!__pyx_t_10) && PyErr_Occurred())) __PYX_ERR(0, 590, __pyx_L1_error)
+  __pyx_v_prop_c = __pyx_t_10;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":492
- *             key = _strenc(key)
- *             ckey = key
- *             list.keys[i] = <char*>malloc(len(key) + 1)             # <<<<<<<<<<<<<<
- *             strcpy(list.keys[i], ckey)
- *         return list
+  /* "vidcutter/libs/pympv/mpv.pyx":591
+ *         userdatas.add()
+ *         cdef const char* prop_c = prop
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_get_property_async(
+ *                 self._ctx,
  */
-    __pyx_t_10 = PyObject_Length(__pyx_v_key); if (unlikely(__pyx_t_10 == ((Py_ssize_t)-1))) __PYX_ERR(0, 492, __pyx_L1_error)
-    __pyx_t_11 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_11 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 492, __pyx_L1_error)
-    (__pyx_v_list->keys[__pyx_t_11]) = ((char *)malloc((__pyx_t_10 + 1)));
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":493
- *             ckey = key
- *             list.keys[i] = <char*>malloc(len(key) + 1)
- *             strcpy(list.keys[i], ckey)             # <<<<<<<<<<<<<<
- *         return list
- * 
+        /* "vidcutter/libs/pympv/mpv.pyx":592
+ *         cdef const char* prop_c = prop
+ *         with nogil:
+ *             err = mpv_get_property_async(             # <<<<<<<<<<<<<<
+ *                 self._ctx,
+ *                 id_data,
  */
-    __pyx_t_10 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_10 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 493, __pyx_L1_error)
-    (void)(strcpy((__pyx_v_list->keys[__pyx_t_10]), __pyx_v_ckey));
+        __pyx_v_err = mpv_get_property_async(__pyx_v_self->_ctx, __pyx_v_id_data, __pyx_v_prop_c, MPV_FORMAT_NODE);
+      }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":489
- *             return list
- *         list.keys = <char**>malloc(list.num)
- *         for i, key in enumerate(keys):             # <<<<<<<<<<<<<<
- *             key = _strenc(key)
- *             ckey = key
+      /* "vidcutter/libs/pympv/mpv.pyx":591
+ *         userdatas.add()
+ *         cdef const char* prop_c = prop
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_get_property_async(
+ *                 self._ctx,
  */
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L6;
+        }
+        __pyx_L6:;
+      }
   }
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":494
- *             list.keys[i] = <char*>malloc(len(key) + 1)
- *             strcpy(list.keys[i], ckey)
- *         return list             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":598
+ *                 MPV_FORMAT_NODE,
+ *             )
+ *         return err             # <<<<<<<<<<<<<<
  * 
- *     cdef mpv_node _prep_native_value(self, value, format):
+ *     def try_get_property_async(self, prop, data=None, default=None):
  */
-  __pyx_r = __pyx_v_list;
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 598, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":481
- *         return node_list
+  /* "vidcutter/libs/pympv/mpv.pyx":574
+ * 
+ *     @_errors
+ *     def get_property_async(self, prop, data=None):             # <<<<<<<<<<<<<<
+ *         """Gets the value of a property asynchronously.
  * 
- *     cdef mpv_node_list* _prep_node_map(self, map):             # <<<<<<<<<<<<<<
- *         cdef char* ckey
- *         cdef mpv_node_list* list
  */
 
   /* function exit code */
@@ -10577,618 +11334,539 @@ static struct mpv_node_list *__pyx_f_9vidcutter_4libs_3mpv_7Context__prep_node_m
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_5);
   __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_WriteUnraisable("vidcutter.libs.mpv.Context._prep_node_map", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
-  __pyx_r = 0;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.get_property_async", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_keys);
-  __Pyx_XDECREF(__pyx_v_i);
-  __Pyx_XDECREF(__pyx_v_key);
+  __Pyx_XDECREF(__pyx_v_userdatas);
+  __Pyx_XDECREF(__pyx_v_prop);
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":496
- *         return list
+/* "vidcutter/libs/pympv/mpv.pyx":600
+ *         return err
  * 
- *     cdef mpv_node _prep_native_value(self, value, format):             # <<<<<<<<<<<<<<
- *         cdef mpv_node node
- *         node.format = format
+ *     def try_get_property_async(self, prop, data=None, default=None):             # <<<<<<<<<<<<<<
+ *         try:
+ *             return self.get_property_async(prop, data=data)
  */
 
-static struct mpv_node __pyx_f_9vidcutter_4libs_3mpv_7Context__prep_native_value(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_value, PyObject *__pyx_v_format) {
-  struct mpv_node __pyx_v_node;
-  struct mpv_node __pyx_r;
-  __Pyx_RefNannyDeclarations
-  enum mpv_format __pyx_t_1;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  int __pyx_t_4;
-  PyObject *__pyx_t_5 = NULL;
-  Py_ssize_t __pyx_t_6;
-  char const *__pyx_t_7;
-  int __pyx_t_8;
-  int64_t __pyx_t_9;
-  double __pyx_t_10;
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_13try_get_property_async(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_13try_get_property_async(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_prop = 0;
+  PyObject *__pyx_v_data = 0;
+  PyObject *__pyx_v_default = 0;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_prep_native_value", 0);
-  __Pyx_INCREF(__pyx_v_value);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":498
- *     cdef mpv_node _prep_native_value(self, value, format):
- *         cdef mpv_node node
- *         node.format = format             # <<<<<<<<<<<<<<
- *         if format == MPV_FORMAT_STRING:
- *             value = _strenc(value)
- */
-  __pyx_t_1 = ((enum mpv_format)__Pyx_PyInt_As_enum__mpv_format(__pyx_v_format)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 498, __pyx_L1_error)
-  __pyx_v_node.format = __pyx_t_1;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":499
- *         cdef mpv_node node
- *         node.format = format
- *         if format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
- *             value = _strenc(value)
- *             node.u.string = <char*>malloc(len(value) + 1)
- */
-  __pyx_t_2 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_STRING); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 499, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyObject_RichCompare(__pyx_v_format, __pyx_t_2, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 499, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 499, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (__pyx_t_4) {
-
-    /* "vidcutter/libs/pympv/mpv.pyx":500
- *         node.format = format
- *         if format == MPV_FORMAT_STRING:
- *             value = _strenc(value)             # <<<<<<<<<<<<<<
- *             node.u.string = <char*>malloc(len(value) + 1)
- *             strcpy(node.u.string, value)
- */
-    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 500, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_5 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
-      if (likely(__pyx_t_5)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_5);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_2, function);
-      }
-    }
-    __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_5, __pyx_v_value) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_value);
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 500, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_DECREF_SET(__pyx_v_value, __pyx_t_3);
-    __pyx_t_3 = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("try_get_property_async (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_data,&__pyx_n_s_default,0};
+    PyObject* values[3] = {0,0,0};
+    values[1] = ((PyObject *)Py_None);
+    values[2] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        CYTHON_FALLTHROUGH;
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_prop)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data);
+          if (value) { values[1] = value; kw_args--; }
+        }
+        CYTHON_FALLTHROUGH;
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_default);
+          if (value) { values[2] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "try_get_property_async") < 0)) __PYX_ERR(0, 600, __pyx_L3_error)
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        CYTHON_FALLTHROUGH;
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_prop = values[0];
+    __pyx_v_data = values[1];
+    __pyx_v_default = values[2];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("try_get_property_async", 0, 1, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 600, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property_async", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_12try_get_property_async(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_data, __pyx_v_default);
 
-    /* "vidcutter/libs/pympv/mpv.pyx":501
- *         if format == MPV_FORMAT_STRING:
- *             value = _strenc(value)
- *             node.u.string = <char*>malloc(len(value) + 1)             # <<<<<<<<<<<<<<
- *             strcpy(node.u.string, value)
- *         elif format == MPV_FORMAT_FLAG:
- */
-    __pyx_t_6 = PyObject_Length(__pyx_v_value); if (unlikely(__pyx_t_6 == ((Py_ssize_t)-1))) __PYX_ERR(0, 501, __pyx_L1_error)
-    __pyx_v_node.u.string = ((char *)malloc((__pyx_t_6 + 1)));
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-    /* "vidcutter/libs/pympv/mpv.pyx":502
- *             value = _strenc(value)
- *             node.u.string = <char*>malloc(len(value) + 1)
- *             strcpy(node.u.string, value)             # <<<<<<<<<<<<<<
- *         elif format == MPV_FORMAT_FLAG:
- *             node.u.flag = 1 if value else 0
- */
-    __pyx_t_7 = __Pyx_PyObject_AsString(__pyx_v_value); if (unlikely((!__pyx_t_7) && PyErr_Occurred())) __PYX_ERR(0, 502, __pyx_L1_error)
-    (void)(strcpy(__pyx_v_node.u.string, __pyx_t_7));
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_12try_get_property_async(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data, PyObject *__pyx_v_default) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyObject *__pyx_t_7 = NULL;
+  int __pyx_t_8;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("try_get_property_async", 0);
 
-    /* "vidcutter/libs/pympv/mpv.pyx":499
- *         cdef mpv_node node
- *         node.format = format
- *         if format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
- *             value = _strenc(value)
- *             node.u.string = <char*>malloc(len(value) + 1)
+  /* "vidcutter/libs/pympv/mpv.pyx":601
+ * 
+ *     def try_get_property_async(self, prop, data=None, default=None):
+ *         try:             # <<<<<<<<<<<<<<
+ *             return self.get_property_async(prop, data=data)
+ *         except MPVError:
  */
-    goto __pyx_L3;
-  }
+  {
+    __Pyx_PyThreadState_declare
+    __Pyx_PyThreadState_assign
+    __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3);
+    __Pyx_XGOTREF(__pyx_t_1);
+    __Pyx_XGOTREF(__pyx_t_2);
+    __Pyx_XGOTREF(__pyx_t_3);
+    /*try:*/ {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":503
- *             node.u.string = <char*>malloc(len(value) + 1)
- *             strcpy(node.u.string, value)
- *         elif format == MPV_FORMAT_FLAG:             # <<<<<<<<<<<<<<
- *             node.u.flag = 1 if value else 0
- *         elif format == MPV_FORMAT_INT64:
+      /* "vidcutter/libs/pympv/mpv.pyx":602
+ *     def try_get_property_async(self, prop, data=None, default=None):
+ *         try:
+ *             return self.get_property_async(prop, data=data)             # <<<<<<<<<<<<<<
+ *         except MPVError:
+ *             return default
  */
-  __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_FLAG); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 503, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_2 = PyObject_RichCompare(__pyx_v_format, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 503, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 503, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (__pyx_t_4) {
+      __Pyx_XDECREF(__pyx_r);
+      __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_property_async); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 602, __pyx_L3_error)
+      __Pyx_GOTREF(__pyx_t_4);
+      __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 602, __pyx_L3_error)
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_INCREF(__pyx_v_prop);
+      __Pyx_GIVEREF(__pyx_v_prop);
+      PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_prop);
+      __pyx_t_6 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 602, __pyx_L3_error)
+      __Pyx_GOTREF(__pyx_t_6);
+      if (PyDict_SetItem(__pyx_t_6, __pyx_n_s_data, __pyx_v_data) < 0) __PYX_ERR(0, 602, __pyx_L3_error)
+      __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 602, __pyx_L3_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+      __pyx_r = __pyx_t_7;
+      __pyx_t_7 = 0;
+      goto __pyx_L7_try_return;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":504
- *             strcpy(node.u.string, value)
- *         elif format == MPV_FORMAT_FLAG:
- *             node.u.flag = 1 if value else 0             # <<<<<<<<<<<<<<
- *         elif format == MPV_FORMAT_INT64:
- *             node.u.int64 = value
+      /* "vidcutter/libs/pympv/mpv.pyx":601
+ * 
+ *     def try_get_property_async(self, prop, data=None, default=None):
+ *         try:             # <<<<<<<<<<<<<<
+ *             return self.get_property_async(prop, data=data)
+ *         except MPVError:
  */
-    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_value); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 504, __pyx_L1_error)
-    if (__pyx_t_4) {
-      __pyx_t_8 = 1;
-    } else {
-      __pyx_t_8 = 0;
     }
-    __pyx_v_node.u.flag = __pyx_t_8;
+    __pyx_L3_error:;
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":503
- *             node.u.string = <char*>malloc(len(value) + 1)
- *             strcpy(node.u.string, value)
- *         elif format == MPV_FORMAT_FLAG:             # <<<<<<<<<<<<<<
- *             node.u.flag = 1 if value else 0
- *         elif format == MPV_FORMAT_INT64:
+    /* "vidcutter/libs/pympv/mpv.pyx":603
+ *         try:
+ *             return self.get_property_async(prop, data=data)
+ *         except MPVError:             # <<<<<<<<<<<<<<
+ *             return default
+ * 
  */
-    goto __pyx_L3;
-  }
+    __Pyx_ErrFetch(&__pyx_t_7, &__pyx_t_6, &__pyx_t_5);
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 603, __pyx_L5_except_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_8 = __Pyx_PyErr_GivenExceptionMatches(__pyx_t_7, __pyx_t_4);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_ErrRestore(__pyx_t_7, __pyx_t_6, __pyx_t_5);
+    __pyx_t_7 = 0; __pyx_t_6 = 0; __pyx_t_5 = 0;
+    if (__pyx_t_8) {
+      __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property_async", __pyx_clineno, __pyx_lineno, __pyx_filename);
+      if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 603, __pyx_L5_except_error)
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_GOTREF(__pyx_t_6);
+      __Pyx_GOTREF(__pyx_t_7);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":505
- *         elif format == MPV_FORMAT_FLAG:
- *             node.u.flag = 1 if value else 0
- *         elif format == MPV_FORMAT_INT64:             # <<<<<<<<<<<<<<
- *             node.u.int64 = value
- *         elif format == MPV_FORMAT_DOUBLE:
+      /* "vidcutter/libs/pympv/mpv.pyx":604
+ *             return self.get_property_async(prop, data=data)
+ *         except MPVError:
+ *             return default             # <<<<<<<<<<<<<<
+ * 
+ *     def try_get_property(self, prop, default=None):
  */
-  __pyx_t_2 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_INT64); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 505, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyObject_RichCompare(__pyx_v_format, __pyx_t_2, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 505, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 505, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (__pyx_t_4) {
+      __Pyx_XDECREF(__pyx_r);
+      __Pyx_INCREF(__pyx_v_default);
+      __pyx_r = __pyx_v_default;
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+      goto __pyx_L6_except_return;
+    }
+    goto __pyx_L5_except_error;
+    __pyx_L5_except_error:;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":506
- *             node.u.flag = 1 if value else 0
- *         elif format == MPV_FORMAT_INT64:
- *             node.u.int64 = value             # <<<<<<<<<<<<<<
- *         elif format == MPV_FORMAT_DOUBLE:
- *             node.u.double_ = value
+    /* "vidcutter/libs/pympv/mpv.pyx":601
+ * 
+ *     def try_get_property_async(self, prop, data=None, default=None):
+ *         try:             # <<<<<<<<<<<<<<
+ *             return self.get_property_async(prop, data=data)
+ *         except MPVError:
  */
-    __pyx_t_9 = __Pyx_PyInt_As_int64_t(__pyx_v_value); if (unlikely((__pyx_t_9 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 506, __pyx_L1_error)
-    __pyx_v_node.u.int64 = __pyx_t_9;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":505
- *         elif format == MPV_FORMAT_FLAG:
- *             node.u.flag = 1 if value else 0
- *         elif format == MPV_FORMAT_INT64:             # <<<<<<<<<<<<<<
- *             node.u.int64 = value
- *         elif format == MPV_FORMAT_DOUBLE:
- */
-    goto __pyx_L3;
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":507
- *         elif format == MPV_FORMAT_INT64:
- *             node.u.int64 = value
- *         elif format == MPV_FORMAT_DOUBLE:             # <<<<<<<<<<<<<<
- *             node.u.double_ = value
- *         elif format == MPV_FORMAT_NODE_ARRAY:
- */
-  __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_DOUBLE); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 507, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_2 = PyObject_RichCompare(__pyx_v_format, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 507, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 507, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (__pyx_t_4) {
-
-    /* "vidcutter/libs/pympv/mpv.pyx":508
- *             node.u.int64 = value
- *         elif format == MPV_FORMAT_DOUBLE:
- *             node.u.double_ = value             # <<<<<<<<<<<<<<
- *         elif format == MPV_FORMAT_NODE_ARRAY:
- *             node.u.list = self._prep_node_list(value)
- */
-    __pyx_t_10 = __pyx_PyFloat_AsDouble(__pyx_v_value); if (unlikely((__pyx_t_10 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 508, __pyx_L1_error)
-    __pyx_v_node.u.double_ = __pyx_t_10;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":507
- *         elif format == MPV_FORMAT_INT64:
- *             node.u.int64 = value
- *         elif format == MPV_FORMAT_DOUBLE:             # <<<<<<<<<<<<<<
- *             node.u.double_ = value
- *         elif format == MPV_FORMAT_NODE_ARRAY:
- */
-    goto __pyx_L3;
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":509
- *         elif format == MPV_FORMAT_DOUBLE:
- *             node.u.double_ = value
- *         elif format == MPV_FORMAT_NODE_ARRAY:             # <<<<<<<<<<<<<<
- *             node.u.list = self._prep_node_list(value)
- *         elif format == MPV_FORMAT_NODE_MAP:
- */
-  __pyx_t_2 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_NODE_ARRAY); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 509, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyObject_RichCompare(__pyx_v_format, __pyx_t_2, Py_EQ); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 509, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 509, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (__pyx_t_4) {
-
-    /* "vidcutter/libs/pympv/mpv.pyx":510
- *             node.u.double_ = value
- *         elif format == MPV_FORMAT_NODE_ARRAY:
- *             node.u.list = self._prep_node_list(value)             # <<<<<<<<<<<<<<
- *         elif format == MPV_FORMAT_NODE_MAP:
- *             node.u.list = self._prep_node_map(value)
- */
-    __pyx_v_node.u.list = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_node_list(__pyx_v_self, __pyx_v_value);
-
-    /* "vidcutter/libs/pympv/mpv.pyx":509
- *         elif format == MPV_FORMAT_DOUBLE:
- *             node.u.double_ = value
- *         elif format == MPV_FORMAT_NODE_ARRAY:             # <<<<<<<<<<<<<<
- *             node.u.list = self._prep_node_list(value)
- *         elif format == MPV_FORMAT_NODE_MAP:
- */
-    goto __pyx_L3;
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":511
- *         elif format == MPV_FORMAT_NODE_ARRAY:
- *             node.u.list = self._prep_node_list(value)
- *         elif format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
- *             node.u.list = self._prep_node_map(value)
- *         else:
- */
-  __pyx_t_3 = __Pyx_PyInt_From_enum__mpv_format(MPV_FORMAT_NODE_MAP); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 511, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_2 = PyObject_RichCompare(__pyx_v_format, __pyx_t_3, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 511, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 511, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (__pyx_t_4) {
-
-    /* "vidcutter/libs/pympv/mpv.pyx":512
- *             node.u.list = self._prep_node_list(value)
- *         elif format == MPV_FORMAT_NODE_MAP:
- *             node.u.list = self._prep_node_map(value)             # <<<<<<<<<<<<<<
- *         else:
- *             node.format = MPV_FORMAT_NONE
- */
-    __pyx_v_node.u.list = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_node_map(__pyx_v_self, __pyx_v_value);
-
-    /* "vidcutter/libs/pympv/mpv.pyx":511
- *         elif format == MPV_FORMAT_NODE_ARRAY:
- *             node.u.list = self._prep_node_list(value)
- *         elif format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
- *             node.u.list = self._prep_node_map(value)
- *         else:
- */
-    goto __pyx_L3;
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":514
- *             node.u.list = self._prep_node_map(value)
- *         else:
- *             node.format = MPV_FORMAT_NONE             # <<<<<<<<<<<<<<
- *         return node
- * 
- */
-  /*else*/ {
-    __pyx_v_node.format = MPV_FORMAT_NONE;
+    __Pyx_XGIVEREF(__pyx_t_1);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
+    goto __pyx_L1_error;
+    __pyx_L7_try_return:;
+    __Pyx_XGIVEREF(__pyx_t_1);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
+    goto __pyx_L0;
+    __pyx_L6_except_return:;
+    __Pyx_XGIVEREF(__pyx_t_1);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
+    goto __pyx_L0;
   }
-  __pyx_L3:;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":515
- *         else:
- *             node.format = MPV_FORMAT_NONE
- *         return node             # <<<<<<<<<<<<<<
- * 
- *     cdef _free_native_value(self, mpv_node node):
- */
-  __pyx_r = __pyx_v_node;
-  goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":496
- *         return list
+  /* "vidcutter/libs/pympv/mpv.pyx":600
+ *         return err
  * 
- *     cdef mpv_node _prep_native_value(self, value, format):             # <<<<<<<<<<<<<<
- *         cdef mpv_node node
- *         node.format = format
+ *     def try_get_property_async(self, prop, data=None, default=None):             # <<<<<<<<<<<<<<
+ *         try:
+ *             return self.get_property_async(prop, data=data)
  */
 
   /* function exit code */
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_WriteUnraisable("vidcutter.libs.mpv.Context._prep_native_value", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
-  __Pyx_pretend_to_initialize(&__pyx_r);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property_async", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_value);
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":517
- *         return node
+/* "vidcutter/libs/pympv/mpv.pyx":606
+ *             return default
  * 
- *     cdef _free_native_value(self, mpv_node node):             # <<<<<<<<<<<<<<
- *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):
- *             for i in range(node.u.list.num):
+ *     def try_get_property(self, prop, default=None):             # <<<<<<<<<<<<<<
+ *         try:
+ *             return self.get_property(prop)
  */
 
-static PyObject *__pyx_f_9vidcutter_4libs_3mpv_7Context__free_native_value(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, struct mpv_node __pyx_v_node) {
-  int __pyx_v_i;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  int __pyx_t_2;
-  int __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  int __pyx_t_5;
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_15try_get_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_15try_get_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_prop = 0;
+  PyObject *__pyx_v_default = 0;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("_free_native_value", 0);
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("try_get_property (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_default,0};
+    PyObject* values[2] = {0,0};
+    values[1] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_prop)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_default);
+          if (value) { values[1] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "try_get_property") < 0)) __PYX_ERR(0, 606, __pyx_L3_error)
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+    }
+    __pyx_v_prop = values[0];
+    __pyx_v_default = values[1];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("try_get_property", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 606, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_14try_get_property(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_default);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":518
- * 
- *     cdef _free_native_value(self, mpv_node node):
- *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):             # <<<<<<<<<<<<<<
- *             for i in range(node.u.list.num):
- *                 self._free_native_value(node.u.list.values[i])
- */
-  switch (__pyx_v_node.format) {
-    case MPV_FORMAT_NODE_ARRAY:
-    case MPV_FORMAT_NODE_MAP:
-
-    /* "vidcutter/libs/pympv/mpv.pyx":519
- *     cdef _free_native_value(self, mpv_node node):
- *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):
- *             for i in range(node.u.list.num):             # <<<<<<<<<<<<<<
- *                 self._free_native_value(node.u.list.values[i])
- *             free(node.u.list.values)
- */
-    __pyx_t_1 = __pyx_v_node.u.list->num;
-    __pyx_t_2 = __pyx_t_1;
-    for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
-      __pyx_v_i = __pyx_t_3;
-
-      /* "vidcutter/libs/pympv/mpv.pyx":520
- *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):
- *             for i in range(node.u.list.num):
- *                 self._free_native_value(node.u.list.values[i])             # <<<<<<<<<<<<<<
- *             free(node.u.list.values)
- *             if node.format == MPV_FORMAT_NODE_MAP:
- */
-      __pyx_t_4 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, (__pyx_v_node.u.list->values[__pyx_v_i])); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 520, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    }
-
-    /* "vidcutter/libs/pympv/mpv.pyx":521
- *             for i in range(node.u.list.num):
- *                 self._free_native_value(node.u.list.values[i])
- *             free(node.u.list.values)             # <<<<<<<<<<<<<<
- *             if node.format == MPV_FORMAT_NODE_MAP:
- *                 for i in range(node.u.list.num):
- */
-    free(__pyx_v_node.u.list->values);
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-    /* "vidcutter/libs/pympv/mpv.pyx":522
- *                 self._free_native_value(node.u.list.values[i])
- *             free(node.u.list.values)
- *             if node.format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
- *                 for i in range(node.u.list.num):
- *                     free(node.u.list.keys[i])
- */
-    __pyx_t_5 = ((__pyx_v_node.format == MPV_FORMAT_NODE_MAP) != 0);
-    if (__pyx_t_5) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_14try_get_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_default) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_6 = NULL;
+  PyObject *__pyx_t_7 = NULL;
+  int __pyx_t_8;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("try_get_property", 0);
 
-      /* "vidcutter/libs/pympv/mpv.pyx":523
- *             free(node.u.list.values)
- *             if node.format == MPV_FORMAT_NODE_MAP:
- *                 for i in range(node.u.list.num):             # <<<<<<<<<<<<<<
- *                     free(node.u.list.keys[i])
- *                 free(node.u.list.keys)
+  /* "vidcutter/libs/pympv/mpv.pyx":607
+ * 
+ *     def try_get_property(self, prop, default=None):
+ *         try:             # <<<<<<<<<<<<<<
+ *             return self.get_property(prop)
+ *         except MPVError:
  */
-      __pyx_t_1 = __pyx_v_node.u.list->num;
-      __pyx_t_2 = __pyx_t_1;
-      for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
-        __pyx_v_i = __pyx_t_3;
+  {
+    __Pyx_PyThreadState_declare
+    __Pyx_PyThreadState_assign
+    __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3);
+    __Pyx_XGOTREF(__pyx_t_1);
+    __Pyx_XGOTREF(__pyx_t_2);
+    __Pyx_XGOTREF(__pyx_t_3);
+    /*try:*/ {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":524
- *             if node.format == MPV_FORMAT_NODE_MAP:
- *                 for i in range(node.u.list.num):
- *                     free(node.u.list.keys[i])             # <<<<<<<<<<<<<<
- *                 free(node.u.list.keys)
- *             free(node.u.list)
+      /* "vidcutter/libs/pympv/mpv.pyx":608
+ *     def try_get_property(self, prop, default=None):
+ *         try:
+ *             return self.get_property(prop)             # <<<<<<<<<<<<<<
+ *         except MPVError:
+ *             return default
  */
-        free((__pyx_v_node.u.list->keys[__pyx_v_i]));
+      __Pyx_XDECREF(__pyx_r);
+      __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_property); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 608, __pyx_L3_error)
+      __Pyx_GOTREF(__pyx_t_5);
+      __pyx_t_6 = NULL;
+      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
+        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
+        if (likely(__pyx_t_6)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+          __Pyx_INCREF(__pyx_t_6);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_5, function);
+        }
       }
+      __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_6, __pyx_v_prop) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_prop);
+      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 608, __pyx_L3_error)
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __pyx_r = __pyx_t_4;
+      __pyx_t_4 = 0;
+      goto __pyx_L7_try_return;
 
-      /* "vidcutter/libs/pympv/mpv.pyx":525
- *                 for i in range(node.u.list.num):
- *                     free(node.u.list.keys[i])
- *                 free(node.u.list.keys)             # <<<<<<<<<<<<<<
- *             free(node.u.list)
- *         elif node.format == MPV_FORMAT_STRING:
- */
-      free(__pyx_v_node.u.list->keys);
-
-      /* "vidcutter/libs/pympv/mpv.pyx":522
- *                 self._free_native_value(node.u.list.values[i])
- *             free(node.u.list.values)
- *             if node.format == MPV_FORMAT_NODE_MAP:             # <<<<<<<<<<<<<<
- *                 for i in range(node.u.list.num):
- *                     free(node.u.list.keys[i])
+      /* "vidcutter/libs/pympv/mpv.pyx":607
+ * 
+ *     def try_get_property(self, prop, default=None):
+ *         try:             # <<<<<<<<<<<<<<
+ *             return self.get_property(prop)
+ *         except MPVError:
  */
     }
+    __pyx_L3_error:;
+    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":526
- *                     free(node.u.list.keys[i])
- *                 free(node.u.list.keys)
- *             free(node.u.list)             # <<<<<<<<<<<<<<
- *         elif node.format == MPV_FORMAT_STRING:
- *             free(node.u.string)
- */
-    free(__pyx_v_node.u.list);
-
-    /* "vidcutter/libs/pympv/mpv.pyx":518
+    /* "vidcutter/libs/pympv/mpv.pyx":609
+ *         try:
+ *             return self.get_property(prop)
+ *         except MPVError:             # <<<<<<<<<<<<<<
+ *             return default
  * 
- *     cdef _free_native_value(self, mpv_node node):
- *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):             # <<<<<<<<<<<<<<
- *             for i in range(node.u.list.num):
- *                 self._free_native_value(node.u.list.values[i])
  */
-    break;
-    case MPV_FORMAT_STRING:
+    __Pyx_ErrFetch(&__pyx_t_4, &__pyx_t_5, &__pyx_t_6);
+    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 609, __pyx_L5_except_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_8 = __Pyx_PyErr_GivenExceptionMatches(__pyx_t_4, __pyx_t_7);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_ErrRestore(__pyx_t_4, __pyx_t_5, __pyx_t_6);
+    __pyx_t_4 = 0; __pyx_t_5 = 0; __pyx_t_6 = 0;
+    if (__pyx_t_8) {
+      __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
+      if (__Pyx_GetException(&__pyx_t_6, &__pyx_t_5, &__pyx_t_4) < 0) __PYX_ERR(0, 609, __pyx_L5_except_error)
+      __Pyx_GOTREF(__pyx_t_6);
+      __Pyx_GOTREF(__pyx_t_5);
+      __Pyx_GOTREF(__pyx_t_4);
 
-    /* "vidcutter/libs/pympv/mpv.pyx":528
- *             free(node.u.list)
- *         elif node.format == MPV_FORMAT_STRING:
- *             free(node.u.string)             # <<<<<<<<<<<<<<
+      /* "vidcutter/libs/pympv/mpv.pyx":610
+ *             return self.get_property(prop)
+ *         except MPVError:
+ *             return default             # <<<<<<<<<<<<<<
  * 
- *     def command(self, *cmdlist, asynchronous=False, data=None):
+ *     def get_property(self, prop):
  */
-    free(__pyx_v_node.u.string);
+      __Pyx_XDECREF(__pyx_r);
+      __Pyx_INCREF(__pyx_v_default);
+      __pyx_r = __pyx_v_default;
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+      goto __pyx_L6_except_return;
+    }
+    goto __pyx_L5_except_error;
+    __pyx_L5_except_error:;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":527
- *                 free(node.u.list.keys)
- *             free(node.u.list)
- *         elif node.format == MPV_FORMAT_STRING:             # <<<<<<<<<<<<<<
- *             free(node.u.string)
+    /* "vidcutter/libs/pympv/mpv.pyx":607
  * 
+ *     def try_get_property(self, prop, default=None):
+ *         try:             # <<<<<<<<<<<<<<
+ *             return self.get_property(prop)
+ *         except MPVError:
  */
-    break;
-    default: break;
+    __Pyx_XGIVEREF(__pyx_t_1);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
+    goto __pyx_L1_error;
+    __pyx_L7_try_return:;
+    __Pyx_XGIVEREF(__pyx_t_1);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
+    goto __pyx_L0;
+    __pyx_L6_except_return:;
+    __Pyx_XGIVEREF(__pyx_t_1);
+    __Pyx_XGIVEREF(__pyx_t_2);
+    __Pyx_XGIVEREF(__pyx_t_3);
+    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
+    goto __pyx_L0;
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":517
- *         return node
+  /* "vidcutter/libs/pympv/mpv.pyx":606
+ *             return default
  * 
- *     cdef _free_native_value(self, mpv_node node):             # <<<<<<<<<<<<<<
- *         if node.format in (MPV_FORMAT_NODE_ARRAY, MPV_FORMAT_NODE_MAP):
- *             for i in range(node.u.list.num):
+ *     def try_get_property(self, prop, default=None):             # <<<<<<<<<<<<<<
+ *         try:
+ *             return self.get_property(prop)
  */
 
   /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context._free_native_value", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":530
- *             free(node.u.string)
- * 
- *     def command(self, *cmdlist, asynchronous=False, data=None):             # <<<<<<<<<<<<<<
- *         """Send a command to mpv.
+/* "vidcutter/libs/pympv/mpv.pyx":612
+ *             return default
  * 
+ *     def get_property(self, prop):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_get_property"""
+ *         assert self._ctx
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_13command(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_12command[] = "Send a command to mpv.\n\n        Non-async success returns the command's response data, otherwise None\n\n        Arguments:\n        Accepts parameters as args\n\n        Keyword Arguments:\n        asynchronous: True will return right away, status comes in as MPV_EVENT_COMMAND_REPLY\n        data: Only valid if async, gets sent back as reply_userdata in the Event\n\n        Wraps: mpv_command_node and mpv_command_node_async\n        ";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_13command(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_asynchronous = 0;
-  PyObject *__pyx_v_data = 0;
-  PyObject *__pyx_v_cmdlist = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_17get_property(PyObject *__pyx_v_self, PyObject *__pyx_v_prop); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_16get_property[] = "Wraps: mpv_get_property";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_17get_property(PyObject *__pyx_v_self, PyObject *__pyx_v_prop) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("command (wrapper)", 0);
-  if (PyTuple_GET_SIZE(__pyx_args) > 0) {
-    __pyx_v_cmdlist = PyTuple_GetSlice(__pyx_args, 0, PyTuple_GET_SIZE(__pyx_args));
-    if (unlikely(!__pyx_v_cmdlist)) {
-      __Pyx_RefNannyFinishContext();
-      return NULL;
-    }
-    __Pyx_GOTREF(__pyx_v_cmdlist);
-  } else {
-    __pyx_v_cmdlist = __pyx_empty_tuple; __Pyx_INCREF(__pyx_empty_tuple);
-  }
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_asynchronous,&__pyx_n_s_data,0};
-    PyObject* values[2] = {0,0};
-    values[0] = ((PyObject *)Py_False);
-    values[1] = ((PyObject *)Py_None);
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        default:
-        case  0: break;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      if (kw_args > 0 && likely(kw_args <= 2)) {
-        Py_ssize_t index;
-        for (index = 0; index < 2 && kw_args > 0; index++) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, *__pyx_pyargnames[index]);
-          if (value) { values[index] = value; kw_args--; }
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, 0, "command") < 0)) __PYX_ERR(0, 530, __pyx_L3_error)
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) < 0) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-    }
-    __pyx_v_asynchronous = values[0];
-    __pyx_v_data = values[1];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("command", 0, 0, 0, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 530, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_DECREF(__pyx_v_cmdlist); __pyx_v_cmdlist = 0;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.command", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_12command(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_asynchronous, __pyx_v_data, __pyx_v_cmdlist);
+  __Pyx_RefNannySetupContext("get_property (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_16get_property(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_prop));
 
   /* function exit code */
-  __Pyx_XDECREF(__pyx_v_cmdlist);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_12command(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_asynchronous, PyObject *__pyx_v_data, PyObject *__pyx_v_cmdlist) {
-  struct mpv_node __pyx_v_node;
-  struct mpv_node __pyx_v_noderesult;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_16get_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop) {
+  struct mpv_node __pyx_v_result;
+  char const *__pyx_v_prop_c;
   int __pyx_v_err;
-  uint64_t __pyx_v_data_id;
-  PyObject *__pyx_v_result = NULL;
-  PyObject *__pyx_v_userdatas = NULL;
+  PyObject *__pyx_v_v = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  uint64_t __pyx_t_4;
+  char const *__pyx_t_4;
   int __pyx_t_5;
-  int __pyx_t_6;
+  PyObject *__pyx_t_6 = NULL;
   int __pyx_t_7;
   int __pyx_t_8;
   char const *__pyx_t_9;
@@ -11198,41 +11876,39 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_12command(struct __pyx_
   PyObject *__pyx_t_13 = NULL;
   PyObject *__pyx_t_14 = NULL;
   PyObject *__pyx_t_15 = NULL;
-  PyObject *__pyx_t_16 = NULL;
-  PyObject *__pyx_t_17 = NULL;
-  char const *__pyx_t_18;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("command", 0);
+  __Pyx_RefNannySetupContext("get_property", 0);
+  __Pyx_INCREF(__pyx_v_prop);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":544
- *         Wraps: mpv_command_node and mpv_command_node_async
- *         """
+  /* "vidcutter/libs/pympv/mpv.pyx":614
+ *     def get_property(self, prop):
+ *         """Wraps: mpv_get_property"""
  *         assert self._ctx             # <<<<<<<<<<<<<<
- *         cdef mpv_node node = self._prep_native_value(cmdlist, self._format_for(cmdlist))
- *         cdef mpv_node noderesult
+ *         cdef mpv_node result
+ *         prop = _strenc(prop)
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
   if (unlikely(!Py_OptimizeFlag)) {
     if (unlikely(!(__pyx_v_self->_ctx != 0))) {
       PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 544, __pyx_L1_error)
+      __PYX_ERR(0, 614, __pyx_L1_error)
     }
   }
   #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":545
- *         """
+  /* "vidcutter/libs/pympv/mpv.pyx":616
  *         assert self._ctx
- *         cdef mpv_node node = self._prep_native_value(cmdlist, self._format_for(cmdlist))             # <<<<<<<<<<<<<<
- *         cdef mpv_node noderesult
+ *         cdef mpv_node result
+ *         prop = _strenc(prop)             # <<<<<<<<<<<<<<
+ *         cdef const char* prop_c = prop
  *         cdef int err
  */
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_format_for); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 545, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 616, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
     __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
     if (likely(__pyx_t_3)) {
       PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
@@ -11241,625 +11917,332 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_12command(struct __pyx_
       __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_cmdlist) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_cmdlist);
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_prop) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_prop);
   __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 545, __pyx_L1_error)
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 616, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_v_node = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_native_value(__pyx_v_self, __pyx_v_cmdlist, __pyx_t_1);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_DECREF_SET(__pyx_v_prop, __pyx_t_1);
+  __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":549
+  /* "vidcutter/libs/pympv/mpv.pyx":617
+ *         cdef mpv_node result
+ *         prop = _strenc(prop)
+ *         cdef const char* prop_c = prop             # <<<<<<<<<<<<<<
  *         cdef int err
- *         cdef uint64_t data_id
- *         result = None             # <<<<<<<<<<<<<<
- *         try:
- *             data_id = id(data)
- */
-  __Pyx_INCREF(Py_None);
-  __pyx_v_result = Py_None;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":550
- *         cdef uint64_t data_id
- *         result = None
- *         try:             # <<<<<<<<<<<<<<
- *             data_id = id(data)
- *             if not asynchronous:
+ *         with nogil:
  */
-  /*try:*/ {
+  __pyx_t_4 = __Pyx_PyObject_AsString(__pyx_v_prop); if (unlikely((!__pyx_t_4) && PyErr_Occurred())) __PYX_ERR(0, 617, __pyx_L1_error)
+  __pyx_v_prop_c = __pyx_t_4;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":551
- *         result = None
- *         try:
- *             data_id = id(data)             # <<<<<<<<<<<<<<
- *             if not asynchronous:
- *                 with nogil:
+  /* "vidcutter/libs/pympv/mpv.pyx":619
+ *         cdef const char* prop_c = prop
+ *         cdef int err
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_get_property(
+ *                 self._ctx,
  */
-    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, __pyx_v_data); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 551, __pyx_L4_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_4 = __Pyx_PyInt_As_uint64_t(__pyx_t_1); if (unlikely((__pyx_t_4 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 551, __pyx_L4_error)
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_v_data_id = __pyx_t_4;
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":552
- *         try:
- *             data_id = id(data)
- *             if not asynchronous:             # <<<<<<<<<<<<<<
- *                 with nogil:
- *                     err = mpv_command_node(self._ctx, &node, &noderesult)
+        /* "vidcutter/libs/pympv/mpv.pyx":620
+ *         cdef int err
+ *         with nogil:
+ *             err = mpv_get_property(             # <<<<<<<<<<<<<<
+ *                 self._ctx,
+ *                 prop_c,
  */
-    __pyx_t_5 = __Pyx_PyObject_IsTrue(__pyx_v_asynchronous); if (unlikely(__pyx_t_5 < 0)) __PYX_ERR(0, 552, __pyx_L4_error)
-    __pyx_t_6 = ((!__pyx_t_5) != 0);
-    if (__pyx_t_6) {
+        __pyx_v_err = mpv_get_property(__pyx_v_self->_ctx, __pyx_v_prop_c, MPV_FORMAT_NODE, (&__pyx_v_result));
+      }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":553
- *             data_id = id(data)
- *             if not asynchronous:
- *                 with nogil:             # <<<<<<<<<<<<<<
- *                     err = mpv_command_node(self._ctx, &node, &noderesult)
- *                 try:
+      /* "vidcutter/libs/pympv/mpv.pyx":619
+ *         cdef const char* prop_c = prop
+ *         cdef int err
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_get_property(
+ *                 self._ctx,
  */
-      {
+      /*finally:*/ {
+        /*normal exit:*/{
           #ifdef WITH_THREAD
-          PyThreadState *_save;
-          Py_UNBLOCK_THREADS
-          __Pyx_FastGIL_Remember();
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
           #endif
-          /*try:*/ {
-
-            /* "vidcutter/libs/pympv/mpv.pyx":554
- *             if not asynchronous:
- *                 with nogil:
- *                     err = mpv_command_node(self._ctx, &node, &noderesult)             # <<<<<<<<<<<<<<
- *                 try:
- *                     result = _convert_node_value(noderesult) if err >= 0 else None
- */
-            __pyx_v_err = mpv_command_node(__pyx_v_self->_ctx, (&__pyx_v_node), (&__pyx_v_noderesult));
-          }
-
-          /* "vidcutter/libs/pympv/mpv.pyx":553
- *             data_id = id(data)
- *             if not asynchronous:
- *                 with nogil:             # <<<<<<<<<<<<<<
- *                     err = mpv_command_node(self._ctx, &node, &noderesult)
- *                 try:
- */
-          /*finally:*/ {
-            /*normal exit:*/{
-              #ifdef WITH_THREAD
-              __Pyx_FastGIL_Forget();
-              Py_BLOCK_THREADS
-              #endif
-              goto __pyx_L9;
-            }
-            __pyx_L9:;
-          }
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
       }
+  }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":555
- *                 with nogil:
- *                     err = mpv_command_node(self._ctx, &node, &noderesult)
- *                 try:             # <<<<<<<<<<<<<<
- *                     result = _convert_node_value(noderesult) if err >= 0 else None
- *                 finally:
+  /* "vidcutter/libs/pympv/mpv.pyx":626
+ *                 &result,
+ *             )
+ *         if err < 0:             # <<<<<<<<<<<<<<
+ *             raise MPVError(err)
+ *         try:
  */
-      /*try:*/ {
+  __pyx_t_5 = ((__pyx_v_err < 0) != 0);
+  if (unlikely(__pyx_t_5)) {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":556
- *                     err = mpv_command_node(self._ctx, &node, &noderesult)
- *                 try:
- *                     result = _convert_node_value(noderesult) if err >= 0 else None             # <<<<<<<<<<<<<<
- *                 finally:
- *                     with nogil:
+    /* "vidcutter/libs/pympv/mpv.pyx":627
+ *             )
+ *         if err < 0:
+ *             raise MPVError(err)             # <<<<<<<<<<<<<<
+ *         try:
+ *             v = _convert_node_value(result)
  */
-        if (((__pyx_v_err >= 0) != 0)) {
-          __pyx_t_2 = __pyx_f_9vidcutter_4libs_3mpv__convert_node_value(__pyx_v_noderesult); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 556, __pyx_L11_error)
-          __Pyx_GOTREF(__pyx_t_2);
-          __pyx_t_1 = __pyx_t_2;
-          __pyx_t_2 = 0;
-        } else {
-          __Pyx_INCREF(Py_None);
-          __pyx_t_1 = Py_None;
-        }
-        __Pyx_DECREF_SET(__pyx_v_result, __pyx_t_1);
-        __pyx_t_1 = 0;
+    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 627, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 627, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_6 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_6)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_6);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
       }
+    }
+    __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_6, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
+    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 627, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 627, __pyx_L1_error)
 
-      /* "vidcutter/libs/pympv/mpv.pyx":558
- *                     result = _convert_node_value(noderesult) if err >= 0 else None
- *                 finally:
- *                     with nogil:             # <<<<<<<<<<<<<<
- *                         mpv_free_node_contents(&noderesult)
- *             else:
+    /* "vidcutter/libs/pympv/mpv.pyx":626
+ *                 &result,
+ *             )
+ *         if err < 0:             # <<<<<<<<<<<<<<
+ *             raise MPVError(err)
+ *         try:
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          {
-              #ifdef WITH_THREAD
-              PyThreadState *_save;
-              Py_UNBLOCK_THREADS
-              __Pyx_FastGIL_Remember();
-              #endif
-              /*try:*/ {
+  }
 
-                /* "vidcutter/libs/pympv/mpv.pyx":559
- *                 finally:
- *                     with nogil:
- *                         mpv_free_node_contents(&noderesult)             # <<<<<<<<<<<<<<
- *             else:
- *                 userdatas = self.reply_userdata.get(data_id, None)
+  /* "vidcutter/libs/pympv/mpv.pyx":628
+ *         if err < 0:
+ *             raise MPVError(err)
+ *         try:             # <<<<<<<<<<<<<<
+ *             v = _convert_node_value(result)
+ *         finally:
  */
-                mpv_free_node_contents((&__pyx_v_noderesult));
-              }
+  /*try:*/ {
 
-              /* "vidcutter/libs/pympv/mpv.pyx":558
- *                     result = _convert_node_value(noderesult) if err >= 0 else None
- *                 finally:
- *                     with nogil:             # <<<<<<<<<<<<<<
- *                         mpv_free_node_contents(&noderesult)
- *             else:
+    /* "vidcutter/libs/pympv/mpv.pyx":629
+ *             raise MPVError(err)
+ *         try:
+ *             v = _convert_node_value(result)             # <<<<<<<<<<<<<<
+ *         finally:
+ *             with nogil:
  */
-              /*finally:*/ {
-                /*normal exit:*/{
-                  #ifdef WITH_THREAD
-                  __Pyx_FastGIL_Forget();
-                  Py_BLOCK_THREADS
-                  #endif
-                  goto __pyx_L15;
-                }
-                __pyx_L15:;
-              }
-          }
-          goto __pyx_L12;
-        }
-        __pyx_L11_error:;
-        /*exception exit:*/{
-          __Pyx_PyThreadState_declare
-          __Pyx_PyThreadState_assign
-          __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0;
-          __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-          __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-          __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-          if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15);
-          if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12) < 0)) __Pyx_ErrFetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
-          __Pyx_XGOTREF(__pyx_t_10);
-          __Pyx_XGOTREF(__pyx_t_11);
-          __Pyx_XGOTREF(__pyx_t_12);
-          __Pyx_XGOTREF(__pyx_t_13);
-          __Pyx_XGOTREF(__pyx_t_14);
-          __Pyx_XGOTREF(__pyx_t_15);
-          __pyx_t_7 = __pyx_lineno; __pyx_t_8 = __pyx_clineno; __pyx_t_9 = __pyx_filename;
-          {
-            {
-                #ifdef WITH_THREAD
-                PyThreadState *_save;
-                Py_UNBLOCK_THREADS
-                __Pyx_FastGIL_Remember();
-                #endif
-                /*try:*/ {
+    __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_node_value(__pyx_v_result); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 629, __pyx_L8_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_v_v = __pyx_t_1;
+    __pyx_t_1 = 0;
+  }
 
-                  /* "vidcutter/libs/pympv/mpv.pyx":559
- *                 finally:
- *                     with nogil:
- *                         mpv_free_node_contents(&noderesult)             # <<<<<<<<<<<<<<
- *             else:
- *                 userdatas = self.reply_userdata.get(data_id, None)
+  /* "vidcutter/libs/pympv/mpv.pyx":631
+ *             v = _convert_node_value(result)
+ *         finally:
+ *             with nogil:             # <<<<<<<<<<<<<<
+ *                 mpv_free_node_contents(&result)
+ *         return v
  */
-                  mpv_free_node_contents((&__pyx_v_noderesult));
-                }
+  /*finally:*/ {
+    /*normal exit:*/{
+      {
+          #ifdef WITH_THREAD
+          PyThreadState *_save;
+          Py_UNBLOCK_THREADS
+          __Pyx_FastGIL_Remember();
+          #endif
+          /*try:*/ {
 
-                /* "vidcutter/libs/pympv/mpv.pyx":558
- *                     result = _convert_node_value(noderesult) if err >= 0 else None
- *                 finally:
- *                     with nogil:             # <<<<<<<<<<<<<<
- *                         mpv_free_node_contents(&noderesult)
- *             else:
+            /* "vidcutter/libs/pympv/mpv.pyx":632
+ *         finally:
+ *             with nogil:
+ *                 mpv_free_node_contents(&result)             # <<<<<<<<<<<<<<
+ *         return v
+ * 
  */
-                /*finally:*/ {
-                  /*normal exit:*/{
-                    #ifdef WITH_THREAD
-                    __Pyx_FastGIL_Forget();
-                    Py_BLOCK_THREADS
-                    #endif
-                    goto __pyx_L20;
-                  }
-                  __pyx_L20:;
-                }
-            }
-          }
-          if (PY_MAJOR_VERSION >= 3) {
-            __Pyx_XGIVEREF(__pyx_t_13);
-            __Pyx_XGIVEREF(__pyx_t_14);
-            __Pyx_XGIVEREF(__pyx_t_15);
-            __Pyx_ExceptionReset(__pyx_t_13, __pyx_t_14, __pyx_t_15);
+            mpv_free_node_contents((&__pyx_v_result));
           }
-          __Pyx_XGIVEREF(__pyx_t_10);
-          __Pyx_XGIVEREF(__pyx_t_11);
-          __Pyx_XGIVEREF(__pyx_t_12);
-          __Pyx_ErrRestore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
-          __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0;
-          __pyx_lineno = __pyx_t_7; __pyx_clineno = __pyx_t_8; __pyx_filename = __pyx_t_9;
-          goto __pyx_L4_error;
-        }
-        __pyx_L12:;
-      }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":552
- *         try:
- *             data_id = id(data)
- *             if not asynchronous:             # <<<<<<<<<<<<<<
- *                 with nogil:
- *                     err = mpv_command_node(self._ctx, &node, &noderesult)
+          /* "vidcutter/libs/pympv/mpv.pyx":631
+ *             v = _convert_node_value(result)
+ *         finally:
+ *             with nogil:             # <<<<<<<<<<<<<<
+ *                 mpv_free_node_contents(&result)
+ *         return v
  */
-      goto __pyx_L6;
+          /*finally:*/ {
+            /*normal exit:*/{
+              #ifdef WITH_THREAD
+              __Pyx_FastGIL_Forget();
+              Py_BLOCK_THREADS
+              #endif
+              goto __pyx_L12;
+            }
+            __pyx_L12:;
+          }
+      }
+      goto __pyx_L9;
     }
+    __pyx_L8_error:;
+    /*exception exit:*/{
+      __Pyx_PyThreadState_declare
+      __Pyx_PyThreadState_assign
+      __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0;
+      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
+      if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15);
+      if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12) < 0)) __Pyx_ErrFetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
+      __Pyx_XGOTREF(__pyx_t_10);
+      __Pyx_XGOTREF(__pyx_t_11);
+      __Pyx_XGOTREF(__pyx_t_12);
+      __Pyx_XGOTREF(__pyx_t_13);
+      __Pyx_XGOTREF(__pyx_t_14);
+      __Pyx_XGOTREF(__pyx_t_15);
+      __pyx_t_7 = __pyx_lineno; __pyx_t_8 = __pyx_clineno; __pyx_t_9 = __pyx_filename;
+      {
+        {
+            #ifdef WITH_THREAD
+            PyThreadState *_save;
+            Py_UNBLOCK_THREADS
+            __Pyx_FastGIL_Remember();
+            #endif
+            /*try:*/ {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":561
- *                         mpv_free_node_contents(&noderesult)
- *             else:
- *                 userdatas = self.reply_userdata.get(data_id, None)             # <<<<<<<<<<<<<<
- *                 if userdatas is None:
- *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
+              /* "vidcutter/libs/pympv/mpv.pyx":632
+ *         finally:
+ *             with nogil:
+ *                 mpv_free_node_contents(&result)             # <<<<<<<<<<<<<<
+ *         return v
+ * 
  */
-    /*else*/ {
-      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->reply_userdata, __pyx_n_s_get); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 561, __pyx_L4_error)
-      __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_3 = __Pyx_PyInt_From_uint64_t(__pyx_v_data_id); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 561, __pyx_L4_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_16 = NULL;
-      __pyx_t_8 = 0;
-      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-        __pyx_t_16 = PyMethod_GET_SELF(__pyx_t_2);
-        if (likely(__pyx_t_16)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-          __Pyx_INCREF(__pyx_t_16);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_2, function);
-          __pyx_t_8 = 1;
-        }
-      }
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_2)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_16, __pyx_t_3, Py_None};
-        __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 561, __pyx_L4_error)
-        __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_16, __pyx_t_3, Py_None};
-        __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_8, 2+__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 561, __pyx_L4_error)
-        __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      } else
-      #endif
-      {
-        __pyx_t_17 = PyTuple_New(2+__pyx_t_8); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 561, __pyx_L4_error)
-        __Pyx_GOTREF(__pyx_t_17);
-        if (__pyx_t_16) {
-          __Pyx_GIVEREF(__pyx_t_16); PyTuple_SET_ITEM(__pyx_t_17, 0, __pyx_t_16); __pyx_t_16 = NULL;
-        }
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_17, 0+__pyx_t_8, __pyx_t_3);
-        __Pyx_INCREF(Py_None);
-        __Pyx_GIVEREF(Py_None);
-        PyTuple_SET_ITEM(__pyx_t_17, 1+__pyx_t_8, Py_None);
-        __pyx_t_3 = 0;
-        __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_17, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 561, __pyx_L4_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
-      }
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_v_userdatas = __pyx_t_1;
-      __pyx_t_1 = 0;
-
-      /* "vidcutter/libs/pympv/mpv.pyx":562
- *             else:
- *                 userdatas = self.reply_userdata.get(data_id, None)
- *                 if userdatas is None:             # <<<<<<<<<<<<<<
- *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
- *                 userdatas.add()
- */
-      __pyx_t_6 = (__pyx_v_userdatas == Py_None);
-      __pyx_t_5 = (__pyx_t_6 != 0);
-      if (__pyx_t_5) {
+              mpv_free_node_contents((&__pyx_v_result));
+            }
 
-        /* "vidcutter/libs/pympv/mpv.pyx":563
- *                 userdatas = self.reply_userdata.get(data_id, None)
- *                 if userdatas is None:
- *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)             # <<<<<<<<<<<<<<
- *                 userdatas.add()
- *                 with nogil:
+            /* "vidcutter/libs/pympv/mpv.pyx":631
+ *             v = _convert_node_value(result)
+ *         finally:
+ *             with nogil:             # <<<<<<<<<<<<<<
+ *                 mpv_free_node_contents(&result)
+ *         return v
  */
-        __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_ReplyUserData); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 563, __pyx_L4_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        __pyx_t_17 = NULL;
-        if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-          __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_2);
-          if (likely(__pyx_t_17)) {
-            PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-            __Pyx_INCREF(__pyx_t_17);
-            __Pyx_INCREF(function);
-            __Pyx_DECREF_SET(__pyx_t_2, function);
-          }
+            /*finally:*/ {
+              /*normal exit:*/{
+                #ifdef WITH_THREAD
+                __Pyx_FastGIL_Forget();
+                Py_BLOCK_THREADS
+                #endif
+                goto __pyx_L17;
+              }
+              __pyx_L17:;
+            }
         }
-        __pyx_t_1 = (__pyx_t_17) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_17, __pyx_v_data) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_data);
-        __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
-        if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 563, __pyx_L4_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-        if (unlikely(__Pyx_SetItemInt(__pyx_v_9vidcutter_4libs_3mpv__reply_userdatas, __pyx_v_data_id, __pyx_t_1, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 563, __pyx_L4_error)
-        __Pyx_INCREF(__pyx_t_1);
-        __Pyx_DECREF_SET(__pyx_v_userdatas, __pyx_t_1);
-        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-        /* "vidcutter/libs/pympv/mpv.pyx":562
- *             else:
- *                 userdatas = self.reply_userdata.get(data_id, None)
- *                 if userdatas is None:             # <<<<<<<<<<<<<<
- *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
- *                 userdatas.add()
- */
       }
-
-      /* "vidcutter/libs/pympv/mpv.pyx":564
- *                 if userdatas is None:
- *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
- *                 userdatas.add()             # <<<<<<<<<<<<<<
- *                 with nogil:
- *                     err = mpv_command_node_async(self._ctx, data_id, &node)
- */
-      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdatas, __pyx_n_s_add); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 564, __pyx_L4_error)
-      __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_17 = NULL;
-      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-        __pyx_t_17 = PyMethod_GET_SELF(__pyx_t_2);
-        if (likely(__pyx_t_17)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-          __Pyx_INCREF(__pyx_t_17);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_2, function);
-        }
+      if (PY_MAJOR_VERSION >= 3) {
+        __Pyx_XGIVEREF(__pyx_t_13);
+        __Pyx_XGIVEREF(__pyx_t_14);
+        __Pyx_XGIVEREF(__pyx_t_15);
+        __Pyx_ExceptionReset(__pyx_t_13, __pyx_t_14, __pyx_t_15);
       }
-      __pyx_t_1 = (__pyx_t_17) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_17) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
-      __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
-      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 564, __pyx_L4_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __Pyx_XGIVEREF(__pyx_t_10);
+      __Pyx_XGIVEREF(__pyx_t_11);
+      __Pyx_XGIVEREF(__pyx_t_12);
+      __Pyx_ErrRestore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
+      __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0;
+      __pyx_lineno = __pyx_t_7; __pyx_clineno = __pyx_t_8; __pyx_filename = __pyx_t_9;
+      goto __pyx_L1_error;
+    }
+    __pyx_L9:;
+  }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":565
- *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
- *                 userdatas.add()
- *                 with nogil:             # <<<<<<<<<<<<<<
- *                     err = mpv_command_node_async(self._ctx, data_id, &node)
- *         finally:
+  /* "vidcutter/libs/pympv/mpv.pyx":633
+ *             with nogil:
+ *                 mpv_free_node_contents(&result)
+ *         return v             # <<<<<<<<<<<<<<
+ * 
+ *     @_errors
  */
-      {
-          #ifdef WITH_THREAD
-          PyThreadState *_save;
-          Py_UNBLOCK_THREADS
-          __Pyx_FastGIL_Remember();
-          #endif
-          /*try:*/ {
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_v);
+  __pyx_r = __pyx_v_v;
+  goto __pyx_L0;
 
-            /* "vidcutter/libs/pympv/mpv.pyx":566
- *                 userdatas.add()
- *                 with nogil:
- *                     err = mpv_command_node_async(self._ctx, data_id, &node)             # <<<<<<<<<<<<<<
- *         finally:
- *             self._free_native_value(node)
+  /* "vidcutter/libs/pympv/mpv.pyx":612
+ *             return default
+ * 
+ *     def get_property(self, prop):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_get_property"""
+ *         assert self._ctx
  */
-            __pyx_v_err = mpv_command_node_async(__pyx_v_self->_ctx, __pyx_v_data_id, (&__pyx_v_node));
-          }
 
-          /* "vidcutter/libs/pympv/mpv.pyx":565
- *                     _reply_userdatas[data_id] = userdatas = _ReplyUserData(data)
- *                 userdatas.add()
- *                 with nogil:             # <<<<<<<<<<<<<<
- *                     err = mpv_command_node_async(self._ctx, data_id, &node)
- *         finally:
- */
-          /*finally:*/ {
-            /*normal exit:*/{
-              #ifdef WITH_THREAD
-              __Pyx_FastGIL_Forget();
-              Py_BLOCK_THREADS
-              #endif
-              goto __pyx_L24;
-            }
-            __pyx_L24:;
-          }
-      }
-    }
-    __pyx_L6:;
-  }
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.get_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_v);
+  __Pyx_XDECREF(__pyx_v_prop);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-  /* "vidcutter/libs/pympv/mpv.pyx":568
- *                     err = mpv_command_node_async(self._ctx, data_id, &node)
- *         finally:
- *             self._free_native_value(node)             # <<<<<<<<<<<<<<
- *         if err < 0:
- *             raise MPVError(err)
- */
-  /*finally:*/ {
-    /*normal exit:*/{
-      __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 568, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L5;
-    }
-    __pyx_L4_error:;
-    /*exception exit:*/{
-      __Pyx_PyThreadState_declare
-      __Pyx_PyThreadState_assign
-      __pyx_t_15 = 0; __pyx_t_14 = 0; __pyx_t_13 = 0; __pyx_t_12 = 0; __pyx_t_11 = 0; __pyx_t_10 = 0;
-      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-      __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
-      __Pyx_XDECREF(__pyx_t_17); __pyx_t_17 = 0;
-      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_12, &__pyx_t_11, &__pyx_t_10);
-      if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_15, &__pyx_t_14, &__pyx_t_13) < 0)) __Pyx_ErrFetch(&__pyx_t_15, &__pyx_t_14, &__pyx_t_13);
-      __Pyx_XGOTREF(__pyx_t_15);
-      __Pyx_XGOTREF(__pyx_t_14);
-      __Pyx_XGOTREF(__pyx_t_13);
-      __Pyx_XGOTREF(__pyx_t_12);
-      __Pyx_XGOTREF(__pyx_t_11);
-      __Pyx_XGOTREF(__pyx_t_10);
-      __pyx_t_8 = __pyx_lineno; __pyx_t_7 = __pyx_clineno; __pyx_t_18 = __pyx_filename;
-      {
-        __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 568, __pyx_L26_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      }
-      if (PY_MAJOR_VERSION >= 3) {
-        __Pyx_XGIVEREF(__pyx_t_12);
-        __Pyx_XGIVEREF(__pyx_t_11);
-        __Pyx_XGIVEREF(__pyx_t_10);
-        __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_11, __pyx_t_10);
-      }
-      __Pyx_XGIVEREF(__pyx_t_15);
-      __Pyx_XGIVEREF(__pyx_t_14);
-      __Pyx_XGIVEREF(__pyx_t_13);
-      __Pyx_ErrRestore(__pyx_t_15, __pyx_t_14, __pyx_t_13);
-      __pyx_t_15 = 0; __pyx_t_14 = 0; __pyx_t_13 = 0; __pyx_t_12 = 0; __pyx_t_11 = 0; __pyx_t_10 = 0;
-      __pyx_lineno = __pyx_t_8; __pyx_clineno = __pyx_t_7; __pyx_filename = __pyx_t_18;
-      goto __pyx_L1_error;
-      __pyx_L26_error:;
-      if (PY_MAJOR_VERSION >= 3) {
-        __Pyx_XGIVEREF(__pyx_t_12);
-        __Pyx_XGIVEREF(__pyx_t_11);
-        __Pyx_XGIVEREF(__pyx_t_10);
-        __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_11, __pyx_t_10);
-      }
-      __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
-      __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
-      __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
-      __pyx_t_12 = 0; __pyx_t_11 = 0; __pyx_t_10 = 0;
-      goto __pyx_L1_error;
-    }
-    __pyx_L5:;
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":569
- *         finally:
- *             self._free_native_value(node)
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
- *         return result
- */
-  __pyx_t_5 = ((__pyx_v_err < 0) != 0);
-  if (unlikely(__pyx_t_5)) {
-
-    /* "vidcutter/libs/pympv/mpv.pyx":570
- *             self._free_native_value(node)
- *         if err < 0:
- *             raise MPVError(err)             # <<<<<<<<<<<<<<
- *         return result
- * 
- */
-    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 570, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_17 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 570, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_17);
-    __pyx_t_3 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
-      if (likely(__pyx_t_3)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_3);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_2, function);
-      }
-    }
-    __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_t_17) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_17);
-    __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_DECREF(__pyx_t_17); __pyx_t_17 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 570, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __PYX_ERR(0, 570, __pyx_L1_error)
-
-    /* "vidcutter/libs/pympv/mpv.pyx":569
- *         finally:
- *             self._free_native_value(node)
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
- *         return result
- */
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":571
- *         if err < 0:
- *             raise MPVError(err)
- *         return result             # <<<<<<<<<<<<<<
- * 
- *     @_errors
- */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_result);
-  __pyx_r = __pyx_v_result;
-  goto __pyx_L0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":530
- *             free(node.u.string)
- * 
- *     def command(self, *cmdlist, asynchronous=False, data=None):             # <<<<<<<<<<<<<<
- *         """Send a command to mpv.
- * 
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_16);
-  __Pyx_XDECREF(__pyx_t_17);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.command", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_result);
-  __Pyx_XDECREF(__pyx_v_userdatas);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "vidcutter/libs/pympv/mpv.pyx":574
- * 
- *     @_errors
- *     def get_property_async(self, prop, data=None):             # <<<<<<<<<<<<<<
- *         """Gets the value of a property asynchronously.
- * 
+/* "vidcutter/libs/pympv/mpv.pyx":636
+ * 
+ *     @_errors
+ *     def set_property(self, prop, value=True, asynchronous=False, data=None):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_set_property and mpv_set_property_async"""
+ *         assert self._ctx
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_15get_property_async(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_14get_property_async[] = "Gets the value of a property asynchronously.\n\n        Arguments:\n        prop: Property to get the value of.\n\n        Keyword arguments:\n        data: Value to be passed into the reply_userdata of the response event.\n        Wraps: mpv_get_property_async";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_15get_property_async(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_19set_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_18set_property[] = "Wraps: mpv_set_property and mpv_set_property_async";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_19set_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_prop = 0;
+  PyObject *__pyx_v_value = 0;
+  PyObject *__pyx_v_asynchronous = 0;
   PyObject *__pyx_v_data = 0;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("get_property_async (wrapper)", 0);
+  __Pyx_RefNannySetupContext("set_property (wrapper)", 0);
   {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_data,0};
-    PyObject* values[2] = {0,0};
-    values[1] = ((PyObject *)Py_None);
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_value,&__pyx_n_s_asynchronous,&__pyx_n_s_data,0};
+    PyObject* values[4] = {0,0,0,0};
+    values[1] = ((PyObject *)Py_True);
+    values[2] = ((PyObject *)Py_False);
+    values[3] = ((PyObject *)Py_None);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
       switch (pos_args) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        CYTHON_FALLTHROUGH;
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        CYTHON_FALLTHROUGH;
         case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
         CYTHON_FALLTHROUGH;
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
@@ -11875,15 +12258,31 @@ static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_15get_property_async(Py
         CYTHON_FALLTHROUGH;
         case  1:
         if (kw_args > 0) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data);
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_value);
           if (value) { values[1] = value; kw_args--; }
         }
+        CYTHON_FALLTHROUGH;
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_asynchronous);
+          if (value) { values[2] = value; kw_args--; }
+        }
+        CYTHON_FALLTHROUGH;
+        case  3:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data);
+          if (value) { values[3] = value; kw_args--; }
+        }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "get_property_async") < 0)) __PYX_ERR(0, 574, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_property") < 0)) __PYX_ERR(0, 636, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        CYTHON_FALLTHROUGH;
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        CYTHON_FALLTHROUGH;
         case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
         CYTHON_FALLTHROUGH;
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
@@ -11892,70 +12291,83 @@ static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_15get_property_async(Py
       }
     }
     __pyx_v_prop = values[0];
-    __pyx_v_data = values[1];
+    __pyx_v_value = values[1];
+    __pyx_v_asynchronous = values[2];
+    __pyx_v_data = values[3];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("get_property_async", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 574, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("set_property", 0, 1, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 636, __pyx_L3_error)
   __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.get_property_async", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_14get_property_async(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_data);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_18set_property(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_value, __pyx_v_asynchronous, __pyx_v_data);
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_14get_property_async(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data) {
-  uint64_t __pyx_v_id_data;
-  PyObject *__pyx_v_userdatas = NULL;
-  char const *__pyx_v_prop_c;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_18set_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_value, PyObject *__pyx_v_asynchronous, PyObject *__pyx_v_data) {
+  enum mpv_format __pyx_v_format;
+  struct mpv_node __pyx_v_v;
   int __pyx_v_err;
+  uint64_t __pyx_v_data_id;
+  char const *__pyx_v_prop_c;
+  PyObject *__pyx_v_userdatas = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  Py_hash_t __pyx_t_4;
-  PyObject *__pyx_t_5 = NULL;
+  enum mpv_format __pyx_t_4;
+  char const *__pyx_t_5;
   int __pyx_t_6;
-  PyObject *__pyx_t_7 = NULL;
-  int __pyx_t_8;
-  int __pyx_t_9;
-  char const *__pyx_t_10;
+  int __pyx_t_7;
+  Py_hash_t __pyx_t_8;
+  PyObject *__pyx_t_9 = NULL;
+  int __pyx_t_10;
+  PyObject *__pyx_t_11 = NULL;
+  int __pyx_t_12;
+  char const *__pyx_t_13;
+  PyObject *__pyx_t_14 = NULL;
+  PyObject *__pyx_t_15 = NULL;
+  PyObject *__pyx_t_16 = NULL;
+  PyObject *__pyx_t_17 = NULL;
+  PyObject *__pyx_t_18 = NULL;
+  PyObject *__pyx_t_19 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("get_property_async", 0);
+  __Pyx_RefNannySetupContext("set_property", 0);
   __Pyx_INCREF(__pyx_v_prop);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":583
- *         data: Value to be passed into the reply_userdata of the response event.
- *         Wraps: mpv_get_property_async"""
+  /* "vidcutter/libs/pympv/mpv.pyx":638
+ *     def set_property(self, prop, value=True, asynchronous=False, data=None):
+ *         """Wraps: mpv_set_property and mpv_set_property_async"""
  *         assert self._ctx             # <<<<<<<<<<<<<<
  *         prop = _strenc(prop)
- *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         cdef mpv_format format = self._format_for(value)
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
   if (unlikely(!Py_OptimizeFlag)) {
     if (unlikely(!(__pyx_v_self->_ctx != 0))) {
       PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 583, __pyx_L1_error)
+      __PYX_ERR(0, 638, __pyx_L1_error)
     }
   }
   #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":584
- *         Wraps: mpv_get_property_async"""
+  /* "vidcutter/libs/pympv/mpv.pyx":639
+ *         """Wraps: mpv_set_property and mpv_set_property_async"""
  *         assert self._ctx
  *         prop = _strenc(prop)             # <<<<<<<<<<<<<<
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)
+ *         cdef mpv_format format = self._format_for(value)
+ *         cdef mpv_node v = self._prep_native_value(value, format)
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 584, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 639, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_t_3 = NULL;
   if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
@@ -11969,523 +12381,480 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_14get_property_async(st
   }
   __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_prop) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_prop);
   __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 584, __pyx_L1_error)
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 639, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF_SET(__pyx_v_prop, __pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":585
+  /* "vidcutter/libs/pympv/mpv.pyx":640
  *         assert self._ctx
  *         prop = _strenc(prop)
- *         cdef uint64_t id_data = <uint64_t>hash(data)             # <<<<<<<<<<<<<<
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is None:
- */
-  __pyx_t_4 = PyObject_Hash(__pyx_v_data); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 585, __pyx_L1_error)
-  __pyx_v_id_data = ((uint64_t)__pyx_t_4);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":586
- *         prop = _strenc(prop)
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)             # <<<<<<<<<<<<<<
- *         if userdatas is None:
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+ *         cdef mpv_format format = self._format_for(value)             # <<<<<<<<<<<<<<
+ *         cdef mpv_node v = self._prep_native_value(value, format)
+ *         cdef int err
  */
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->reply_userdata, __pyx_n_s_get); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 586, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_format_for); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 640, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyInt_From_uint64_t(__pyx_v_id_data); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 586, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_5 = NULL;
-  __pyx_t_6 = 0;
+  __pyx_t_3 = NULL;
   if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_5)) {
+    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_3)) {
       PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(__pyx_t_3);
       __Pyx_INCREF(function);
       __Pyx_DECREF_SET(__pyx_t_2, function);
-      __pyx_t_6 = 1;
-    }
-  }
-  #if CYTHON_FAST_PYCALL
-  if (PyFunction_Check(__pyx_t_2)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, Py_None};
-    __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 586, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  } else
-  #endif
-  #if CYTHON_FAST_PYCCALL
-  if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_3, Py_None};
-    __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 586, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  } else
-  #endif
-  {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 586, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    if (__pyx_t_5) {
-      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
     }
-    __Pyx_GIVEREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_t_3);
-    __Pyx_INCREF(Py_None);
-    __Pyx_GIVEREF(Py_None);
-    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, Py_None);
-    __pyx_t_3 = 0;
-    __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_7, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 586, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
   }
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_value) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_value);
+  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 640, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_v_userdatas = __pyx_t_1;
-  __pyx_t_1 = 0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":587
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is None:             # <<<<<<<<<<<<<<
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
- *         userdatas.add()
- */
-  __pyx_t_8 = (__pyx_v_userdatas == Py_None);
-  __pyx_t_9 = (__pyx_t_8 != 0);
-  if (__pyx_t_9) {
-
-    /* "vidcutter/libs/pympv/mpv.pyx":588
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is None:
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)             # <<<<<<<<<<<<<<
- *         userdatas.add()
- *         cdef const char* prop_c = prop
- */
-    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_ReplyUserData); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 588, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_7 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_2);
-      if (likely(__pyx_t_7)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_7);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_2, function);
-      }
-    }
-    __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_7, __pyx_v_data) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_data);
-    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 588, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    if (unlikely(__Pyx_SetItemInt(__pyx_v_self->reply_userdata, __pyx_v_id_data, __pyx_t_1, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 588, __pyx_L1_error)
-    __Pyx_INCREF(__pyx_t_1);
-    __Pyx_DECREF_SET(__pyx_v_userdatas, __pyx_t_1);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":587
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is None:             # <<<<<<<<<<<<<<
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
- *         userdatas.add()
- */
-  }
+  __pyx_t_4 = ((enum mpv_format)__Pyx_PyInt_As_enum__mpv_format(__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 640, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_format = __pyx_t_4;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":589
- *         if userdatas is None:
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
- *         userdatas.add()             # <<<<<<<<<<<<<<
- *         cdef const char* prop_c = prop
- *         with nogil:
+  /* "vidcutter/libs/pympv/mpv.pyx":641
+ *         prop = _strenc(prop)
+ *         cdef mpv_format format = self._format_for(value)
+ *         cdef mpv_node v = self._prep_native_value(value, format)             # <<<<<<<<<<<<<<
+ *         cdef int err
+ *         cdef uint64_t data_id
  */
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdatas, __pyx_n_s_add); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 589, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_7 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_7)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_7);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 589, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_enum__mpv_format(__pyx_v_format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 641, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_v_v = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_native_value(__pyx_v_self, __pyx_v_value, __pyx_t_1);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":590
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
- *         userdatas.add()
- *         cdef const char* prop_c = prop             # <<<<<<<<<<<<<<
- *         with nogil:
- *             err = mpv_get_property_async(
+  /* "vidcutter/libs/pympv/mpv.pyx":645
+ *         cdef uint64_t data_id
+ *         cdef const char* prop_c
+ *         try:             # <<<<<<<<<<<<<<
+ *             prop_c = prop
+ *             if not asynchronous:
  */
-  __pyx_t_10 = __Pyx_PyObject_AsString(__pyx_v_prop); if (unlikely((!__pyx_t_10) && PyErr_Occurred())) __PYX_ERR(0, 590, __pyx_L1_error)
-  __pyx_v_prop_c = __pyx_t_10;
+  /*try:*/ {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":591
- *         userdatas.add()
- *         cdef const char* prop_c = prop
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_get_property_async(
- *                 self._ctx,
+    /* "vidcutter/libs/pympv/mpv.pyx":646
+ *         cdef const char* prop_c
+ *         try:
+ *             prop_c = prop             # <<<<<<<<<<<<<<
+ *             if not asynchronous:
+ *                 with nogil:
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+    __pyx_t_5 = __Pyx_PyObject_AsString(__pyx_v_prop); if (unlikely((!__pyx_t_5) && PyErr_Occurred())) __PYX_ERR(0, 646, __pyx_L4_error)
+    __pyx_v_prop_c = __pyx_t_5;
 
-        /* "vidcutter/libs/pympv/mpv.pyx":592
- *         cdef const char* prop_c = prop
- *         with nogil:
- *             err = mpv_get_property_async(             # <<<<<<<<<<<<<<
- *                 self._ctx,
- *                 id_data,
+    /* "vidcutter/libs/pympv/mpv.pyx":647
+ *         try:
+ *             prop_c = prop
+ *             if not asynchronous:             # <<<<<<<<<<<<<<
+ *                 with nogil:
+ *                     err = mpv_set_property(
  */
-        __pyx_v_err = mpv_get_property_async(__pyx_v_self->_ctx, __pyx_v_id_data, __pyx_v_prop_c, MPV_FORMAT_NODE);
-      }
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_asynchronous); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 647, __pyx_L4_error)
+    __pyx_t_7 = ((!__pyx_t_6) != 0);
+    if (__pyx_t_7) {
 
-      /* "vidcutter/libs/pympv/mpv.pyx":591
- *         userdatas.add()
- *         cdef const char* prop_c = prop
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_get_property_async(
- *                 self._ctx,
+      /* "vidcutter/libs/pympv/mpv.pyx":648
+ *             prop_c = prop
+ *             if not asynchronous:
+ *                 with nogil:             # <<<<<<<<<<<<<<
+ *                     err = mpv_set_property(
+ *                         self._ctx,
  */
-      /*finally:*/ {
-        /*normal exit:*/{
+      {
           #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
+          PyThreadState *_save;
+          Py_UNBLOCK_THREADS
+          __Pyx_FastGIL_Remember();
           #endif
-          goto __pyx_L6;
-        }
-        __pyx_L6:;
-      }
-  }
+          /*try:*/ {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":598
- *                 MPV_FORMAT_NODE,
- *             )
- *         return err             # <<<<<<<<<<<<<<
- * 
- *     def try_get_property_async(self, prop, data=None, default=None):
+            /* "vidcutter/libs/pympv/mpv.pyx":649
+ *             if not asynchronous:
+ *                 with nogil:
+ *                     err = mpv_set_property(             # <<<<<<<<<<<<<<
+ *                         self._ctx,
+ *                         prop_c,
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 598, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
+            __pyx_v_err = mpv_set_property(__pyx_v_self->_ctx, __pyx_v_prop_c, MPV_FORMAT_NODE, (&__pyx_v_v));
+          }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":574
- * 
- *     @_errors
- *     def get_property_async(self, prop, data=None):             # <<<<<<<<<<<<<<
- *         """Gets the value of a property asynchronously.
- * 
+          /* "vidcutter/libs/pympv/mpv.pyx":648
+ *             prop_c = prop
+ *             if not asynchronous:
+ *                 with nogil:             # <<<<<<<<<<<<<<
+ *                     err = mpv_set_property(
+ *                         self._ctx,
  */
+          /*finally:*/ {
+            /*normal exit:*/{
+              #ifdef WITH_THREAD
+              __Pyx_FastGIL_Forget();
+              Py_BLOCK_THREADS
+              #endif
+              goto __pyx_L9;
+            }
+            __pyx_L9:;
+          }
+      }
 
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.get_property_async", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_userdatas);
-  __Pyx_XDECREF(__pyx_v_prop);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+      /* "vidcutter/libs/pympv/mpv.pyx":655
+ *                         &v
+ *                     )
+ *                 return err             # <<<<<<<<<<<<<<
+ *             data_id = <uint64_t>hash(data)
+ *             userdatas = self.reply_userdata.get(data_id, None)
+ */
+      __Pyx_XDECREF(__pyx_r);
+      __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 655, __pyx_L4_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_r = __pyx_t_1;
+      __pyx_t_1 = 0;
+      goto __pyx_L3_return;
 
-/* "vidcutter/libs/pympv/mpv.pyx":600
- *         return err
- * 
- *     def try_get_property_async(self, prop, data=None, default=None):             # <<<<<<<<<<<<<<
+      /* "vidcutter/libs/pympv/mpv.pyx":647
  *         try:
- *             return self.get_property_async(prop, data=data)
+ *             prop_c = prop
+ *             if not asynchronous:             # <<<<<<<<<<<<<<
+ *                 with nogil:
+ *                     err = mpv_set_property(
  */
+    }
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_17try_get_property_async(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_17try_get_property_async(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_prop = 0;
-  PyObject *__pyx_v_data = 0;
-  PyObject *__pyx_v_default = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("try_get_property_async (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_data,&__pyx_n_s_default,0};
-    PyObject* values[3] = {0,0,0};
-    values[1] = ((PyObject *)Py_None);
-    values[2] = ((PyObject *)Py_None);
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_prop)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (kw_args > 0) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data);
-          if (value) { values[1] = value; kw_args--; }
-        }
-        CYTHON_FALLTHROUGH;
-        case  2:
-        if (kw_args > 0) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_default);
-          if (value) { values[2] = value; kw_args--; }
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "try_get_property_async") < 0)) __PYX_ERR(0, 600, __pyx_L3_error)
+    /* "vidcutter/libs/pympv/mpv.pyx":656
+ *                     )
+ *                 return err
+ *             data_id = <uint64_t>hash(data)             # <<<<<<<<<<<<<<
+ *             userdatas = self.reply_userdata.get(data_id, None)
+ *             if userdatas is None:
+ */
+    __pyx_t_8 = PyObject_Hash(__pyx_v_data); if (unlikely(__pyx_t_8 == ((Py_hash_t)-1))) __PYX_ERR(0, 656, __pyx_L4_error)
+    __pyx_v_data_id = ((uint64_t)__pyx_t_8);
+
+    /* "vidcutter/libs/pympv/mpv.pyx":657
+ *                 return err
+ *             data_id = <uint64_t>hash(data)
+ *             userdatas = self.reply_userdata.get(data_id, None)             # <<<<<<<<<<<<<<
+ *             if userdatas is None:
+ *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
+ */
+    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->reply_userdata, __pyx_n_s_get); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 657, __pyx_L4_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_3 = __Pyx_PyInt_From_uint64_t(__pyx_v_data_id); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 657, __pyx_L4_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_9 = NULL;
+    __pyx_t_10 = 0;
+    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_9)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_9);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+        __pyx_t_10 = 1;
       }
-    } else {
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
-        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        break;
-        default: goto __pyx_L5_argtuple_error;
+    }
+    #if CYTHON_FAST_PYCALL
+    if (PyFunction_Check(__pyx_t_2)) {
+      PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_3, Py_None};
+      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 657, __pyx_L4_error)
+      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    } else
+    #endif
+    #if CYTHON_FAST_PYCCALL
+    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
+      PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_3, Py_None};
+      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 657, __pyx_L4_error)
+      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    } else
+    #endif
+    {
+      __pyx_t_11 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 657, __pyx_L4_error)
+      __Pyx_GOTREF(__pyx_t_11);
+      if (__pyx_t_9) {
+        __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_9); __pyx_t_9 = NULL;
       }
+      __Pyx_GIVEREF(__pyx_t_3);
+      PyTuple_SET_ITEM(__pyx_t_11, 0+__pyx_t_10, __pyx_t_3);
+      __Pyx_INCREF(Py_None);
+      __Pyx_GIVEREF(Py_None);
+      PyTuple_SET_ITEM(__pyx_t_11, 1+__pyx_t_10, Py_None);
+      __pyx_t_3 = 0;
+      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 657, __pyx_L4_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
     }
-    __pyx_v_prop = values[0];
-    __pyx_v_data = values[1];
-    __pyx_v_default = values[2];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("try_get_property_async", 0, 1, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 600, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property_async", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_16try_get_property_async(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_data, __pyx_v_default);
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_v_userdatas = __pyx_t_1;
+    __pyx_t_1 = 0;
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_16try_get_property_async(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data, PyObject *__pyx_v_default) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  PyObject *__pyx_t_7 = NULL;
-  int __pyx_t_8;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("try_get_property_async", 0);
+    /* "vidcutter/libs/pympv/mpv.pyx":658
+ *             data_id = <uint64_t>hash(data)
+ *             userdatas = self.reply_userdata.get(data_id, None)
+ *             if userdatas is None:             # <<<<<<<<<<<<<<
+ *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
+ *             userdatas.add()
+ */
+    __pyx_t_7 = (__pyx_v_userdatas == Py_None);
+    __pyx_t_6 = (__pyx_t_7 != 0);
+    if (__pyx_t_6) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":601
- * 
- *     def try_get_property_async(self, prop, data=None, default=None):
- *         try:             # <<<<<<<<<<<<<<
- *             return self.get_property_async(prop, data=data)
- *         except MPVError:
+      /* "vidcutter/libs/pympv/mpv.pyx":659
+ *             userdatas = self.reply_userdata.get(data_id, None)
+ *             if userdatas is None:
+ *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)             # <<<<<<<<<<<<<<
+ *             userdatas.add()
+ *             with nogil:
  */
-  {
-    __Pyx_PyThreadState_declare
-    __Pyx_PyThreadState_assign
-    __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3);
-    __Pyx_XGOTREF(__pyx_t_1);
-    __Pyx_XGOTREF(__pyx_t_2);
-    __Pyx_XGOTREF(__pyx_t_3);
-    /*try:*/ {
+      __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_ReplyUserData); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 659, __pyx_L4_error)
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_11 = NULL;
+      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+        __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_2);
+        if (likely(__pyx_t_11)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+          __Pyx_INCREF(__pyx_t_11);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_2, function);
+        }
+      }
+      __pyx_t_1 = (__pyx_t_11) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_11, __pyx_v_data) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_data);
+      __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
+      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 659, __pyx_L4_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      if (unlikely(__Pyx_SetItemInt(__pyx_v_self->reply_userdata, __pyx_v_data_id, __pyx_t_1, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 659, __pyx_L4_error)
+      __Pyx_INCREF(__pyx_t_1);
+      __Pyx_DECREF_SET(__pyx_v_userdatas, __pyx_t_1);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-      /* "vidcutter/libs/pympv/mpv.pyx":602
- *     def try_get_property_async(self, prop, data=None, default=None):
- *         try:
- *             return self.get_property_async(prop, data=data)             # <<<<<<<<<<<<<<
- *         except MPVError:
- *             return default
+      /* "vidcutter/libs/pympv/mpv.pyx":658
+ *             data_id = <uint64_t>hash(data)
+ *             userdatas = self.reply_userdata.get(data_id, None)
+ *             if userdatas is None:             # <<<<<<<<<<<<<<
+ *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
+ *             userdatas.add()
  */
-      __Pyx_XDECREF(__pyx_r);
-      __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_property_async); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 602, __pyx_L3_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 602, __pyx_L3_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_INCREF(__pyx_v_prop);
-      __Pyx_GIVEREF(__pyx_v_prop);
-      PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_v_prop);
-      __pyx_t_6 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 602, __pyx_L3_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      if (PyDict_SetItem(__pyx_t_6, __pyx_n_s_data, __pyx_v_data) < 0) __PYX_ERR(0, 602, __pyx_L3_error)
-      __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_4, __pyx_t_5, __pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 602, __pyx_L3_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __pyx_r = __pyx_t_7;
-      __pyx_t_7 = 0;
-      goto __pyx_L7_try_return;
+    }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":601
- * 
- *     def try_get_property_async(self, prop, data=None, default=None):
- *         try:             # <<<<<<<<<<<<<<
- *             return self.get_property_async(prop, data=data)
- *         except MPVError:
+    /* "vidcutter/libs/pympv/mpv.pyx":660
+ *             if userdatas is None:
+ *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
+ *             userdatas.add()             # <<<<<<<<<<<<<<
+ *             with nogil:
+ *                 err = mpv_set_property_async(
  */
+    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdatas, __pyx_n_s_add); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 660, __pyx_L4_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_11 = NULL;
+    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+      __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_2);
+      if (likely(__pyx_t_11)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_11);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_2, function);
+      }
     }
-    __pyx_L3_error:;
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __pyx_t_1 = (__pyx_t_11) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_11) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
+    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 660, __pyx_L4_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":603
- *         try:
- *             return self.get_property_async(prop, data=data)
- *         except MPVError:             # <<<<<<<<<<<<<<
- *             return default
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":661
+ *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
+ *             userdatas.add()
+ *             with nogil:             # <<<<<<<<<<<<<<
+ *                 err = mpv_set_property_async(
+ *                     self._ctx,
  */
-    __Pyx_ErrFetch(&__pyx_t_7, &__pyx_t_6, &__pyx_t_5);
-    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 603, __pyx_L5_except_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_8 = __Pyx_PyErr_GivenExceptionMatches(__pyx_t_7, __pyx_t_4);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_ErrRestore(__pyx_t_7, __pyx_t_6, __pyx_t_5);
-    __pyx_t_7 = 0; __pyx_t_6 = 0; __pyx_t_5 = 0;
-    if (__pyx_t_8) {
-      __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property_async", __pyx_clineno, __pyx_lineno, __pyx_filename);
-      if (__Pyx_GetException(&__pyx_t_5, &__pyx_t_6, &__pyx_t_7) < 0) __PYX_ERR(0, 603, __pyx_L5_except_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_GOTREF(__pyx_t_6);
-      __Pyx_GOTREF(__pyx_t_7);
+    {
+        #ifdef WITH_THREAD
+        PyThreadState *_save;
+        Py_UNBLOCK_THREADS
+        __Pyx_FastGIL_Remember();
+        #endif
+        /*try:*/ {
 
-      /* "vidcutter/libs/pympv/mpv.pyx":604
- *             return self.get_property_async(prop, data=data)
- *         except MPVError:
- *             return default             # <<<<<<<<<<<<<<
- * 
- *     def try_get_property(self, prop, default=None):
+          /* "vidcutter/libs/pympv/mpv.pyx":662
+ *             userdatas.add()
+ *             with nogil:
+ *                 err = mpv_set_property_async(             # <<<<<<<<<<<<<<
+ *                     self._ctx,
+ *                     data_id,
  */
-      __Pyx_XDECREF(__pyx_r);
-      __Pyx_INCREF(__pyx_v_default);
-      __pyx_r = __pyx_v_default;
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      goto __pyx_L6_except_return;
+          __pyx_v_err = mpv_set_property_async(__pyx_v_self->_ctx, __pyx_v_data_id, __pyx_v_prop_c, MPV_FORMAT_NODE, (&__pyx_v_v));
+        }
+
+        /* "vidcutter/libs/pympv/mpv.pyx":661
+ *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
+ *             userdatas.add()
+ *             with nogil:             # <<<<<<<<<<<<<<
+ *                 err = mpv_set_property_async(
+ *                     self._ctx,
+ */
+        /*finally:*/ {
+          /*normal exit:*/{
+            #ifdef WITH_THREAD
+            __Pyx_FastGIL_Forget();
+            Py_BLOCK_THREADS
+            #endif
+            goto __pyx_L13;
+          }
+          __pyx_L13:;
+        }
     }
-    goto __pyx_L5_except_error;
-    __pyx_L5_except_error:;
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":601
+  /* "vidcutter/libs/pympv/mpv.pyx":670
+ *                 )
+ *         finally:
+ *             self._free_native_value(v)             # <<<<<<<<<<<<<<
+ *         return err
  * 
- *     def try_get_property_async(self, prop, data=None, default=None):
- *         try:             # <<<<<<<<<<<<<<
- *             return self.get_property_async(prop, data=data)
- *         except MPVError:
  */
-    __Pyx_XGIVEREF(__pyx_t_1);
-    __Pyx_XGIVEREF(__pyx_t_2);
-    __Pyx_XGIVEREF(__pyx_t_3);
-    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
-    goto __pyx_L1_error;
-    __pyx_L7_try_return:;
-    __Pyx_XGIVEREF(__pyx_t_1);
-    __Pyx_XGIVEREF(__pyx_t_2);
-    __Pyx_XGIVEREF(__pyx_t_3);
-    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
-    goto __pyx_L0;
-    __pyx_L6_except_return:;
-    __Pyx_XGIVEREF(__pyx_t_1);
-    __Pyx_XGIVEREF(__pyx_t_2);
-    __Pyx_XGIVEREF(__pyx_t_3);
-    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
-    goto __pyx_L0;
+  /*finally:*/ {
+    /*normal exit:*/{
+      __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 670, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      goto __pyx_L5;
+    }
+    __pyx_L4_error:;
+    /*exception exit:*/{
+      __Pyx_PyThreadState_declare
+      __Pyx_PyThreadState_assign
+      __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; __pyx_t_18 = 0; __pyx_t_19 = 0;
+      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
+      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
+      if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_17, &__pyx_t_18, &__pyx_t_19);
+      if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16) < 0)) __Pyx_ErrFetch(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16);
+      __Pyx_XGOTREF(__pyx_t_14);
+      __Pyx_XGOTREF(__pyx_t_15);
+      __Pyx_XGOTREF(__pyx_t_16);
+      __Pyx_XGOTREF(__pyx_t_17);
+      __Pyx_XGOTREF(__pyx_t_18);
+      __Pyx_XGOTREF(__pyx_t_19);
+      __pyx_t_10 = __pyx_lineno; __pyx_t_12 = __pyx_clineno; __pyx_t_13 = __pyx_filename;
+      {
+        __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 670, __pyx_L15_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      }
+      if (PY_MAJOR_VERSION >= 3) {
+        __Pyx_XGIVEREF(__pyx_t_17);
+        __Pyx_XGIVEREF(__pyx_t_18);
+        __Pyx_XGIVEREF(__pyx_t_19);
+        __Pyx_ExceptionReset(__pyx_t_17, __pyx_t_18, __pyx_t_19);
+      }
+      __Pyx_XGIVEREF(__pyx_t_14);
+      __Pyx_XGIVEREF(__pyx_t_15);
+      __Pyx_XGIVEREF(__pyx_t_16);
+      __Pyx_ErrRestore(__pyx_t_14, __pyx_t_15, __pyx_t_16);
+      __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; __pyx_t_18 = 0; __pyx_t_19 = 0;
+      __pyx_lineno = __pyx_t_10; __pyx_clineno = __pyx_t_12; __pyx_filename = __pyx_t_13;
+      goto __pyx_L1_error;
+      __pyx_L15_error:;
+      if (PY_MAJOR_VERSION >= 3) {
+        __Pyx_XGIVEREF(__pyx_t_17);
+        __Pyx_XGIVEREF(__pyx_t_18);
+        __Pyx_XGIVEREF(__pyx_t_19);
+        __Pyx_ExceptionReset(__pyx_t_17, __pyx_t_18, __pyx_t_19);
+      }
+      __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
+      __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
+      __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
+      __pyx_t_17 = 0; __pyx_t_18 = 0; __pyx_t_19 = 0;
+      goto __pyx_L1_error;
+    }
+    __pyx_L3_return: {
+      __pyx_t_19 = __pyx_r;
+      __pyx_r = 0;
+      __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 670, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __pyx_r = __pyx_t_19;
+      __pyx_t_19 = 0;
+      goto __pyx_L0;
+    }
+    __pyx_L5:;
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":600
- *         return err
+  /* "vidcutter/libs/pympv/mpv.pyx":671
+ *         finally:
+ *             self._free_native_value(v)
+ *         return err             # <<<<<<<<<<<<<<
  * 
- *     def try_get_property_async(self, prop, data=None, default=None):             # <<<<<<<<<<<<<<
- *         try:
- *             return self.get_property_async(prop, data=data)
+ *     @_errors
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 671, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":636
+ * 
+ *     @_errors
+ *     def set_property(self, prop, value=True, asynchronous=False, data=None):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_set_property and mpv_set_property_async"""
+ *         assert self._ctx
  */
 
   /* function exit code */
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property_async", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_9);
+  __Pyx_XDECREF(__pyx_t_11);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_XDECREF(__pyx_v_userdatas);
+  __Pyx_XDECREF(__pyx_v_prop);
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":606
- *             return default
+/* "vidcutter/libs/pympv/mpv.pyx":674
  * 
- *     def try_get_property(self, prop, default=None):             # <<<<<<<<<<<<<<
- *         try:
- *             return self.get_property(prop)
+ *     @_errors
+ *     def set_option(self, prop, value=True):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_set_option"""
+ *         assert self._ctx
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_19try_get_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_19try_get_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_21set_option(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_20set_option[] = "Wraps: mpv_set_option";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_21set_option(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_prop = 0;
-  PyObject *__pyx_v_default = 0;
+  PyObject *__pyx_v_value = 0;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("try_get_property (wrapper)", 0);
+  __Pyx_RefNannySetupContext("set_option (wrapper)", 0);
   {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_default,0};
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_value,0};
     PyObject* values[2] = {0,0};
-    values[1] = ((PyObject *)Py_None);
+    values[1] = ((PyObject *)Py_True);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
@@ -12505,12 +12874,12 @@ static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_19try_get_property(PyOb
         CYTHON_FALLTHROUGH;
         case  1:
         if (kw_args > 0) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_default);
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_value);
           if (value) { values[1] = value; kw_args--; }
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "try_get_property") < 0)) __PYX_ERR(0, 606, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_option") < 0)) __PYX_ERR(0, 674, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -12522,258 +12891,74 @@ static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_19try_get_property(PyOb
       }
     }
     __pyx_v_prop = values[0];
-    __pyx_v_default = values[1];
+    __pyx_v_value = values[1];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("try_get_property", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 606, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("set_option", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 674, __pyx_L3_error)
   __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_option", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_18try_get_property(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_default);
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_18try_get_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_default) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  PyObject *__pyx_t_7 = NULL;
-  int __pyx_t_8;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("try_get_property", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":607
- * 
- *     def try_get_property(self, prop, default=None):
- *         try:             # <<<<<<<<<<<<<<
- *             return self.get_property(prop)
- *         except MPVError:
- */
-  {
-    __Pyx_PyThreadState_declare
-    __Pyx_PyThreadState_assign
-    __Pyx_ExceptionSave(&__pyx_t_1, &__pyx_t_2, &__pyx_t_3);
-    __Pyx_XGOTREF(__pyx_t_1);
-    __Pyx_XGOTREF(__pyx_t_2);
-    __Pyx_XGOTREF(__pyx_t_3);
-    /*try:*/ {
-
-      /* "vidcutter/libs/pympv/mpv.pyx":608
- *     def try_get_property(self, prop, default=None):
- *         try:
- *             return self.get_property(prop)             # <<<<<<<<<<<<<<
- *         except MPVError:
- *             return default
- */
-      __Pyx_XDECREF(__pyx_r);
-      __pyx_t_5 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_get_property); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 608, __pyx_L3_error)
-      __Pyx_GOTREF(__pyx_t_5);
-      __pyx_t_6 = NULL;
-      if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
-        __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_5);
-        if (likely(__pyx_t_6)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-          __Pyx_INCREF(__pyx_t_6);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_5, function);
-        }
-      }
-      __pyx_t_4 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_5, __pyx_t_6, __pyx_v_prop) : __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_v_prop);
-      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-      if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 608, __pyx_L3_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __pyx_r = __pyx_t_4;
-      __pyx_t_4 = 0;
-      goto __pyx_L7_try_return;
-
-      /* "vidcutter/libs/pympv/mpv.pyx":607
- * 
- *     def try_get_property(self, prop, default=None):
- *         try:             # <<<<<<<<<<<<<<
- *             return self.get_property(prop)
- *         except MPVError:
- */
-    }
-    __pyx_L3_error:;
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":609
- *         try:
- *             return self.get_property(prop)
- *         except MPVError:             # <<<<<<<<<<<<<<
- *             return default
- * 
- */
-    __Pyx_ErrFetch(&__pyx_t_4, &__pyx_t_5, &__pyx_t_6);
-    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 609, __pyx_L5_except_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_8 = __Pyx_PyErr_GivenExceptionMatches(__pyx_t_4, __pyx_t_7);
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __Pyx_ErrRestore(__pyx_t_4, __pyx_t_5, __pyx_t_6);
-    __pyx_t_4 = 0; __pyx_t_5 = 0; __pyx_t_6 = 0;
-    if (__pyx_t_8) {
-      __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
-      if (__Pyx_GetException(&__pyx_t_6, &__pyx_t_5, &__pyx_t_4) < 0) __PYX_ERR(0, 609, __pyx_L5_except_error)
-      __Pyx_GOTREF(__pyx_t_6);
-      __Pyx_GOTREF(__pyx_t_5);
-      __Pyx_GOTREF(__pyx_t_4);
-
-      /* "vidcutter/libs/pympv/mpv.pyx":610
- *             return self.get_property(prop)
- *         except MPVError:
- *             return default             # <<<<<<<<<<<<<<
- * 
- *     def get_property(self, prop):
- */
-      __Pyx_XDECREF(__pyx_r);
-      __Pyx_INCREF(__pyx_v_default);
-      __pyx_r = __pyx_v_default;
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
-      goto __pyx_L6_except_return;
-    }
-    goto __pyx_L5_except_error;
-    __pyx_L5_except_error:;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":607
- * 
- *     def try_get_property(self, prop, default=None):
- *         try:             # <<<<<<<<<<<<<<
- *             return self.get_property(prop)
- *         except MPVError:
- */
-    __Pyx_XGIVEREF(__pyx_t_1);
-    __Pyx_XGIVEREF(__pyx_t_2);
-    __Pyx_XGIVEREF(__pyx_t_3);
-    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
-    goto __pyx_L1_error;
-    __pyx_L7_try_return:;
-    __Pyx_XGIVEREF(__pyx_t_1);
-    __Pyx_XGIVEREF(__pyx_t_2);
-    __Pyx_XGIVEREF(__pyx_t_3);
-    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
-    goto __pyx_L0;
-    __pyx_L6_except_return:;
-    __Pyx_XGIVEREF(__pyx_t_1);
-    __Pyx_XGIVEREF(__pyx_t_2);
-    __Pyx_XGIVEREF(__pyx_t_3);
-    __Pyx_ExceptionReset(__pyx_t_1, __pyx_t_2, __pyx_t_3);
-    goto __pyx_L0;
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":606
- *             return default
- * 
- *     def try_get_property(self, prop, default=None):             # <<<<<<<<<<<<<<
- *         try:
- *             return self.get_property(prop)
- */
-
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.try_get_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "vidcutter/libs/pympv/mpv.pyx":612
- *             return default
- * 
- *     def get_property(self, prop):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_get_property"""
- *         assert self._ctx
- */
-
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_21get_property(PyObject *__pyx_v_self, PyObject *__pyx_v_prop); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_20get_property[] = "Wraps: mpv_get_property";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_21get_property(PyObject *__pyx_v_self, PyObject *__pyx_v_prop) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("get_property (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_20get_property(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_prop));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_20set_option(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_value);
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_20get_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop) {
-  struct mpv_node __pyx_v_result;
-  char const *__pyx_v_prop_c;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_20set_option(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_value) {
+  enum mpv_format __pyx_v_format;
+  struct mpv_node __pyx_v_v;
   int __pyx_v_err;
-  PyObject *__pyx_v_v = NULL;
+  char const *__pyx_v_prop_c;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   PyObject *__pyx_t_3 = NULL;
-  char const *__pyx_t_4;
-  int __pyx_t_5;
-  PyObject *__pyx_t_6 = NULL;
+  enum mpv_format __pyx_t_4;
+  char const *__pyx_t_5;
+  int __pyx_t_6;
   int __pyx_t_7;
-  int __pyx_t_8;
-  char const *__pyx_t_9;
+  char const *__pyx_t_8;
+  PyObject *__pyx_t_9 = NULL;
   PyObject *__pyx_t_10 = NULL;
   PyObject *__pyx_t_11 = NULL;
   PyObject *__pyx_t_12 = NULL;
   PyObject *__pyx_t_13 = NULL;
   PyObject *__pyx_t_14 = NULL;
-  PyObject *__pyx_t_15 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("get_property", 0);
+  __Pyx_RefNannySetupContext("set_option", 0);
   __Pyx_INCREF(__pyx_v_prop);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":614
- *     def get_property(self, prop):
- *         """Wraps: mpv_get_property"""
+  /* "vidcutter/libs/pympv/mpv.pyx":676
+ *     def set_option(self, prop, value=True):
+ *         """Wraps: mpv_set_option"""
  *         assert self._ctx             # <<<<<<<<<<<<<<
- *         cdef mpv_node result
  *         prop = _strenc(prop)
+ *         cdef mpv_format format = self._format_for(value)
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
   if (unlikely(!Py_OptimizeFlag)) {
     if (unlikely(!(__pyx_v_self->_ctx != 0))) {
       PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 614, __pyx_L1_error)
+      __PYX_ERR(0, 676, __pyx_L1_error)
     }
   }
   #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":616
+  /* "vidcutter/libs/pympv/mpv.pyx":677
+ *         """Wraps: mpv_set_option"""
  *         assert self._ctx
- *         cdef mpv_node result
  *         prop = _strenc(prop)             # <<<<<<<<<<<<<<
- *         cdef const char* prop_c = prop
- *         cdef int err
+ *         cdef mpv_format format = self._format_for(value)
+ *         cdef mpv_node v = self._prep_native_value(value, format)
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 616, __pyx_L1_error)
+  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 677, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_2);
   __pyx_t_3 = NULL;
   if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
@@ -12787,275 +12972,200 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_20get_property(struct _
   }
   __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_prop) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_prop);
   __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 616, __pyx_L1_error)
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 677, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF_SET(__pyx_v_prop, __pyx_t_1);
   __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":617
- *         cdef mpv_node result
+  /* "vidcutter/libs/pympv/mpv.pyx":678
+ *         assert self._ctx
  *         prop = _strenc(prop)
- *         cdef const char* prop_c = prop             # <<<<<<<<<<<<<<
- *         cdef int err
- *         with nogil:
- */
-  __pyx_t_4 = __Pyx_PyObject_AsString(__pyx_v_prop); if (unlikely((!__pyx_t_4) && PyErr_Occurred())) __PYX_ERR(0, 617, __pyx_L1_error)
-  __pyx_v_prop_c = __pyx_t_4;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":619
- *         cdef const char* prop_c = prop
+ *         cdef mpv_format format = self._format_for(value)             # <<<<<<<<<<<<<<
+ *         cdef mpv_node v = self._prep_native_value(value, format)
  *         cdef int err
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_get_property(
- *                 self._ctx,
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_format_for); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 678, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_3)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_value) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_value);
+  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 678, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_4 = ((enum mpv_format)__Pyx_PyInt_As_enum__mpv_format(__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 678, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_format = __pyx_t_4;
 
-        /* "vidcutter/libs/pympv/mpv.pyx":620
+  /* "vidcutter/libs/pympv/mpv.pyx":679
+ *         prop = _strenc(prop)
+ *         cdef mpv_format format = self._format_for(value)
+ *         cdef mpv_node v = self._prep_native_value(value, format)             # <<<<<<<<<<<<<<
  *         cdef int err
- *         with nogil:
- *             err = mpv_get_property(             # <<<<<<<<<<<<<<
- *                 self._ctx,
- *                 prop_c,
+ *         cdef const char* prop_c
  */
-        __pyx_v_err = mpv_get_property(__pyx_v_self->_ctx, __pyx_v_prop_c, MPV_FORMAT_NODE, (&__pyx_v_result));
-      }
+  __pyx_t_1 = __Pyx_PyInt_From_enum__mpv_format(__pyx_v_format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 679, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_v = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_native_value(__pyx_v_self, __pyx_v_value, __pyx_t_1);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-      /* "vidcutter/libs/pympv/mpv.pyx":619
- *         cdef const char* prop_c = prop
+  /* "vidcutter/libs/pympv/mpv.pyx":682
  *         cdef int err
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_get_property(
- *                 self._ctx,
- */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":626
- *                 &result,
- *             )
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
- *         try:
+ *         cdef const char* prop_c
+ *         try:             # <<<<<<<<<<<<<<
+ *             prop_c = prop
+ *             with nogil:
  */
-  __pyx_t_5 = ((__pyx_v_err < 0) != 0);
-  if (unlikely(__pyx_t_5)) {
+  /*try:*/ {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":627
- *             )
- *         if err < 0:
- *             raise MPVError(err)             # <<<<<<<<<<<<<<
+    /* "vidcutter/libs/pympv/mpv.pyx":683
+ *         cdef const char* prop_c
  *         try:
- *             v = _convert_node_value(result)
+ *             prop_c = prop             # <<<<<<<<<<<<<<
+ *             with nogil:
+ *                 err = mpv_set_option(
  */
-    __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 627, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 627, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_6 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_2);
-      if (likely(__pyx_t_6)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_6);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_2, function);
-      }
-    }
-    __pyx_t_1 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_6, __pyx_t_3) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3);
-    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 627, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __PYX_ERR(0, 627, __pyx_L1_error)
+    __pyx_t_5 = __Pyx_PyObject_AsString(__pyx_v_prop); if (unlikely((!__pyx_t_5) && PyErr_Occurred())) __PYX_ERR(0, 683, __pyx_L4_error)
+    __pyx_v_prop_c = __pyx_t_5;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":626
- *                 &result,
- *             )
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
+    /* "vidcutter/libs/pympv/mpv.pyx":684
  *         try:
+ *             prop_c = prop
+ *             with nogil:             # <<<<<<<<<<<<<<
+ *                 err = mpv_set_option(
+ *                     self._ctx,
  */
-  }
+    {
+        #ifdef WITH_THREAD
+        PyThreadState *_save;
+        Py_UNBLOCK_THREADS
+        __Pyx_FastGIL_Remember();
+        #endif
+        /*try:*/ {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":628
- *         if err < 0:
- *             raise MPVError(err)
- *         try:             # <<<<<<<<<<<<<<
- *             v = _convert_node_value(result)
- *         finally:
+          /* "vidcutter/libs/pympv/mpv.pyx":685
+ *             prop_c = prop
+ *             with nogil:
+ *                 err = mpv_set_option(             # <<<<<<<<<<<<<<
+ *                     self._ctx,
+ *                     prop_c,
  */
-  /*try:*/ {
+          __pyx_v_err = mpv_set_option(__pyx_v_self->_ctx, __pyx_v_prop_c, MPV_FORMAT_NODE, (&__pyx_v_v));
+        }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":629
- *             raise MPVError(err)
+        /* "vidcutter/libs/pympv/mpv.pyx":684
  *         try:
- *             v = _convert_node_value(result)             # <<<<<<<<<<<<<<
- *         finally:
- *             with nogil:
+ *             prop_c = prop
+ *             with nogil:             # <<<<<<<<<<<<<<
+ *                 err = mpv_set_option(
+ *                     self._ctx,
  */
-    __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv__convert_node_value(__pyx_v_result); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 629, __pyx_L8_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_v_v = __pyx_t_1;
-    __pyx_t_1 = 0;
+        /*finally:*/ {
+          /*normal exit:*/{
+            #ifdef WITH_THREAD
+            __Pyx_FastGIL_Forget();
+            Py_BLOCK_THREADS
+            #endif
+            goto __pyx_L8;
+          }
+          __pyx_L8:;
+        }
+    }
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":631
- *             v = _convert_node_value(result)
+  /* "vidcutter/libs/pympv/mpv.pyx":692
+ *                 )
  *         finally:
- *             with nogil:             # <<<<<<<<<<<<<<
- *                 mpv_free_node_contents(&result)
- *         return v
+ *             self._free_native_value(v)             # <<<<<<<<<<<<<<
+ *         return err
+ * 
  */
   /*finally:*/ {
     /*normal exit:*/{
-      {
-          #ifdef WITH_THREAD
-          PyThreadState *_save;
-          Py_UNBLOCK_THREADS
-          __Pyx_FastGIL_Remember();
-          #endif
-          /*try:*/ {
-
-            /* "vidcutter/libs/pympv/mpv.pyx":632
- *         finally:
- *             with nogil:
- *                 mpv_free_node_contents(&result)             # <<<<<<<<<<<<<<
- *         return v
- * 
- */
-            mpv_free_node_contents((&__pyx_v_result));
-          }
-
-          /* "vidcutter/libs/pympv/mpv.pyx":631
- *             v = _convert_node_value(result)
- *         finally:
- *             with nogil:             # <<<<<<<<<<<<<<
- *                 mpv_free_node_contents(&result)
- *         return v
- */
-          /*finally:*/ {
-            /*normal exit:*/{
-              #ifdef WITH_THREAD
-              __Pyx_FastGIL_Forget();
-              Py_BLOCK_THREADS
-              #endif
-              goto __pyx_L12;
-            }
-            __pyx_L12:;
-          }
-      }
-      goto __pyx_L9;
+      __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 692, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      goto __pyx_L5;
     }
-    __pyx_L8_error:;
+    __pyx_L4_error:;
     /*exception exit:*/{
       __Pyx_PyThreadState_declare
       __Pyx_PyThreadState_assign
-      __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0;
+      __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0;
       __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
       __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
       __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-      if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_13, &__pyx_t_14, &__pyx_t_15);
-      if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12) < 0)) __Pyx_ErrFetch(&__pyx_t_10, &__pyx_t_11, &__pyx_t_12);
+      if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14);
+      if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_9, &__pyx_t_10, &__pyx_t_11) < 0)) __Pyx_ErrFetch(&__pyx_t_9, &__pyx_t_10, &__pyx_t_11);
+      __Pyx_XGOTREF(__pyx_t_9);
       __Pyx_XGOTREF(__pyx_t_10);
       __Pyx_XGOTREF(__pyx_t_11);
       __Pyx_XGOTREF(__pyx_t_12);
       __Pyx_XGOTREF(__pyx_t_13);
       __Pyx_XGOTREF(__pyx_t_14);
-      __Pyx_XGOTREF(__pyx_t_15);
-      __pyx_t_7 = __pyx_lineno; __pyx_t_8 = __pyx_clineno; __pyx_t_9 = __pyx_filename;
+      __pyx_t_6 = __pyx_lineno; __pyx_t_7 = __pyx_clineno; __pyx_t_8 = __pyx_filename;
       {
-        {
-            #ifdef WITH_THREAD
-            PyThreadState *_save;
-            Py_UNBLOCK_THREADS
-            __Pyx_FastGIL_Remember();
-            #endif
-            /*try:*/ {
-
-              /* "vidcutter/libs/pympv/mpv.pyx":632
- *         finally:
- *             with nogil:
- *                 mpv_free_node_contents(&result)             # <<<<<<<<<<<<<<
- *         return v
- * 
- */
-              mpv_free_node_contents((&__pyx_v_result));
-            }
-
-            /* "vidcutter/libs/pympv/mpv.pyx":631
- *             v = _convert_node_value(result)
- *         finally:
- *             with nogil:             # <<<<<<<<<<<<<<
- *                 mpv_free_node_contents(&result)
- *         return v
- */
-            /*finally:*/ {
-              /*normal exit:*/{
-                #ifdef WITH_THREAD
-                __Pyx_FastGIL_Forget();
-                Py_BLOCK_THREADS
-                #endif
-                goto __pyx_L17;
-              }
-              __pyx_L17:;
-            }
-        }
+        __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 692, __pyx_L10_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
       }
       if (PY_MAJOR_VERSION >= 3) {
+        __Pyx_XGIVEREF(__pyx_t_12);
         __Pyx_XGIVEREF(__pyx_t_13);
         __Pyx_XGIVEREF(__pyx_t_14);
-        __Pyx_XGIVEREF(__pyx_t_15);
-        __Pyx_ExceptionReset(__pyx_t_13, __pyx_t_14, __pyx_t_15);
+        __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_13, __pyx_t_14);
       }
+      __Pyx_XGIVEREF(__pyx_t_9);
       __Pyx_XGIVEREF(__pyx_t_10);
       __Pyx_XGIVEREF(__pyx_t_11);
-      __Pyx_XGIVEREF(__pyx_t_12);
-      __Pyx_ErrRestore(__pyx_t_10, __pyx_t_11, __pyx_t_12);
-      __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0; __pyx_t_15 = 0;
-      __pyx_lineno = __pyx_t_7; __pyx_clineno = __pyx_t_8; __pyx_filename = __pyx_t_9;
+      __Pyx_ErrRestore(__pyx_t_9, __pyx_t_10, __pyx_t_11);
+      __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0;
+      __pyx_lineno = __pyx_t_6; __pyx_clineno = __pyx_t_7; __pyx_filename = __pyx_t_8;
+      goto __pyx_L1_error;
+      __pyx_L10_error:;
+      if (PY_MAJOR_VERSION >= 3) {
+        __Pyx_XGIVEREF(__pyx_t_12);
+        __Pyx_XGIVEREF(__pyx_t_13);
+        __Pyx_XGIVEREF(__pyx_t_14);
+        __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_13, __pyx_t_14);
+      }
+      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
+      __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
+      __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
+      __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0;
       goto __pyx_L1_error;
     }
-    __pyx_L9:;
+    __pyx_L5:;
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":633
- *             with nogil:
- *                 mpv_free_node_contents(&result)
- *         return v             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":693
+ *         finally:
+ *             self._free_native_value(v)
+ *         return err             # <<<<<<<<<<<<<<
  * 
  *     @_errors
  */
   __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_v);
-  __pyx_r = __pyx_v_v;
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 693, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":612
- *             return default
+  /* "vidcutter/libs/pympv/mpv.pyx":674
  * 
- *     def get_property(self, prop):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_get_property"""
+ *     @_errors
+ *     def set_option(self, prop, value=True):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_set_option"""
  *         assert self._ctx
  */
 
@@ -13064,1047 +13174,798 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_20get_property(struct _
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.get_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_option", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_v);
   __Pyx_XDECREF(__pyx_v_prop);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":636
+/* "vidcutter/libs/pympv/mpv.pyx":696
  * 
  *     @_errors
- *     def set_property(self, prop, value=True, asynchronous=False, data=None):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_set_property and mpv_set_property_async"""
+ *     def initialize(self):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_initialize"""
  *         assert self._ctx
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_23set_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_22set_property[] = "Wraps: mpv_set_property and mpv_set_property_async";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_23set_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_prop = 0;
-  PyObject *__pyx_v_value = 0;
-  PyObject *__pyx_v_asynchronous = 0;
-  PyObject *__pyx_v_data = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_23initialize(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_22initialize[] = "Wraps: mpv_initialize";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_23initialize(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("set_property (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_value,&__pyx_n_s_asynchronous,&__pyx_n_s_data,0};
-    PyObject* values[4] = {0,0,0,0};
-    values[1] = ((PyObject *)Py_True);
-    values[2] = ((PyObject *)Py_False);
-    values[3] = ((PyObject *)Py_None);
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
-        CYTHON_FALLTHROUGH;
-        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_prop)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (kw_args > 0) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_value);
-          if (value) { values[1] = value; kw_args--; }
-        }
-        CYTHON_FALLTHROUGH;
-        case  2:
-        if (kw_args > 0) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_asynchronous);
-          if (value) { values[2] = value; kw_args--; }
-        }
-        CYTHON_FALLTHROUGH;
-        case  3:
-        if (kw_args > 0) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data);
-          if (value) { values[3] = value; kw_args--; }
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_property") < 0)) __PYX_ERR(0, 636, __pyx_L3_error)
-      }
-    } else {
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
-        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
-        CYTHON_FALLTHROUGH;
-        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-    }
-    __pyx_v_prop = values[0];
-    __pyx_v_value = values[1];
-    __pyx_v_asynchronous = values[2];
-    __pyx_v_data = values[3];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("set_property", 0, 1, 4, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 636, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_22set_property(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_value, __pyx_v_asynchronous, __pyx_v_data);
+  __Pyx_RefNannySetupContext("initialize (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_22initialize(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_22set_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_value, PyObject *__pyx_v_asynchronous, PyObject *__pyx_v_data) {
-  enum mpv_format __pyx_v_format;
-  struct mpv_node __pyx_v_v;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_22initialize(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
   int __pyx_v_err;
-  uint64_t __pyx_v_data_id;
-  char const *__pyx_v_prop_c;
-  PyObject *__pyx_v_userdatas = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  enum mpv_format __pyx_t_4;
-  char const *__pyx_t_5;
-  int __pyx_t_6;
-  int __pyx_t_7;
-  Py_hash_t __pyx_t_8;
-  PyObject *__pyx_t_9 = NULL;
-  int __pyx_t_10;
-  PyObject *__pyx_t_11 = NULL;
-  int __pyx_t_12;
-  char const *__pyx_t_13;
-  PyObject *__pyx_t_14 = NULL;
-  PyObject *__pyx_t_15 = NULL;
-  PyObject *__pyx_t_16 = NULL;
-  PyObject *__pyx_t_17 = NULL;
-  PyObject *__pyx_t_18 = NULL;
-  PyObject *__pyx_t_19 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("set_property", 0);
-  __Pyx_INCREF(__pyx_v_prop);
+  __Pyx_RefNannySetupContext("initialize", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":638
- *     def set_property(self, prop, value=True, asynchronous=False, data=None):
- *         """Wraps: mpv_set_property and mpv_set_property_async"""
+  /* "vidcutter/libs/pympv/mpv.pyx":698
+ *     def initialize(self):
+ *         """Wraps: mpv_initialize"""
  *         assert self._ctx             # <<<<<<<<<<<<<<
- *         prop = _strenc(prop)
- *         cdef mpv_format format = self._format_for(value)
+ *         cdef int err
+ *         with nogil:
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
   if (unlikely(!Py_OptimizeFlag)) {
     if (unlikely(!(__pyx_v_self->_ctx != 0))) {
       PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 638, __pyx_L1_error)
+      __PYX_ERR(0, 698, __pyx_L1_error)
     }
   }
   #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":639
- *         """Wraps: mpv_set_property and mpv_set_property_async"""
+  /* "vidcutter/libs/pympv/mpv.pyx":700
  *         assert self._ctx
- *         prop = _strenc(prop)             # <<<<<<<<<<<<<<
- *         cdef mpv_format format = self._format_for(value)
- *         cdef mpv_node v = self._prep_native_value(value, format)
+ *         cdef int err
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_initialize(self._ctx)
+ *         return err
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 639, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_3)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_prop) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_prop);
-  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 639, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF_SET(__pyx_v_prop, __pyx_t_1);
-  __pyx_t_1 = 0;
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":640
- *         assert self._ctx
- *         prop = _strenc(prop)
- *         cdef mpv_format format = self._format_for(value)             # <<<<<<<<<<<<<<
- *         cdef mpv_node v = self._prep_native_value(value, format)
+        /* "vidcutter/libs/pympv/mpv.pyx":701
  *         cdef int err
+ *         with nogil:
+ *             err = mpv_initialize(self._ctx)             # <<<<<<<<<<<<<<
+ *         return err
+ * 
  */
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_format_for); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 640, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_3)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_value) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_value);
-  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 640, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = ((enum mpv_format)__Pyx_PyInt_As_enum__mpv_format(__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 640, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_format = __pyx_t_4;
+        __pyx_v_err = mpv_initialize(__pyx_v_self->_ctx);
+      }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":641
- *         prop = _strenc(prop)
- *         cdef mpv_format format = self._format_for(value)
- *         cdef mpv_node v = self._prep_native_value(value, format)             # <<<<<<<<<<<<<<
+      /* "vidcutter/libs/pympv/mpv.pyx":700
+ *         assert self._ctx
  *         cdef int err
- *         cdef uint64_t data_id
- */
-  __pyx_t_1 = __Pyx_PyInt_From_enum__mpv_format(__pyx_v_format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 641, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_v = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_native_value(__pyx_v_self, __pyx_v_value, __pyx_t_1);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":645
- *         cdef uint64_t data_id
- *         cdef const char* prop_c
- *         try:             # <<<<<<<<<<<<<<
- *             prop_c = prop
- *             if not asynchronous:
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_initialize(self._ctx)
+ *         return err
  */
-  /*try:*/ {
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
+      }
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":646
- *         cdef const char* prop_c
- *         try:
- *             prop_c = prop             # <<<<<<<<<<<<<<
- *             if not asynchronous:
- *                 with nogil:
+  /* "vidcutter/libs/pympv/mpv.pyx":702
+ *         with nogil:
+ *             err = mpv_initialize(self._ctx)
+ *         return err             # <<<<<<<<<<<<<<
+ * 
+ *     def wait_event(self, timeout=None):
  */
-    __pyx_t_5 = __Pyx_PyObject_AsString(__pyx_v_prop); if (unlikely((!__pyx_t_5) && PyErr_Occurred())) __PYX_ERR(0, 646, __pyx_L4_error)
-    __pyx_v_prop_c = __pyx_t_5;
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 702, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_r = __pyx_t_1;
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":647
- *         try:
- *             prop_c = prop
- *             if not asynchronous:             # <<<<<<<<<<<<<<
- *                 with nogil:
- *                     err = mpv_set_property(
+  /* "vidcutter/libs/pympv/mpv.pyx":696
+ * 
+ *     @_errors
+ *     def initialize(self):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_initialize"""
+ *         assert self._ctx
  */
-    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_asynchronous); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 647, __pyx_L4_error)
-    __pyx_t_7 = ((!__pyx_t_6) != 0);
-    if (__pyx_t_7) {
 
-      /* "vidcutter/libs/pympv/mpv.pyx":648
- *             prop_c = prop
- *             if not asynchronous:
- *                 with nogil:             # <<<<<<<<<<<<<<
- *                     err = mpv_set_property(
- *                         self._ctx,
- */
-      {
-          #ifdef WITH_THREAD
-          PyThreadState *_save;
-          Py_UNBLOCK_THREADS
-          __Pyx_FastGIL_Remember();
-          #endif
-          /*try:*/ {
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.initialize", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-            /* "vidcutter/libs/pympv/mpv.pyx":649
- *             if not asynchronous:
- *                 with nogil:
- *                     err = mpv_set_property(             # <<<<<<<<<<<<<<
- *                         self._ctx,
- *                         prop_c,
+/* "vidcutter/libs/pympv/mpv.pyx":704
+ *         return err
+ * 
+ *     def wait_event(self, timeout=None):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_wait_event"""
+ *         assert self._ctx
  */
-            __pyx_v_err = mpv_set_property(__pyx_v_self->_ctx, __pyx_v_prop_c, MPV_FORMAT_NODE, (&__pyx_v_v));
-          }
 
-          /* "vidcutter/libs/pympv/mpv.pyx":648
- *             prop_c = prop
- *             if not asynchronous:
- *                 with nogil:             # <<<<<<<<<<<<<<
- *                     err = mpv_set_property(
- *                         self._ctx,
- */
-          /*finally:*/ {
-            /*normal exit:*/{
-              #ifdef WITH_THREAD
-              __Pyx_FastGIL_Forget();
-              Py_BLOCK_THREADS
-              #endif
-              goto __pyx_L9;
-            }
-            __pyx_L9:;
-          }
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_25wait_event(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_24wait_event[] = "Wraps: mpv_wait_event";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_25wait_event(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_timeout = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("wait_event (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_timeout,0};
+    PyObject* values[1] = {0};
+    values[0] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_timeout);
+          if (value) { values[0] = value; kw_args--; }
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "wait_event") < 0)) __PYX_ERR(0, 704, __pyx_L3_error)
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
       }
+    }
+    __pyx_v_timeout = values[0];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("wait_event", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 704, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.wait_event", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_24wait_event(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_timeout);
 
-      /* "vidcutter/libs/pympv/mpv.pyx":655
- *                         &v
- *                     )
- *                 return err             # <<<<<<<<<<<<<<
- *             data_id = <uint64_t>hash(data)
- *             userdatas = self.reply_userdata.get(data_id, None)
- */
-      __Pyx_XDECREF(__pyx_r);
-      __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 655, __pyx_L4_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __pyx_r = __pyx_t_1;
-      __pyx_t_1 = 0;
-      goto __pyx_L3_return;
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-      /* "vidcutter/libs/pympv/mpv.pyx":647
- *         try:
- *             prop_c = prop
- *             if not asynchronous:             # <<<<<<<<<<<<<<
- *                 with nogil:
- *                     err = mpv_set_property(
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_24wait_event(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_timeout) {
+  double __pyx_v_timeout_d;
+  struct mpv_event *__pyx_v_event;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  double __pyx_t_1;
+  int __pyx_t_2;
+  double __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("wait_event", 0);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":706
+ *     def wait_event(self, timeout=None):
+ *         """Wraps: mpv_wait_event"""
+ *         assert self._ctx             # <<<<<<<<<<<<<<
+ *         cdef double timeout_d = timeout if timeout is not None else -1
+ *         cdef mpv_event* event
  */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!Py_OptimizeFlag)) {
+    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
+      PyErr_SetNone(PyExc_AssertionError);
+      __PYX_ERR(0, 706, __pyx_L1_error)
     }
+  }
+  #endif
 
-    /* "vidcutter/libs/pympv/mpv.pyx":656
- *                     )
- *                 return err
- *             data_id = <uint64_t>hash(data)             # <<<<<<<<<<<<<<
- *             userdatas = self.reply_userdata.get(data_id, None)
- *             if userdatas is None:
+  /* "vidcutter/libs/pympv/mpv.pyx":707
+ *         """Wraps: mpv_wait_event"""
+ *         assert self._ctx
+ *         cdef double timeout_d = timeout if timeout is not None else -1             # <<<<<<<<<<<<<<
+ *         cdef mpv_event* event
+ *         with nogil:
  */
-    __pyx_t_8 = PyObject_Hash(__pyx_v_data); if (unlikely(__pyx_t_8 == ((Py_hash_t)-1))) __PYX_ERR(0, 656, __pyx_L4_error)
-    __pyx_v_data_id = ((uint64_t)__pyx_t_8);
-
-    /* "vidcutter/libs/pympv/mpv.pyx":657
- *                 return err
- *             data_id = <uint64_t>hash(data)
- *             userdatas = self.reply_userdata.get(data_id, None)             # <<<<<<<<<<<<<<
- *             if userdatas is None:
- *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
- */
-    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->reply_userdata, __pyx_n_s_get); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 657, __pyx_L4_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyInt_From_uint64_t(__pyx_v_data_id); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 657, __pyx_L4_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_9 = NULL;
-    __pyx_t_10 = 0;
-    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_2);
-      if (likely(__pyx_t_9)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_9);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_2, function);
-        __pyx_t_10 = 1;
-      }
-    }
-    #if CYTHON_FAST_PYCALL
-    if (PyFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_3, Py_None};
-      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 657, __pyx_L4_error)
-      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    #if CYTHON_FAST_PYCCALL
-    if (__Pyx_PyFastCFunction_Check(__pyx_t_2)) {
-      PyObject *__pyx_temp[3] = {__pyx_t_9, __pyx_t_3, Py_None};
-      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_2, __pyx_temp+1-__pyx_t_10, 2+__pyx_t_10); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 657, __pyx_L4_error)
-      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else
-    #endif
-    {
-      __pyx_t_11 = PyTuple_New(2+__pyx_t_10); if (unlikely(!__pyx_t_11)) __PYX_ERR(0, 657, __pyx_L4_error)
-      __Pyx_GOTREF(__pyx_t_11);
-      if (__pyx_t_9) {
-        __Pyx_GIVEREF(__pyx_t_9); PyTuple_SET_ITEM(__pyx_t_11, 0, __pyx_t_9); __pyx_t_9 = NULL;
-      }
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_11, 0+__pyx_t_10, __pyx_t_3);
-      __Pyx_INCREF(Py_None);
-      __Pyx_GIVEREF(Py_None);
-      PyTuple_SET_ITEM(__pyx_t_11, 1+__pyx_t_10, Py_None);
-      __pyx_t_3 = 0;
-      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_11, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 657, __pyx_L4_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
-    }
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_v_userdatas = __pyx_t_1;
-    __pyx_t_1 = 0;
+  __pyx_t_2 = (__pyx_v_timeout != Py_None);
+  if ((__pyx_t_2 != 0)) {
+    __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_v_timeout); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 707, __pyx_L1_error)
+    __pyx_t_1 = __pyx_t_3;
+  } else {
+    __pyx_t_1 = -1.0;
+  }
+  __pyx_v_timeout_d = __pyx_t_1;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":658
- *             data_id = <uint64_t>hash(data)
- *             userdatas = self.reply_userdata.get(data_id, None)
- *             if userdatas is None:             # <<<<<<<<<<<<<<
- *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
- *             userdatas.add()
+  /* "vidcutter/libs/pympv/mpv.pyx":709
+ *         cdef double timeout_d = timeout if timeout is not None else -1
+ *         cdef mpv_event* event
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             event = mpv_wait_event(self._ctx, timeout_d)
+ *         return Event()._init(event, self)
  */
-    __pyx_t_7 = (__pyx_v_userdatas == Py_None);
-    __pyx_t_6 = (__pyx_t_7 != 0);
-    if (__pyx_t_6) {
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
 
-      /* "vidcutter/libs/pympv/mpv.pyx":659
- *             userdatas = self.reply_userdata.get(data_id, None)
- *             if userdatas is None:
- *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)             # <<<<<<<<<<<<<<
- *             userdatas.add()
- *             with nogil:
+        /* "vidcutter/libs/pympv/mpv.pyx":710
+ *         cdef mpv_event* event
+ *         with nogil:
+ *             event = mpv_wait_event(self._ctx, timeout_d)             # <<<<<<<<<<<<<<
+ *         return Event()._init(event, self)
+ * 
  */
-      __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_ReplyUserData); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 659, __pyx_L4_error)
-      __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_11 = NULL;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-        __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_2);
-        if (likely(__pyx_t_11)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-          __Pyx_INCREF(__pyx_t_11);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_2, function);
-        }
+        __pyx_v_event = mpv_wait_event(__pyx_v_self->_ctx, __pyx_v_timeout_d);
       }
-      __pyx_t_1 = (__pyx_t_11) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_11, __pyx_v_data) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_data);
-      __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
-      if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 659, __pyx_L4_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      if (unlikely(__Pyx_SetItemInt(__pyx_v_self->reply_userdata, __pyx_v_data_id, __pyx_t_1, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 659, __pyx_L4_error)
-      __Pyx_INCREF(__pyx_t_1);
-      __Pyx_DECREF_SET(__pyx_v_userdatas, __pyx_t_1);
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
-      /* "vidcutter/libs/pympv/mpv.pyx":658
- *             data_id = <uint64_t>hash(data)
- *             userdatas = self.reply_userdata.get(data_id, None)
- *             if userdatas is None:             # <<<<<<<<<<<<<<
- *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
- *             userdatas.add()
- */
-    }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":660
- *             if userdatas is None:
- *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
- *             userdatas.add()             # <<<<<<<<<<<<<<
- *             with nogil:
- *                 err = mpv_set_property_async(
+      /* "vidcutter/libs/pympv/mpv.pyx":709
+ *         cdef double timeout_d = timeout if timeout is not None else -1
+ *         cdef mpv_event* event
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             event = mpv_wait_event(self._ctx, timeout_d)
+ *         return Event()._init(event, self)
  */
-    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdatas, __pyx_n_s_add); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 660, __pyx_L4_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_11 = NULL;
-    if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-      __pyx_t_11 = PyMethod_GET_SELF(__pyx_t_2);
-      if (likely(__pyx_t_11)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_11);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_2, function);
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
       }
-    }
-    __pyx_t_1 = (__pyx_t_11) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_11) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
-    __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 660, __pyx_L4_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":661
- *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
- *             userdatas.add()
- *             with nogil:             # <<<<<<<<<<<<<<
- *                 err = mpv_set_property_async(
- *                     self._ctx,
+  /* "vidcutter/libs/pympv/mpv.pyx":711
+ *         with nogil:
+ *             event = mpv_wait_event(self._ctx, timeout_d)
+ *         return Event()._init(event, self)             # <<<<<<<<<<<<<<
+ * 
+ *     def wakeup(self):
  */
-    {
-        #ifdef WITH_THREAD
-        PyThreadState *_save;
-        Py_UNBLOCK_THREADS
-        __Pyx_FastGIL_Remember();
-        #endif
-        /*try:*/ {
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_4 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_Event)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 711, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Event *)((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_t_4)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_t_4), __pyx_v_event, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 711, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_r = __pyx_t_5;
+  __pyx_t_5 = 0;
+  goto __pyx_L0;
 
-          /* "vidcutter/libs/pympv/mpv.pyx":662
- *             userdatas.add()
- *             with nogil:
- *                 err = mpv_set_property_async(             # <<<<<<<<<<<<<<
- *                     self._ctx,
- *                     data_id,
+  /* "vidcutter/libs/pympv/mpv.pyx":704
+ *         return err
+ * 
+ *     def wait_event(self, timeout=None):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_wait_event"""
+ *         assert self._ctx
  */
-          __pyx_v_err = mpv_set_property_async(__pyx_v_self->_ctx, __pyx_v_data_id, __pyx_v_prop_c, MPV_FORMAT_NODE, (&__pyx_v_v));
-        }
 
-        /* "vidcutter/libs/pympv/mpv.pyx":661
- *                 self.reply_userdata[data_id] = userdatas = _ReplyUserData(data)
- *             userdatas.add()
- *             with nogil:             # <<<<<<<<<<<<<<
- *                 err = mpv_set_property_async(
- *                     self._ctx,
- */
-        /*finally:*/ {
-          /*normal exit:*/{
-            #ifdef WITH_THREAD
-            __Pyx_FastGIL_Forget();
-            Py_BLOCK_THREADS
-            #endif
-            goto __pyx_L13;
-          }
-          __pyx_L13:;
-        }
-    }
-  }
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.wait_event", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
 
-  /* "vidcutter/libs/pympv/mpv.pyx":670
- *                 )
- *         finally:
- *             self._free_native_value(v)             # <<<<<<<<<<<<<<
- *         return err
+/* "vidcutter/libs/pympv/mpv.pyx":713
+ *         return Event()._init(event, self)
  * 
+ *     def wakeup(self):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_wakeup"""
+ *         assert self._ctx
  */
-  /*finally:*/ {
-    /*normal exit:*/{
-      __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 670, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L5;
-    }
-    __pyx_L4_error:;
-    /*exception exit:*/{
-      __Pyx_PyThreadState_declare
-      __Pyx_PyThreadState_assign
-      __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; __pyx_t_18 = 0; __pyx_t_19 = 0;
-      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-      __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
-      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
-      if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_17, &__pyx_t_18, &__pyx_t_19);
-      if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16) < 0)) __Pyx_ErrFetch(&__pyx_t_14, &__pyx_t_15, &__pyx_t_16);
-      __Pyx_XGOTREF(__pyx_t_14);
-      __Pyx_XGOTREF(__pyx_t_15);
-      __Pyx_XGOTREF(__pyx_t_16);
-      __Pyx_XGOTREF(__pyx_t_17);
-      __Pyx_XGOTREF(__pyx_t_18);
-      __Pyx_XGOTREF(__pyx_t_19);
-      __pyx_t_10 = __pyx_lineno; __pyx_t_12 = __pyx_clineno; __pyx_t_13 = __pyx_filename;
-      {
-        __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 670, __pyx_L15_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      }
-      if (PY_MAJOR_VERSION >= 3) {
-        __Pyx_XGIVEREF(__pyx_t_17);
-        __Pyx_XGIVEREF(__pyx_t_18);
-        __Pyx_XGIVEREF(__pyx_t_19);
-        __Pyx_ExceptionReset(__pyx_t_17, __pyx_t_18, __pyx_t_19);
-      }
-      __Pyx_XGIVEREF(__pyx_t_14);
-      __Pyx_XGIVEREF(__pyx_t_15);
-      __Pyx_XGIVEREF(__pyx_t_16);
-      __Pyx_ErrRestore(__pyx_t_14, __pyx_t_15, __pyx_t_16);
-      __pyx_t_14 = 0; __pyx_t_15 = 0; __pyx_t_16 = 0; __pyx_t_17 = 0; __pyx_t_18 = 0; __pyx_t_19 = 0;
-      __pyx_lineno = __pyx_t_10; __pyx_clineno = __pyx_t_12; __pyx_filename = __pyx_t_13;
-      goto __pyx_L1_error;
-      __pyx_L15_error:;
-      if (PY_MAJOR_VERSION >= 3) {
-        __Pyx_XGIVEREF(__pyx_t_17);
-        __Pyx_XGIVEREF(__pyx_t_18);
-        __Pyx_XGIVEREF(__pyx_t_19);
-        __Pyx_ExceptionReset(__pyx_t_17, __pyx_t_18, __pyx_t_19);
-      }
-      __Pyx_XDECREF(__pyx_t_14); __pyx_t_14 = 0;
-      __Pyx_XDECREF(__pyx_t_15); __pyx_t_15 = 0;
-      __Pyx_XDECREF(__pyx_t_16); __pyx_t_16 = 0;
-      __pyx_t_17 = 0; __pyx_t_18 = 0; __pyx_t_19 = 0;
-      goto __pyx_L1_error;
-    }
-    __pyx_L3_return: {
-      __pyx_t_19 = __pyx_r;
-      __pyx_r = 0;
-      __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 670, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      __pyx_r = __pyx_t_19;
-      __pyx_t_19 = 0;
-      goto __pyx_L0;
+
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_27wakeup(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_26wakeup[] = "Wraps: mpv_wakeup";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_27wakeup(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("wakeup (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_26wakeup(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_26wakeup(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("wakeup", 0);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":715
+ *     def wakeup(self):
+ *         """Wraps: mpv_wakeup"""
+ *         assert self._ctx             # <<<<<<<<<<<<<<
+ *         with nogil:
+ *             mpv_wakeup(self._ctx)
+ */
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!Py_OptimizeFlag)) {
+    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
+      PyErr_SetNone(PyExc_AssertionError);
+      __PYX_ERR(0, 715, __pyx_L1_error)
     }
-    __pyx_L5:;
   }
+  #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":671
- *         finally:
- *             self._free_native_value(v)
- *         return err             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":716
+ *         """Wraps: mpv_wakeup"""
+ *         assert self._ctx
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             mpv_wakeup(self._ctx)
  * 
- *     @_errors
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 671, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":636
+        /* "vidcutter/libs/pympv/mpv.pyx":717
+ *         assert self._ctx
+ *         with nogil:
+ *             mpv_wakeup(self._ctx)             # <<<<<<<<<<<<<<
  * 
- *     @_errors
- *     def set_property(self, prop, value=True, asynchronous=False, data=None):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_set_property and mpv_set_property_async"""
+ *     def set_wakeup_callback(self, callback):
+ */
+        mpv_wakeup(__pyx_v_self->_ctx);
+      }
+
+      /* "vidcutter/libs/pympv/mpv.pyx":716
+ *         """Wraps: mpv_wakeup"""
+ *         assert self._ctx
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             mpv_wakeup(self._ctx)
+ * 
+ */
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
+      }
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":713
+ *         return Event()._init(event, self)
+ * 
+ *     def wakeup(self):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_wakeup"""
  *         assert self._ctx
  */
 
   /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_XDECREF(__pyx_t_11);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.wakeup", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_userdatas);
-  __Pyx_XDECREF(__pyx_v_prop);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":674
+/* "vidcutter/libs/pympv/mpv.pyx":719
+ *             mpv_wakeup(self._ctx)
  * 
- *     @_errors
- *     def set_option(self, prop, value=True):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_set_option"""
+ *     def set_wakeup_callback(self, callback):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_set_wakeup_callback"""
  *         assert self._ctx
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_25set_option(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_24set_option[] = "Wraps: mpv_set_option";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_25set_option(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_prop = 0;
-  PyObject *__pyx_v_value = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_29set_wakeup_callback(PyObject *__pyx_v_self, PyObject *__pyx_v_callback); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_28set_wakeup_callback[] = "Wraps: mpv_set_wakeup_callback";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_29set_wakeup_callback(PyObject *__pyx_v_self, PyObject *__pyx_v_callback) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("set_option (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_value,0};
-    PyObject* values[2] = {0,0};
-    values[1] = ((PyObject *)Py_True);
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_prop)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (kw_args > 0) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_value);
-          if (value) { values[1] = value; kw_args--; }
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "set_option") < 0)) __PYX_ERR(0, 674, __pyx_L3_error)
-      }
-    } else {
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-    }
-    __pyx_v_prop = values[0];
-    __pyx_v_value = values[1];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("set_option", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 674, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_option", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_24set_option(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_value);
+  __Pyx_RefNannySetupContext("set_wakeup_callback (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_28set_wakeup_callback(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_callback));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_24set_option(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_value) {
-  enum mpv_format __pyx_v_format;
-  struct mpv_node __pyx_v_v;
-  int __pyx_v_err;
-  char const *__pyx_v_prop_c;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_28set_wakeup_callback(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_callback) {
+  uint64_t __pyx_v_name;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
+  uint64_t __pyx_t_2;
   PyObject *__pyx_t_3 = NULL;
-  enum mpv_format __pyx_t_4;
-  char const *__pyx_t_5;
-  int __pyx_t_6;
-  int __pyx_t_7;
-  char const *__pyx_t_8;
-  PyObject *__pyx_t_9 = NULL;
-  PyObject *__pyx_t_10 = NULL;
-  PyObject *__pyx_t_11 = NULL;
-  PyObject *__pyx_t_12 = NULL;
-  PyObject *__pyx_t_13 = NULL;
-  PyObject *__pyx_t_14 = NULL;
+  PyObject *__pyx_t_4 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("set_option", 0);
-  __Pyx_INCREF(__pyx_v_prop);
+  __Pyx_RefNannySetupContext("set_wakeup_callback", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":676
- *     def set_option(self, prop, value=True):
- *         """Wraps: mpv_set_option"""
+  /* "vidcutter/libs/pympv/mpv.pyx":721
+ *     def set_wakeup_callback(self, callback):
+ *         """Wraps: mpv_set_wakeup_callback"""
  *         assert self._ctx             # <<<<<<<<<<<<<<
- *         prop = _strenc(prop)
- *         cdef mpv_format format = self._format_for(value)
+ *         cdef uint64_t name = <uint64_t>id(self)
+ *         self.callback = callback
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
   if (unlikely(!Py_OptimizeFlag)) {
     if (unlikely(!(__pyx_v_self->_ctx != 0))) {
       PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 676, __pyx_L1_error)
+      __PYX_ERR(0, 721, __pyx_L1_error)
     }
   }
   #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":677
- *         """Wraps: mpv_set_option"""
+  /* "vidcutter/libs/pympv/mpv.pyx":722
+ *         """Wraps: mpv_set_wakeup_callback"""
  *         assert self._ctx
- *         prop = _strenc(prop)             # <<<<<<<<<<<<<<
- *         cdef mpv_format format = self._format_for(value)
- *         cdef mpv_node v = self._prep_native_value(value, format)
+ *         cdef uint64_t name = <uint64_t>id(self)             # <<<<<<<<<<<<<<
+ *         self.callback = callback
+ *         self.callbackthread.set(callback)
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_2, __pyx_n_s_strenc); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 677, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_3)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_prop) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_prop);
-  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 677, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 722, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF_SET(__pyx_v_prop, __pyx_t_1);
-  __pyx_t_1 = 0;
+  __pyx_t_2 = __Pyx_PyInt_As_uint64_t(__pyx_t_1); if (unlikely((__pyx_t_2 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 722, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_name = ((uint64_t)__pyx_t_2);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":678
+  /* "vidcutter/libs/pympv/mpv.pyx":723
  *         assert self._ctx
- *         prop = _strenc(prop)
- *         cdef mpv_format format = self._format_for(value)             # <<<<<<<<<<<<<<
- *         cdef mpv_node v = self._prep_native_value(value, format)
- *         cdef int err
+ *         cdef uint64_t name = <uint64_t>id(self)
+ *         self.callback = callback             # <<<<<<<<<<<<<<
+ *         self.callbackthread.set(callback)
+ *         with nogil:
  */
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_format_for); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 678, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_3)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_callback);
+  __Pyx_GIVEREF(__pyx_v_callback);
+  __Pyx_GOTREF(__pyx_v_self->callback);
+  __Pyx_DECREF(__pyx_v_self->callback);
+  __pyx_v_self->callback = __pyx_v_callback;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":724
+ *         cdef uint64_t name = <uint64_t>id(self)
+ *         self.callback = callback
+ *         self.callbackthread.set(callback)             # <<<<<<<<<<<<<<
+ *         with nogil:
+ *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)
+ */
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->callbackthread, __pyx_n_s_set); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 724, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
+    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+    if (likely(__pyx_t_4)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_4);
       __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
+      __Pyx_DECREF_SET(__pyx_t_3, function);
     }
   }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_Call2Args(__pyx_t_2, __pyx_t_3, __pyx_v_value) : __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_v_value);
-  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 678, __pyx_L1_error)
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_callback) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_callback);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 724, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_4 = ((enum mpv_format)__Pyx_PyInt_As_enum__mpv_format(__pyx_t_1)); if (unlikely(PyErr_Occurred())) __PYX_ERR(0, 678, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_format = __pyx_t_4;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":679
- *         prop = _strenc(prop)
- *         cdef mpv_format format = self._format_for(value)
- *         cdef mpv_node v = self._prep_native_value(value, format)             # <<<<<<<<<<<<<<
- *         cdef int err
- *         cdef const char* prop_c
+  /* "vidcutter/libs/pympv/mpv.pyx":725
+ *         self.callback = callback
+ *         self.callbackthread.set(callback)
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)
+ * 
  */
-  __pyx_t_1 = __Pyx_PyInt_From_enum__mpv_format(__pyx_v_format); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 679, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_v = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_prep_native_value(__pyx_v_self, __pyx_v_value, __pyx_t_1);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":682
- *         cdef int err
- *         cdef const char* prop_c
- *         try:             # <<<<<<<<<<<<<<
- *             prop_c = prop
- *             with nogil:
+        /* "vidcutter/libs/pympv/mpv.pyx":726
+ *         self.callbackthread.set(callback)
+ *         with nogil:
+ *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)             # <<<<<<<<<<<<<<
+ * 
+ *     def get_wakeup_pipe(self):
  */
-  /*try:*/ {
+        mpv_set_wakeup_callback(__pyx_v_self->_ctx, __pyx_f_9vidcutter_4libs_3mpv__c_callback, ((void *)__pyx_v_name));
+      }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":683
- *         cdef const char* prop_c
- *         try:
- *             prop_c = prop             # <<<<<<<<<<<<<<
- *             with nogil:
- *                 err = mpv_set_option(
+      /* "vidcutter/libs/pympv/mpv.pyx":725
+ *         self.callback = callback
+ *         self.callbackthread.set(callback)
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)
+ * 
  */
-    __pyx_t_5 = __Pyx_PyObject_AsString(__pyx_v_prop); if (unlikely((!__pyx_t_5) && PyErr_Occurred())) __PYX_ERR(0, 683, __pyx_L4_error)
-    __pyx_v_prop_c = __pyx_t_5;
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
+      }
+  }
 
-    /* "vidcutter/libs/pympv/mpv.pyx":684
- *         try:
- *             prop_c = prop
- *             with nogil:             # <<<<<<<<<<<<<<
- *                 err = mpv_set_option(
- *                     self._ctx,
+  /* "vidcutter/libs/pympv/mpv.pyx":719
+ *             mpv_wakeup(self._ctx)
+ * 
+ *     def set_wakeup_callback(self, callback):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_set_wakeup_callback"""
+ *         assert self._ctx
  */
-    {
-        #ifdef WITH_THREAD
-        PyThreadState *_save;
-        Py_UNBLOCK_THREADS
-        __Pyx_FastGIL_Remember();
-        #endif
-        /*try:*/ {
 
-          /* "vidcutter/libs/pympv/mpv.pyx":685
- *             prop_c = prop
- *             with nogil:
- *                 err = mpv_set_option(             # <<<<<<<<<<<<<<
- *                     self._ctx,
- *                     prop_c,
+  /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_wakeup_callback", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "vidcutter/libs/pympv/mpv.pyx":728
+ *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)
+ * 
+ *     def get_wakeup_pipe(self):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_get_wakeup_pipe"""
+ *         assert self._ctx
  */
-          __pyx_v_err = mpv_set_option(__pyx_v_self->_ctx, __pyx_v_prop_c, MPV_FORMAT_NODE, (&__pyx_v_v));
-        }
 
-        /* "vidcutter/libs/pympv/mpv.pyx":684
- *         try:
- *             prop_c = prop
- *             with nogil:             # <<<<<<<<<<<<<<
- *                 err = mpv_set_option(
- *                     self._ctx,
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_31get_wakeup_pipe(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_30get_wakeup_pipe[] = "Wraps: mpv_get_wakeup_pipe";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_31get_wakeup_pipe(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("get_wakeup_pipe (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_30get_wakeup_pipe(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_30get_wakeup_pipe(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
+  int __pyx_v_pipe;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("get_wakeup_pipe", 0);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":730
+ *     def get_wakeup_pipe(self):
+ *         """Wraps: mpv_get_wakeup_pipe"""
+ *         assert self._ctx             # <<<<<<<<<<<<<<
+ *         cdef int pipe
+ *         with nogil:
  */
-        /*finally:*/ {
-          /*normal exit:*/{
-            #ifdef WITH_THREAD
-            __Pyx_FastGIL_Forget();
-            Py_BLOCK_THREADS
-            #endif
-            goto __pyx_L8;
-          }
-          __pyx_L8:;
-        }
+  #ifndef CYTHON_WITHOUT_ASSERTIONS
+  if (unlikely(!Py_OptimizeFlag)) {
+    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
+      PyErr_SetNone(PyExc_AssertionError);
+      __PYX_ERR(0, 730, __pyx_L1_error)
     }
   }
+  #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":692
- *                 )
- *         finally:
- *             self._free_native_value(v)             # <<<<<<<<<<<<<<
- *         return err
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":732
+ *         assert self._ctx
+ *         cdef int pipe
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             pipe = mpv_get_wakeup_pipe(self._ctx)
+ *         return pipe
  */
-  /*finally:*/ {
-    /*normal exit:*/{
-      __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 692, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L5;
-    }
-    __pyx_L4_error:;
-    /*exception exit:*/{
-      __Pyx_PyThreadState_declare
-      __Pyx_PyThreadState_assign
-      __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0;
-      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-      __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (PY_MAJOR_VERSION >= 3) __Pyx_ExceptionSwap(&__pyx_t_12, &__pyx_t_13, &__pyx_t_14);
-      if ((PY_MAJOR_VERSION < 3) || unlikely(__Pyx_GetException(&__pyx_t_9, &__pyx_t_10, &__pyx_t_11) < 0)) __Pyx_ErrFetch(&__pyx_t_9, &__pyx_t_10, &__pyx_t_11);
-      __Pyx_XGOTREF(__pyx_t_9);
-      __Pyx_XGOTREF(__pyx_t_10);
-      __Pyx_XGOTREF(__pyx_t_11);
-      __Pyx_XGOTREF(__pyx_t_12);
-      __Pyx_XGOTREF(__pyx_t_13);
-      __Pyx_XGOTREF(__pyx_t_14);
-      __pyx_t_6 = __pyx_lineno; __pyx_t_7 = __pyx_clineno; __pyx_t_8 = __pyx_filename;
-      {
-        __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Context *)__pyx_v_self->__pyx_vtab)->_free_native_value(__pyx_v_self, __pyx_v_v); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 692, __pyx_L10_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      }
-      if (PY_MAJOR_VERSION >= 3) {
-        __Pyx_XGIVEREF(__pyx_t_12);
-        __Pyx_XGIVEREF(__pyx_t_13);
-        __Pyx_XGIVEREF(__pyx_t_14);
-        __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_13, __pyx_t_14);
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
+
+        /* "vidcutter/libs/pympv/mpv.pyx":733
+ *         cdef int pipe
+ *         with nogil:
+ *             pipe = mpv_get_wakeup_pipe(self._ctx)             # <<<<<<<<<<<<<<
+ *         return pipe
+ * 
+ */
+        __pyx_v_pipe = mpv_get_wakeup_pipe(__pyx_v_self->_ctx);
       }
-      __Pyx_XGIVEREF(__pyx_t_9);
-      __Pyx_XGIVEREF(__pyx_t_10);
-      __Pyx_XGIVEREF(__pyx_t_11);
-      __Pyx_ErrRestore(__pyx_t_9, __pyx_t_10, __pyx_t_11);
-      __pyx_t_9 = 0; __pyx_t_10 = 0; __pyx_t_11 = 0; __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0;
-      __pyx_lineno = __pyx_t_6; __pyx_clineno = __pyx_t_7; __pyx_filename = __pyx_t_8;
-      goto __pyx_L1_error;
-      __pyx_L10_error:;
-      if (PY_MAJOR_VERSION >= 3) {
-        __Pyx_XGIVEREF(__pyx_t_12);
-        __Pyx_XGIVEREF(__pyx_t_13);
-        __Pyx_XGIVEREF(__pyx_t_14);
-        __Pyx_ExceptionReset(__pyx_t_12, __pyx_t_13, __pyx_t_14);
+
+      /* "vidcutter/libs/pympv/mpv.pyx":732
+ *         assert self._ctx
+ *         cdef int pipe
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             pipe = mpv_get_wakeup_pipe(self._ctx)
+ *         return pipe
+ */
+      /*finally:*/ {
+        /*normal exit:*/{
+          #ifdef WITH_THREAD
+          __Pyx_FastGIL_Forget();
+          Py_BLOCK_THREADS
+          #endif
+          goto __pyx_L5;
+        }
+        __pyx_L5:;
       }
-      __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
-      __Pyx_XDECREF(__pyx_t_10); __pyx_t_10 = 0;
-      __Pyx_XDECREF(__pyx_t_11); __pyx_t_11 = 0;
-      __pyx_t_12 = 0; __pyx_t_13 = 0; __pyx_t_14 = 0;
-      goto __pyx_L1_error;
-    }
-    __pyx_L5:;
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":693
- *         finally:
- *             self._free_native_value(v)
- *         return err             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":734
+ *         with nogil:
+ *             pipe = mpv_get_wakeup_pipe(self._ctx)
+ *         return pipe             # <<<<<<<<<<<<<<
  * 
- *     @_errors
+ *     def __cinit__(self):
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 693, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_pipe); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 734, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_r = __pyx_t_1;
   __pyx_t_1 = 0;
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":674
+  /* "vidcutter/libs/pympv/mpv.pyx":728
+ *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)
  * 
- *     @_errors
- *     def set_option(self, prop, value=True):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_set_option"""
+ *     def get_wakeup_pipe(self):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_get_wakeup_pipe"""
  *         assert self._ctx
  */
 
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_option", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.get_wakeup_pipe", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_prop);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":696
+/* "vidcutter/libs/pympv/mpv.pyx":736
+ *         return pipe
  * 
- *     @_errors
- *     def initialize(self):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_initialize"""
- *         assert self._ctx
+ *     def __cinit__(self):             # <<<<<<<<<<<<<<
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
+ *         with nogil:
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_27initialize(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_26initialize[] = "Wraps: mpv_initialize";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_27initialize(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
+static int __pyx_pw_9vidcutter_4libs_3mpv_7Context_33__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_7Context_33__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  int __pyx_r;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("initialize (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_26initialize(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
+  if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) {
+    __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;}
+  if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__cinit__", 0))) return -1;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_32__cinit__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_26initialize(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  int __pyx_v_err;
-  PyObject *__pyx_r = NULL;
+static int __pyx_pf_9vidcutter_4libs_3mpv_7Context_32__cinit__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
+  uint64_t __pyx_v_ctxid;
+  int __pyx_r;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
+  uint64_t __pyx_t_2;
+  int __pyx_t_3;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("initialize", 0);
+  __Pyx_RefNannySetupContext("__cinit__", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":698
- *     def initialize(self):
- *         """Wraps: mpv_initialize"""
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         cdef int err
+  /* "vidcutter/libs/pympv/mpv.pyx":737
+ * 
+ *     def __cinit__(self):
+ *         cdef uint64_t ctxid = <uint64_t>id(self)             # <<<<<<<<<<<<<<
  *         with nogil:
+ *             self._ctx = mpv_create()
  */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 698, __pyx_L1_error)
-    }
-  }
-  #endif
+  __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 737, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyInt_As_uint64_t(__pyx_t_1); if (unlikely((__pyx_t_2 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 737, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_ctxid = ((uint64_t)__pyx_t_2);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":700
- *         assert self._ctx
- *         cdef int err
+  /* "vidcutter/libs/pympv/mpv.pyx":738
+ *     def __cinit__(self):
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
  *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_initialize(self._ctx)
- *         return err
+ *             self._ctx = mpv_create()
+ *         if not self._ctx:
  */
   {
       #ifdef WITH_THREAD
@@ -14114,22 +13975,22 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_26initialize(struct __p
       #endif
       /*try:*/ {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":701
- *         cdef int err
+        /* "vidcutter/libs/pympv/mpv.pyx":739
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
  *         with nogil:
- *             err = mpv_initialize(self._ctx)             # <<<<<<<<<<<<<<
- *         return err
- * 
+ *             self._ctx = mpv_create()             # <<<<<<<<<<<<<<
+ *         if not self._ctx:
+ *             raise MPVError("Context creation error")
  */
-        __pyx_v_err = mpv_initialize(__pyx_v_self->_ctx);
+        __pyx_v_self->_ctx = mpv_create();
       }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":700
- *         assert self._ctx
- *         cdef int err
+      /* "vidcutter/libs/pympv/mpv.pyx":738
+ *     def __cinit__(self):
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
  *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_initialize(self._ctx)
- *         return err
+ *             self._ctx = mpv_create()
+ *         if not self._ctx:
  */
       /*finally:*/ {
         /*normal exit:*/{
@@ -14143,66 +14004,200 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_26initialize(struct __p
       }
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":702
+  /* "vidcutter/libs/pympv/mpv.pyx":740
  *         with nogil:
- *             err = mpv_initialize(self._ctx)
- *         return err             # <<<<<<<<<<<<<<
- * 
- *     def wait_event(self, timeout=None):
+ *             self._ctx = mpv_create()
+ *         if not self._ctx:             # <<<<<<<<<<<<<<
+ *             raise MPVError("Context creation error")
+ *         self.callbackthread = CallbackThread()
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 702, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
+  __pyx_t_3 = ((!(__pyx_v_self->_ctx != 0)) != 0);
+  if (unlikely(__pyx_t_3)) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":696
- * 
- *     @_errors
- *     def initialize(self):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_initialize"""
- *         assert self._ctx
+    /* "vidcutter/libs/pympv/mpv.pyx":741
+ *             self._ctx = mpv_create()
+ *         if not self._ctx:
+ *             raise MPVError("Context creation error")             # <<<<<<<<<<<<<<
+ *         self.callbackthread = CallbackThread()
+ *         _callbacks[ctxid] = self.callbackthread
  */
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 741, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
+    }
+    __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_s_Context_creation_error) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_s_Context_creation_error);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 741, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 741, __pyx_L1_error)
 
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.initialize", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
+    /* "vidcutter/libs/pympv/mpv.pyx":740
+ *         with nogil:
+ *             self._ctx = mpv_create()
+ *         if not self._ctx:             # <<<<<<<<<<<<<<
+ *             raise MPVError("Context creation error")
+ *         self.callbackthread = CallbackThread()
+ */
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":742
+ *         if not self._ctx:
+ *             raise MPVError("Context creation error")
+ *         self.callbackthread = CallbackThread()             # <<<<<<<<<<<<<<
+ *         _callbacks[ctxid] = self.callbackthread
+ *         self.reply_userdata = dict()
+ */
+  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_CallbackThread); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 742, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+    if (likely(__pyx_t_5)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_4, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 742, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->callbackthread);
+  __Pyx_DECREF(__pyx_v_self->callbackthread);
+  __pyx_v_self->callbackthread = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":743
+ *             raise MPVError("Context creation error")
+ *         self.callbackthread = CallbackThread()
+ *         _callbacks[ctxid] = self.callbackthread             # <<<<<<<<<<<<<<
+ *         self.reply_userdata = dict()
+ *         _reply_userdatas[ctxid] = self.reply_userdata
+ */
+  __pyx_t_1 = __pyx_v_self->callbackthread;
+  __Pyx_INCREF(__pyx_t_1);
+  if (unlikely(__Pyx_SetItemInt(__pyx_v_9vidcutter_4libs_3mpv__callbacks, __pyx_v_ctxid, __pyx_t_1, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 743, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":744
+ *         self.callbackthread = CallbackThread()
+ *         _callbacks[ctxid] = self.callbackthread
+ *         self.reply_userdata = dict()             # <<<<<<<<<<<<<<
+ *         _reply_userdatas[ctxid] = self.reply_userdata
+ *         self.callbackthread.start()
+ */
+  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 744, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->reply_userdata);
+  __Pyx_DECREF(__pyx_v_self->reply_userdata);
+  __pyx_v_self->reply_userdata = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":745
+ *         _callbacks[ctxid] = self.callbackthread
+ *         self.reply_userdata = dict()
+ *         _reply_userdatas[ctxid] = self.reply_userdata             # <<<<<<<<<<<<<<
+ *         self.callbackthread.start()
+ * 
+ */
+  __pyx_t_1 = __pyx_v_self->reply_userdata;
+  __Pyx_INCREF(__pyx_t_1);
+  if (unlikely(__Pyx_SetItemInt(__pyx_v_9vidcutter_4libs_3mpv__reply_userdatas, __pyx_v_ctxid, __pyx_t_1, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 745, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":746
+ *         self.reply_userdata = dict()
+ *         _reply_userdatas[ctxid] = self.reply_userdata
+ *         self.callbackthread.start()             # <<<<<<<<<<<<<<
+ * 
+ *     @_errors
+ */
+  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->callbackthread, __pyx_n_s_start); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 746, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+    if (likely(__pyx_t_5)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_4, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 746, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":736
+ *         return pipe
+ * 
+ *     def __cinit__(self):             # <<<<<<<<<<<<<<
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
+ *         with nogil:
+ */
+
+  /* function exit code */
+  __pyx_r = 0;
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = -1;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":704
- *         return err
+/* "vidcutter/libs/pympv/mpv.pyx":749
  * 
- *     def wait_event(self, timeout=None):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_wait_event"""
+ *     @_errors
+ *     def observe_property(self, prop, data=None):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_observe_property"""
  *         assert self._ctx
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_29wait_event(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_28wait_event[] = "Wraps: mpv_wait_event";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_29wait_event(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_timeout = 0;
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_35observe_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_34observe_property[] = "Wraps: mpv_observe_property";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_35observe_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_prop = 0;
+  PyObject *__pyx_v_data = 0;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("wait_event (wrapper)", 0);
+  __Pyx_RefNannySetupContext("observe_property (wrapper)", 0);
   {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_timeout,0};
-    PyObject* values[1] = {0};
-    values[0] = ((PyObject *)Py_None);
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_data,0};
+    PyObject* values[2] = {0,0};
+    values[1] = ((PyObject *)Py_None);
     if (unlikely(__pyx_kwds)) {
       Py_ssize_t kw_args;
       const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
       switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
         case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
         CYTHON_FALLTHROUGH;
         case  0: break;
@@ -14211,117 +14206,291 @@ static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_29wait_event(PyObject *
       kw_args = PyDict_Size(__pyx_kwds);
       switch (pos_args) {
         case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_prop)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
         if (kw_args > 0) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_timeout);
-          if (value) { values[0] = value; kw_args--; }
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data);
+          if (value) { values[1] = value; kw_args--; }
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "wait_event") < 0)) __PYX_ERR(0, 704, __pyx_L3_error)
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "observe_property") < 0)) __PYX_ERR(0, 749, __pyx_L3_error)
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
         CYTHON_FALLTHROUGH;
-        case  0: break;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
         default: goto __pyx_L5_argtuple_error;
       }
     }
-    __pyx_v_timeout = values[0];
+    __pyx_v_prop = values[0];
+    __pyx_v_data = values[1];
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("wait_event", 0, 0, 1, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 704, __pyx_L3_error)
+  __Pyx_RaiseArgtupleInvalid("observe_property", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 749, __pyx_L3_error)
   __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.wait_event", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.observe_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_28wait_event(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_timeout);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_34observe_property(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_data);
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_28wait_event(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_timeout) {
-  double __pyx_v_timeout_d;
-  struct mpv_event *__pyx_v_event;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_34observe_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data) {
+  uint64_t __pyx_v_id_data;
+  PyObject *__pyx_v_userdatas = NULL;
+  char *__pyx_v_propc;
+  int __pyx_v_err;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  double __pyx_t_1;
-  int __pyx_t_2;
-  double __pyx_t_3;
+  Py_hash_t __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
+  int __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
+  int __pyx_t_8;
+  int __pyx_t_9;
+  char *__pyx_t_10;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("wait_event", 0);
+  __Pyx_RefNannySetupContext("observe_property", 0);
+  __Pyx_INCREF(__pyx_v_prop);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":706
- *     def wait_event(self, timeout=None):
- *         """Wraps: mpv_wait_event"""
+  /* "vidcutter/libs/pympv/mpv.pyx":751
+ *     def observe_property(self, prop, data=None):
+ *         """Wraps: mpv_observe_property"""
  *         assert self._ctx             # <<<<<<<<<<<<<<
- *         cdef double timeout_d = timeout if timeout is not None else -1
- *         cdef mpv_event* event
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         id_data = <uint64_t>hash(data)
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
   if (unlikely(!Py_OptimizeFlag)) {
     if (unlikely(!(__pyx_v_self->_ctx != 0))) {
       PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 706, __pyx_L1_error)
+      __PYX_ERR(0, 751, __pyx_L1_error)
     }
   }
   #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":707
- *         """Wraps: mpv_wait_event"""
+  /* "vidcutter/libs/pympv/mpv.pyx":752
+ *         """Wraps: mpv_observe_property"""
  *         assert self._ctx
- *         cdef double timeout_d = timeout if timeout is not None else -1             # <<<<<<<<<<<<<<
- *         cdef mpv_event* event
- *         with nogil:
+ *         cdef uint64_t id_data = <uint64_t>hash(data)             # <<<<<<<<<<<<<<
+ *         id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)
  */
-  __pyx_t_2 = (__pyx_v_timeout != Py_None);
-  if ((__pyx_t_2 != 0)) {
-    __pyx_t_3 = __pyx_PyFloat_AsDouble(__pyx_v_timeout); if (unlikely((__pyx_t_3 == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 707, __pyx_L1_error)
-    __pyx_t_1 = __pyx_t_3;
-  } else {
-    __pyx_t_1 = -1.0;
-  }
-  __pyx_v_timeout_d = __pyx_t_1;
+  __pyx_t_1 = PyObject_Hash(__pyx_v_data); if (unlikely(__pyx_t_1 == ((Py_hash_t)-1))) __PYX_ERR(0, 752, __pyx_L1_error)
+  __pyx_v_id_data = ((uint64_t)__pyx_t_1);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":709
- *         cdef double timeout_d = timeout if timeout is not None else -1
- *         cdef mpv_event* event
- *         with nogil:             # <<<<<<<<<<<<<<
- *             event = mpv_wait_event(self._ctx, timeout_d)
- *         return Event()._init(event, self)
+  /* "vidcutter/libs/pympv/mpv.pyx":753
+ *         assert self._ctx
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         id_data = <uint64_t>hash(data)             # <<<<<<<<<<<<<<
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is None:
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+  __pyx_t_1 = PyObject_Hash(__pyx_v_data); if (unlikely(__pyx_t_1 == ((Py_hash_t)-1))) __PYX_ERR(0, 753, __pyx_L1_error)
+  __pyx_v_id_data = ((uint64_t)__pyx_t_1);
 
-        /* "vidcutter/libs/pympv/mpv.pyx":710
- *         cdef mpv_event* event
- *         with nogil:
- *             event = mpv_wait_event(self._ctx, timeout_d)             # <<<<<<<<<<<<<<
- *         return Event()._init(event, self)
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":754
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)             # <<<<<<<<<<<<<<
+ *         if userdatas is None:
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
  */
-        __pyx_v_event = mpv_wait_event(__pyx_v_self->_ctx, __pyx_v_timeout_d);
-      }
-
-      /* "vidcutter/libs/pympv/mpv.pyx":709
- *         cdef double timeout_d = timeout if timeout is not None else -1
- *         cdef mpv_event* event
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->reply_userdata, __pyx_n_s_get); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 754, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = __Pyx_PyInt_From_uint64_t(__pyx_v_id_data); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 754, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = NULL;
+  __pyx_t_6 = 0;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
+    if (likely(__pyx_t_5)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_3, function);
+      __pyx_t_6 = 1;
+    }
+  }
+  #if CYTHON_FAST_PYCALL
+  if (PyFunction_Check(__pyx_t_3)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_4, Py_None};
+    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 754, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  } else
+  #endif
+  #if CYTHON_FAST_PYCCALL
+  if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_4, Py_None};
+    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 754, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  } else
+  #endif
+  {
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 754, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    if (__pyx_t_5) {
+      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
+    }
+    __Pyx_GIVEREF(__pyx_t_4);
+    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_t_4);
+    __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(Py_None);
+    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, Py_None);
+    __pyx_t_4 = 0;
+    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_7, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 754, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+  }
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_userdatas = __pyx_t_2;
+  __pyx_t_2 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":755
+ *         id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is None:             # <<<<<<<<<<<<<<
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+ *         userdatas.observed = True
+ */
+  __pyx_t_8 = (__pyx_v_userdatas == Py_None);
+  __pyx_t_9 = (__pyx_t_8 != 0);
+  if (__pyx_t_9) {
+
+    /* "vidcutter/libs/pympv/mpv.pyx":756
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is None:
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)             # <<<<<<<<<<<<<<
+ *         userdatas.observed = True
+ *         prop = _strenc(prop)
+ */
+    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_ReplyUserData); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 756, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_7 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3);
+      if (likely(__pyx_t_7)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_7);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_3, function);
+      }
+    }
+    __pyx_t_2 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_7, __pyx_v_data) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_data);
+    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 756, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (unlikely(__Pyx_SetItemInt(__pyx_v_self->reply_userdata, __pyx_v_id_data, __pyx_t_2, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 756, __pyx_L1_error)
+    __Pyx_INCREF(__pyx_t_2);
+    __Pyx_DECREF_SET(__pyx_v_userdatas, __pyx_t_2);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+    /* "vidcutter/libs/pympv/mpv.pyx":755
+ *         id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is None:             # <<<<<<<<<<<<<<
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+ *         userdatas.observed = True
+ */
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":757
+ *         if userdatas is None:
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+ *         userdatas.observed = True             # <<<<<<<<<<<<<<
+ *         prop = _strenc(prop)
+ *         cdef char* propc = prop
+ */
+  if (__Pyx_PyObject_SetAttrStr(__pyx_v_userdatas, __pyx_n_s_observed, Py_True) < 0) __PYX_ERR(0, 757, __pyx_L1_error)
+
+  /* "vidcutter/libs/pympv/mpv.pyx":758
+ *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+ *         userdatas.observed = True
+ *         prop = _strenc(prop)             # <<<<<<<<<<<<<<
+ *         cdef char* propc = prop
+ *         cdef int err
+ */
+  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_strenc); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 758, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_7 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3);
+    if (likely(__pyx_t_7)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_7);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_3, function);
+    }
+  }
+  __pyx_t_2 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_7, __pyx_v_prop) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_prop);
+  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 758, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_DECREF_SET(__pyx_v_prop, __pyx_t_2);
+  __pyx_t_2 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":759
+ *         userdatas.observed = True
+ *         prop = _strenc(prop)
+ *         cdef char* propc = prop             # <<<<<<<<<<<<<<
+ *         cdef int err
+ *         with nogil:
+ */
+  __pyx_t_10 = __Pyx_PyObject_AsWritableString(__pyx_v_prop); if (unlikely((!__pyx_t_10) && PyErr_Occurred())) __PYX_ERR(0, 759, __pyx_L1_error)
+  __pyx_v_propc = __pyx_t_10;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":761
+ *         cdef char* propc = prop
+ *         cdef int err
  *         with nogil:             # <<<<<<<<<<<<<<
- *             event = mpv_wait_event(self._ctx, timeout_d)
- *         return Event()._init(event, self)
+ *             err = mpv_observe_property(
+ *                 self._ctx,
+ */
+  {
+      #ifdef WITH_THREAD
+      PyThreadState *_save;
+      Py_UNBLOCK_THREADS
+      __Pyx_FastGIL_Remember();
+      #endif
+      /*try:*/ {
+
+        /* "vidcutter/libs/pympv/mpv.pyx":762
+ *         cdef int err
+ *         with nogil:
+ *             err = mpv_observe_property(             # <<<<<<<<<<<<<<
+ *                 self._ctx,
+ *                 id_data,
+ */
+        __pyx_v_err = mpv_observe_property(__pyx_v_self->_ctx, __pyx_v_id_data, __pyx_v_propc, MPV_FORMAT_NODE);
+      }
+
+      /* "vidcutter/libs/pympv/mpv.pyx":761
+ *         cdef char* propc = prop
+ *         cdef int err
+ *         with nogil:             # <<<<<<<<<<<<<<
+ *             err = mpv_observe_property(
+ *                 self._ctx,
  */
       /*finally:*/ {
         /*normal exit:*/{
@@ -14329,101 +14498,248 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_28wait_event(struct __p
           __Pyx_FastGIL_Forget();
           Py_BLOCK_THREADS
           #endif
-          goto __pyx_L5;
+          goto __pyx_L6;
         }
-        __pyx_L5:;
+        __pyx_L6:;
       }
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":711
- *         with nogil:
- *             event = mpv_wait_event(self._ctx, timeout_d)
- *         return Event()._init(event, self)             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":768
+ *                 MPV_FORMAT_NODE,
+ *             )
+ *         return err             # <<<<<<<<<<<<<<
  * 
- *     def wakeup(self):
+ *     @_errors
  */
   __Pyx_XDECREF(__pyx_r);
-  __pyx_t_4 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_Event)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 711, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv_Event *)((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_t_4)->__pyx_vtab)->_init(((struct __pyx_obj_9vidcutter_4libs_3mpv_Event *)__pyx_t_4), __pyx_v_event, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 711, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_r = __pyx_t_5;
-  __pyx_t_5 = 0;
+  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 768, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_r = __pyx_t_2;
+  __pyx_t_2 = 0;
   goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":704
- *         return err
+  /* "vidcutter/libs/pympv/mpv.pyx":749
  * 
- *     def wait_event(self, timeout=None):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_wait_event"""
+ *     @_errors
+ *     def observe_property(self, prop, data=None):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_observe_property"""
  *         assert self._ctx
  */
 
   /* function exit code */
   __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.wait_event", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.observe_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_userdatas);
+  __Pyx_XDECREF(__pyx_v_prop);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":713
- *         return Event()._init(event, self)
+/* "vidcutter/libs/pympv/mpv.pyx":771
  * 
- *     def wakeup(self):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_wakeup"""
+ *     @_errors
+ *     def unobserve_property(self, data):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_unobserve_property"""
  *         assert self._ctx
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_31wakeup(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_30wakeup[] = "Wraps: mpv_wakeup";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_31wakeup(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_37unobserve_property(PyObject *__pyx_v_self, PyObject *__pyx_v_data); /*proto*/
+static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_36unobserve_property[] = "Wraps: mpv_unobserve_property";
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_37unobserve_property(PyObject *__pyx_v_self, PyObject *__pyx_v_data) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("wakeup (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_30wakeup(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("unobserve_property (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_36unobserve_property(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_data));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_30wakeup(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_36unobserve_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_data) {
+  uint64_t __pyx_v_id_data;
+  PyObject *__pyx_v_userdatas = NULL;
+  int __pyx_v_err;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
+  Py_hash_t __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
+  int __pyx_t_8;
+  int __pyx_t_9;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("wakeup", 0);
+  __Pyx_RefNannySetupContext("unobserve_property", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":715
- *     def wakeup(self):
- *         """Wraps: mpv_wakeup"""
+  /* "vidcutter/libs/pympv/mpv.pyx":773
+ *     def unobserve_property(self, data):
+ *         """Wraps: mpv_unobserve_property"""
  *         assert self._ctx             # <<<<<<<<<<<<<<
- *         with nogil:
- *             mpv_wakeup(self._ctx)
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)
  */
   #ifndef CYTHON_WITHOUT_ASSERTIONS
   if (unlikely(!Py_OptimizeFlag)) {
     if (unlikely(!(__pyx_v_self->_ctx != 0))) {
       PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 715, __pyx_L1_error)
+      __PYX_ERR(0, 773, __pyx_L1_error)
     }
   }
   #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":716
- *         """Wraps: mpv_wakeup"""
+  /* "vidcutter/libs/pympv/mpv.pyx":774
+ *         """Wraps: mpv_unobserve_property"""
+ *         assert self._ctx
+ *         cdef uint64_t id_data = <uint64_t>hash(data)             # <<<<<<<<<<<<<<
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is not None:
+ */
+  __pyx_t_1 = PyObject_Hash(__pyx_v_data); if (unlikely(__pyx_t_1 == ((Py_hash_t)-1))) __PYX_ERR(0, 774, __pyx_L1_error)
+  __pyx_v_id_data = ((uint64_t)__pyx_t_1);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":775
  *         assert self._ctx
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)             # <<<<<<<<<<<<<<
+ *         if userdatas is not None:
+ *             userdatas.observed = False
+ */
+  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->reply_userdata, __pyx_n_s_get); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 775, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_4 = __Pyx_PyInt_From_uint64_t(__pyx_v_id_data); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 775, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = NULL;
+  __pyx_t_6 = 0;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
+    if (likely(__pyx_t_5)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_3, function);
+      __pyx_t_6 = 1;
+    }
+  }
+  #if CYTHON_FAST_PYCALL
+  if (PyFunction_Check(__pyx_t_3)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_4, Py_None};
+    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 775, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  } else
+  #endif
+  #if CYTHON_FAST_PYCCALL
+  if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
+    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_4, Py_None};
+    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 775, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  } else
+  #endif
+  {
+    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 775, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    if (__pyx_t_5) {
+      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
+    }
+    __Pyx_GIVEREF(__pyx_t_4);
+    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_t_4);
+    __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(Py_None);
+    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, Py_None);
+    __pyx_t_4 = 0;
+    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_7, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 775, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+  }
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_userdatas = __pyx_t_2;
+  __pyx_t_2 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":776
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is not None:             # <<<<<<<<<<<<<<
+ *             userdatas.observed = False
+ *             if userdatas.counter <= 0:
+ */
+  __pyx_t_8 = (__pyx_v_userdatas != Py_None);
+  __pyx_t_9 = (__pyx_t_8 != 0);
+  if (__pyx_t_9) {
+
+    /* "vidcutter/libs/pympv/mpv.pyx":777
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is not None:
+ *             userdatas.observed = False             # <<<<<<<<<<<<<<
+ *             if userdatas.counter <= 0:
+ *                 del self.reply_userdata[id_data]
+ */
+    if (__Pyx_PyObject_SetAttrStr(__pyx_v_userdatas, __pyx_n_s_observed, Py_False) < 0) __PYX_ERR(0, 777, __pyx_L1_error)
+
+    /* "vidcutter/libs/pympv/mpv.pyx":778
+ *         if userdatas is not None:
+ *             userdatas.observed = False
+ *             if userdatas.counter <= 0:             # <<<<<<<<<<<<<<
+ *                 del self.reply_userdata[id_data]
+ *         cdef int err
+ */
+    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdatas, __pyx_n_s_counter); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 778, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_3 = PyObject_RichCompare(__pyx_t_2, __pyx_int_0, Py_LE); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 778, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 778, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    if (__pyx_t_9) {
+
+      /* "vidcutter/libs/pympv/mpv.pyx":779
+ *             userdatas.observed = False
+ *             if userdatas.counter <= 0:
+ *                 del self.reply_userdata[id_data]             # <<<<<<<<<<<<<<
+ *         cdef int err
+ *         with nogil:
+ */
+      if (unlikely(__Pyx_DelItemInt(__pyx_v_self->reply_userdata, __pyx_v_id_data, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 779, __pyx_L1_error)
+
+      /* "vidcutter/libs/pympv/mpv.pyx":778
+ *         if userdatas is not None:
+ *             userdatas.observed = False
+ *             if userdatas.counter <= 0:             # <<<<<<<<<<<<<<
+ *                 del self.reply_userdata[id_data]
+ *         cdef int err
+ */
+    }
+
+    /* "vidcutter/libs/pympv/mpv.pyx":776
+ *         cdef uint64_t id_data = <uint64_t>hash(data)
+ *         userdatas = self.reply_userdata.get(id_data, None)
+ *         if userdatas is not None:             # <<<<<<<<<<<<<<
+ *             userdatas.observed = False
+ *             if userdatas.counter <= 0:
+ */
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":781
+ *                 del self.reply_userdata[id_data]
+ *         cdef int err
  *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_wakeup(self._ctx)
- * 
+ *             err = mpv_unobserve_property(
+ *                 self._ctx,
  */
   {
       #ifdef WITH_THREAD
@@ -14433,22 +14749,22 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_30wakeup(struct __pyx_o
       #endif
       /*try:*/ {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":717
- *         assert self._ctx
+        /* "vidcutter/libs/pympv/mpv.pyx":782
+ *         cdef int err
  *         with nogil:
- *             mpv_wakeup(self._ctx)             # <<<<<<<<<<<<<<
- * 
- *     def set_wakeup_callback(self, callback):
+ *             err = mpv_unobserve_property(             # <<<<<<<<<<<<<<
+ *                 self._ctx,
+ *                 id_data,
  */
-        mpv_wakeup(__pyx_v_self->_ctx);
+        __pyx_v_err = mpv_unobserve_property(__pyx_v_self->_ctx, __pyx_v_id_data);
       }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":716
- *         """Wraps: mpv_wakeup"""
- *         assert self._ctx
+      /* "vidcutter/libs/pympv/mpv.pyx":781
+ *                 del self.reply_userdata[id_data]
+ *         cdef int err
  *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_wakeup(self._ctx)
- * 
+ *             err = mpv_unobserve_property(
+ *                 self._ctx,
  */
       /*finally:*/ {
         /*normal exit:*/{
@@ -14456,141 +14772,134 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_30wakeup(struct __pyx_o
           __Pyx_FastGIL_Forget();
           Py_BLOCK_THREADS
           #endif
-          goto __pyx_L5;
+          goto __pyx_L7;
         }
-        __pyx_L5:;
+        __pyx_L7:;
       }
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":713
- *         return Event()._init(event, self)
+  /* "vidcutter/libs/pympv/mpv.pyx":786
+ *                 id_data,
+ *             )
+ *         return err             # <<<<<<<<<<<<<<
  * 
- *     def wakeup(self):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_wakeup"""
+ *     def shutdown(self):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 786, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_r = __pyx_t_3;
+  __pyx_t_3 = 0;
+  goto __pyx_L0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":771
+ * 
+ *     @_errors
+ *     def unobserve_property(self, data):             # <<<<<<<<<<<<<<
+ *         """Wraps: mpv_unobserve_property"""
  *         assert self._ctx
  */
 
   /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.wakeup", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.unobserve_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_userdatas);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":719
- *             mpv_wakeup(self._ctx)
+/* "vidcutter/libs/pympv/mpv.pyx":788
+ *         return err
  * 
- *     def set_wakeup_callback(self, callback):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_set_wakeup_callback"""
- *         assert self._ctx
+ *     def shutdown(self):             # <<<<<<<<<<<<<<
+ *         if self._ctx == NULL:
+ *             return
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_33set_wakeup_callback(PyObject *__pyx_v_self, PyObject *__pyx_v_callback); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_32set_wakeup_callback[] = "Wraps: mpv_set_wakeup_callback";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_33set_wakeup_callback(PyObject *__pyx_v_self, PyObject *__pyx_v_callback) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_39shutdown(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_39shutdown(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("set_wakeup_callback (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_32set_wakeup_callback(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_callback));
+  __Pyx_RefNannySetupContext("shutdown (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_38shutdown(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_32set_wakeup_callback(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_callback) {
-  uint64_t __pyx_v_name;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_38shutdown(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
+  uint64_t __pyx_v_ctxid;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  uint64_t __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
+  int __pyx_t_1;
+  PyObject *__pyx_t_2 = NULL;
+  uint64_t __pyx_t_3;
   PyObject *__pyx_t_4 = NULL;
+  PyObject *__pyx_t_5 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("set_wakeup_callback", 0);
+  __Pyx_RefNannySetupContext("shutdown", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":721
- *     def set_wakeup_callback(self, callback):
- *         """Wraps: mpv_set_wakeup_callback"""
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         cdef uint64_t name = <uint64_t>id(self)
- *         self.callback = callback
+  /* "vidcutter/libs/pympv/mpv.pyx":789
+ * 
+ *     def shutdown(self):
+ *         if self._ctx == NULL:             # <<<<<<<<<<<<<<
+ *             return
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
  */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 721, __pyx_L1_error)
-    }
-  }
-  #endif
+  __pyx_t_1 = ((__pyx_v_self->_ctx == NULL) != 0);
+  if (__pyx_t_1) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":722
- *         """Wraps: mpv_set_wakeup_callback"""
- *         assert self._ctx
- *         cdef uint64_t name = <uint64_t>id(self)             # <<<<<<<<<<<<<<
- *         self.callback = callback
- *         self.callbackthread.set(callback)
- */
-  __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 722, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyInt_As_uint64_t(__pyx_t_1); if (unlikely((__pyx_t_2 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 722, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_name = ((uint64_t)__pyx_t_2);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":723
- *         assert self._ctx
- *         cdef uint64_t name = <uint64_t>id(self)
- *         self.callback = callback             # <<<<<<<<<<<<<<
- *         self.callbackthread.set(callback)
+    /* "vidcutter/libs/pympv/mpv.pyx":790
+ *     def shutdown(self):
+ *         if self._ctx == NULL:
+ *             return             # <<<<<<<<<<<<<<
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
  *         with nogil:
  */
-  __Pyx_INCREF(__pyx_v_callback);
-  __Pyx_GIVEREF(__pyx_v_callback);
-  __Pyx_GOTREF(__pyx_v_self->callback);
-  __Pyx_DECREF(__pyx_v_self->callback);
-  __pyx_v_self->callback = __pyx_v_callback;
+    __Pyx_XDECREF(__pyx_r);
+    __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+    goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":724
- *         cdef uint64_t name = <uint64_t>id(self)
- *         self.callback = callback
- *         self.callbackthread.set(callback)             # <<<<<<<<<<<<<<
- *         with nogil:
- *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)
+    /* "vidcutter/libs/pympv/mpv.pyx":789
+ * 
+ *     def shutdown(self):
+ *         if self._ctx == NULL:             # <<<<<<<<<<<<<<
+ *             return
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
  */
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->callbackthread, __pyx_n_s_set); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 724, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_3, function);
-    }
   }
-  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_v_callback) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_callback);
-  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 724, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":725
- *         self.callback = callback
- *         self.callbackthread.set(callback)
+  /* "vidcutter/libs/pympv/mpv.pyx":791
+ *         if self._ctx == NULL:
+ *             return
+ *         cdef uint64_t ctxid = <uint64_t>id(self)             # <<<<<<<<<<<<<<
+ *         with nogil:
+ *             mpv_terminate_destroy(self._ctx)
+ */
+  __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 791, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = __Pyx_PyInt_As_uint64_t(__pyx_t_2); if (unlikely((__pyx_t_3 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 791, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_v_ctxid = ((uint64_t)__pyx_t_3);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":792
+ *             return
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
  *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)
- * 
+ *             mpv_terminate_destroy(self._ctx)
+ *         self.callbackthread.shutdown()
  */
   {
       #ifdef WITH_THREAD
@@ -14600,22 +14909,22 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_32set_wakeup_callback(s
       #endif
       /*try:*/ {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":726
- *         self.callbackthread.set(callback)
+        /* "vidcutter/libs/pympv/mpv.pyx":793
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
  *         with nogil:
- *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)             # <<<<<<<<<<<<<<
- * 
- *     def get_wakeup_pipe(self):
+ *             mpv_terminate_destroy(self._ctx)             # <<<<<<<<<<<<<<
+ *         self.callbackthread.shutdown()
+ *         del _callbacks[ctxid]
  */
-        mpv_set_wakeup_callback(__pyx_v_self->_ctx, __pyx_f_9vidcutter_4libs_3mpv__c_callback, ((void *)__pyx_v_name));
+        mpv_terminate_destroy(__pyx_v_self->_ctx);
       }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":725
- *         self.callback = callback
- *         self.callbackthread.set(callback)
+      /* "vidcutter/libs/pympv/mpv.pyx":792
+ *             return
+ *         cdef uint64_t ctxid = <uint64_t>id(self)
  *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)
- * 
+ *             mpv_terminate_destroy(self._ctx)
+ *         self.callbackthread.shutdown()
  */
       /*finally:*/ {
         /*normal exit:*/{
@@ -14623,28 +14932,107 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_32set_wakeup_callback(s
           __Pyx_FastGIL_Forget();
           Py_BLOCK_THREADS
           #endif
-          goto __pyx_L5;
+          goto __pyx_L6;
         }
-        __pyx_L5:;
+        __pyx_L6:;
       }
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":719
- *             mpv_wakeup(self._ctx)
+  /* "vidcutter/libs/pympv/mpv.pyx":794
+ *         with nogil:
+ *             mpv_terminate_destroy(self._ctx)
+ *         self.callbackthread.shutdown()             # <<<<<<<<<<<<<<
+ *         del _callbacks[ctxid]
+ *         del _reply_userdatas[ctxid]
+ */
+  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->callbackthread, __pyx_n_s_shutdown); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 794, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+    if (likely(__pyx_t_5)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_4, function);
+    }
+  }
+  __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 794, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":795
+ *             mpv_terminate_destroy(self._ctx)
+ *         self.callbackthread.shutdown()
+ *         del _callbacks[ctxid]             # <<<<<<<<<<<<<<
+ *         del _reply_userdatas[ctxid]
+ *         self.callback = None
+ */
+  if (unlikely(__Pyx_DelItemInt(__pyx_v_9vidcutter_4libs_3mpv__callbacks, __pyx_v_ctxid, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 795, __pyx_L1_error)
+
+  /* "vidcutter/libs/pympv/mpv.pyx":796
+ *         self.callbackthread.shutdown()
+ *         del _callbacks[ctxid]
+ *         del _reply_userdatas[ctxid]             # <<<<<<<<<<<<<<
+ *         self.callback = None
+ *         self.reply_userdata = None
+ */
+  if (unlikely(__Pyx_DelItemInt(__pyx_v_9vidcutter_4libs_3mpv__reply_userdatas, __pyx_v_ctxid, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 796, __pyx_L1_error)
+
+  /* "vidcutter/libs/pympv/mpv.pyx":797
+ *         del _callbacks[ctxid]
+ *         del _reply_userdatas[ctxid]
+ *         self.callback = None             # <<<<<<<<<<<<<<
+ *         self.reply_userdata = None
+ *         self._ctx = NULL
+ */
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->callback);
+  __Pyx_DECREF(__pyx_v_self->callback);
+  __pyx_v_self->callback = Py_None;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":798
+ *         del _reply_userdatas[ctxid]
+ *         self.callback = None
+ *         self.reply_userdata = None             # <<<<<<<<<<<<<<
+ *         self._ctx = NULL
  * 
- *     def set_wakeup_callback(self, callback):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_set_wakeup_callback"""
- *         assert self._ctx
+ */
+  __Pyx_INCREF(Py_None);
+  __Pyx_GIVEREF(Py_None);
+  __Pyx_GOTREF(__pyx_v_self->reply_userdata);
+  __Pyx_DECREF(__pyx_v_self->reply_userdata);
+  __pyx_v_self->reply_userdata = Py_None;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":799
+ *         self.callback = None
+ *         self.reply_userdata = None
+ *         self._ctx = NULL             # <<<<<<<<<<<<<<
+ * 
+ *     # def opengl_cb_api(self):
+ */
+  __pyx_v_self->_ctx = NULL;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":788
+ *         return err
+ * 
+ *     def shutdown(self):             # <<<<<<<<<<<<<<
+ *         if self._ctx == NULL:
+ *             return
  */
 
   /* function exit code */
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_2);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.set_wakeup_callback", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.shutdown", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
@@ -14652,374 +15040,403 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_32set_wakeup_callback(s
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":728
- *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)
+/* "vidcutter/libs/pympv/mpv.pyx":813
+ *     #     return ctx
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         self.shutdown()
  * 
- *     def get_wakeup_pipe(self):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_get_wakeup_pipe"""
- *         assert self._ctx
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_35get_wakeup_pipe(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_34get_wakeup_pipe[] = "Wraps: mpv_get_wakeup_pipe";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_35get_wakeup_pipe(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
+static void __pyx_pw_9vidcutter_4libs_3mpv_7Context_41__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_9vidcutter_4libs_3mpv_7Context_41__dealloc__(PyObject *__pyx_v_self) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("get_wakeup_pipe (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_34get_wakeup_pipe(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_9vidcutter_4libs_3mpv_7Context_40__dealloc__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
-  return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_34get_wakeup_pipe(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  int __pyx_v_pipe;
-  PyObject *__pyx_r = NULL;
+static void __pyx_pf_9vidcutter_4libs_3mpv_7Context_40__dealloc__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("get_wakeup_pipe", 0);
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":730
- *     def get_wakeup_pipe(self):
- *         """Wraps: mpv_get_wakeup_pipe"""
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         cdef int pipe
- *         with nogil:
+  /* "vidcutter/libs/pympv/mpv.pyx":814
+ * 
+ *     def __dealloc__(self):
+ *         self.shutdown()             # <<<<<<<<<<<<<<
+ * 
+ * cdef void *_c_getprocaddress(void *ctx, const char *name) with gil:
  */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 730, __pyx_L1_error)
+  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_shutdown); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 814, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_3)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  #endif
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 814, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":732
- *         assert self._ctx
- *         cdef int pipe
- *         with nogil:             # <<<<<<<<<<<<<<
- *             pipe = mpv_get_wakeup_pipe(self._ctx)
- *         return pipe
- */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
-
-        /* "vidcutter/libs/pympv/mpv.pyx":733
- *         cdef int pipe
- *         with nogil:
- *             pipe = mpv_get_wakeup_pipe(self._ctx)             # <<<<<<<<<<<<<<
- *         return pipe
+  /* "vidcutter/libs/pympv/mpv.pyx":813
+ *     #     return ctx
+ * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         self.shutdown()
  * 
  */
-        __pyx_v_pipe = mpv_get_wakeup_pipe(__pyx_v_self->_ctx);
-      }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":732
- *         assert self._ctx
- *         cdef int pipe
- *         with nogil:             # <<<<<<<<<<<<<<
- *             pipe = mpv_get_wakeup_pipe(self._ctx)
- *         return pipe
+  /* function exit code */
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_WriteUnraisable("vidcutter.libs.mpv.Context.__dealloc__", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+}
+
+/* "(tree fragment)":1
+ * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
+ *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ * def __setstate_cython__(self, __pyx_state):
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
-  }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":734
- *         with nogil:
- *             pipe = mpv_get_wakeup_pipe(self._ctx)
- *         return pipe             # <<<<<<<<<<<<<<
- * 
- *     def __cinit__(self):
+/* Python wrapper */
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_43__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_43__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_42__reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_42__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
+
+  /* "(tree fragment)":2
+ * def __reduce_cython__(self):
+ *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")             # <<<<<<<<<<<<<<
+ * def __setstate_cython__(self, __pyx_state):
+ *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_pipe); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 734, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_r = __pyx_t_1;
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
+  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __PYX_ERR(1, 2, __pyx_L1_error)
 
-  /* "vidcutter/libs/pympv/mpv.pyx":728
- *             mpv_set_wakeup_callback(self._ctx, _c_callback, <void*>name)
- * 
- *     def get_wakeup_pipe(self):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_get_wakeup_pipe"""
- *         assert self._ctx
+  /* "(tree fragment)":1
+ * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
+ *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ * def __setstate_cython__(self, __pyx_state):
  */
 
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.get_wakeup_pipe", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
-  __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":736
- *         return pipe
- * 
- *     def __cinit__(self):             # <<<<<<<<<<<<<<
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- *         with nogil:
+/* "(tree fragment)":3
+ * def __reduce_cython__(self):
+ *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
+ *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
  */
 
 /* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_7Context_37__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_7Context_37__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  int __pyx_r;
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_45__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_45__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+  PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
-  if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) {
-    __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;}
-  if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__cinit__", 0))) return -1;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_36__cinit__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_44__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_7Context_36__cinit__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  uint64_t __pyx_v_ctxid;
-  int __pyx_r;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_44__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) {
+  PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  uint64_t __pyx_t_2;
-  int __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__cinit__", 0);
+  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":737
- * 
- *     def __cinit__(self):
- *         cdef uint64_t ctxid = <uint64_t>id(self)             # <<<<<<<<<<<<<<
- *         with nogil:
- *             self._ctx = mpv_create()
+  /* "(tree fragment)":4
+ *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ * def __setstate_cython__(self, __pyx_state):
+ *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 737, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyInt_As_uint64_t(__pyx_t_1); if (unlikely((__pyx_t_2 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 737, __pyx_L1_error)
+  __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_ctxid = ((uint64_t)__pyx_t_2);
+  __PYX_ERR(1, 4, __pyx_L1_error)
 
-  /* "vidcutter/libs/pympv/mpv.pyx":738
- *     def __cinit__(self):
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- *         with nogil:             # <<<<<<<<<<<<<<
- *             self._ctx = mpv_create()
- *         if not self._ctx:
+  /* "(tree fragment)":3
+ * def __reduce_cython__(self):
+ *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
+ *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":739
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- *         with nogil:
- *             self._ctx = mpv_create()             # <<<<<<<<<<<<<<
- *         if not self._ctx:
- *             raise MPVError("Context creation error")
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+/* "vidcutter/libs/pympv/mpv.pyx":816
+ *         self.shutdown()
+ * 
+ * cdef void *_c_getprocaddress(void *ctx, const char *name) with gil:             # <<<<<<<<<<<<<<
+ *     return <void *><intptr_t>(<object>ctx)(name)
+ * 
  */
-        __pyx_v_self->_ctx = mpv_create();
-      }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":738
- *     def __cinit__(self):
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- *         with nogil:             # <<<<<<<<<<<<<<
- *             self._ctx = mpv_create()
- *         if not self._ctx:
+static void *__pyx_f_9vidcutter_4libs_3mpv__c_getprocaddress(void *__pyx_v_ctx, char const *__pyx_v_name) {
+  void *__pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_4 = NULL;
+  intptr_t __pyx_t_5;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  #ifdef WITH_THREAD
+  PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
+  #endif
+  __Pyx_RefNannySetupContext("_c_getprocaddress", 0);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":817
+ * 
+ * cdef void *_c_getprocaddress(void *ctx, const char *name) with gil:
+ *     return <void *><intptr_t>(<object>ctx)(name)             # <<<<<<<<<<<<<<
+ * 
+ * cdef void _c_updatecb(void *ctx) with gil:
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
+  __pyx_t_2 = __Pyx_PyBytes_FromString(__pyx_v_name); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 817, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_INCREF(((PyObject *)__pyx_v_ctx));
+  __pyx_t_3 = ((PyObject *)__pyx_v_ctx); __pyx_t_4 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
+    if (likely(__pyx_t_4)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_4);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_3, function);
+    }
   }
+  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 817, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_5 = __Pyx_PyInt_As_intptr_t(__pyx_t_1); if (unlikely((__pyx_t_5 == ((intptr_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 817, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_r = ((void *)((intptr_t)__pyx_t_5));
+  goto __pyx_L0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":740
- *         with nogil:
- *             self._ctx = mpv_create()
- *         if not self._ctx:             # <<<<<<<<<<<<<<
- *             raise MPVError("Context creation error")
- *         self.callbackthread = CallbackThread()
+  /* "vidcutter/libs/pympv/mpv.pyx":816
+ *         self.shutdown()
+ * 
+ * cdef void *_c_getprocaddress(void *ctx, const char *name) with gil:             # <<<<<<<<<<<<<<
+ *     return <void *><intptr_t>(<object>ctx)(name)
+ * 
  */
-  __pyx_t_3 = ((!(__pyx_v_self->_ctx != 0)) != 0);
-  if (unlikely(__pyx_t_3)) {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":741
- *             self._ctx = mpv_create()
- *         if not self._ctx:
- *             raise MPVError("Context creation error")             # <<<<<<<<<<<<<<
- *         self.callbackthread = CallbackThread()
- *         _callbacks[ctxid] = self.callbackthread
- */
-    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 741, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-      if (likely(__pyx_t_5)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-        __Pyx_INCREF(__pyx_t_5);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_4, function);
-      }
-    }
-    __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_s_Context_creation_error) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_s_Context_creation_error);
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 741, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __PYX_ERR(0, 741, __pyx_L1_error)
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_WriteUnraisable("vidcutter.libs.mpv._c_getprocaddress", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  #ifdef WITH_THREAD
+  __Pyx_PyGILState_Release(__pyx_gilstate_save);
+  #endif
+  return __pyx_r;
+}
 
-    /* "vidcutter/libs/pympv/mpv.pyx":740
- *         with nogil:
- *             self._ctx = mpv_create()
- *         if not self._ctx:             # <<<<<<<<<<<<<<
- *             raise MPVError("Context creation error")
- *         self.callbackthread = CallbackThread()
+/* "vidcutter/libs/pympv/mpv.pyx":819
+ *     return <void *><intptr_t>(<object>ctx)(name)
+ * 
+ * cdef void _c_updatecb(void *ctx) with gil:             # <<<<<<<<<<<<<<
+ *     (<object>ctx)()
+ * 
  */
-  }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":742
- *         if not self._ctx:
- *             raise MPVError("Context creation error")
- *         self.callbackthread = CallbackThread()             # <<<<<<<<<<<<<<
- *         _callbacks[ctxid] = self.callbackthread
- *         self.reply_userdata = dict()
+static void __pyx_f_9vidcutter_4libs_3mpv__c_updatecb(void *__pyx_v_ctx) {
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  PyObject *__pyx_t_3 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  #ifdef WITH_THREAD
+  PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
+  #endif
+  __Pyx_RefNannySetupContext("_c_updatecb", 0);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":820
+ * 
+ * cdef void _c_updatecb(void *ctx) with gil:
+ *     (<object>ctx)()             # <<<<<<<<<<<<<<
+ * 
+ * # cdef class OpenGLContext(object):
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_CallbackThread); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 742, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-    if (likely(__pyx_t_5)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_5);
+  __Pyx_INCREF(((PyObject *)__pyx_v_ctx));
+  __pyx_t_2 = ((PyObject *)__pyx_v_ctx); __pyx_t_3 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_3)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_3);
       __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_4, function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
     }
   }
-  __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 742, __pyx_L1_error)
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 820, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->callbackthread);
-  __Pyx_DECREF(__pyx_v_self->callbackthread);
-  __pyx_v_self->callbackthread = __pyx_t_1;
-  __pyx_t_1 = 0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":743
- *             raise MPVError("Context creation error")
- *         self.callbackthread = CallbackThread()
- *         _callbacks[ctxid] = self.callbackthread             # <<<<<<<<<<<<<<
- *         self.reply_userdata = dict()
- *         _reply_userdatas[ctxid] = self.reply_userdata
- */
-  __pyx_t_1 = __pyx_v_self->callbackthread;
-  __Pyx_INCREF(__pyx_t_1);
-  if (unlikely(__Pyx_SetItemInt(__pyx_v_9vidcutter_4libs_3mpv__callbacks, __pyx_v_ctxid, __pyx_t_1, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 743, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":744
- *         self.callbackthread = CallbackThread()
- *         _callbacks[ctxid] = self.callbackthread
- *         self.reply_userdata = dict()             # <<<<<<<<<<<<<<
- *         _reply_userdatas[ctxid] = self.reply_userdata
- *         self.callbackthread.start()
+  /* "vidcutter/libs/pympv/mpv.pyx":819
+ *     return <void *><intptr_t>(<object>ctx)(name)
+ * 
+ * cdef void _c_updatecb(void *ctx) with gil:             # <<<<<<<<<<<<<<
+ *     (<object>ctx)()
+ * 
  */
-  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 744, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_1);
-  __Pyx_GOTREF(__pyx_v_self->reply_userdata);
-  __Pyx_DECREF(__pyx_v_self->reply_userdata);
-  __pyx_v_self->reply_userdata = __pyx_t_1;
-  __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":745
- *         _callbacks[ctxid] = self.callbackthread
- *         self.reply_userdata = dict()
- *         _reply_userdatas[ctxid] = self.reply_userdata             # <<<<<<<<<<<<<<
- *         self.callbackthread.start()
+  /* function exit code */
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_WriteUnraisable("vidcutter.libs.mpv._c_updatecb", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
+  __pyx_L0:;
+  __Pyx_RefNannyFinishContext();
+  #ifdef WITH_THREAD
+  __Pyx_PyGILState_Release(__pyx_gilstate_save);
+  #endif
+}
+
+/* "vidcutter/libs/pympv/mpv.pyx":886
+ *         object owned
  * 
+ *     def __init__(self):             # <<<<<<<<<<<<<<
+ *         self.owned = []
+ *         self.params[0].type = MPV_RENDER_PARAM_INVALID
  */
-  __pyx_t_1 = __pyx_v_self->reply_userdata;
-  __Pyx_INCREF(__pyx_t_1);
-  if (unlikely(__Pyx_SetItemInt(__pyx_v_9vidcutter_4libs_3mpv__reply_userdatas, __pyx_v_ctxid, __pyx_t_1, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 745, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":746
- *         self.reply_userdata = dict()
- *         _reply_userdatas[ctxid] = self.reply_userdata
- *         self.callbackthread.start()             # <<<<<<<<<<<<<<
+/* Python wrapper */
+static int __pyx_pw_9vidcutter_4libs_3mpv_13_RenderParams_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_13_RenderParams_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
+  if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) {
+    __Pyx_RaiseArgtupleInvalid("__init__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;}
+  if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__init__", 0))) return -1;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams___init__(((struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *)__pyx_v_self));
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static int __pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams___init__(struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_self) {
+  int __pyx_r;
+  __Pyx_RefNannyDeclarations
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__init__", 0);
+
+  /* "vidcutter/libs/pympv/mpv.pyx":887
+ * 
+ *     def __init__(self):
+ *         self.owned = []             # <<<<<<<<<<<<<<
+ *         self.params[0].type = MPV_RENDER_PARAM_INVALID
  * 
- *     @_errors
  */
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->callbackthread, __pyx_n_s_start); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 746, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
-    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-    if (likely(__pyx_t_5)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_5);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_4, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 746, __pyx_L1_error)
+  __pyx_t_1 = PyList_New(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 887, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->owned);
+  __Pyx_DECREF(__pyx_v_self->owned);
+  __pyx_v_self->owned = __pyx_t_1;
+  __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":736
- *         return pipe
+  /* "vidcutter/libs/pympv/mpv.pyx":888
+ *     def __init__(self):
+ *         self.owned = []
+ *         self.params[0].type = MPV_RENDER_PARAM_INVALID             # <<<<<<<<<<<<<<
  * 
- *     def __cinit__(self):             # <<<<<<<<<<<<<<
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- *         with nogil:
+ *     cdef add_voidp(self, mpv_render_param_type t, void *p, bint owned=False):
+ */
+  (__pyx_v_self->params[0]).type = MPV_RENDER_PARAM_INVALID;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":886
+ *         object owned
+ * 
+ *     def __init__(self):             # <<<<<<<<<<<<<<
+ *         self.owned = []
+ *         self.params[0].type = MPV_RENDER_PARAM_INVALID
  */
 
   /* function exit code */
@@ -15027,1094 +15444,479 @@ static int __pyx_pf_9vidcutter_4libs_3mpv_7Context_36__cinit__(struct __pyx_obj_
   goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._RenderParams.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = -1;
   __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":749
+/* "vidcutter/libs/pympv/mpv.pyx":890
+ *         self.params[0].type = MPV_RENDER_PARAM_INVALID
  * 
- *     @_errors
- *     def observe_property(self, prop, data=None):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_observe_property"""
- *         assert self._ctx
+ *     cdef add_voidp(self, mpv_render_param_type t, void *p, bint owned=False):             # <<<<<<<<<<<<<<
+ *         count = len(self.owned)
+ *         if count >= MAX_RENDER_PARAMS:
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_39observe_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_38observe_property[] = "Wraps: mpv_observe_property";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_39observe_property(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_prop = 0;
-  PyObject *__pyx_v_data = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("observe_property (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_prop,&__pyx_n_s_data,0};
-    PyObject* values[2] = {0,0};
-    values[1] = ((PyObject *)Py_None);
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_prop)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (kw_args > 0) {
-          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_data);
-          if (value) { values[1] = value; kw_args--; }
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "observe_property") < 0)) __PYX_ERR(0, 749, __pyx_L3_error)
-      }
-    } else {
-      switch (PyTuple_GET_SIZE(__pyx_args)) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-    }
-    __pyx_v_prop = values[0];
-    __pyx_v_data = values[1];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("observe_property", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 749, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.observe_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_38observe_property(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), __pyx_v_prop, __pyx_v_data);
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_38observe_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_prop, PyObject *__pyx_v_data) {
-  uint64_t __pyx_v_id_data;
-  PyObject *__pyx_v_userdatas = NULL;
-  char *__pyx_v_propc;
-  int __pyx_v_err;
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv_13_RenderParams_add_voidp(struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_self, enum mpv_render_param_type __pyx_v_t, void *__pyx_v_p, struct __pyx_opt_args_9vidcutter_4libs_3mpv_13_RenderParams_add_voidp *__pyx_optional_args) {
+  int __pyx_v_owned = ((int)0);
+  PyObject *__pyx_v_count = NULL;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  Py_hash_t __pyx_t_1;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_1 = NULL;
+  Py_ssize_t __pyx_t_2;
+  int __pyx_t_3;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
   int __pyx_t_6;
-  PyObject *__pyx_t_7 = NULL;
-  int __pyx_t_8;
-  int __pyx_t_9;
-  char *__pyx_t_10;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("observe_property", 0);
-  __Pyx_INCREF(__pyx_v_prop);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":751
- *     def observe_property(self, prop, data=None):
- *         """Wraps: mpv_observe_property"""
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         id_data = <uint64_t>hash(data)
- */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 751, __pyx_L1_error)
+  __Pyx_RefNannySetupContext("add_voidp", 0);
+  if (__pyx_optional_args) {
+    if (__pyx_optional_args->__pyx_n > 0) {
+      __pyx_v_owned = __pyx_optional_args->owned;
     }
   }
-  #endif
 
-  /* "vidcutter/libs/pympv/mpv.pyx":752
- *         """Wraps: mpv_observe_property"""
- *         assert self._ctx
- *         cdef uint64_t id_data = <uint64_t>hash(data)             # <<<<<<<<<<<<<<
- *         id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)
+  /* "vidcutter/libs/pympv/mpv.pyx":891
+ * 
+ *     cdef add_voidp(self, mpv_render_param_type t, void *p, bint owned=False):
+ *         count = len(self.owned)             # <<<<<<<<<<<<<<
+ *         if count >= MAX_RENDER_PARAMS:
+ *             if owned:
  */
-  __pyx_t_1 = PyObject_Hash(__pyx_v_data); if (unlikely(__pyx_t_1 == ((Py_hash_t)-1))) __PYX_ERR(0, 752, __pyx_L1_error)
-  __pyx_v_id_data = ((uint64_t)__pyx_t_1);
+  __pyx_t_1 = __pyx_v_self->owned;
+  __Pyx_INCREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_Length(__pyx_t_1); if (unlikely(__pyx_t_2 == ((Py_ssize_t)-1))) __PYX_ERR(0, 891, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = PyInt_FromSsize_t(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 891, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_count = __pyx_t_1;
+  __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":753
- *         assert self._ctx
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         id_data = <uint64_t>hash(data)             # <<<<<<<<<<<<<<
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is None:
+  /* "vidcutter/libs/pympv/mpv.pyx":892
+ *     cdef add_voidp(self, mpv_render_param_type t, void *p, bint owned=False):
+ *         count = len(self.owned)
+ *         if count >= MAX_RENDER_PARAMS:             # <<<<<<<<<<<<<<
+ *             if owned:
+ *                 free(p)
  */
-  __pyx_t_1 = PyObject_Hash(__pyx_v_data); if (unlikely(__pyx_t_1 == ((Py_hash_t)-1))) __PYX_ERR(0, 753, __pyx_L1_error)
-  __pyx_v_id_data = ((uint64_t)__pyx_t_1);
+  __pyx_t_1 = PyObject_RichCompare(__pyx_v_count, __pyx_int_32, Py_GE); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 892, __pyx_L1_error)
+  __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 892, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  if (__pyx_t_3) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":754
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)             # <<<<<<<<<<<<<<
- *         if userdatas is None:
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
+    /* "vidcutter/libs/pympv/mpv.pyx":893
+ *         count = len(self.owned)
+ *         if count >= MAX_RENDER_PARAMS:
+ *             if owned:             # <<<<<<<<<<<<<<
+ *                 free(p)
+ *             raise PyMPVError("RenderParams overflow")
  */
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->reply_userdata, __pyx_n_s_get); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 754, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyInt_From_uint64_t(__pyx_v_id_data); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 754, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = NULL;
-  __pyx_t_6 = 0;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
-    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
-    if (likely(__pyx_t_5)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_5);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_3, function);
-      __pyx_t_6 = 1;
-    }
-  }
-  #if CYTHON_FAST_PYCALL
-  if (PyFunction_Check(__pyx_t_3)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_4, Py_None};
-    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 754, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  } else
-  #endif
-  #if CYTHON_FAST_PYCCALL
-  if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_4, Py_None};
-    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 754, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  } else
-  #endif
-  {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 754, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    if (__pyx_t_5) {
-      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
-    }
-    __Pyx_GIVEREF(__pyx_t_4);
-    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_t_4);
-    __Pyx_INCREF(Py_None);
-    __Pyx_GIVEREF(Py_None);
-    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, Py_None);
-    __pyx_t_4 = 0;
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_7, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 754, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  }
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_v_userdatas = __pyx_t_2;
-  __pyx_t_2 = 0;
+    __pyx_t_3 = (__pyx_v_owned != 0);
+    if (__pyx_t_3) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":755
- *         id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is None:             # <<<<<<<<<<<<<<
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
- *         userdatas.observed = True
+      /* "vidcutter/libs/pympv/mpv.pyx":894
+ *         if count >= MAX_RENDER_PARAMS:
+ *             if owned:
+ *                 free(p)             # <<<<<<<<<<<<<<
+ *             raise PyMPVError("RenderParams overflow")
+ * 
  */
-  __pyx_t_8 = (__pyx_v_userdatas == Py_None);
-  __pyx_t_9 = (__pyx_t_8 != 0);
-  if (__pyx_t_9) {
+      free(__pyx_v_p);
 
-    /* "vidcutter/libs/pympv/mpv.pyx":756
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is None:
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)             # <<<<<<<<<<<<<<
- *         userdatas.observed = True
- *         prop = _strenc(prop)
+      /* "vidcutter/libs/pympv/mpv.pyx":893
+ *         count = len(self.owned)
+ *         if count >= MAX_RENDER_PARAMS:
+ *             if owned:             # <<<<<<<<<<<<<<
+ *                 free(p)
+ *             raise PyMPVError("RenderParams overflow")
  */
-    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_ReplyUserData); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 756, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_7 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-      __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3);
-      if (likely(__pyx_t_7)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-        __Pyx_INCREF(__pyx_t_7);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_3, function);
-      }
     }
-    __pyx_t_2 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_7, __pyx_v_data) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_data);
-    __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 756, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (unlikely(__Pyx_SetItemInt(__pyx_v_self->reply_userdata, __pyx_v_id_data, __pyx_t_2, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 756, __pyx_L1_error)
-    __Pyx_INCREF(__pyx_t_2);
-    __Pyx_DECREF_SET(__pyx_v_userdatas, __pyx_t_2);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":755
- *         id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is None:             # <<<<<<<<<<<<<<
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
- *         userdatas.observed = True
- */
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":757
- *         if userdatas is None:
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
- *         userdatas.observed = True             # <<<<<<<<<<<<<<
- *         prop = _strenc(prop)
- *         cdef char* propc = prop
- */
-  if (__Pyx_PyObject_SetAttrStr(__pyx_v_userdatas, __pyx_n_s_observed, Py_True) < 0) __PYX_ERR(0, 757, __pyx_L1_error)
 
-  /* "vidcutter/libs/pympv/mpv.pyx":758
- *             self.reply_userdata[id_data] = userdatas = _ReplyUserData(data)
- *         userdatas.observed = True
- *         prop = _strenc(prop)             # <<<<<<<<<<<<<<
- *         cdef char* propc = prop
- *         cdef int err
+    /* "vidcutter/libs/pympv/mpv.pyx":895
+ *             if owned:
+ *                 free(p)
+ *             raise PyMPVError("RenderParams overflow")             # <<<<<<<<<<<<<<
+ * 
+ *         self.params[count].type = t
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_strenc); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 758, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_7 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_3);
-    if (likely(__pyx_t_7)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_7);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_3, function);
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_PyMPVError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 895, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
     }
-  }
-  __pyx_t_2 = (__pyx_t_7) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_7, __pyx_v_prop) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_prop);
-  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 758, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __Pyx_DECREF_SET(__pyx_v_prop, __pyx_t_2);
-  __pyx_t_2 = 0;
+    __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_kp_s_RenderParams_overflow) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_kp_s_RenderParams_overflow);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 895, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __PYX_ERR(0, 895, __pyx_L1_error)
 
-  /* "vidcutter/libs/pympv/mpv.pyx":759
- *         userdatas.observed = True
- *         prop = _strenc(prop)
- *         cdef char* propc = prop             # <<<<<<<<<<<<<<
- *         cdef int err
- *         with nogil:
+    /* "vidcutter/libs/pympv/mpv.pyx":892
+ *     cdef add_voidp(self, mpv_render_param_type t, void *p, bint owned=False):
+ *         count = len(self.owned)
+ *         if count >= MAX_RENDER_PARAMS:             # <<<<<<<<<<<<<<
+ *             if owned:
+ *                 free(p)
  */
-  __pyx_t_10 = __Pyx_PyObject_AsWritableString(__pyx_v_prop); if (unlikely((!__pyx_t_10) && PyErr_Occurred())) __PYX_ERR(0, 759, __pyx_L1_error)
-  __pyx_v_propc = __pyx_t_10;
+  }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":761
- *         cdef char* propc = prop
- *         cdef int err
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_observe_property(
- *                 self._ctx,
+  /* "vidcutter/libs/pympv/mpv.pyx":897
+ *             raise PyMPVError("RenderParams overflow")
+ * 
+ *         self.params[count].type = t             # <<<<<<<<<<<<<<
+ *         self.params[count].data = p
+ *         self.params[count + 1].type = MPV_RENDER_PARAM_INVALID
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+  __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_v_count); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 897, __pyx_L1_error)
+  (__pyx_v_self->params[__pyx_t_2]).type = __pyx_v_t;
 
-        /* "vidcutter/libs/pympv/mpv.pyx":762
- *         cdef int err
- *         with nogil:
- *             err = mpv_observe_property(             # <<<<<<<<<<<<<<
- *                 self._ctx,
- *                 id_data,
+  /* "vidcutter/libs/pympv/mpv.pyx":898
+ * 
+ *         self.params[count].type = t
+ *         self.params[count].data = p             # <<<<<<<<<<<<<<
+ *         self.params[count + 1].type = MPV_RENDER_PARAM_INVALID
+ *         self.owned.append(owned)
  */
-        __pyx_v_err = mpv_observe_property(__pyx_v_self->_ctx, __pyx_v_id_data, __pyx_v_propc, MPV_FORMAT_NODE);
-      }
+  __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_v_count); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 898, __pyx_L1_error)
+  (__pyx_v_self->params[__pyx_t_2]).data = __pyx_v_p;
 
-      /* "vidcutter/libs/pympv/mpv.pyx":761
- *         cdef char* propc = prop
- *         cdef int err
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_observe_property(
- *                 self._ctx,
+  /* "vidcutter/libs/pympv/mpv.pyx":899
+ *         self.params[count].type = t
+ *         self.params[count].data = p
+ *         self.params[count + 1].type = MPV_RENDER_PARAM_INVALID             # <<<<<<<<<<<<<<
+ *         self.owned.append(owned)
+ * 
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L6;
-        }
-        __pyx_L6:;
-      }
-  }
+  __pyx_t_1 = __Pyx_PyInt_AddObjC(__pyx_v_count, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 899, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyIndex_AsSsize_t(__pyx_t_1); if (unlikely((__pyx_t_2 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 899, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  (__pyx_v_self->params[__pyx_t_2]).type = MPV_RENDER_PARAM_INVALID;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":768
- *                 MPV_FORMAT_NODE,
- *             )
- *         return err             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":900
+ *         self.params[count].data = p
+ *         self.params[count + 1].type = MPV_RENDER_PARAM_INVALID
+ *         self.owned.append(owned)             # <<<<<<<<<<<<<<
  * 
- *     @_errors
+ *     cdef add_int(self, mpv_render_param_type t, int val):
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 768, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_r = __pyx_t_2;
-  __pyx_t_2 = 0;
-  goto __pyx_L0;
+  __pyx_t_1 = __Pyx_PyBool_FromLong(__pyx_v_owned); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 900, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_6 = __Pyx_PyObject_Append(__pyx_v_self->owned, __pyx_t_1); if (unlikely(__pyx_t_6 == ((int)-1))) __PYX_ERR(0, 900, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":749
+  /* "vidcutter/libs/pympv/mpv.pyx":890
+ *         self.params[0].type = MPV_RENDER_PARAM_INVALID
  * 
- *     @_errors
- *     def observe_property(self, prop, data=None):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_observe_property"""
- *         assert self._ctx
+ *     cdef add_voidp(self, mpv_render_param_type t, void *p, bint owned=False):             # <<<<<<<<<<<<<<
+ *         count = len(self.owned)
+ *         if count >= MAX_RENDER_PARAMS:
  */
 
   /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.observe_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
+  __Pyx_AddTraceback("vidcutter.libs.mpv._RenderParams.add_voidp", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_userdatas);
-  __Pyx_XDECREF(__pyx_v_prop);
+  __Pyx_XDECREF(__pyx_v_count);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":771
+/* "vidcutter/libs/pympv/mpv.pyx":902
+ *         self.owned.append(owned)
  * 
- *     @_errors
- *     def unobserve_property(self, data):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_unobserve_property"""
- *         assert self._ctx
+ *     cdef add_int(self, mpv_render_param_type t, int val):             # <<<<<<<<<<<<<<
+ *         cdef int *p = <int *>malloc(sizeof(int))
+ *         p[0] = val
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_41unobserve_property(PyObject *__pyx_v_self, PyObject *__pyx_v_data); /*proto*/
-static char __pyx_doc_9vidcutter_4libs_3mpv_7Context_40unobserve_property[] = "Wraps: mpv_unobserve_property";
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_41unobserve_property(PyObject *__pyx_v_self, PyObject *__pyx_v_data) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("unobserve_property (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_40unobserve_property(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v_data));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_40unobserve_property(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, PyObject *__pyx_v_data) {
-  uint64_t __pyx_v_id_data;
-  PyObject *__pyx_v_userdatas = NULL;
-  int __pyx_v_err;
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv_13_RenderParams_add_int(struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_self, enum mpv_render_param_type __pyx_v_t, int __pyx_v_val) {
+  int *__pyx_v_p;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  Py_hash_t __pyx_t_1;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  int __pyx_t_6;
-  PyObject *__pyx_t_7 = NULL;
-  int __pyx_t_8;
-  int __pyx_t_9;
+  PyObject *__pyx_t_1 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("unobserve_property", 0);
+  __Pyx_RefNannySetupContext("add_int", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":773
- *     def unobserve_property(self, data):
- *         """Wraps: mpv_unobserve_property"""
- *         assert self._ctx             # <<<<<<<<<<<<<<
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)
+  /* "vidcutter/libs/pympv/mpv.pyx":903
+ * 
+ *     cdef add_int(self, mpv_render_param_type t, int val):
+ *         cdef int *p = <int *>malloc(sizeof(int))             # <<<<<<<<<<<<<<
+ *         p[0] = val
+ *         self.add_voidp(t, p)
  */
-  #ifndef CYTHON_WITHOUT_ASSERTIONS
-  if (unlikely(!Py_OptimizeFlag)) {
-    if (unlikely(!(__pyx_v_self->_ctx != 0))) {
-      PyErr_SetNone(PyExc_AssertionError);
-      __PYX_ERR(0, 773, __pyx_L1_error)
-    }
-  }
-  #endif
+  __pyx_v_p = ((int *)malloc((sizeof(int))));
 
-  /* "vidcutter/libs/pympv/mpv.pyx":774
- *         """Wraps: mpv_unobserve_property"""
- *         assert self._ctx
- *         cdef uint64_t id_data = <uint64_t>hash(data)             # <<<<<<<<<<<<<<
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is not None:
- */
-  __pyx_t_1 = PyObject_Hash(__pyx_v_data); if (unlikely(__pyx_t_1 == ((Py_hash_t)-1))) __PYX_ERR(0, 774, __pyx_L1_error)
-  __pyx_v_id_data = ((uint64_t)__pyx_t_1);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":775
- *         assert self._ctx
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)             # <<<<<<<<<<<<<<
- *         if userdatas is not None:
- *             userdatas.observed = False
- */
-  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->reply_userdata, __pyx_n_s_get); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 775, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_4 = __Pyx_PyInt_From_uint64_t(__pyx_v_id_data); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 775, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = NULL;
-  __pyx_t_6 = 0;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
-    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
-    if (likely(__pyx_t_5)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_5);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_3, function);
-      __pyx_t_6 = 1;
-    }
-  }
-  #if CYTHON_FAST_PYCALL
-  if (PyFunction_Check(__pyx_t_3)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_4, Py_None};
-    __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 775, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  } else
-  #endif
-  #if CYTHON_FAST_PYCCALL
-  if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-    PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_t_4, Py_None};
-    __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_6, 2+__pyx_t_6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 775, __pyx_L1_error)
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  } else
-  #endif
-  {
-    __pyx_t_7 = PyTuple_New(2+__pyx_t_6); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 775, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    if (__pyx_t_5) {
-      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
-    }
-    __Pyx_GIVEREF(__pyx_t_4);
-    PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_6, __pyx_t_4);
-    __Pyx_INCREF(Py_None);
-    __Pyx_GIVEREF(Py_None);
-    PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_6, Py_None);
-    __pyx_t_4 = 0;
-    __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_7, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 775, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-  }
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_v_userdatas = __pyx_t_2;
-  __pyx_t_2 = 0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":776
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is not None:             # <<<<<<<<<<<<<<
- *             userdatas.observed = False
- *             if userdatas.counter <= 0:
- */
-  __pyx_t_8 = (__pyx_v_userdatas != Py_None);
-  __pyx_t_9 = (__pyx_t_8 != 0);
-  if (__pyx_t_9) {
-
-    /* "vidcutter/libs/pympv/mpv.pyx":777
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is not None:
- *             userdatas.observed = False             # <<<<<<<<<<<<<<
- *             if userdatas.counter <= 0:
- *                 del self.reply_userdata[id_data]
- */
-    if (__Pyx_PyObject_SetAttrStr(__pyx_v_userdatas, __pyx_n_s_observed, Py_False) < 0) __PYX_ERR(0, 777, __pyx_L1_error)
-
-    /* "vidcutter/libs/pympv/mpv.pyx":778
- *         if userdatas is not None:
- *             userdatas.observed = False
- *             if userdatas.counter <= 0:             # <<<<<<<<<<<<<<
- *                 del self.reply_userdata[id_data]
- *         cdef int err
- */
-    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_v_userdatas, __pyx_n_s_counter); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 778, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = PyObject_RichCompare(__pyx_t_2, __pyx_int_0, Py_LE); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 778, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_9 = __Pyx_PyObject_IsTrue(__pyx_t_3); if (unlikely(__pyx_t_9 < 0)) __PYX_ERR(0, 778, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    if (__pyx_t_9) {
-
-      /* "vidcutter/libs/pympv/mpv.pyx":779
- *             userdatas.observed = False
- *             if userdatas.counter <= 0:
- *                 del self.reply_userdata[id_data]             # <<<<<<<<<<<<<<
- *         cdef int err
- *         with nogil:
- */
-      if (unlikely(__Pyx_DelItemInt(__pyx_v_self->reply_userdata, __pyx_v_id_data, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 779, __pyx_L1_error)
-
-      /* "vidcutter/libs/pympv/mpv.pyx":778
- *         if userdatas is not None:
- *             userdatas.observed = False
- *             if userdatas.counter <= 0:             # <<<<<<<<<<<<<<
- *                 del self.reply_userdata[id_data]
- *         cdef int err
- */
-    }
-
-    /* "vidcutter/libs/pympv/mpv.pyx":776
- *         cdef uint64_t id_data = <uint64_t>hash(data)
- *         userdatas = self.reply_userdata.get(id_data, None)
- *         if userdatas is not None:             # <<<<<<<<<<<<<<
- *             userdatas.observed = False
- *             if userdatas.counter <= 0:
- */
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":781
- *                 del self.reply_userdata[id_data]
- *         cdef int err
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_unobserve_property(
- *                 self._ctx,
- */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
-
-        /* "vidcutter/libs/pympv/mpv.pyx":782
- *         cdef int err
- *         with nogil:
- *             err = mpv_unobserve_property(             # <<<<<<<<<<<<<<
- *                 self._ctx,
- *                 id_data,
- */
-        __pyx_v_err = mpv_unobserve_property(__pyx_v_self->_ctx, __pyx_v_id_data);
-      }
-
-      /* "vidcutter/libs/pympv/mpv.pyx":781
- *                 del self.reply_userdata[id_data]
- *         cdef int err
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_unobserve_property(
- *                 self._ctx,
+  /* "vidcutter/libs/pympv/mpv.pyx":904
+ *     cdef add_int(self, mpv_render_param_type t, int val):
+ *         cdef int *p = <int *>malloc(sizeof(int))
+ *         p[0] = val             # <<<<<<<<<<<<<<
+ *         self.add_voidp(t, p)
+ * 
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L7;
-        }
-        __pyx_L7:;
-      }
-  }
+  (__pyx_v_p[0]) = __pyx_v_val;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":786
- *                 id_data,
- *             )
- *         return err             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":905
+ *         cdef int *p = <int *>malloc(sizeof(int))
+ *         p[0] = val
+ *         self.add_voidp(t, p)             # <<<<<<<<<<<<<<
  * 
- *     def shutdown(self):
+ *     cdef add_string(self, mpv_render_param_type t, char *s):
  */
-  __Pyx_XDECREF(__pyx_r);
-  __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 786, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_r = __pyx_t_3;
-  __pyx_t_3 = 0;
-  goto __pyx_L0;
+  __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv__RenderParams *)__pyx_v_self->__pyx_vtab)->add_voidp(__pyx_v_self, __pyx_v_t, __pyx_v_p, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 905, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":771
+  /* "vidcutter/libs/pympv/mpv.pyx":902
+ *         self.owned.append(owned)
  * 
- *     @_errors
- *     def unobserve_property(self, data):             # <<<<<<<<<<<<<<
- *         """Wraps: mpv_unobserve_property"""
- *         assert self._ctx
+ *     cdef add_int(self, mpv_render_param_type t, int val):             # <<<<<<<<<<<<<<
+ *         cdef int *p = <int *>malloc(sizeof(int))
+ *         p[0] = val
  */
 
   /* function exit code */
+  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.unobserve_property", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._RenderParams.add_int", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_userdatas);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":788
- *         return err
+/* "vidcutter/libs/pympv/mpv.pyx":907
+ *         self.add_voidp(t, p)
  * 
- *     def shutdown(self):             # <<<<<<<<<<<<<<
- *         if self._ctx == NULL:
- *             return
+ *     cdef add_string(self, mpv_render_param_type t, char *s):             # <<<<<<<<<<<<<<
+ *         cdef char *p = <char *>malloc(strlen(s) + 1)
+ *         strcpy(p, s)
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_43shutdown(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_43shutdown(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("shutdown (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_42shutdown(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_42shutdown(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  uint64_t __pyx_v_ctxid;
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv_13_RenderParams_add_string(struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_self, enum mpv_render_param_type __pyx_v_t, char *__pyx_v_s) {
+  char *__pyx_v_p;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  PyObject *__pyx_t_2 = NULL;
-  uint64_t __pyx_t_3;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
+  PyObject *__pyx_t_1 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("shutdown", 0);
+  __Pyx_RefNannySetupContext("add_string", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":789
+  /* "vidcutter/libs/pympv/mpv.pyx":908
  * 
- *     def shutdown(self):
- *         if self._ctx == NULL:             # <<<<<<<<<<<<<<
- *             return
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- */
-  __pyx_t_1 = ((__pyx_v_self->_ctx == NULL) != 0);
-  if (__pyx_t_1) {
-
-    /* "vidcutter/libs/pympv/mpv.pyx":790
- *     def shutdown(self):
- *         if self._ctx == NULL:
- *             return             # <<<<<<<<<<<<<<
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- *         with nogil:
- */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-    goto __pyx_L0;
-
-    /* "vidcutter/libs/pympv/mpv.pyx":789
- * 
- *     def shutdown(self):
- *         if self._ctx == NULL:             # <<<<<<<<<<<<<<
- *             return
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- */
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":791
- *         if self._ctx == NULL:
- *             return
- *         cdef uint64_t ctxid = <uint64_t>id(self)             # <<<<<<<<<<<<<<
- *         with nogil:
- *             mpv_terminate_destroy(self._ctx)
- */
-  __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_id, ((PyObject *)__pyx_v_self)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 791, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = __Pyx_PyInt_As_uint64_t(__pyx_t_2); if (unlikely((__pyx_t_3 == ((uint64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 791, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_v_ctxid = ((uint64_t)__pyx_t_3);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":792
- *             return
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_terminate_destroy(self._ctx)
- *         self.callbackthread.shutdown()
- */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
-
-        /* "vidcutter/libs/pympv/mpv.pyx":793
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- *         with nogil:
- *             mpv_terminate_destroy(self._ctx)             # <<<<<<<<<<<<<<
- *         self.callbackthread.shutdown()
- *         del _callbacks[ctxid]
- */
-        mpv_terminate_destroy(__pyx_v_self->_ctx);
-      }
-
-      /* "vidcutter/libs/pympv/mpv.pyx":792
- *             return
- *         cdef uint64_t ctxid = <uint64_t>id(self)
- *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_terminate_destroy(self._ctx)
- *         self.callbackthread.shutdown()
- */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L6;
-        }
-        __pyx_L6:;
-      }
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":794
- *         with nogil:
- *             mpv_terminate_destroy(self._ctx)
- *         self.callbackthread.shutdown()             # <<<<<<<<<<<<<<
- *         del _callbacks[ctxid]
- *         del _reply_userdatas[ctxid]
- */
-  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_self->callbackthread, __pyx_n_s_shutdown); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 794, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
-    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-    if (likely(__pyx_t_5)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_5);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_4, function);
-    }
-  }
-  __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-  if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 794, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":795
- *             mpv_terminate_destroy(self._ctx)
- *         self.callbackthread.shutdown()
- *         del _callbacks[ctxid]             # <<<<<<<<<<<<<<
- *         del _reply_userdatas[ctxid]
- *         self.callback = None
- */
-  if (unlikely(__Pyx_DelItemInt(__pyx_v_9vidcutter_4libs_3mpv__callbacks, __pyx_v_ctxid, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 795, __pyx_L1_error)
-
-  /* "vidcutter/libs/pympv/mpv.pyx":796
- *         self.callbackthread.shutdown()
- *         del _callbacks[ctxid]
- *         del _reply_userdatas[ctxid]             # <<<<<<<<<<<<<<
- *         self.callback = None
- *         self.reply_userdata = None
- */
-  if (unlikely(__Pyx_DelItemInt(__pyx_v_9vidcutter_4libs_3mpv__reply_userdatas, __pyx_v_ctxid, uint64_t, 0, __Pyx_PyInt_From_uint64_t, 0, 0, 1) < 0)) __PYX_ERR(0, 796, __pyx_L1_error)
-
-  /* "vidcutter/libs/pympv/mpv.pyx":797
- *         del _callbacks[ctxid]
- *         del _reply_userdatas[ctxid]
- *         self.callback = None             # <<<<<<<<<<<<<<
- *         self.reply_userdata = None
- *         self._ctx = NULL
+ *     cdef add_string(self, mpv_render_param_type t, char *s):
+ *         cdef char *p = <char *>malloc(strlen(s) + 1)             # <<<<<<<<<<<<<<
+ *         strcpy(p, s)
+ *         self.add_voidp(t, p)
  */
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->callback);
-  __Pyx_DECREF(__pyx_v_self->callback);
-  __pyx_v_self->callback = Py_None;
+  __pyx_v_p = ((char *)malloc((strlen(__pyx_v_s) + 1)));
 
-  /* "vidcutter/libs/pympv/mpv.pyx":798
- *         del _reply_userdatas[ctxid]
- *         self.callback = None
- *         self.reply_userdata = None             # <<<<<<<<<<<<<<
- *         self._ctx = NULL
+  /* "vidcutter/libs/pympv/mpv.pyx":909
+ *     cdef add_string(self, mpv_render_param_type t, char *s):
+ *         cdef char *p = <char *>malloc(strlen(s) + 1)
+ *         strcpy(p, s)             # <<<<<<<<<<<<<<
+ *         self.add_voidp(t, p)
  * 
  */
-  __Pyx_INCREF(Py_None);
-  __Pyx_GIVEREF(Py_None);
-  __Pyx_GOTREF(__pyx_v_self->reply_userdata);
-  __Pyx_DECREF(__pyx_v_self->reply_userdata);
-  __pyx_v_self->reply_userdata = Py_None;
+  (void)(strcpy(__pyx_v_p, __pyx_v_s));
 
-  /* "vidcutter/libs/pympv/mpv.pyx":799
- *         self.callback = None
- *         self.reply_userdata = None
- *         self._ctx = NULL             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":910
+ *         cdef char *p = <char *>malloc(strlen(s) + 1)
+ *         strcpy(p, s)
+ *         self.add_voidp(t, p)             # <<<<<<<<<<<<<<
  * 
- *     def opengl_cb_api(self):
+ *     def __dealloc__(self):
  */
-  __pyx_v_self->_ctx = NULL;
+  __pyx_t_1 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv__RenderParams *)__pyx_v_self->__pyx_vtab)->add_voidp(__pyx_v_self, __pyx_v_t, __pyx_v_p, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 910, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":788
- *         return err
+  /* "vidcutter/libs/pympv/mpv.pyx":907
+ *         self.add_voidp(t, p)
  * 
- *     def shutdown(self):             # <<<<<<<<<<<<<<
- *         if self._ctx == NULL:
- *             return
+ *     cdef add_string(self, mpv_render_param_type t, char *s):             # <<<<<<<<<<<<<<
+ *         cdef char *p = <char *>malloc(strlen(s) + 1)
+ *         strcpy(p, s)
  */
 
   /* function exit code */
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
   goto __pyx_L0;
   __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.shutdown", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._RenderParams.add_string", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
   __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":801
- *         self._ctx = NULL
- * 
- *     def opengl_cb_api(self):             # <<<<<<<<<<<<<<
- *         cdef void *cb
+/* "vidcutter/libs/pympv/mpv.pyx":912
+ *         self.add_voidp(t, p)
  * 
+ *     def __dealloc__(self):             # <<<<<<<<<<<<<<
+ *         for i, j in enumerate(self.owned):
+ *             if j:
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_45opengl_cb_api(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_45opengl_cb_api(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
+static void __pyx_pw_9vidcutter_4libs_3mpv_13_RenderParams_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
+static void __pyx_pw_9vidcutter_4libs_3mpv_13_RenderParams_3__dealloc__(PyObject *__pyx_v_self) {
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("opengl_cb_api (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_44opengl_cb_api(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
+  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
+  __pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams_2__dealloc__(((struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
-  return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_44opengl_cb_api(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  void *__pyx_v__ctx;
-  struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_ctx = NULL;
-  PyObject *__pyx_r = NULL;
+static void __pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams_2__dealloc__(struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_self) {
+  PyObject *__pyx_v_i = NULL;
+  PyObject *__pyx_v_j = NULL;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
+  PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
+  Py_ssize_t __pyx_t_3;
+  PyObject *(*__pyx_t_4)(PyObject *);
+  PyObject *__pyx_t_5 = NULL;
+  int __pyx_t_6;
+  Py_ssize_t __pyx_t_7;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("opengl_cb_api", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":804
- *         cdef void *cb
- * 
- *         _ctx = mpv_get_sub_api(self._ctx, MPV_SUB_API_OPENGL_CB)             # <<<<<<<<<<<<<<
- *         if not _ctx:
- *             raise MPVError("OpenGL API not available")
- */
-  __pyx_v__ctx = mpv_get_sub_api(__pyx_v_self->_ctx, MPV_SUB_API_OPENGL_CB);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":805
- * 
- *         _ctx = mpv_get_sub_api(self._ctx, MPV_SUB_API_OPENGL_CB)
- *         if not _ctx:             # <<<<<<<<<<<<<<
- *             raise MPVError("OpenGL API not available")
- * 
- */
-  __pyx_t_1 = ((!(__pyx_v__ctx != 0)) != 0);
-  if (unlikely(__pyx_t_1)) {
+  __Pyx_RefNannySetupContext("__dealloc__", 0);
 
-    /* "vidcutter/libs/pympv/mpv.pyx":806
- *         _ctx = mpv_get_sub_api(self._ctx, MPV_SUB_API_OPENGL_CB)
- *         if not _ctx:
- *             raise MPVError("OpenGL API not available")             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":913
  * 
- *         ctx = OpenGLContext()
+ *     def __dealloc__(self):
+ *         for i, j in enumerate(self.owned):             # <<<<<<<<<<<<<<
+ *             if j:
+ *                 free(self.params[i].data)
  */
-    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 806, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_int_0);
+  __pyx_t_1 = __pyx_int_0;
+  if (likely(PyList_CheckExact(__pyx_v_self->owned)) || PyTuple_CheckExact(__pyx_v_self->owned)) {
+    __pyx_t_2 = __pyx_v_self->owned; __Pyx_INCREF(__pyx_t_2); __pyx_t_3 = 0;
     __pyx_t_4 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-      __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-      if (likely(__pyx_t_4)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-        __Pyx_INCREF(__pyx_t_4);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_3, function);
-      }
-    }
-    __pyx_t_2 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_kp_s_OpenGL_API_not_available) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_kp_s_OpenGL_API_not_available);
-    __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 806, __pyx_L1_error)
+  } else {
+    __pyx_t_3 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_v_self->owned); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 913, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_2);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __PYX_ERR(0, 806, __pyx_L1_error)
-
-    /* "vidcutter/libs/pympv/mpv.pyx":805
- * 
- *         _ctx = mpv_get_sub_api(self._ctx, MPV_SUB_API_OPENGL_CB)
- *         if not _ctx:             # <<<<<<<<<<<<<<
- *             raise MPVError("OpenGL API not available")
- * 
- */
+    __pyx_t_4 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 913, __pyx_L1_error)
   }
+  for (;;) {
+    if (likely(!__pyx_t_4)) {
+      if (likely(PyList_CheckExact(__pyx_t_2))) {
+        if (__pyx_t_3 >= PyList_GET_SIZE(__pyx_t_2)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_5 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 913, __pyx_L1_error)
+        #else
+        __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 913, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_5);
+        #endif
+      } else {
+        if (__pyx_t_3 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_5 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_3); __Pyx_INCREF(__pyx_t_5); __pyx_t_3++; if (unlikely(0 < 0)) __PYX_ERR(0, 913, __pyx_L1_error)
+        #else
+        __pyx_t_5 = PySequence_ITEM(__pyx_t_2, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 913, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_5);
+        #endif
+      }
+    } else {
+      __pyx_t_5 = __pyx_t_4(__pyx_t_2);
+      if (unlikely(!__pyx_t_5)) {
+        PyObject* exc_type = PyErr_Occurred();
+        if (exc_type) {
+          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+          else __PYX_ERR(0, 913, __pyx_L1_error)
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_5);
+    }
+    __Pyx_XDECREF_SET(__pyx_v_j, __pyx_t_5);
+    __pyx_t_5 = 0;
+    __Pyx_INCREF(__pyx_t_1);
+    __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_1);
+    __pyx_t_5 = __Pyx_PyInt_AddObjC(__pyx_t_1, __pyx_int_1, 1, 0, 0); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 913, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_1);
+    __pyx_t_1 = __pyx_t_5;
+    __pyx_t_5 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":808
- *             raise MPVError("OpenGL API not available")
- * 
- *         ctx = OpenGLContext()             # <<<<<<<<<<<<<<
- *         ctx._ctx = <mpv_opengl_cb_context*>_ctx
- * 
- */
-  __pyx_t_2 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv_OpenGLContext)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 808, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_v_ctx = ((struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *)__pyx_t_2);
-  __pyx_t_2 = 0;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":809
- * 
- *         ctx = OpenGLContext()
- *         ctx._ctx = <mpv_opengl_cb_context*>_ctx             # <<<<<<<<<<<<<<
- * 
- *         return ctx
- */
-  __pyx_v_ctx->_ctx = ((struct mpv_opengl_cb_context *)__pyx_v__ctx);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":811
- *         ctx._ctx = <mpv_opengl_cb_context*>_ctx
- * 
- *         return ctx             # <<<<<<<<<<<<<<
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":914
  *     def __dealloc__(self):
+ *         for i, j in enumerate(self.owned):
+ *             if j:             # <<<<<<<<<<<<<<
+ *                 free(self.params[i].data)
+ * 
  */
-  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(((PyObject *)__pyx_v_ctx));
-  __pyx_r = ((PyObject *)__pyx_v_ctx);
-  goto __pyx_L0;
+    __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_j); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 914, __pyx_L1_error)
+    if (__pyx_t_6) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":801
- *         self._ctx = NULL
- * 
- *     def opengl_cb_api(self):             # <<<<<<<<<<<<<<
- *         cdef void *cb
+      /* "vidcutter/libs/pympv/mpv.pyx":915
+ *         for i, j in enumerate(self.owned):
+ *             if j:
+ *                 free(self.params[i].data)             # <<<<<<<<<<<<<<
  * 
+ * cdef void *get_pointer(const char *name, object obj):
  */
+      __pyx_t_7 = __Pyx_PyIndex_AsSsize_t(__pyx_v_i); if (unlikely((__pyx_t_7 == (Py_ssize_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 915, __pyx_L1_error)
+      free((__pyx_v_self->params[__pyx_t_7]).data);
 
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.opengl_cb_api", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF((PyObject *)__pyx_v_ctx);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-/* "vidcutter/libs/pympv/mpv.pyx":813
- *         return ctx
- * 
- *     def __dealloc__(self):             # <<<<<<<<<<<<<<
- *         self.shutdown()
+      /* "vidcutter/libs/pympv/mpv.pyx":914
+ *     def __dealloc__(self):
+ *         for i, j in enumerate(self.owned):
+ *             if j:             # <<<<<<<<<<<<<<
+ *                 free(self.params[i].data)
  * 
  */
+    }
 
-/* Python wrapper */
-static void __pyx_pw_9vidcutter_4libs_3mpv_7Context_47__dealloc__(PyObject *__pyx_v_self); /*proto*/
-static void __pyx_pw_9vidcutter_4libs_3mpv_7Context_47__dealloc__(PyObject *__pyx_v_self) {
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
-  __pyx_pf_9vidcutter_4libs_3mpv_7Context_46__dealloc__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-}
-
-static void __pyx_pf_9vidcutter_4libs_3mpv_7Context_46__dealloc__(struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__dealloc__", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":814
+    /* "vidcutter/libs/pympv/mpv.pyx":913
  * 
  *     def __dealloc__(self):
- *         self.shutdown()             # <<<<<<<<<<<<<<
- * 
- * cdef void *_c_getprocaddress(void *ctx, const char *name) with gil:
+ *         for i, j in enumerate(self.owned):             # <<<<<<<<<<<<<<
+ *             if j:
+ *                 free(self.params[i].data)
  */
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_shutdown); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 814, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_3)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-    }
   }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 814, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
   __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":813
- *         return ctx
+  /* "vidcutter/libs/pympv/mpv.pyx":912
+ *         self.add_voidp(t, p)
  * 
  *     def __dealloc__(self):             # <<<<<<<<<<<<<<
- *         self.shutdown()
- * 
+ *         for i, j in enumerate(self.owned):
+ *             if j:
  */
 
   /* function exit code */
@@ -16122,32 +15924,34 @@ static void __pyx_pf_9vidcutter_4libs_3mpv_7Context_46__dealloc__(struct __pyx_o
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_WriteUnraisable("vidcutter.libs.mpv.Context.__dealloc__", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_WriteUnraisable("vidcutter.libs.mpv._RenderParams.__dealloc__", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
   __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_i);
+  __Pyx_XDECREF(__pyx_v_j);
   __Pyx_RefNannyFinishContext();
 }
 
 /* "(tree fragment)":1
  * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ *     raise TypeError("self.params cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_49__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_49__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13_RenderParams_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13_RenderParams_5__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_48__reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams_4__reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_48__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams_4__reduce_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_self) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -16158,11 +15962,11 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_48__reduce_cython__(CYT
 
   /* "(tree fragment)":2
  * def __reduce_cython__(self):
- *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")             # <<<<<<<<<<<<<<
+ *     raise TypeError("self.params cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ *     raise TypeError("self.params cannot be converted to a Python object for pickling")
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__3, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 2, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -16170,14 +15974,14 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_48__reduce_cython__(CYT
 
   /* "(tree fragment)":1
  * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
- *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ *     raise TypeError("self.params cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
  */
 
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._RenderParams.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
@@ -16186,25 +15990,25 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_48__reduce_cython__(CYT
 
 /* "(tree fragment)":3
  * def __reduce_cython__(self):
- *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ *     raise TypeError("self.params cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ *     raise TypeError("self.params cannot be converted to a Python object for pickling")
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_51__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_7Context_51__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13_RenderParams_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13_RenderParams_7__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_7Context_50__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams_6__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_50__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv_Context *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13_RenderParams_6__setstate_cython__(CYTHON_UNUSED struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_self, CYTHON_UNUSED PyObject *__pyx_v___pyx_state) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
@@ -16214,11 +16018,11 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_50__setstate_cython__(C
   __Pyx_RefNannySetupContext("__setstate_cython__", 0);
 
   /* "(tree fragment)":4
- *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ *     raise TypeError("self.params cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):
- *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")             # <<<<<<<<<<<<<<
+ *     raise TypeError("self.params cannot be converted to a Python object for pickling")             # <<<<<<<<<<<<<<
  */
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__4, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_builtin_TypeError, __pyx_tuple__6, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 4, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
   __Pyx_Raise(__pyx_t_1, 0, 0, 0);
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
@@ -16226,2675 +16030,2187 @@ static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_7Context_50__setstate_cython__(C
 
   /* "(tree fragment)":3
  * def __reduce_cython__(self):
- *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ *     raise TypeError("self.params cannot be converted to a Python object for pickling")
  * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
- *     raise TypeError("no default __reduce__ due to non-trivial __cinit__")
+ *     raise TypeError("self.params cannot be converted to a Python object for pickling")
  */
 
   /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.Context.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv._RenderParams.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":816
- *         self.shutdown()
- * 
- * cdef void *_c_getprocaddress(void *ctx, const char *name) with gil:             # <<<<<<<<<<<<<<
- *     return <void *><intptr_t>(<object>ctx)(name)
+/* "vidcutter/libs/pympv/mpv.pyx":917
+ *                 free(self.params[i].data)
  * 
+ * cdef void *get_pointer(const char *name, object obj):             # <<<<<<<<<<<<<<
+ *     cdef void *p
+ *     if PyCapsule_IsValid(obj, name):
  */
 
-static void *__pyx_f_9vidcutter_4libs_3mpv__c_getprocaddress(void *__pyx_v_ctx, char const *__pyx_v_name) {
+static void *__pyx_f_9vidcutter_4libs_3mpv_get_pointer(char const *__pyx_v_name, PyObject *__pyx_v_obj) {
+  void *__pyx_v_p;
   void *__pyx_r;
   __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
+  int __pyx_t_1;
+  void *__pyx_t_2;
+  int __pyx_t_3;
+  int __pyx_t_4;
   intptr_t __pyx_t_5;
+  PyObject *__pyx_t_6 = NULL;
+  PyObject *__pyx_t_7 = NULL;
+  PyObject *__pyx_t_8 = NULL;
+  PyObject *__pyx_t_9 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  #ifdef WITH_THREAD
-  PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
-  #endif
-  __Pyx_RefNannySetupContext("_c_getprocaddress", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":817
- * 
- * cdef void *_c_getprocaddress(void *ctx, const char *name) with gil:
- *     return <void *><intptr_t>(<object>ctx)(name)             # <<<<<<<<<<<<<<
- * 
- * cdef void _c_updatecb(void *ctx) with gil:
- */
-  __pyx_t_2 = __Pyx_PyBytes_FromString(__pyx_v_name); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 817, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_INCREF(((PyObject *)__pyx_v_ctx));
-  __pyx_t_3 = ((PyObject *)__pyx_v_ctx); __pyx_t_4 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_3, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_4) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_4, __pyx_t_2) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 817, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_5 = __Pyx_PyInt_As_intptr_t(__pyx_t_1); if (unlikely((__pyx_t_5 == ((intptr_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 817, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_r = ((void *)((intptr_t)__pyx_t_5));
-  goto __pyx_L0;
+  __Pyx_RefNannySetupContext("get_pointer", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":816
- *         self.shutdown()
- * 
- * cdef void *_c_getprocaddress(void *ctx, const char *name) with gil:             # <<<<<<<<<<<<<<
- *     return <void *><intptr_t>(<object>ctx)(name)
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":919
+ * cdef void *get_pointer(const char *name, object obj):
+ *     cdef void *p
+ *     if PyCapsule_IsValid(obj, name):             # <<<<<<<<<<<<<<
+ *         p = PyCapsule_GetPointer(obj, name)
+ *     elif isinstance(obj, int) or isinstance(obj, long) and obj:
  */
+  __pyx_t_1 = (PyCapsule_IsValid(__pyx_v_obj, __pyx_v_name) != 0);
+  if (__pyx_t_1) {
 
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_WriteUnraisable("vidcutter.libs.mpv._c_getprocaddress", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  #ifdef WITH_THREAD
-  __Pyx_PyGILState_Release(__pyx_gilstate_save);
-  #endif
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":920
+ *     cdef void *p
+ *     if PyCapsule_IsValid(obj, name):
+ *         p = PyCapsule_GetPointer(obj, name)             # <<<<<<<<<<<<<<
+ *     elif isinstance(obj, int) or isinstance(obj, long) and obj:
+ *         p = <void *><intptr_t>obj
+ */
+    __pyx_t_2 = PyCapsule_GetPointer(__pyx_v_obj, __pyx_v_name); if (unlikely(__pyx_t_2 == ((void *)NULL) && PyErr_Occurred())) __PYX_ERR(0, 920, __pyx_L1_error)
+    __pyx_v_p = __pyx_t_2;
 
-/* "vidcutter/libs/pympv/mpv.pyx":819
- *     return <void *><intptr_t>(<object>ctx)(name)
- * 
- * cdef void _c_updatecb(void *ctx) with gil:             # <<<<<<<<<<<<<<
- *     (<object>ctx)()
- * 
+    /* "vidcutter/libs/pympv/mpv.pyx":919
+ * cdef void *get_pointer(const char *name, object obj):
+ *     cdef void *p
+ *     if PyCapsule_IsValid(obj, name):             # <<<<<<<<<<<<<<
+ *         p = PyCapsule_GetPointer(obj, name)
+ *     elif isinstance(obj, int) or isinstance(obj, long) and obj:
  */
+    goto __pyx_L3;
+  }
 
-static void __pyx_f_9vidcutter_4libs_3mpv__c_updatecb(void *__pyx_v_ctx) {
-  __Pyx_RefNannyDeclarations
-  PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  #ifdef WITH_THREAD
-  PyGILState_STATE __pyx_gilstate_save = __Pyx_PyGILState_Ensure();
-  #endif
-  __Pyx_RefNannySetupContext("_c_updatecb", 0);
+  /* "vidcutter/libs/pympv/mpv.pyx":921
+ *     if PyCapsule_IsValid(obj, name):
+ *         p = PyCapsule_GetPointer(obj, name)
+ *     elif isinstance(obj, int) or isinstance(obj, long) and obj:             # <<<<<<<<<<<<<<
+ *         p = <void *><intptr_t>obj
+ *     else:
+ */
+  __pyx_t_3 = PyInt_Check(__pyx_v_obj); 
+  __pyx_t_4 = (__pyx_t_3 != 0);
+  if (!__pyx_t_4) {
+  } else {
+    __pyx_t_1 = __pyx_t_4;
+    goto __pyx_L4_bool_binop_done;
+  }
+  __pyx_t_4 = PyLong_Check(__pyx_v_obj); 
+  __pyx_t_3 = (__pyx_t_4 != 0);
+  if (__pyx_t_3) {
+  } else {
+    __pyx_t_1 = __pyx_t_3;
+    goto __pyx_L4_bool_binop_done;
+  }
+  __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_v_obj); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 921, __pyx_L1_error)
+  __pyx_t_1 = __pyx_t_3;
+  __pyx_L4_bool_binop_done:;
+  if (likely(__pyx_t_1)) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":820
- * 
- * cdef void _c_updatecb(void *ctx) with gil:
- *     (<object>ctx)()             # <<<<<<<<<<<<<<
+    /* "vidcutter/libs/pympv/mpv.pyx":922
+ *         p = PyCapsule_GetPointer(obj, name)
+ *     elif isinstance(obj, int) or isinstance(obj, long) and obj:
+ *         p = <void *><intptr_t>obj             # <<<<<<<<<<<<<<
+ *     else:
+ *         raise PyMPVError("Unknown or invalid pointer object: %r" % obj)
+ */
+    __pyx_t_5 = __Pyx_PyInt_As_intptr_t(__pyx_v_obj); if (unlikely((__pyx_t_5 == ((intptr_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 922, __pyx_L1_error)
+    __pyx_v_p = ((void *)((intptr_t)__pyx_t_5));
+
+    /* "vidcutter/libs/pympv/mpv.pyx":921
+ *     if PyCapsule_IsValid(obj, name):
+ *         p = PyCapsule_GetPointer(obj, name)
+ *     elif isinstance(obj, int) or isinstance(obj, long) and obj:             # <<<<<<<<<<<<<<
+ *         p = <void *><intptr_t>obj
+ *     else:
+ */
+    goto __pyx_L3;
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":924
+ *         p = <void *><intptr_t>obj
+ *     else:
+ *         raise PyMPVError("Unknown or invalid pointer object: %r" % obj)             # <<<<<<<<<<<<<<
+ *     return p
  * 
- * cdef class OpenGLContext(object):
  */
-  __Pyx_INCREF(((PyObject *)__pyx_v_ctx));
-  __pyx_t_2 = ((PyObject *)__pyx_v_ctx); __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_3)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
+  /*else*/ {
+    __Pyx_GetModuleGlobalName(__pyx_t_7, __pyx_n_s_PyMPVError); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 924, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_8 = __Pyx_PyString_FormatSafe(__pyx_kp_s_Unknown_or_invalid_pointer_objec, __pyx_v_obj); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 924, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    __pyx_t_9 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_7))) {
+      __pyx_t_9 = PyMethod_GET_SELF(__pyx_t_7);
+      if (likely(__pyx_t_9)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_7);
+        __Pyx_INCREF(__pyx_t_9);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_7, function);
+      }
     }
+    __pyx_t_6 = (__pyx_t_9) ? __Pyx_PyObject_Call2Args(__pyx_t_7, __pyx_t_9, __pyx_t_8) : __Pyx_PyObject_CallOneArg(__pyx_t_7, __pyx_t_8);
+    __Pyx_XDECREF(__pyx_t_9); __pyx_t_9 = 0;
+    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+    if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 924, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_6);
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __Pyx_Raise(__pyx_t_6, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
+    __PYX_ERR(0, 924, __pyx_L1_error)
   }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 820, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_L3:;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":819
- *     return <void *><intptr_t>(<object>ctx)(name)
- * 
- * cdef void _c_updatecb(void *ctx) with gil:             # <<<<<<<<<<<<<<
- *     (<object>ctx)()
+  /* "vidcutter/libs/pympv/mpv.pyx":925
+ *     else:
+ *         raise PyMPVError("Unknown or invalid pointer object: %r" % obj)
+ *     return p             # <<<<<<<<<<<<<<
  * 
+ * @cython.internal
  */
-
-  /* function exit code */
+  __pyx_r = __pyx_v_p;
   goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_WriteUnraisable("vidcutter.libs.mpv._c_updatecb", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
-  __pyx_L0:;
-  __Pyx_RefNannyFinishContext();
-  #ifdef WITH_THREAD
-  __Pyx_PyGILState_Release(__pyx_gilstate_save);
-  #endif
-}
 
-/* "vidcutter/libs/pympv/mpv.pyx":828
- *         object update_cb
+  /* "vidcutter/libs/pympv/mpv.pyx":917
+ *                 free(self.params[i].data)
  * 
- *     def __init__(self):             # <<<<<<<<<<<<<<
- *         self.inited = False
- *         warnings.warn("OpenGLContext is deprecated, please switch to RenderContext", DeprecationWarning)
+ * cdef void *get_pointer(const char *name, object obj):             # <<<<<<<<<<<<<<
+ *     cdef void *p
+ *     if PyCapsule_IsValid(obj, name):
  */
 
-/* Python wrapper */
-static int __pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static int __pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  int __pyx_r;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
-  if (unlikely(PyTuple_GET_SIZE(__pyx_args) > 0)) {
-    __Pyx_RaiseArgtupleInvalid("__init__", 1, 0, 0, PyTuple_GET_SIZE(__pyx_args)); return -1;}
-  if (unlikely(__pyx_kwds) && unlikely(PyDict_Size(__pyx_kwds) > 0) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__init__", 0))) return -1;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext___init__(((struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *)__pyx_v_self));
-
   /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_XDECREF(__pyx_t_9);
+  __Pyx_WriteUnraisable("vidcutter.libs.mpv.get_pointer", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0);
+  __pyx_r = 0;
+  __pyx_L0:;
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static int __pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext___init__(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self) {
-  int __pyx_r;
+/* "vidcutter/libs/pympv/mpv.pyx":929
+ * @cython.internal
+ * cdef class RenderFrameInfo(object):
+ *     cdef _from_struct(self, mpv_render_frame_info *info):             # <<<<<<<<<<<<<<
+ *         self.present = bool(info[0].flags & MPV_RENDER_FRAME_INFO_PRESENT)
+ *         self.redraw = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REDRAW)
+ */
+
+static PyObject *__pyx_f_9vidcutter_4libs_3mpv_15RenderFrameInfo__from_struct(struct __pyx_obj_9vidcutter_4libs_3mpv_RenderFrameInfo *__pyx_v_self, struct mpv_render_frame_info *__pyx_v_info) {
+  PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
-  PyObject *__pyx_t_2 = NULL;
+  int __pyx_t_2;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("__init__", 0);
+  __Pyx_RefNannySetupContext("_from_struct", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":829
- * 
- *     def __init__(self):
- *         self.inited = False             # <<<<<<<<<<<<<<
- *         warnings.warn("OpenGLContext is deprecated, please switch to RenderContext", DeprecationWarning)
- * 
+  /* "vidcutter/libs/pympv/mpv.pyx":930
+ * cdef class RenderFrameInfo(object):
+ *     cdef _from_struct(self, mpv_render_frame_info *info):
+ *         self.present = bool(info[0].flags & MPV_RENDER_FRAME_INFO_PRESENT)             # <<<<<<<<<<<<<<
+ *         self.redraw = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REDRAW)
+ *         self.repeat = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REPEAT)
  */
-  __pyx_v_self->inited = 0;
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(((__pyx_v_info[0]).flags & MPV_RENDER_FRAME_INFO_PRESENT)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 930, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 930, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_PyBool_FromLong((!(!__pyx_t_2))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 930, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  if (__Pyx_PyObject_SetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_present, __pyx_t_1) < 0) __PYX_ERR(0, 930, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":830
- *     def __init__(self):
- *         self.inited = False
- *         warnings.warn("OpenGLContext is deprecated, please switch to RenderContext", DeprecationWarning)             # <<<<<<<<<<<<<<
- * 
- *     def init_gl(self, exts, get_proc_address):
+  /* "vidcutter/libs/pympv/mpv.pyx":931
+ *     cdef _from_struct(self, mpv_render_frame_info *info):
+ *         self.present = bool(info[0].flags & MPV_RENDER_FRAME_INFO_PRESENT)
+ *         self.redraw = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REDRAW)             # <<<<<<<<<<<<<<
+ *         self.repeat = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REPEAT)
+ *         self.block_vsync = bool(info[0].flags & MPV_RENDER_FRAME_INFO_BLOCK_VSYNC)
  */
-  __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_warnings); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 830, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(((__pyx_v_info[0]).flags & MPV_RENDER_FRAME_INFO_REDRAW)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 931, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_warn); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 830, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 931, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__5, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 830, __pyx_L1_error)
+  __pyx_t_1 = __Pyx_PyBool_FromLong((!(!__pyx_t_2))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 931, __pyx_L1_error)
   __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (__Pyx_PyObject_SetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_redraw, __pyx_t_1) < 0) __PYX_ERR(0, 931, __pyx_L1_error)
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":828
- *         object update_cb
- * 
- *     def __init__(self):             # <<<<<<<<<<<<<<
- *         self.inited = False
- *         warnings.warn("OpenGLContext is deprecated, please switch to RenderContext", DeprecationWarning)
+  /* "vidcutter/libs/pympv/mpv.pyx":932
+ *         self.present = bool(info[0].flags & MPV_RENDER_FRAME_INFO_PRESENT)
+ *         self.redraw = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REDRAW)
+ *         self.repeat = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REPEAT)             # <<<<<<<<<<<<<<
+ *         self.block_vsync = bool(info[0].flags & MPV_RENDER_FRAME_INFO_BLOCK_VSYNC)
+ *         self.target_time = info[0].target_time
  */
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(((__pyx_v_info[0]).flags & MPV_RENDER_FRAME_INFO_REPEAT)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 932, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 932, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_PyBool_FromLong((!(!__pyx_t_2))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 932, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  if (__Pyx_PyObject_SetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_repeat, __pyx_t_1) < 0) __PYX_ERR(0, 932, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* function exit code */
-  __pyx_r = 0;
-  goto __pyx_L0;
+  /* "vidcutter/libs/pympv/mpv.pyx":933
+ *         self.redraw = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REDRAW)
+ *         self.repeat = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REPEAT)
+ *         self.block_vsync = bool(info[0].flags & MPV_RENDER_FRAME_INFO_BLOCK_VSYNC)             # <<<<<<<<<<<<<<
+ *         self.target_time = info[0].target_time
+ *         return self
+ */
+  __pyx_t_1 = __Pyx_PyInt_From_uint64_t(((__pyx_v_info[0]).flags & MPV_RENDER_FRAME_INFO_BLOCK_VSYNC)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 933, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 933, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_1 = __Pyx_PyBool_FromLong((!(!__pyx_t_2))); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 933, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  if (__Pyx_PyObject_SetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_block_vsync, __pyx_t_1) < 0) __PYX_ERR(0, 933, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":934
+ *         self.repeat = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REPEAT)
+ *         self.block_vsync = bool(info[0].flags & MPV_RENDER_FRAME_INFO_BLOCK_VSYNC)
+ *         self.target_time = info[0].target_time             # <<<<<<<<<<<<<<
+ *         return self
+ * 
+ */
+  __pyx_t_1 = __Pyx_PyInt_From_int64_t((__pyx_v_info[0]).target_time); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 934, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  if (__Pyx_PyObject_SetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_target_time, __pyx_t_1) < 0) __PYX_ERR(0, 934, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":935
+ *         self.block_vsync = bool(info[0].flags & MPV_RENDER_FRAME_INFO_BLOCK_VSYNC)
+ *         self.target_time = info[0].target_time
+ *         return self             # <<<<<<<<<<<<<<
+ * 
+ * cdef class RenderContext(object):
+ */
+  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(((PyObject *)__pyx_v_self));
+  __pyx_r = ((PyObject *)__pyx_v_self);
+  goto __pyx_L0;
+
+  /* "vidcutter/libs/pympv/mpv.pyx":929
+ * @cython.internal
+ * cdef class RenderFrameInfo(object):
+ *     cdef _from_struct(self, mpv_render_frame_info *info):             # <<<<<<<<<<<<<<
+ *         self.present = bool(info[0].flags & MPV_RENDER_FRAME_INFO_PRESENT)
+ *         self.redraw = bool(info[0].flags & MPV_RENDER_FRAME_INFO_REDRAW)
+ */
+
+  /* function exit code */
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.OpenGLContext.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = -1;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.RenderFrameInfo._from_struct", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
   __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":832
- *         warnings.warn("OpenGLContext is deprecated, please switch to RenderContext", DeprecationWarning)
- * 
- *     def init_gl(self, exts, get_proc_address):             # <<<<<<<<<<<<<<
- *         exts = _strenc(exts) if exts is not None else None
- *         cdef char* extsc = NULL
+/* "(tree fragment)":1
+ * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
+ *     cdef tuple state
+ *     cdef object _dict
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_3init_gl(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_3init_gl(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_exts = 0;
-  PyObject *__pyx_v_get_proc_address = 0;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_15RenderFrameInfo_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_15RenderFrameInfo_1__reduce_cython__(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("init_gl (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_exts,&__pyx_n_s_get_proc_address,0};
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_exts)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_get_proc_address)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("init_gl", 1, 2, 2, 1); __PYX_ERR(0, 832, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "init_gl") < 0)) __PYX_ERR(0, 832, __pyx_L3_error)
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_exts = values[0];
-    __pyx_v_get_proc_address = values[1];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("init_gl", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 832, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.OpenGLContext.init_gl", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_2init_gl(((struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *)__pyx_v_self), __pyx_v_exts, __pyx_v_get_proc_address);
+  __Pyx_RefNannySetupContext("__reduce_cython__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_15RenderFrameInfo___reduce_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_RenderFrameInfo *)__pyx_v_self));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_2init_gl(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self, PyObject *__pyx_v_exts, PyObject *__pyx_v_get_proc_address) {
-  char *__pyx_v_extsc;
-  int __pyx_v_err;
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_15RenderFrameInfo___reduce_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_RenderFrameInfo *__pyx_v_self) {
+  PyObject *__pyx_v_state = 0;
+  PyObject *__pyx_v__dict = 0;
+  int __pyx_v_use_setstate;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   int __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
+  int __pyx_t_3;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  int __pyx_t_6;
-  char *__pyx_t_7;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("init_gl", 0);
-  __Pyx_INCREF(__pyx_v_exts);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":833
- * 
- *     def init_gl(self, exts, get_proc_address):
- *         exts = _strenc(exts) if exts is not None else None             # <<<<<<<<<<<<<<
- *         cdef char* extsc = NULL
- *         if exts is not None:
- */
-  __pyx_t_2 = (__pyx_v_exts != Py_None);
-  if ((__pyx_t_2 != 0)) {
-    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_strenc); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 833, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-      if (likely(__pyx_t_5)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-        __Pyx_INCREF(__pyx_t_5);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_4, function);
-      }
-    }
-    __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_5, __pyx_v_exts) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_v_exts);
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 833, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __pyx_t_1 = __pyx_t_3;
-    __pyx_t_3 = 0;
-  } else {
-    __Pyx_INCREF(Py_None);
-    __pyx_t_1 = Py_None;
-  }
-  __Pyx_DECREF_SET(__pyx_v_exts, __pyx_t_1);
-  __pyx_t_1 = 0;
+  __Pyx_RefNannySetupContext("__reduce_cython__", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":834
- *     def init_gl(self, exts, get_proc_address):
- *         exts = _strenc(exts) if exts is not None else None
- *         cdef char* extsc = NULL             # <<<<<<<<<<<<<<
- *         if exts is not None:
- *             extsc = exts
+  /* "(tree fragment)":5
+ *     cdef object _dict
+ *     cdef bint use_setstate
+ *     state = ()             # <<<<<<<<<<<<<<
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:
  */
-  __pyx_v_extsc = NULL;
+  __Pyx_INCREF(__pyx_empty_tuple);
+  __pyx_v_state = __pyx_empty_tuple;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":835
- *         exts = _strenc(exts) if exts is not None else None
- *         cdef char* extsc = NULL
- *         if exts is not None:             # <<<<<<<<<<<<<<
- *             extsc = exts
- *         with nogil:
+  /* "(tree fragment)":6
+ *     cdef bint use_setstate
+ *     state = ()
+ *     _dict = getattr(self, '__dict__', None)             # <<<<<<<<<<<<<<
+ *     if _dict is not None:
+ *         state += (_dict,)
  */
-  __pyx_t_2 = (__pyx_v_exts != Py_None);
-  __pyx_t_6 = (__pyx_t_2 != 0);
-  if (__pyx_t_6) {
+  __pyx_t_1 = __Pyx_GetAttr3(((PyObject *)__pyx_v_self), __pyx_n_s_dict, Py_None); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 6, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v__dict = __pyx_t_1;
+  __pyx_t_1 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":836
- *         cdef char* extsc = NULL
- *         if exts is not None:
- *             extsc = exts             # <<<<<<<<<<<<<<
- *         with nogil:
- *             err = mpv_opengl_cb_init_gl(self._ctx, extsc, &_c_getprocaddress,
+  /* "(tree fragment)":7
+ *     state = ()
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:             # <<<<<<<<<<<<<<
+ *         state += (_dict,)
+ *         use_setstate = True
  */
-    __pyx_t_7 = __Pyx_PyObject_AsWritableString(__pyx_v_exts); if (unlikely((!__pyx_t_7) && PyErr_Occurred())) __PYX_ERR(0, 836, __pyx_L1_error)
-    __pyx_v_extsc = __pyx_t_7;
+  __pyx_t_2 = (__pyx_v__dict != Py_None);
+  __pyx_t_3 = (__pyx_t_2 != 0);
+  if (__pyx_t_3) {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":835
- *         exts = _strenc(exts) if exts is not None else None
- *         cdef char* extsc = NULL
- *         if exts is not None:             # <<<<<<<<<<<<<<
- *             extsc = exts
- *         with nogil:
+    /* "(tree fragment)":8
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:
+ *         state += (_dict,)             # <<<<<<<<<<<<<<
+ *         use_setstate = True
+ *     else:
  */
-  }
+    __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 8, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_INCREF(__pyx_v__dict);
+    __Pyx_GIVEREF(__pyx_v__dict);
+    PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v__dict);
+    __pyx_t_4 = PyNumber_InPlaceAdd(__pyx_v_state, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 8, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_DECREF_SET(__pyx_v_state, ((PyObject*)__pyx_t_4));
+    __pyx_t_4 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":837
- *         if exts is not None:
- *             extsc = exts
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_opengl_cb_init_gl(self._ctx, extsc, &_c_getprocaddress,
- *                                         <void *>get_proc_address)
+    /* "(tree fragment)":9
+ *     if _dict is not None:
+ *         state += (_dict,)
+ *         use_setstate = True             # <<<<<<<<<<<<<<
+ *     else:
+ *         use_setstate = False
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+    __pyx_v_use_setstate = 1;
 
-        /* "vidcutter/libs/pympv/mpv.pyx":838
- *             extsc = exts
- *         with nogil:
- *             err = mpv_opengl_cb_init_gl(self._ctx, extsc, &_c_getprocaddress,             # <<<<<<<<<<<<<<
- *                                         <void *>get_proc_address)
- *         if err < 0:
+    /* "(tree fragment)":7
+ *     state = ()
+ *     _dict = getattr(self, '__dict__', None)
+ *     if _dict is not None:             # <<<<<<<<<<<<<<
+ *         state += (_dict,)
+ *         use_setstate = True
  */
-        __pyx_v_err = mpv_opengl_cb_init_gl(__pyx_v_self->_ctx, __pyx_v_extsc, (&__pyx_f_9vidcutter_4libs_3mpv__c_getprocaddress), ((void *)__pyx_v_get_proc_address));
-      }
+    goto __pyx_L3;
+  }
 
-      /* "vidcutter/libs/pympv/mpv.pyx":837
- *         if exts is not None:
- *             extsc = exts
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_opengl_cb_init_gl(self._ctx, extsc, &_c_getprocaddress,
- *                                         <void *>get_proc_address)
+  /* "(tree fragment)":11
+ *         use_setstate = True
+ *     else:
+ *         use_setstate = False             # <<<<<<<<<<<<<<
+ *     if use_setstate:
+ *         return __pyx_unpickle_RenderFrameInfo, (type(self), 0xd41d8cd, None), state
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L6;
-        }
-        __pyx_L6:;
-      }
+  /*else*/ {
+    __pyx_v_use_setstate = 0;
   }
+  __pyx_L3:;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":840
- *             err = mpv_opengl_cb_init_gl(self._ctx, extsc, &_c_getprocaddress,
- *                                         <void *>get_proc_address)
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
- * 
+  /* "(tree fragment)":12
+ *     else:
+ *         use_setstate = False
+ *     if use_setstate:             # <<<<<<<<<<<<<<
+ *         return __pyx_unpickle_RenderFrameInfo, (type(self), 0xd41d8cd, None), state
+ *     else:
  */
-  __pyx_t_6 = ((__pyx_v_err < 0) != 0);
-  if (unlikely(__pyx_t_6)) {
+  __pyx_t_3 = (__pyx_v_use_setstate != 0);
+  if (__pyx_t_3) {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":841
- *                                         <void *>get_proc_address)
- *         if err < 0:
- *             raise MPVError(err)             # <<<<<<<<<<<<<<
- * 
- *         self.inited = True
+    /* "(tree fragment)":13
+ *         use_setstate = False
+ *     if use_setstate:
+ *         return __pyx_unpickle_RenderFrameInfo, (type(self), 0xd41d8cd, None), state             # <<<<<<<<<<<<<<
+ *     else:
+ *         return __pyx_unpickle_RenderFrameInfo, (type(self), 0xd41d8cd, state)
  */
-    __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 841, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_4 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 841, __pyx_L1_error)
+    __Pyx_XDECREF(__pyx_r);
+    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_pyx_unpickle_RenderFrameInfo); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 13, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
-      if (likely(__pyx_t_5)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-        __Pyx_INCREF(__pyx_t_5);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_3, function);
-      }
-    }
-    __pyx_t_1 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_3, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_4);
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 841, __pyx_L1_error)
+    __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 13, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __Pyx_Raise(__pyx_t_1, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __PYX_ERR(0, 841, __pyx_L1_error)
+    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_INCREF(__pyx_int_222419149);
+    __Pyx_GIVEREF(__pyx_int_222419149);
+    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_222419149);
+    __Pyx_INCREF(Py_None);
+    __Pyx_GIVEREF(Py_None);
+    PyTuple_SET_ITEM(__pyx_t_1, 2, Py_None);
+    __pyx_t_5 = PyTuple_New(3); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 13, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_4);
+    PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_4);
+    __Pyx_GIVEREF(__pyx_t_1);
+    PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_1);
+    __Pyx_INCREF(__pyx_v_state);
+    __Pyx_GIVEREF(__pyx_v_state);
+    PyTuple_SET_ITEM(__pyx_t_5, 2, __pyx_v_state);
+    __pyx_t_4 = 0;
+    __pyx_t_1 = 0;
+    __pyx_r = __pyx_t_5;
+    __pyx_t_5 = 0;
+    goto __pyx_L0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":840
- *             err = mpv_opengl_cb_init_gl(self._ctx, extsc, &_c_getprocaddress,
- *                                         <void *>get_proc_address)
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
- * 
+    /* "(tree fragment)":12
+ *     else:
+ *         use_setstate = False
+ *     if use_setstate:             # <<<<<<<<<<<<<<
+ *         return __pyx_unpickle_RenderFrameInfo, (type(self), 0xd41d8cd, None), state
+ *     else:
  */
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":843
- *             raise MPVError(err)
- * 
- *         self.inited = True             # <<<<<<<<<<<<<<
- * 
- *     def set_update_callback(self, cb):
+  /* "(tree fragment)":15
+ *         return __pyx_unpickle_RenderFrameInfo, (type(self), 0xd41d8cd, None), state
+ *     else:
+ *         return __pyx_unpickle_RenderFrameInfo, (type(self), 0xd41d8cd, state)             # <<<<<<<<<<<<<<
+ * def __setstate_cython__(self, __pyx_state):
+ *     __pyx_unpickle_RenderFrameInfo__set_state(self, __pyx_state)
  */
-  __pyx_v_self->inited = 1;
+  /*else*/ {
+    __Pyx_XDECREF(__pyx_r);
+    __Pyx_GetModuleGlobalName(__pyx_t_5, __pyx_n_s_pyx_unpickle_RenderFrameInfo); if (unlikely(!__pyx_t_5)) __PYX_ERR(1, 15, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
+    __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 15, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_INCREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_GIVEREF(((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    PyTuple_SET_ITEM(__pyx_t_1, 0, ((PyObject *)Py_TYPE(((PyObject *)__pyx_v_self))));
+    __Pyx_INCREF(__pyx_int_222419149);
+    __Pyx_GIVEREF(__pyx_int_222419149);
+    PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_int_222419149);
+    __Pyx_INCREF(__pyx_v_state);
+    __Pyx_GIVEREF(__pyx_v_state);
+    PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_state);
+    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(1, 15, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_GIVEREF(__pyx_t_5);
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_5);
+    __Pyx_GIVEREF(__pyx_t_1);
+    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_1);
+    __pyx_t_5 = 0;
+    __pyx_t_1 = 0;
+    __pyx_r = __pyx_t_4;
+    __pyx_t_4 = 0;
+    goto __pyx_L0;
+  }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":832
- *         warnings.warn("OpenGLContext is deprecated, please switch to RenderContext", DeprecationWarning)
- * 
- *     def init_gl(self, exts, get_proc_address):             # <<<<<<<<<<<<<<
- *         exts = _strenc(exts) if exts is not None else None
- *         cdef char* extsc = NULL
+  /* "(tree fragment)":1
+ * def __reduce_cython__(self):             # <<<<<<<<<<<<<<
+ *     cdef tuple state
+ *     cdef object _dict
  */
 
   /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_3);
   __Pyx_XDECREF(__pyx_t_4);
   __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.OpenGLContext.init_gl", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.RenderFrameInfo.__reduce_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_exts);
+  __Pyx_XDECREF(__pyx_v_state);
+  __Pyx_XDECREF(__pyx_v__dict);
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":845
- *         self.inited = True
- * 
- *     def set_update_callback(self, cb):             # <<<<<<<<<<<<<<
- *         self.update_cb = cb
- *         with nogil:
+/* "(tree fragment)":16
+ *     else:
+ *         return __pyx_unpickle_RenderFrameInfo, (type(self), 0xd41d8cd, state)
+ * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
+ *     __pyx_unpickle_RenderFrameInfo__set_state(self, __pyx_state)
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_5set_update_callback(PyObject *__pyx_v_self, PyObject *__pyx_v_cb); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_5set_update_callback(PyObject *__pyx_v_self, PyObject *__pyx_v_cb) {
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_15RenderFrameInfo_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state); /*proto*/
+static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_15RenderFrameInfo_3__setstate_cython__(PyObject *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("set_update_callback (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_4set_update_callback(((struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *)__pyx_v_self), ((PyObject *)__pyx_v_cb));
+  __Pyx_RefNannySetupContext("__setstate_cython__ (wrapper)", 0);
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_15RenderFrameInfo_2__setstate_cython__(((struct __pyx_obj_9vidcutter_4libs_3mpv_RenderFrameInfo *)__pyx_v_self), ((PyObject *)__pyx_v___pyx_state));
 
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_4set_update_callback(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self, PyObject *__pyx_v_cb) {
+static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_15RenderFrameInfo_2__setstate_cython__(struct __pyx_obj_9vidcutter_4libs_3mpv_RenderFrameInfo *__pyx_v_self, PyObject *__pyx_v___pyx_state) {
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("set_update_callback", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":846
- * 
- *     def set_update_callback(self, cb):
- *         self.update_cb = cb             # <<<<<<<<<<<<<<
- *         with nogil:
- *             mpv_opengl_cb_set_update_callback(self._ctx, &_c_updatecb, <void *>cb)
- */
-  __Pyx_INCREF(__pyx_v_cb);
-  __Pyx_GIVEREF(__pyx_v_cb);
-  __Pyx_GOTREF(__pyx_v_self->update_cb);
-  __Pyx_DECREF(__pyx_v_self->update_cb);
-  __pyx_v_self->update_cb = __pyx_v_cb;
-
-  /* "vidcutter/libs/pympv/mpv.pyx":847
- *     def set_update_callback(self, cb):
- *         self.update_cb = cb
- *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_opengl_cb_set_update_callback(self._ctx, &_c_updatecb, <void *>cb)
- * 
- */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
-
-        /* "vidcutter/libs/pympv/mpv.pyx":848
- *         self.update_cb = cb
- *         with nogil:
- *             mpv_opengl_cb_set_update_callback(self._ctx, &_c_updatecb, <void *>cb)             # <<<<<<<<<<<<<<
- * 
- *     def draw(self, fbo, w, h):
- */
-        mpv_opengl_cb_set_update_callback(__pyx_v_self->_ctx, (&__pyx_f_9vidcutter_4libs_3mpv__c_updatecb), ((void *)__pyx_v_cb));
-      }
+  PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+  __Pyx_RefNannySetupContext("__setstate_cython__", 0);
 
-      /* "vidcutter/libs/pympv/mpv.pyx":847
- *     def set_update_callback(self, cb):
- *         self.update_cb = cb
- *         with nogil:             # <<<<<<<<<<<<<<
- *             mpv_opengl_cb_set_update_callback(self._ctx, &_c_updatecb, <void *>cb)
- * 
+  /* "(tree fragment)":17
+ *         return __pyx_unpickle_RenderFrameInfo, (type(self), 0xd41d8cd, state)
+ * def __setstate_cython__(self, __pyx_state):
+ *     __pyx_unpickle_RenderFrameInfo__set_state(self, __pyx_state)             # <<<<<<<<<<<<<<
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
-  }
+  if (!(likely(PyTuple_CheckExact(__pyx_v___pyx_state))||((__pyx_v___pyx_state) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_v___pyx_state)->tp_name), 0))) __PYX_ERR(1, 17, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_9vidcutter_4libs_3mpv___pyx_unpickle_RenderFrameInfo__set_state(__pyx_v_self, ((PyObject*)__pyx_v___pyx_state)); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 17, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":845
- *         self.inited = True
- * 
- *     def set_update_callback(self, cb):             # <<<<<<<<<<<<<<
- *         self.update_cb = cb
- *         with nogil:
+  /* "(tree fragment)":16
+ *     else:
+ *         return __pyx_unpickle_RenderFrameInfo, (type(self), 0xd41d8cd, state)
+ * def __setstate_cython__(self, __pyx_state):             # <<<<<<<<<<<<<<
+ *     __pyx_unpickle_RenderFrameInfo__set_state(self, __pyx_state)
  */
 
   /* function exit code */
   __pyx_r = Py_None; __Pyx_INCREF(Py_None);
+  goto __pyx_L0;
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("vidcutter.libs.mpv.RenderFrameInfo.__setstate_cython__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
   __Pyx_XGIVEREF(__pyx_r);
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-/* "vidcutter/libs/pympv/mpv.pyx":850
- *             mpv_opengl_cb_set_update_callback(self._ctx, &_c_updatecb, <void *>cb)
+/* "vidcutter/libs/pympv/mpv.pyx":950
+ *         bint inited
  * 
- *     def draw(self, fbo, w, h):             # <<<<<<<<<<<<<<
- *         cdef:
- *             int fboc = fbo
+ *     def __init__(self, mpv,             # <<<<<<<<<<<<<<
+ *                  api_type,
+ *                  opengl_init_params=None,
  */
 
 /* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_7draw(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_7draw(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_fbo = 0;
-  PyObject *__pyx_v_w = 0;
-  PyObject *__pyx_v_h = 0;
+static int __pyx_pw_9vidcutter_4libs_3mpv_13RenderContext_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static int __pyx_pw_9vidcutter_4libs_3mpv_13RenderContext_1__init__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_mpv = 0;
+  PyObject *__pyx_v_api_type = 0;
+  PyObject *__pyx_v_opengl_init_params = 0;
+  PyObject *__pyx_v_advanced_control = 0;
+  PyObject *__pyx_v_x11_display = 0;
+  PyObject *__pyx_v_wl_display = 0;
+  PyObject *__pyx_v_drm_display = 0;
+  PyObject *__pyx_v_drm_osd_size = 0;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  PyObject *__pyx_r = 0;
+  int __pyx_r;
   __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("draw (wrapper)", 0);
+  __Pyx_RefNannySetupContext("__init__ (wrapper)", 0);
   {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_fbo,&__pyx_n_s_w,&__pyx_n_s_h,0};
-    PyObject* values[3] = {0,0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_fbo)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_w)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("draw", 1, 3, 3, 1); __PYX_ERR(0, 850, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  2:
-        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_h)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("draw", 1, 3, 3, 2); __PYX_ERR(0, 850, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "draw") < 0)) __PYX_ERR(0, 850, __pyx_L3_error)
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-    }
-    __pyx_v_fbo = values[0];
-    __pyx_v_w = values[1];
-    __pyx_v_h = values[2];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("draw", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 850, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("vidcutter.libs.mpv.OpenGLContext.draw", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_6draw(((struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *)__pyx_v_self), __pyx_v_fbo, __pyx_v_w, __pyx_v_h);
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_mpv,&__pyx_n_s_api_type,&__pyx_n_s_opengl_init_params,&__pyx_n_s_advanced_control,&__pyx_n_s_x11_display,&__pyx_n_s_wl_display,&__pyx_n_s_drm_display,&__pyx_n_s_drm_osd_size,0};
+    PyObject* values[8] = {0,0,0,0,0,0,0,0};
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_6draw(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self, PyObject *__pyx_v_fbo, PyObject *__pyx_v_w, PyObject *__pyx_v_h) {
-  int __pyx_v_fboc;
-  int __pyx_v_wc;
-  int __pyx_v_hc;
-  int __pyx_v_err;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  int __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("draw", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":852
- *     def draw(self, fbo, w, h):
- *         cdef:
- *             int fboc = fbo             # <<<<<<<<<<<<<<
- *             int wc = w
- *             int hc = h
+    /* "vidcutter/libs/pympv/mpv.pyx":952
+ *     def __init__(self, mpv,
+ *                  api_type,
+ *                  opengl_init_params=None,             # <<<<<<<<<<<<<<
+ *                  advanced_control=False,
+ *                  x11_display=None,
  */
-  __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_fbo); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 852, __pyx_L1_error)
-  __pyx_v_fboc = __pyx_t_1;
+    values[2] = ((PyObject *)Py_None);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":853
- *         cdef:
- *             int fboc = fbo
- *             int wc = w             # <<<<<<<<<<<<<<
- *             int hc = h
- *         with nogil:
+    /* "vidcutter/libs/pympv/mpv.pyx":953
+ *                  api_type,
+ *                  opengl_init_params=None,
+ *                  advanced_control=False,             # <<<<<<<<<<<<<<
+ *                  x11_display=None,
+ *                  wl_display=None,
  */
-  __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_w); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 853, __pyx_L1_error)
-  __pyx_v_wc = __pyx_t_1;
+    values[3] = ((PyObject *)Py_False);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":854
- *             int fboc = fbo
- *             int wc = w
- *             int hc = h             # <<<<<<<<<<<<<<
- *         with nogil:
- *             err = mpv_opengl_cb_draw(self._ctx, fboc, wc, hc)
+    /* "vidcutter/libs/pympv/mpv.pyx":954
+ *                  opengl_init_params=None,
+ *                  advanced_control=False,
+ *                  x11_display=None,             # <<<<<<<<<<<<<<
+ *                  wl_display=None,
+ *                  drm_display=None,
  */
-  __pyx_t_1 = __Pyx_PyInt_As_int(__pyx_v_h); if (unlikely((__pyx_t_1 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 854, __pyx_L1_error)
-  __pyx_v_hc = __pyx_t_1;
+    values[4] = ((PyObject *)Py_None);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":855
- *             int wc = w
- *             int hc = h
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_opengl_cb_draw(self._ctx, fboc, wc, hc)
- *         if err < 0:
+    /* "vidcutter/libs/pympv/mpv.pyx":955
+ *                  advanced_control=False,
+ *                  x11_display=None,
+ *                  wl_display=None,             # <<<<<<<<<<<<<<
+ *                  drm_display=None,
+ *                  drm_osd_size=None
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+    values[5] = ((PyObject *)Py_None);
 
-        /* "vidcutter/libs/pympv/mpv.pyx":856
- *             int hc = h
- *         with nogil:
- *             err = mpv_opengl_cb_draw(self._ctx, fboc, wc, hc)             # <<<<<<<<<<<<<<
- *         if err < 0:
- *             raise MPVError(err)
+    /* "vidcutter/libs/pympv/mpv.pyx":956
+ *                  x11_display=None,
+ *                  wl_display=None,
+ *                  drm_display=None,             # <<<<<<<<<<<<<<
+ *                  drm_osd_size=None
+ *                  ):
  */
-        __pyx_v_err = mpv_opengl_cb_draw(__pyx_v_self->_ctx, __pyx_v_fboc, __pyx_v_wc, __pyx_v_hc);
-      }
+    values[6] = ((PyObject *)Py_None);
 
-      /* "vidcutter/libs/pympv/mpv.pyx":855
- *             int wc = w
- *             int hc = h
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_opengl_cb_draw(self._ctx, fboc, wc, hc)
- *         if err < 0:
+    /* "vidcutter/libs/pympv/mpv.pyx":957
+ *                  wl_display=None,
+ *                  drm_display=None,
+ *                  drm_osd_size=None             # <<<<<<<<<<<<<<
+ *                  ):
+ * 
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
+    values[7] = ((PyObject *)Py_None);
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
+        CYTHON_FALLTHROUGH;
+        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
+        CYTHON_FALLTHROUGH;
+        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
+        CYTHON_FALLTHROUGH;
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        CYTHON_FALLTHROUGH;
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        CYTHON_FALLTHROUGH;
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        CYTHON_FALLTHROUGH;
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_mpv)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
+        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_api_type)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("__init__", 0, 2, 8, 1); __PYX_ERR(0, 950, __pyx_L3_error)
+        }
+        CYTHON_FALLTHROUGH;
+        case  2:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_opengl_init_params);
+          if (value) { values[2] = value; kw_args--; }
+        }
+        CYTHON_FALLTHROUGH;
+        case  3:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_advanced_control);
+          if (value) { values[3] = value; kw_args--; }
+        }
+        CYTHON_FALLTHROUGH;
+        case  4:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_x11_display);
+          if (value) { values[4] = value; kw_args--; }
+        }
+        CYTHON_FALLTHROUGH;
+        case  5:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_wl_display);
+          if (value) { values[5] = value; kw_args--; }
+        }
+        CYTHON_FALLTHROUGH;
+        case  6:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_drm_display);
+          if (value) { values[6] = value; kw_args--; }
+        }
+        CYTHON_FALLTHROUGH;
+        case  7:
+        if (kw_args > 0) {
+          PyObject* value = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_drm_osd_size);
+          if (value) { values[7] = value; kw_args--; }
         }
-        __pyx_L5:;
       }
-  }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":857
- *         with nogil:
- *             err = mpv_opengl_cb_draw(self._ctx, fboc, wc, hc)
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
- * 
- */
-  __pyx_t_2 = ((__pyx_v_err < 0) != 0);
-  if (unlikely(__pyx_t_2)) {
-
-    /* "vidcutter/libs/pympv/mpv.pyx":858
- *             err = mpv_opengl_cb_draw(self._ctx, fboc, wc, hc)
- *         if err < 0:
- *             raise MPVError(err)             # <<<<<<<<<<<<<<
- * 
- *     def report_flip(self, time):
- */
-    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 858, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 858, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_6 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4);
-      if (likely(__pyx_t_6)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-        __Pyx_INCREF(__pyx_t_6);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_4, function);
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__init__") < 0)) __PYX_ERR(0, 950, __pyx_L3_error)
+      }
+    } else {
+      switch (PyTuple_GET_SIZE(__pyx_args)) {
+        case  8: values[7] = PyTuple_GET_ITEM(__pyx_args, 7);
+        CYTHON_FALLTHROUGH;
+        case  7: values[6] = PyTuple_GET_ITEM(__pyx_args, 6);
+        CYTHON_FALLTHROUGH;
+        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);
+        CYTHON_FALLTHROUGH;
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        CYTHON_FALLTHROUGH;
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        CYTHON_FALLTHROUGH;
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        CYTHON_FALLTHROUGH;
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        break;
+        default: goto __pyx_L5_argtuple_error;
       }
     }
-    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
-    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 858, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 858, __pyx_L1_error)
-
-    /* "vidcutter/libs/pympv/mpv.pyx":857
- *         with nogil:
- *             err = mpv_opengl_cb_draw(self._ctx, fboc, wc, hc)
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
- * 
- */
+    __pyx_v_mpv = values[0];
+    __pyx_v_api_type = values[1];
+    __pyx_v_opengl_init_params = values[2];
+    __pyx_v_advanced_control = values[3];
+    __pyx_v_x11_display = values[4];
+    __pyx_v_wl_display = values[5];
+    __pyx_v_drm_display = values[6];
+    __pyx_v_drm_osd_size = values[7];
   }
-
-  /* "vidcutter/libs/pympv/mpv.pyx":850
- *             mpv_opengl_cb_set_update_callback(self._ctx, &_c_updatecb, <void *>cb)
- * 
- *     def draw(self, fbo, w, h):             # <<<<<<<<<<<<<<
- *         cdef:
- *             int fboc = fbo
- */
-
-  /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.OpenGLContext.draw", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__init__", 0, 2, 8, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 950, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("vidcutter.libs.mpv.RenderContext.__init__", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+  return -1;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13RenderContext___init__(((struct __pyx_obj_9vidcutter_4libs_3mpv_RenderContext *)__pyx_v_self), __pyx_v_mpv, __pyx_v_api_type, __pyx_v_opengl_init_params, __pyx_v_advanced_control, __pyx_v_x11_display, __pyx_v_wl_display, __pyx_v_drm_display, __pyx_v_drm_osd_size);
 
-/* "vidcutter/libs/pympv/mpv.pyx":860
- *             raise MPVError(err)
+  /* "vidcutter/libs/pympv/mpv.pyx":950
+ *         bint inited
  * 
- *     def report_flip(self, time):             # <<<<<<<<<<<<<<
- *         cdef int64_t ctime = time
- *         with nogil:
+ *     def __init__(self, mpv,             # <<<<<<<<<<<<<<
+ *                  api_type,
+ *                  opengl_init_params=None,
  */
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_9report_flip(PyObject *__pyx_v_self, PyObject *__pyx_v_time); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_9report_flip(PyObject *__pyx_v_self, PyObject *__pyx_v_time) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("report_flip (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_8report_flip(((struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *)__pyx_v_self), ((PyObject *)__pyx_v_time));
-
   /* function exit code */
   __Pyx_RefNannyFinishContext();
   return __pyx_r;
 }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_8report_flip(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self, PyObject *__pyx_v_time) {
-  int64_t __pyx_v_ctime;
-  int __pyx_v_err;
-  PyObject *__pyx_r = NULL;
+static int __pyx_pf_9vidcutter_4libs_3mpv_13RenderContext___init__(struct __pyx_obj_9vidcutter_4libs_3mpv_RenderContext *__pyx_v_self, PyObject *__pyx_v_mpv, PyObject *__pyx_v_api_type, PyObject *__pyx_v_opengl_init_params, PyObject *__pyx_v_advanced_control, PyObject *__pyx_v_x11_display, PyObject *__pyx_v_wl_display, PyObject *__pyx_v_drm_display, PyObject *__pyx_v_drm_osd_size) {
+  struct mpv_opengl_init_params __pyx_v_gl_params;
+  struct mpv_opengl_drm_params __pyx_v_drm_params;
+  struct mpv_opengl_drm_osd_size __pyx_v__drm_osd_size;
+  struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *__pyx_v_params = NULL;
+  PyObject *__pyx_v_arp = NULL;
+  int __pyx_v_err;
+  int __pyx_r;
   __Pyx_RefNannyDeclarations
-  int64_t __pyx_t_1;
-  int __pyx_t_2;
-  PyObject *__pyx_t_3 = NULL;
+  PyObject *__pyx_t_1 = NULL;
+  PyObject *__pyx_t_2 = NULL;
+  int __pyx_t_3;
   PyObject *__pyx_t_4 = NULL;
   PyObject *__pyx_t_5 = NULL;
-  PyObject *__pyx_t_6 = NULL;
+  int __pyx_t_6;
+  int __pyx_t_7;
+  char const *__pyx_t_8;
+  PyObject *(*__pyx_t_9)(PyObject *);
+  int __pyx_t_10;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("report_flip", 0);
+  __Pyx_RefNannySetupContext("__init__", 0);
 
-  /* "vidcutter/libs/pympv/mpv.pyx":861
+  /* "vidcutter/libs/pympv/mpv.pyx":965
+ *             mpv_opengl_drm_osd_size _drm_osd_size
  * 
- *     def report_flip(self, time):
- *         cdef int64_t ctime = time             # <<<<<<<<<<<<<<
- *         with nogil:
- *             err = mpv_opengl_cb_report_flip(self._ctx, ctime)
+ *         self._mpv = mpv             # <<<<<<<<<<<<<<
+ * 
+ *         memset(&gl_params, 0, sizeof(gl_params))
  */
-  __pyx_t_1 = __Pyx_PyInt_As_int64_t(__pyx_v_time); if (unlikely((__pyx_t_1 == ((int64_t)-1)) && PyErr_Occurred())) __PYX_ERR(0, 861, __pyx_L1_error)
-  __pyx_v_ctime = __pyx_t_1;
+  if (!(likely(((__pyx_v_mpv) == Py_None) || likely(__Pyx_TypeTest(__pyx_v_mpv, __pyx_ptype_9vidcutter_4libs_3mpv_Context))))) __PYX_ERR(0, 965, __pyx_L1_error)
+  __pyx_t_1 = __pyx_v_mpv;
+  __Pyx_INCREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_1);
+  __Pyx_GOTREF(__pyx_v_self->_mpv);
+  __Pyx_DECREF(((PyObject *)__pyx_v_self->_mpv));
+  __pyx_v_self->_mpv = ((struct __pyx_obj_9vidcutter_4libs_3mpv_Context *)__pyx_t_1);
+  __pyx_t_1 = 0;
 
-  /* "vidcutter/libs/pympv/mpv.pyx":862
- *     def report_flip(self, time):
- *         cdef int64_t ctime = time
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_opengl_cb_report_flip(self._ctx, ctime)
- *         if err < 0:
+  /* "vidcutter/libs/pympv/mpv.pyx":967
+ *         self._mpv = mpv
+ * 
+ *         memset(&gl_params, 0, sizeof(gl_params))             # <<<<<<<<<<<<<<
+ *         memset(&drm_params, 0, sizeof(drm_params))
+ *         memset(&_drm_osd_size, 0, sizeof(_drm_osd_size))
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+  (void)(memset((&__pyx_v_gl_params), 0, (sizeof(__pyx_v_gl_params))));
 
-        /* "vidcutter/libs/pympv/mpv.pyx":863
- *         cdef int64_t ctime = time
- *         with nogil:
- *             err = mpv_opengl_cb_report_flip(self._ctx, ctime)             # <<<<<<<<<<<<<<
- *         if err < 0:
- *             raise MPVError(err)
+  /* "vidcutter/libs/pympv/mpv.pyx":968
+ * 
+ *         memset(&gl_params, 0, sizeof(gl_params))
+ *         memset(&drm_params, 0, sizeof(drm_params))             # <<<<<<<<<<<<<<
+ *         memset(&_drm_osd_size, 0, sizeof(_drm_osd_size))
+ * 
  */
-        __pyx_v_err = mpv_opengl_cb_report_flip(__pyx_v_self->_ctx, __pyx_v_ctime);
-      }
+  (void)(memset((&__pyx_v_drm_params), 0, (sizeof(__pyx_v_drm_params))));
 
-      /* "vidcutter/libs/pympv/mpv.pyx":862
- *     def report_flip(self, time):
- *         cdef int64_t ctime = time
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_opengl_cb_report_flip(self._ctx, ctime)
- *         if err < 0:
+  /* "vidcutter/libs/pympv/mpv.pyx":969
+ *         memset(&gl_params, 0, sizeof(gl_params))
+ *         memset(&drm_params, 0, sizeof(drm_params))
+ *         memset(&_drm_osd_size, 0, sizeof(_drm_osd_size))             # <<<<<<<<<<<<<<
+ * 
+ *         params = _RenderParams()
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L5;
-        }
-        __pyx_L5:;
-      }
-  }
+  (void)(memset((&__pyx_v__drm_osd_size), 0, (sizeof(__pyx_v__drm_osd_size))));
 
-  /* "vidcutter/libs/pympv/mpv.pyx":864
- *         with nogil:
- *             err = mpv_opengl_cb_report_flip(self._ctx, ctime)
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
+  /* "vidcutter/libs/pympv/mpv.pyx":971
+ *         memset(&_drm_osd_size, 0, sizeof(_drm_osd_size))
+ * 
+ *         params = _RenderParams()             # <<<<<<<<<<<<<<
  * 
+ *         if api_type == self.API_OPENGL:
  */
-  __pyx_t_2 = ((__pyx_v_err < 0) != 0);
-  if (unlikely(__pyx_t_2)) {
+  __pyx_t_1 = __Pyx_PyObject_CallNoArg(((PyObject *)__pyx_ptype_9vidcutter_4libs_3mpv__RenderParams)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 971, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_params = ((struct __pyx_obj_9vidcutter_4libs_3mpv__RenderParams *)__pyx_t_1);
+  __pyx_t_1 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":865
- *             err = mpv_opengl_cb_report_flip(self._ctx, ctime)
- *         if err < 0:
- *             raise MPVError(err)             # <<<<<<<<<<<<<<
+  /* "vidcutter/libs/pympv/mpv.pyx":973
+ *         params = _RenderParams()
+ * 
+ *         if api_type == self.API_OPENGL:             # <<<<<<<<<<<<<<
+ *             params.add_string(MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL)
+ *         else:
+ */
+  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_self), __pyx_n_s_API_OPENGL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 973, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_2 = PyObject_RichCompare(__pyx_v_api_type, __pyx_t_1, Py_EQ); __Pyx_XGOTREF(__pyx_t_2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 973, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_t_3 = __Pyx_PyObject_IsTrue(__pyx_t_2); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 973, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (likely(__pyx_t_3)) {
+
+    /* "vidcutter/libs/pympv/mpv.pyx":974
+ * 
+ *         if api_type == self.API_OPENGL:
+ *             params.add_string(MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL)             # <<<<<<<<<<<<<<
+ *         else:
+ *             raise PyMPVError("Unknown api_type %r" % api_type)
+ */
+    __pyx_t_2 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv__RenderParams *)__pyx_v_params->__pyx_vtab)->add_string(__pyx_v_params, MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 974, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+    /* "vidcutter/libs/pympv/mpv.pyx":973
+ *         params = _RenderParams()
+ * 
+ *         if api_type == self.API_OPENGL:             # <<<<<<<<<<<<<<
+ *             params.add_string(MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL)
+ *         else:
+ */
+    goto __pyx_L3;
+  }
+
+  /* "vidcutter/libs/pympv/mpv.pyx":976
+ *             params.add_string(MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL)
+ *         else:
+ *             raise PyMPVError("Unknown api_type %r" % api_type)             # <<<<<<<<<<<<<<
  * 
- *     def uninit_gl(self):
+ *         if opengl_init_params is not None:
  */
-    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_MPVError); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 865, __pyx_L1_error)
+  /*else*/ {
+    __Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_PyMPVError); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 976, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_4 = __Pyx_PyString_FormatSafe(__pyx_kp_s_Unknown_api_type_r, __pyx_v_api_type); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 976, __pyx_L1_error)
     __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_err); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 865, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __pyx_t_6 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-      __pyx_t_6 = PyMethod_GET_SELF(__pyx_t_4);
-      if (likely(__pyx_t_6)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-        __Pyx_INCREF(__pyx_t_6);
+    __pyx_t_5 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);
+        __Pyx_INCREF(__pyx_t_5);
         __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_4, function);
+        __Pyx_DECREF_SET(__pyx_t_1, function);
       }
     }
-    __pyx_t_3 = (__pyx_t_6) ? __Pyx_PyObject_Call2Args(__pyx_t_4, __pyx_t_6, __pyx_t_5) : __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5);
-    __Pyx_XDECREF(__pyx_t_6); __pyx_t_6 = 0;
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 865, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_2 = (__pyx_t_5) ? __Pyx_PyObject_Call2Args(__pyx_t_1, __pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_t_4);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_Raise(__pyx_t_3, 0, 0, 0);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __PYX_ERR(0, 865, __pyx_L1_error)
+    if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 976, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __Pyx_Raise(__pyx_t_2, 0, 0, 0);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __PYX_ERR(0, 976, __pyx_L1_error)
+  }
+  __pyx_L3:;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":864
- *         with nogil:
- *             err = mpv_opengl_cb_report_flip(self._ctx, ctime)
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
+  /* "vidcutter/libs/pympv/mpv.pyx":978
+ *             raise PyMPVError("Unknown api_type %r" % api_type)
  * 
+ *         if opengl_init_params is not None:             # <<<<<<<<<<<<<<
+ *             self._get_proc_address = opengl_init_params["get_proc_address"]
+ *             gl_params.get_proc_address = &_c_getprocaddress
  */
-  }
+  __pyx_t_3 = (__pyx_v_opengl_init_params != Py_None);
+  __pyx_t_6 = (__pyx_t_3 != 0);
+  if (__pyx_t_6) {
 
-  /* "vidcutter/libs/pympv/mpv.pyx":860
- *             raise MPVError(err)
+    /* "vidcutter/libs/pympv/mpv.pyx":979
  * 
- *     def report_flip(self, time):             # <<<<<<<<<<<<<<
- *         cdef int64_t ctime = time
- *         with nogil:
+ *         if opengl_init_params is not None:
+ *             self._get_proc_address = opengl_init_params["get_proc_address"]             # <<<<<<<<<<<<<<
+ *             gl_params.get_proc_address = &_c_getprocaddress
+ *             gl_params.get_proc_address_ctx = <void *>self._get_proc_address
  */
+    __pyx_t_2 = __Pyx_PyObject_Dict_GetItem(__pyx_v_opengl_init_params, __pyx_n_s_get_proc_address); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 979, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_GIVEREF(__pyx_t_2);
+    __Pyx_GOTREF(__pyx_v_self->_get_proc_address);
+    __Pyx_DECREF(__pyx_v_self->_get_proc_address);
+    __pyx_v_self->_get_proc_address = __pyx_t_2;
+    __pyx_t_2 = 0;
 
-  /* function exit code */
-  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-  goto __pyx_L0;
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("vidcutter.libs.mpv.OpenGLContext.report_flip", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":980
+ *         if opengl_init_params is not None:
+ *             self._get_proc_address = opengl_init_params["get_proc_address"]
+ *             gl_params.get_proc_address = &_c_getprocaddress             # <<<<<<<<<<<<<<
+ *             gl_params.get_proc_address_ctx = <void *>self._get_proc_address
+ *             params.add_voidp(MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_params)
+ */
+    __pyx_v_gl_params.get_proc_address = (&__pyx_f_9vidcutter_4libs_3mpv__c_getprocaddress);
 
-/* "vidcutter/libs/pympv/mpv.pyx":867
- *             raise MPVError(err)
- * 
- *     def uninit_gl(self):             # <<<<<<<<<<<<<<
- *         if not self.inited:
- *             return
+    /* "vidcutter/libs/pympv/mpv.pyx":981
+ *             self._get_proc_address = opengl_init_params["get_proc_address"]
+ *             gl_params.get_proc_address = &_c_getprocaddress
+ *             gl_params.get_proc_address_ctx = <void *>self._get_proc_address             # <<<<<<<<<<<<<<
+ *             params.add_voidp(MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_params)
+ *         if advanced_control:
  */
+    __pyx_v_gl_params.get_proc_address_ctx = ((void *)__pyx_v_self->_get_proc_address);
 
-/* Python wrapper */
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_11uninit_gl(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused); /*proto*/
-static PyObject *__pyx_pw_9vidcutter_4libs_3mpv_13OpenGLContext_11uninit_gl(PyObject *__pyx_v_self, CYTHON_UNUSED PyObject *unused) {
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("uninit_gl (wrapper)", 0);
-  __pyx_r = __pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_10uninit_gl(((struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *)__pyx_v_self));
+    /* "vidcutter/libs/pympv/mpv.pyx":982
+ *             gl_params.get_proc_address = &_c_getprocaddress
+ *             gl_params.get_proc_address_ctx = <void *>self._get_proc_address
+ *             params.add_voidp(MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_params)             # <<<<<<<<<<<<<<
+ *         if advanced_control:
+ *             params.add_int(MPV_RENDER_PARAM_ADVANCED_CONTROL, 1)
+ */
+    __pyx_t_2 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv__RenderParams *)__pyx_v_params->__pyx_vtab)->add_voidp(__pyx_v_params, MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, (&__pyx_v_gl_params), NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 982, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
+    /* "vidcutter/libs/pympv/mpv.pyx":978
+ *             raise PyMPVError("Unknown api_type %r" % api_type)
+ * 
+ *         if opengl_init_params is not None:             # <<<<<<<<<<<<<<
+ *             self._get_proc_address = opengl_init_params["get_proc_address"]
+ *             gl_params.get_proc_address = &_c_getprocaddress
+ */
+  }
 
-static PyObject *__pyx_pf_9vidcutter_4libs_3mpv_13OpenGLContext_10uninit_gl(struct __pyx_obj_9vidcutter_4libs_3mpv_OpenGLContext *__pyx_v_self) {
-  int __pyx_v_err;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  PyObject *__pyx_t_2 = NULL;
-  PyObject *__pyx_t_3 = NULL;
-  PyObject *__pyx_t_4 = NULL;
-  PyObject *__pyx_t_5 = NULL;
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-  __Pyx_RefNannySetupContext("uninit_gl", 0);
-
-  /* "vidcutter/libs/pympv/mpv.pyx":868
- * 
- *     def uninit_gl(self):
- *         if not self.inited:             # <<<<<<<<<<<<<<
- *             return
- *         with nogil:
+  /* "vidcutter/libs/pympv/mpv.pyx":983
+ *             gl_params.get_proc_address_ctx = <void *>self._get_proc_address
+ *             params.add_voidp(MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_params)
+ *         if advanced_control:             # <<<<<<<<<<<<<<
+ *             params.add_int(MPV_RENDER_PARAM_ADVANCED_CONTROL, 1)
+ *         if x11_display:
  */
-  __pyx_t_1 = ((!(__pyx_v_self->inited != 0)) != 0);
-  if (__pyx_t_1) {
+  __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_advanced_control); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 983, __pyx_L1_error)
+  if (__pyx_t_6) {
 
-    /* "vidcutter/libs/pympv/mpv.pyx":869
- *     def uninit_gl(self):
- *         if not self.inited:
- *             return             # <<<<<<<<<<<<<<
- *         with nogil:
- *             err = mpv_opengl_cb_uninit_gl(self._ctx)
+    /* "vidcutter/libs/pympv/mpv.pyx":984
+ *             params.add_voidp(MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_params)
+ *         if advanced_control:
+ *             params.add_int(MPV_RENDER_PARAM_ADVANCED_CONTROL, 1)             # <<<<<<<<<<<<<<
+ *         if x11_display:
+ *             self._x11_display = x11_display
  */
-    __Pyx_XDECREF(__pyx_r);
-    __pyx_r = Py_None; __Pyx_INCREF(Py_None);
-    goto __pyx_L0;
+    __pyx_t_2 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv__RenderParams *)__pyx_v_params->__pyx_vtab)->add_int(__pyx_v_params, MPV_RENDER_PARAM_ADVANCED_CONTROL, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 984, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-    /* "vidcutter/libs/pympv/mpv.pyx":868
- * 
- *     def uninit_gl(self):
- *         if not self.inited:             # <<<<<<<<<<<<<<
- *             return
- *         with nogil:
+    /* "vidcutter/libs/pympv/mpv.pyx":983
+ *             gl_params.get_proc_address_ctx = <void *>self._get_proc_address
+ *             params.add_voidp(MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_params)
+ *         if advanced_control:             # <<<<<<<<<<<<<<
+ *             params.add_int(MPV_RENDER_PARAM_ADVANCED_CONTROL, 1)
+ *         if x11_display:
  */
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":870
- *         if not self.inited:
- *             return
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_opengl_cb_uninit_gl(self._ctx)
- *         if err < 0:
+  /* "vidcutter/libs/pympv/mpv.pyx":985
+ *         if advanced_control:
+ *             params.add_int(MPV_RENDER_PARAM_ADVANCED_CONTROL, 1)
+ *         if x11_display:             # <<<<<<<<<<<<<<
+ *             self._x11_display = x11_display
+ *             params.add_voidp(MPV_RENDER_PARAM_X11_DISPLAY, get_pointer("Display", x11_display))
  */
-  {
-      #ifdef WITH_THREAD
-      PyThreadState *_save;
-      Py_UNBLOCK_THREADS
-      __Pyx_FastGIL_Remember();
-      #endif
-      /*try:*/ {
+  __pyx_t_6 = __Pyx_PyObject_IsTrue(__pyx_v_x11_display); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 985, __pyx_L1_error)
+  if (__pyx_t_6) {
 
-        /* "vidcutter/libs/pympv/mpv.pyx":871
- *             return
- *         with nogil:
- *             err = mpv_opengl_cb_uninit_gl(self._ctx)             # <<<<<<<<<<<<<<
- *         if err < 0:
- *             raise MPVError(err)
+    /* "vidcutter/libs/pympv/mpv.pyx":986
+ *             params.add_int(MPV_RENDER_PARAM_ADVANCED_CONTROL, 1)
+ *         if x11_display:
+ *             self._x11_display = x11_display             # <<<<<<<<<<<<<<
+ *             params.add_voidp(MPV_RENDER_PARAM_X11_DISPLAY, get_pointer("Display", x11_display))
+ *         if wl_display:
  */
-        __pyx_v_err = mpv_opengl_cb_uninit_gl(__pyx_v_self->_ctx);
-      }
+    __Pyx_INCREF(__pyx_v_x11_display);
+    __Pyx_GIVEREF(__pyx_v_x11_display);
+    __Pyx_GOTREF(__pyx_v_self->_x11_display);
+    __Pyx_DECREF(__pyx_v_self->_x11_display);
+    __pyx_v_self->_x11_display = __pyx_v_x11_display;
 
-      /* "vidcutter/libs/pympv/mpv.pyx":870
- *         if not self.inited:
- *             return
- *         with nogil:             # <<<<<<<<<<<<<<
- *             err = mpv_opengl_cb_uninit_gl(self._ctx)
- *         if err < 0:
+    /* "vidcutter/libs/pympv/mpv.pyx":987
+ *         if x11_display:
+ *             self._x11_display = x11_display
+ *             params.add_voidp(MPV_RENDER_PARAM_X11_DISPLAY, get_pointer("Display", x11_display))             # <<<<<<<<<<<<<<
+ *         if wl_display:
+ *             self._wl_display = wl_display
+ */
+    __pyx_t_2 = ((struct __pyx_vtabstruct_9vidcutter_4libs_3mpv__RenderParams *)__pyx_v_params->__pyx_vtab)->add_voidp(__pyx_v_params, MPV_RENDER_PARAM_X11_DISPLAY, __pyx_f_9vidcutter_4libs_3mpv_get_pointer(((char const *)"Display"), __pyx_v_x11_display), NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 987, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+    /* "vidcutter/libs/pympv/mpv.pyx":985
+ *         if advanced_control:
+ *             params.add_int(MPV_RENDER_PARAM_ADVANCED_CONTROL, 1)
+ *         if x11_display:             # <<<<<<<<<<<<<<
+ *             self._x11_display = x11_display
+ *             params.add_voidp(MPV_RENDER_PARAM_X11_DISPLAY, get_pointer("Display", x11_display))
  */
-      /*finally:*/ {
-        /*normal exit:*/{
-          #ifdef WITH_THREAD
-          __Pyx_FastGIL_Forget();
-          Py_BLOCK_THREADS
-          #endif
-          goto __pyx_L6;
-        }
-        __pyx_L6:;
-      }
   }
 
-  /* "vidcutter/libs/pympv/mpv.pyx":872
- *         with nogil:
- *             err = mpv_opengl_cb_uninit_gl(self._ctx)
- *         if err < 0:             # <<<<<<<<<<<<<<
- *             raise MPVError(err)
- *         self.inited = False
+  /* "vidcutter/libs/pympv/mpv.pyx":988
+ *   