summaryrefslogtreecommitdiffstats
path: root/DOCS/client_api_examples
diff options
context:
space:
mode:
Diffstat (limited to 'DOCS/client_api_examples')
-rw-r--r--DOCS/client_api_examples/README.md30
-rw-r--r--DOCS/client_api_examples/qml_direct/main.cpp149
-rw-r--r--DOCS/client_api_examples/qml_direct/main.h49
-rw-r--r--DOCS/client_api_examples/qml_direct/main.qml49
-rw-r--r--DOCS/client_api_examples/qml_direct/mpvtest.pro11
-rw-r--r--DOCS/client_api_examples/qml_direct/mpvtest.qrc5
6 files changed, 293 insertions, 0 deletions
diff --git a/DOCS/client_api_examples/README.md b/DOCS/client_api_examples/README.md
new file mode 100644
index 0000000000..9de90a6748
--- /dev/null
+++ b/DOCS/client_api_examples/README.md
@@ -0,0 +1,30 @@
+Client API examples
+===================
+
+All these examples use the mpv client API through libmpv.
+
+cocoa
+-----
+
+Shows how to embed the mpv video window in Objective-C/Cocoa.
+
+qml
+---
+
+Shows how to use mpv's OpenGL video renderer in QtQuick2 with QML.
+
+qml_direct
+----------
+
+Alternative example, which typically avoids a FBO indirection. Might be
+slightly faster, but is less flexible and harder to use.
+
+qt
+--
+
+Shows how to embed the mpv video window in Qt (using normal desktop widgets).
+
+simple
+------
+
+Very primitive terminal-only example. Shows some most basic API usage.
diff --git a/DOCS/client_api_examples/qml_direct/main.cpp b/DOCS/client_api_examples/qml_direct/main.cpp
new file mode 100644
index 0000000000..b999d10ff4
--- /dev/null
+++ b/DOCS/client_api_examples/qml_direct/main.cpp
@@ -0,0 +1,149 @@
+#include "main.h"
+
+#include <stdexcept>
+
+#include <QObject>
+#include <QtGlobal>
+#include <QOpenGLContext>
+
+#include <QGuiApplication>
+#include <QtQuick/QQuickWindow>
+#include <QtQuick/QQuickView>
+
+static void *get_proc_address(void *ctx, const char *name) {
+ (void)ctx;
+ QOpenGLContext *glctx = QOpenGLContext::currentContext();
+ if (!glctx)
+ return NULL;
+ return (void *)glctx->getProcAddress(QByteArray(name));
+}
+
+MpvRenderer::MpvRenderer(mpv::qt::Handle a_mpv, mpv_opengl_cb_context *a_mpv_gl)
+ : mpv(a_mpv), mpv_gl(a_mpv_gl), window(0)
+{
+ int r = mpv_opengl_cb_init_gl(mpv_gl, NULL, get_proc_address, NULL);
+ if (r < 0)
+ throw std::runtime_error("could not initialize OpenGL");
+}
+
+MpvRenderer::~MpvRenderer()
+{
+ // Until this call is done, we need to make sure the player remains
+ // alive. This is done implicitly with the mpv::qt::Handle instance
+ // in this class.
+ mpv_opengl_cb_uninit_gl(mpv_gl);
+}
+
+void MpvRenderer::paint()
+{
+ window->resetOpenGLState();
+
+ // Render to the whole window.
+ QSize s = window->size() * window->devicePixelRatio();
+ int vp[4] = {0, 0, s.width(), -s.height()};
+
+ // This uses 0 as framebuffer, which indicates that mpv will render directly
+ // to the frontbuffer. Note that mpv will always switch framebuffers
+ // explicitly. Some QWindow setups (such as using QQuickWidget) actually
+ // want you to render into a FBO in the beforeRendering() signal, and this
+ // code won't work there.
+ mpv_opengl_cb_render(mpv_gl, 0, vp);
+
+ window->resetOpenGLState();
+}
+
+MpvObject::MpvObject(QQuickItem * parent)
+ : QQuickItem(parent), mpv_gl(0), renderer(0)
+{
+ mpv = mpv::qt::Handle::FromRawHandle(mpv_create());
+ if (!mpv)
+ throw std::runtime_error("could not create mpv context");
+
+ mpv_set_option_string(mpv, "terminal", "yes");
+ mpv_set_option_string(mpv, "msg-level", "all=v");
+
+ if (mpv_initialize(mpv) < 0)
+ throw std::runtime_error("could not initialize mpv context");
+
+ // Make use of the MPV_SUB_API_OPENGL_CB API.
+ mpv::qt::set_option_variant(mpv, "vo", "opengl-cb");
+
+ // Setup the callback that will make QtQuick update and redraw if there
+ // is a new video frame. Use a queued connection: this makes sure the
+ // doUpdate() function is run on the GUI thread.
+ mpv_gl = (mpv_opengl_cb_context *)mpv_get_sub_api(mpv, MPV_SUB_API_OPENGL_CB);
+ if (!mpv_gl)
+ throw std::runtime_error("OpenGL not compiled in");
+ mpv_opengl_cb_set_update_callback(mpv_gl, MpvObject::on_update, (void *)this);
+ connect(this, &MpvObject::onUpdate, this, &MpvObject::doUpdate,
+ Qt::QueuedConnection);
+
+ connect(this, &QQuickItem::windowChanged,
+ this, &MpvObject::handleWindowChanged);
+}
+
+MpvObject::~MpvObject()
+{
+ if (mpv_gl)
+ mpv_opengl_cb_set_update_callback(mpv_gl, NULL, NULL);
+}
+
+void MpvObject::handleWindowChanged(QQuickWindow *win)
+{
+ if (!win)
+ return;
+ connect(win, &QQuickWindow::beforeSynchronizing,
+ this, &MpvObject::sync, Qt::DirectConnection);
+ connect(win, &QQuickWindow::sceneGraphInvalidated,
+ this, &MpvObject::cleanup, Qt::DirectConnection);
+ win->setClearBeforeRendering(false);
+}
+
+void MpvObject::sync()
+{
+ if (!renderer) {
+ renderer = new MpvRenderer(mpv, mpv_gl);
+ connect(window(), &QQuickWindow::beforeRendering,
+ renderer, &MpvRenderer::paint, Qt::DirectConnection);
+ }
+ renderer->window = window();
+}
+
+void MpvObject::cleanup()
+{
+ if (renderer) {
+ delete renderer;
+ renderer = 0;
+ }
+}
+
+void MpvObject::on_update(void *ctx)
+{
+ MpvObject *self = (MpvObject *)ctx;
+ emit self->onUpdate();
+}
+
+// connected to onUpdate(); signal makes sure it runs on the GUI thread
+void MpvObject::doUpdate()
+{
+ window()->update();
+}
+
+void MpvObject::command(const QVariant& params)
+{
+ mpv::qt::command_variant(mpv, params);
+}
+
+int main(int argc, char **argv)
+{
+ QGuiApplication app(argc, argv);
+
+ qmlRegisterType<MpvObject>("mpvtest", 1, 0, "MpvObject");
+
+ QQuickView view;
+ view.setResizeMode(QQuickView::SizeRootObjectToView);
+ view.setSource(QUrl("qrc:///mpvtest/main.qml"));
+ view.show();
+
+ return app.exec();
+}
diff --git a/DOCS/client_api_examples/qml_direct/main.h b/DOCS/client_api_examples/qml_direct/main.h
new file mode 100644
index 0000000000..90acdeedd2
--- /dev/null
+++ b/DOCS/client_api_examples/qml_direct/main.h
@@ -0,0 +1,49 @@
+#ifndef MPVRENDERER_H_
+#define MPVRENDERER_H_
+
+#include <QtQuick/QQuickItem>
+
+#include <mpv/client.h>
+#include <mpv/opengl_cb.h>
+#include <mpv/qthelper.hpp>
+
+class MpvRenderer : public QObject
+{
+ Q_OBJECT
+ mpv::qt::Handle mpv;
+ mpv_opengl_cb_context *mpv_gl;
+ QQuickWindow *window;
+
+ friend class MpvObject;
+public:
+ MpvRenderer(mpv::qt::Handle a_mpv, mpv_opengl_cb_context *a_mpv_gl);
+ virtual ~MpvRenderer();
+public slots:
+ void paint();
+};
+
+class MpvObject : public QQuickItem
+{
+ Q_OBJECT
+
+ mpv::qt::Handle mpv;
+ mpv_opengl_cb_context *mpv_gl;
+ MpvRenderer *renderer;
+
+public:
+ MpvObject(QQuickItem * parent = 0);
+ virtual ~MpvObject();
+public slots:
+ void command(const QVariant& params);
+ void sync();
+ void cleanup();
+signals:
+ void onUpdate();
+private slots:
+ void doUpdate();
+ void handleWindowChanged(QQuickWindow *win);
+private:
+ static void on_update(void *ctx);
+};
+
+#endif
diff --git a/DOCS/client_api_examples/qml_direct/main.qml b/DOCS/client_api_examples/qml_direct/main.qml
new file mode 100644
index 0000000000..92be9bc405
--- /dev/null
+++ b/DOCS/client_api_examples/qml_direct/main.qml
@@ -0,0 +1,49 @@
+import QtQuick 2.0
+import QtQuick.Controls 1.0
+
+import mpvtest 1.0
+
+Item {
+ width: 1280
+ height: 720
+
+ MpvObject {
+ id: renderer
+
+ // This object isn't real and not visible; it just renders into the
+ // background of the containing Window.
+ width: 0
+ height: 0
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: renderer.command(["loadfile", "../../../test.mkv"])
+ }
+
+ Rectangle {
+ id: labelFrame
+ anchors.margins: -50
+ radius: 5
+ color: "white"
+ border.color: "black"
+ opacity: 0.8
+ anchors.fill: box
+ }
+
+ Row {
+ id: box
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.margins: 100
+
+ Text {
+ anchors.margins: 10
+ wrapMode: Text.WordWrap
+ text: "QtQuick and mpv are both rendering stuff.\n
+ In this example, mpv is always in the background.\n
+ Click to load ../../../test.mkv"
+ }
+ }
+}
diff --git a/DOCS/client_api_examples/qml_direct/mpvtest.pro b/DOCS/client_api_examples/qml_direct/mpvtest.pro
new file mode 100644
index 0000000000..323b8bef71
--- /dev/null
+++ b/DOCS/client_api_examples/qml_direct/mpvtest.pro
@@ -0,0 +1,11 @@
+QT += qml quick
+
+HEADERS += main.h
+SOURCES += main.cpp
+
+CONFIG += link_pkgconfig debug
+PKGCONFIG += mpv
+
+RESOURCES += mpvtest.qrc
+
+OTHER_FILES += main.qml
diff --git a/DOCS/client_api_examples/qml_direct/mpvtest.qrc b/DOCS/client_api_examples/qml_direct/mpvtest.qrc
new file mode 100644
index 0000000000..bb672657e5
--- /dev/null
+++ b/DOCS/client_api_examples/qml_direct/mpvtest.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/mpvtest">
+ <file>main.qml</file>
+ </qresource>
+</RCC>