2018-10-13 15:38:31 +01:00
|
|
|
|
|
|
|
#include <clocale>
|
2018-11-07 11:10:38 +00:00
|
|
|
#include <stdbool.h>
|
2018-11-06 07:39:42 +00:00
|
|
|
#include <stdexcept>
|
2018-10-13 15:38:31 +01:00
|
|
|
|
2018-11-04 12:45:08 +00:00
|
|
|
#include "MpvPlayerBackend.h"
|
2018-10-13 15:38:31 +01:00
|
|
|
|
2018-11-07 11:10:38 +00:00
|
|
|
#include "utils.hpp"
|
2018-10-29 14:19:12 +00:00
|
|
|
#include <QApplication>
|
2018-10-13 15:38:31 +01:00
|
|
|
#include <QOpenGLContext>
|
2018-10-30 11:05:31 +00:00
|
|
|
#include <QOpenGLFramebufferObject>
|
2018-11-06 07:39:42 +00:00
|
|
|
#include <QQuickWindow>
|
2018-11-06 08:24:24 +00:00
|
|
|
#include <math.h>
|
2018-11-07 07:42:47 +00:00
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
namespace {
|
2018-10-13 15:38:31 +01:00
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
wakeup(void* ctx)
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
QMetaObject::invokeMethod(
|
|
|
|
(MpvPlayerBackend*)ctx, "on_mpv_events", Qt::QueuedConnection);
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
on_mpv_redraw(void* ctx)
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
MpvPlayerBackend::on_update(ctx);
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
static void*
|
|
|
|
get_proc_address_mpv(void* ctx, const char* name)
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
Q_UNUSED(ctx)
|
2018-10-13 15:38:31 +01:00
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
QOpenGLContext* glctx = QOpenGLContext::currentContext();
|
|
|
|
if (!glctx)
|
|
|
|
return nullptr;
|
2018-10-13 15:38:31 +01:00
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
return reinterpret_cast<void*>(glctx->getProcAddress(QByteArray(name)));
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
} // namespace
|
2018-10-13 15:38:31 +01:00
|
|
|
|
|
|
|
class MpvRenderer : public QQuickFramebufferObject::Renderer
|
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
MpvPlayerBackend* obj;
|
2018-10-13 15:38:31 +01:00
|
|
|
|
|
|
|
public:
|
2018-11-06 07:39:42 +00:00
|
|
|
MpvRenderer(MpvPlayerBackend* new_obj)
|
|
|
|
: obj{ new_obj }
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual ~MpvRenderer() {}
|
|
|
|
|
|
|
|
// This function is called when a new FBO is needed.
|
|
|
|
// This happens on the initial frame.
|
|
|
|
QOpenGLFramebufferObject* createFramebufferObject(const QSize& size)
|
|
|
|
{
|
|
|
|
// init mpv_gl:
|
|
|
|
if (!obj->mpv_gl) {
|
|
|
|
mpv_opengl_init_params gl_init_params{ get_proc_address_mpv,
|
|
|
|
nullptr,
|
|
|
|
nullptr };
|
|
|
|
mpv_render_param params[]{
|
|
|
|
{ MPV_RENDER_PARAM_API_TYPE,
|
|
|
|
const_cast<char*>(MPV_RENDER_API_TYPE_OPENGL) },
|
|
|
|
{ MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &gl_init_params },
|
|
|
|
{ MPV_RENDER_PARAM_INVALID, nullptr }
|
|
|
|
};
|
|
|
|
if (mpv_render_context_create(&obj->mpv_gl, obj->mpv, params) < 0)
|
|
|
|
throw std::runtime_error("failed to initialize mpv GL context");
|
|
|
|
mpv_render_context_set_update_callback(obj->mpv_gl, on_mpv_redraw, obj);
|
|
|
|
QMetaObject::invokeMethod(obj, "startPlayer");
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
return QQuickFramebufferObject::Renderer::createFramebufferObject(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void render()
|
|
|
|
{
|
|
|
|
obj->window()->resetOpenGLState();
|
|
|
|
|
|
|
|
QOpenGLFramebufferObject* fbo = framebufferObject();
|
|
|
|
mpv_opengl_fbo mpfbo{ .fbo = static_cast<int>(fbo->handle()),
|
|
|
|
.w = fbo->width(),
|
|
|
|
.h = fbo->height(),
|
|
|
|
.internal_format = 0 };
|
|
|
|
int flip_y{ 0 };
|
|
|
|
|
|
|
|
mpv_render_param params[] = {
|
|
|
|
// Specify the default framebuffer (0) as target. This will
|
|
|
|
// render onto the entire screen. If you want to show the video
|
|
|
|
// in a smaller rectangle or apply fancy transformations, you'll
|
|
|
|
// need to render into a separate FBO and draw it manually.
|
|
|
|
{ MPV_RENDER_PARAM_OPENGL_FBO, &mpfbo },
|
|
|
|
// Flip rendering (needed due to flipped GL coordinate system).
|
|
|
|
{ MPV_RENDER_PARAM_FLIP_Y, &flip_y },
|
|
|
|
{ MPV_RENDER_PARAM_INVALID, nullptr }
|
|
|
|
};
|
|
|
|
// See render_gl.h on what OpenGL environment mpv expects, and
|
|
|
|
// other API details.
|
|
|
|
mpv_render_context_render(obj->mpv_gl, params);
|
|
|
|
obj->window()->resetOpenGLState();
|
|
|
|
}
|
2018-10-13 15:38:31 +01:00
|
|
|
};
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
MpvPlayerBackend::MpvPlayerBackend(QQuickItem* parent)
|
|
|
|
: QQuickFramebufferObject(parent)
|
|
|
|
, mpv{ mpv_create() }
|
|
|
|
, mpv_gl(nullptr)
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
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");
|
|
|
|
|
|
|
|
// Fix?
|
|
|
|
mpv_set_option_string(mpv, "ytdl", "yes");
|
|
|
|
mpv_set_option_string(mpv, "vo", "libmpv");
|
|
|
|
// mpp_set_option_string(mpv, "no-sub-ass", "yes)
|
|
|
|
|
|
|
|
mpv_set_option_string(mpv, "slang", "en");
|
|
|
|
|
|
|
|
mpv_set_option_string(mpv, "config", "yes");
|
|
|
|
// mpv_set_option_string(mpv, "sub-visibility", "no");
|
2018-11-07 12:00:26 +00:00
|
|
|
mpv_observe_property(mpv, 0, "tracks-menu", MPV_FORMAT_NONE);
|
2018-11-06 07:39:42 +00:00
|
|
|
mpv_observe_property(mpv, 0, "playback-abort", MPV_FORMAT_NONE);
|
|
|
|
mpv_observe_property(mpv, 0, "chapter-list", MPV_FORMAT_NODE);
|
|
|
|
mpv_observe_property(mpv, 0, "track-list", MPV_FORMAT_NODE);
|
|
|
|
mpv_observe_property(mpv, 0, "playlist-pos", MPV_FORMAT_DOUBLE);
|
|
|
|
mpv_observe_property(mpv, 0, "volume", MPV_FORMAT_DOUBLE);
|
|
|
|
mpv_observe_property(mpv, 0, "muted", MPV_FORMAT_DOUBLE);
|
|
|
|
mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_DOUBLE);
|
|
|
|
mpv_observe_property(mpv, 0, "media-title", MPV_FORMAT_STRING);
|
|
|
|
mpv_observe_property(mpv, 0, "sub-text", MPV_FORMAT_STRING);
|
|
|
|
mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE);
|
|
|
|
mpv_observe_property(mpv, 0, "demuxer-cache-duration", MPV_FORMAT_DOUBLE);
|
|
|
|
mpv_observe_property(mpv, 0, "pause", MPV_FORMAT_NONE);
|
|
|
|
mpv_set_wakeup_callback(mpv, wakeup, this);
|
|
|
|
|
|
|
|
if (mpv_initialize(mpv) < 0)
|
|
|
|
throw std::runtime_error("could not initialize mpv context");
|
|
|
|
|
|
|
|
connect(this,
|
|
|
|
&MpvPlayerBackend::onUpdate,
|
|
|
|
this,
|
|
|
|
&MpvPlayerBackend::doUpdate,
|
|
|
|
Qt::QueuedConnection);
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-04 12:45:08 +00:00
|
|
|
MpvPlayerBackend::~MpvPlayerBackend()
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-07 11:10:38 +00:00
|
|
|
SetDPMS(true);
|
2018-11-07 08:01:18 +00:00
|
|
|
mpv_render_context_free(mpv_gl);
|
2018-11-06 07:39:42 +00:00
|
|
|
mpv_terminate_destroy(mpv);
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::on_update(void* ctx)
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
MpvPlayerBackend* self = (MpvPlayerBackend*)ctx;
|
|
|
|
emit self->onUpdate();
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// connected to onUpdate(); signal makes sure it runs on the GUI thread
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::doUpdate()
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
update();
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
QVariant
|
|
|
|
MpvPlayerBackend::getProperty(const QString& name) const
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
return mpv::qt::get_property_variant(mpv, name);
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::command(const QVariant& params)
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
mpv::qt::command_variant(mpv, params);
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::setProperty(const QString& name, const QVariant& value)
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
mpv::qt::set_property_variant(mpv, name, value);
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::setOption(const QString& name, const QVariant& value)
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
mpv::qt::set_option_variant(mpv, name, value);
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::launchAboutQt()
|
2018-10-29 14:19:12 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
QApplication* qapp =
|
|
|
|
qobject_cast<QApplication*>(QCoreApplication::instance());
|
|
|
|
qapp->aboutQt();
|
2018-10-29 14:19:12 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::togglePlayPause()
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "cycle"
|
|
|
|
<< "pause");
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::toggleMute()
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "cycle"
|
|
|
|
<< "mute");
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::nextAudioTrack()
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "cycle"
|
|
|
|
<< "audio");
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::nextSubtitleTrack()
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "cycle"
|
|
|
|
<< "sub");
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::nextVideoTrack()
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "cycle"
|
|
|
|
<< "video");
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::prevPlaylistItem()
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "playlist-prev");
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::nextPlaylistItem()
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "playlist-next"
|
|
|
|
<< "force");
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::loadFile(const QVariant& filename)
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "loadfile" << filename);
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::setVolume(const QVariant& volume)
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "set"
|
|
|
|
<< "volume" << volume);
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::addVolume(const QVariant& volume)
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "add"
|
|
|
|
<< "volume" << volume);
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::seek(const QVariant& seekTime)
|
2018-11-04 12:45:08 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
command(QVariantList() << "seek" << seekTime);
|
2018-11-04 12:45:08 +00:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
QVariant
|
|
|
|
MpvPlayerBackend::getTracks() const
|
2018-11-04 13:21:50 +00:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
return mpv::qt::get_property_variant(mpv, "track-list");
|
2018-11-04 13:21:50 +00:00
|
|
|
}
|
|
|
|
|
2018-11-07 17:22:18 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::setTrack(const QVariant& track, const QVariant& id)
|
|
|
|
{
|
|
|
|
command(QVariantList() << "set" << track << id);
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant
|
|
|
|
MpvPlayerBackend::getTrack(const QString& track)
|
|
|
|
{
|
|
|
|
return mpv::qt::get_property_variant(mpv, track);
|
|
|
|
}
|
|
|
|
|
2018-11-06 08:24:24 +00:00
|
|
|
QVariant
|
|
|
|
MpvPlayerBackend::createTimestamp(const QVariant& seconds) const
|
|
|
|
{
|
|
|
|
int d = seconds.toInt();
|
|
|
|
double h = floor(d / 3600);
|
|
|
|
double m = floor(d % 3600 / 60);
|
|
|
|
double s = floor(d % 3600 % 60);
|
|
|
|
|
|
|
|
QString hour = h > 0 ? QString::number(h) + ":" : "";
|
|
|
|
QString minute = h < 1 ? QString::number(m) + ":"
|
|
|
|
: (m < 10 ? "0" + QString::number(m) + ":"
|
|
|
|
: QString::number(m) + ":");
|
|
|
|
QString second = s < 10 ? "0" + QString::number(s) : QString::number(s);
|
|
|
|
return hour + minute + second;
|
|
|
|
}
|
|
|
|
|
2018-11-07 11:10:38 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::toggleOnTop()
|
|
|
|
{
|
|
|
|
onTop = !onTop;
|
|
|
|
AlwaysOnTop(window()->winId(), onTop);
|
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
void
|
|
|
|
MpvPlayerBackend::on_mpv_events()
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
while (mpv) {
|
|
|
|
mpv_event* event = mpv_wait_event(mpv, 0);
|
2018-10-13 15:38:31 +01:00
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
if (event->event_id == MPV_EVENT_NONE) {
|
|
|
|
break;
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
2018-11-06 07:39:42 +00:00
|
|
|
handle_mpv_event(event);
|
|
|
|
}
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
2018-11-06 07:39:42 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
MpvPlayerBackend::handle_mpv_event(mpv_event* event)
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
switch (event->event_id) {
|
2018-10-13 15:38:31 +01:00
|
|
|
case MPV_EVENT_PROPERTY_CHANGE: {
|
2018-11-06 07:39:42 +00:00
|
|
|
mpv_event_property* prop = (mpv_event_property*)event->data;
|
|
|
|
if (strcmp(prop->name, "time-pos") == 0) {
|
|
|
|
if (prop->format == MPV_FORMAT_DOUBLE) {
|
|
|
|
double time = *(double*)prop->data;
|
|
|
|
QMetaObject::invokeMethod(
|
|
|
|
this, "setProgressBarValue", Q_ARG(QVariant, time));
|
|
|
|
}
|
|
|
|
} else if (strcmp(prop->name, "duration") == 0) {
|
|
|
|
if (prop->format == MPV_FORMAT_DOUBLE) {
|
|
|
|
double time = *(double*)prop->data;
|
|
|
|
Q_ARG(QVariant, "txt1"),
|
|
|
|
QMetaObject::invokeMethod(
|
|
|
|
this, "setProgressBarEnd", Q_ARG(QVariant, time));
|
|
|
|
}
|
|
|
|
} else if (strcmp(prop->name, "volume") == 0) {
|
|
|
|
if (prop->format == MPV_FORMAT_DOUBLE) {
|
|
|
|
double volume = *(double*)prop->data;
|
|
|
|
QMetaObject::invokeMethod(
|
|
|
|
this, "updateVolume", Q_ARG(QVariant, volume));
|
|
|
|
}
|
|
|
|
} else if (strcmp(prop->name, "muted") == 0) {
|
|
|
|
if (prop->format == MPV_FORMAT_DOUBLE) {
|
|
|
|
double muted = *(double*)prop->data;
|
|
|
|
QMetaObject::invokeMethod(
|
|
|
|
this, "updateMuted", Q_ARG(QVariant, muted));
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
2018-11-06 07:39:42 +00:00
|
|
|
} else if (strcmp(prop->name, "media-title") == 0) {
|
|
|
|
if (prop->format == MPV_FORMAT_STRING) {
|
|
|
|
char* title = *(char**)prop->data;
|
|
|
|
QMetaObject::invokeMethod(this, "setTitle", Q_ARG(QVariant, title));
|
|
|
|
}
|
|
|
|
} else if (strcmp(prop->name, "sub-text") == 0) {
|
|
|
|
if (prop->format == MPV_FORMAT_STRING) {
|
|
|
|
char* subs = *(char**)prop->data;
|
|
|
|
QMetaObject::invokeMethod(
|
|
|
|
this, "setSubtitles", Q_ARG(QVariant, subs));
|
|
|
|
}
|
|
|
|
} else if (strcmp(prop->name, "demuxer-cache-duration") == 0) {
|
|
|
|
if (prop->format == MPV_FORMAT_DOUBLE) {
|
|
|
|
double duration = *(double*)prop->data;
|
|
|
|
QMetaObject::invokeMethod(
|
|
|
|
this, "setCachedDuration", Q_ARG(QVariant, duration));
|
|
|
|
}
|
|
|
|
} else if (strcmp(prop->name, "playlist-pos") == 0) {
|
|
|
|
if (prop->format == MPV_FORMAT_DOUBLE) {
|
|
|
|
double pos = *(double*)prop->data;
|
|
|
|
QMetaObject::invokeMethod(this, "updatePrev", Q_ARG(QVariant, pos));
|
|
|
|
}
|
|
|
|
} else if (strcmp(prop->name, "pause") == 0) {
|
|
|
|
QMetaObject::invokeMethod(this, "updatePlayPause");
|
2018-11-07 12:00:26 +00:00
|
|
|
} else if (strcmp(prop->name, "tracks-menu") == 0) {
|
|
|
|
QMetaObject::invokeMethod(this, "tracksUpdate");
|
2018-11-06 07:39:42 +00:00
|
|
|
}
|
|
|
|
break;
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
case MPV_EVENT_SHUTDOWN: {
|
2018-11-06 07:39:42 +00:00
|
|
|
exit(0);
|
|
|
|
break;
|
2018-10-16 11:07:14 +01:00
|
|
|
}
|
|
|
|
default: {
|
2018-11-06 07:39:42 +00:00
|
|
|
break;
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
2018-11-06 07:39:42 +00:00
|
|
|
}
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|
|
|
|
|
2018-11-06 07:39:42 +00:00
|
|
|
QQuickFramebufferObject::Renderer*
|
|
|
|
MpvPlayerBackend::createRenderer() const
|
2018-10-13 15:38:31 +01:00
|
|
|
{
|
2018-11-06 07:39:42 +00:00
|
|
|
window()->setPersistentOpenGLContext(true);
|
|
|
|
window()->setPersistentSceneGraph(true);
|
|
|
|
return new MpvRenderer(const_cast<MpvPlayerBackend*>(this));
|
2018-10-13 15:38:31 +01:00
|
|
|
}
|