Move stuff to MPVCommon namespace for shareding across MPV backends.
This commit is contained in:
parent
299ee556a9
commit
f7167ee478
|
@ -50,6 +50,7 @@ set(SOURCES
|
|||
src/ThumbnailCache.cpp
|
||||
src/logger.cpp
|
||||
src/qmldebugger.cpp
|
||||
src/Backends/MPVCommon/MPVCommon.cpp
|
||||
src/Backends/MPV/MPVBackend.cpp
|
||||
src/Backends/MPVNoFBO/MPVNoFBOBackend.cpp
|
||||
)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "src/Backends/MPV/MPVBackend.hpp"
|
||||
#include "src/logger.h"
|
||||
#include "src/utils.hpp"
|
||||
#include <QApplication>
|
||||
#include <QElapsedTimer>
|
||||
|
@ -19,11 +18,11 @@
|
|||
#include <X11/Xutil.h>
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
||||
#include "src/Backends/MPVCommon/MPVCommon.hpp"
|
||||
|
||||
|
||||
bool usedirect = false;
|
||||
|
||||
auto mpvLogger = initLogger("mpv");
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
|
@ -140,10 +139,10 @@ MPVBackend::MPVBackend(QQuickItem* parent)
|
|||
if (!mpv)
|
||||
throw std::runtime_error("could not create mpv context");
|
||||
|
||||
std::cout << QString("Direct: ").toUtf8().constData() << QString(usedirect ? "true" : "false").toUtf8().constData();
|
||||
QSettings settings;
|
||||
usedirect = settings.value("Backend/direct", false).toBool();
|
||||
|
||||
|
||||
mpv_set_option_string(mpv, "terminal", "on");
|
||||
mpv_set_option_string(mpv, "terminal", "false");
|
||||
mpv_set_option_string(mpv, "msg-level", "all=v");
|
||||
|
||||
// Fix?
|
||||
|
@ -170,7 +169,7 @@ MPVBackend::MPVBackend(QQuickItem* parent)
|
|||
mpv_observe_property(mpv, 0, "playlist", MPV_FORMAT_NODE);
|
||||
mpv_observe_property(mpv, 0, "speed", MPV_FORMAT_DOUBLE);
|
||||
|
||||
mpv_request_log_messages(mpv, "verbose");
|
||||
mpv_request_log_messages(mpv, "v");
|
||||
|
||||
mpv_set_wakeup_callback(mpv, wakeup, this);
|
||||
|
||||
|
@ -210,10 +209,10 @@ MPVBackend::~MPVBackend()
|
|||
Utils::SetDPMS(true);
|
||||
command("write-watch-later-config");
|
||||
|
||||
if (usedirect) {
|
||||
if (usedirect && mpv_gl_cb) {
|
||||
mpv_opengl_cb_uninit_gl(mpv_gl_cb);
|
||||
} else if (mpv_gl){
|
||||
mpv_render_context_free(mpv_gl);
|
||||
} else {
|
||||
mpv_opengl_cb_set_update_callback(mpv_gl_cb, NULL, NULL);
|
||||
}
|
||||
|
||||
mpv_terminate_destroy(mpv);
|
||||
|
@ -269,172 +268,24 @@ MPVBackend::playerCommand(const Enums::Commands& cmd)
|
|||
QVariant
|
||||
MPVBackend::playerCommand(const Enums::Commands& cmd, const QVariant& args)
|
||||
{
|
||||
switch (cmd) {
|
||||
case Enums::Commands::TogglePlayPause: {
|
||||
command(QVariantList() << "cycle"
|
||||
<< "pause");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::ToggleMute: {
|
||||
command(QVariantList() << "cycle"
|
||||
<< "mute");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::SetAudioDevice: {
|
||||
setProperty("audio-device", args.toString());
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::SetVolume: {
|
||||
command(QVariantList() << "set"
|
||||
<< "volume" << args);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::AddVolume: {
|
||||
|
||||
command(QVariantList() << "add"
|
||||
<< "volume" << args);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::AddSpeed: {
|
||||
|
||||
QString speedString =
|
||||
QString::number(getProperty("speed").toDouble() + args.toDouble());
|
||||
QVariant newSpeed =
|
||||
QVariant(speedString.left(speedString.lastIndexOf('.') + 2));
|
||||
|
||||
playerCommand(Enums::Commands::SetSpeed, newSpeed);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SubtractSpeed: {
|
||||
|
||||
QString speedString =
|
||||
QString::number(getProperty("speed").toDouble() - args.toDouble());
|
||||
QVariant newSpeed =
|
||||
QVariant(speedString.left(speedString.lastIndexOf('.') + 2));
|
||||
playerCommand(Enums::Commands::SetSpeed, newSpeed);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::ChangeSpeed: {
|
||||
|
||||
playerCommand(
|
||||
Enums::Commands::SetSpeed,
|
||||
QVariant(getProperty("speed").toDouble() * args.toDouble()));
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SetSpeed: {
|
||||
|
||||
command(QVariantList() << "set"
|
||||
<< "speed" << args.toString());
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::ToggleStats: {
|
||||
|
||||
command(QVariantList() << "script-binding"
|
||||
<< "stats/display-stats-toggle");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextAudioTrack: {
|
||||
|
||||
command(QVariantList() << "cycle"
|
||||
<< "audio");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextSubtitleTrack: {
|
||||
|
||||
command(QVariantList() << "cycle"
|
||||
<< "sub");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextVideoTrack: {
|
||||
command(QVariantList() << "cycle"
|
||||
<< "video");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::PreviousPlaylistItem: {
|
||||
|
||||
command(QVariantList() << "playlist-prev");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextPlaylistItem: {
|
||||
|
||||
command(QVariantList() << "playlist-next"
|
||||
<< "force");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::LoadFile: {
|
||||
command(QVariantList() << "loadfile" << args);
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::AppendFile: {
|
||||
|
||||
command(QVariantList() << "loadfile" << args << "append-play");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::Seek: {
|
||||
|
||||
command(QVariantList() << "seek" << args);
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::SeekAbsolute: {
|
||||
|
||||
command(QVariantList() << "seek" << args << "absolute");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::ForwardFrame: {
|
||||
|
||||
command(QVariantList() << "frame-step");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::BackwardFrame: {
|
||||
|
||||
command(QVariantList() << "frame-back-step");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SetTrack: {
|
||||
|
||||
command(QVariantList() << "set" << args.toList()[0] << args.toList()[1]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SetPlaylistPos: {
|
||||
|
||||
command(QVariantList() << "set"
|
||||
<< "playlist-pos" << args);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::ForcePause: {
|
||||
|
||||
command(QVariantList() << "set"
|
||||
<< "pause"
|
||||
<< "yes");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
qDebug() << "Command not found: " << cmd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant("NoOutput");
|
||||
return MPVCommon::playerCommand(this, cmd, args);
|
||||
}
|
||||
|
||||
QString
|
||||
MPVBackend::getStats()
|
||||
{
|
||||
return MPVCommon::getStats(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MPVBackend::updateDurationString(int numTime)
|
||||
{
|
||||
QMetaMethod metaMethod = sender()->metaObject()->method(senderSignalIndex());
|
||||
MPVCommon::updateDurationString(this, numTime, metaMethod);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MPVBackend::toggleOnTop()
|
||||
{
|
||||
|
@ -463,335 +314,16 @@ MPVBackend::on_mpv_events()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MPVBackend::updateDurationString(int numTime)
|
||||
{
|
||||
QVariant speed = getProperty("speed");
|
||||
QMetaMethod metaMethod = sender()->metaObject()->method(senderSignalIndex());
|
||||
if (metaMethod.name() == "positionChanged") {
|
||||
if (speed != lastSpeed) {
|
||||
lastSpeed = speed.toDouble();
|
||||
} else {
|
||||
if (numTime == lastTime) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
lastTime = numTime;
|
||||
lastPositionString = Utils::createTimestamp(lastTime);
|
||||
} else if (metaMethod.name() == "durationChanged") {
|
||||
totalDurationString = Utils::createTimestamp(numTime);
|
||||
}
|
||||
QString durationString;
|
||||
durationString += lastPositionString;
|
||||
durationString += " / ";
|
||||
durationString += totalDurationString;
|
||||
if (lastSpeed != 1) {
|
||||
if (settings.value("Appearance/themeName", "").toString() !=
|
||||
"RoosterTeeth") {
|
||||
durationString += " (" + speed.toString() + "x)";
|
||||
}
|
||||
}
|
||||
emit durationStringChanged(durationString);
|
||||
}
|
||||
|
||||
QVariantMap
|
||||
MPVBackend::getAudioDevices(const QVariant& drivers) const
|
||||
{
|
||||
QVariantMap newDrivers;
|
||||
|
||||
QSequentialIterable iterable = drivers.value<QSequentialIterable>();
|
||||
foreach (const QVariant& v, iterable) {
|
||||
QVariantMap item = v.toMap();
|
||||
newDrivers[item["description"].toString()] = item;
|
||||
}
|
||||
return newDrivers;
|
||||
return MPVCommon::getAudioDevices(drivers);
|
||||
}
|
||||
|
||||
void
|
||||
MPVBackend::handle_mpv_event(mpv_event* event)
|
||||
{
|
||||
switch (event->event_id) {
|
||||
case MPV_EVENT_PROPERTY_CHANGE: {
|
||||
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;
|
||||
emit positionChanged(time);
|
||||
}
|
||||
} else if (strcmp(prop->name, "duration") == 0) {
|
||||
if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
double time = *(double*)prop->data;
|
||||
emit durationChanged(time);
|
||||
}
|
||||
} else if (strcmp(prop->name, "mute") == 0 ||
|
||||
strcmp(prop->name, "volume") == 0) {
|
||||
double volume = getProperty("volume").toDouble();
|
||||
bool mute = getProperty("mute").toBool();
|
||||
if (mute || volume == 0) {
|
||||
emit volumeStatusChanged(Enums::VolumeStatus::Muted);
|
||||
} else {
|
||||
if (volume < 25) {
|
||||
emit volumeStatusChanged(Enums::VolumeStatus::Low);
|
||||
} else {
|
||||
emit volumeStatusChanged(Enums::VolumeStatus::Normal);
|
||||
}
|
||||
}
|
||||
// emit volumeChanged(volume);
|
||||
} else if (strcmp(prop->name, "media-title") == 0) {
|
||||
if (prop->format == MPV_FORMAT_STRING) {
|
||||
char* title = *(char**)prop->data;
|
||||
emit titleChanged(QString(title));
|
||||
}
|
||||
} else if (strcmp(prop->name, "sub-text") == 0) {
|
||||
if (prop->format == MPV_FORMAT_STRING) {
|
||||
char* subs = *(char**)prop->data;
|
||||
emit subtitlesChanged(QString(subs));
|
||||
}
|
||||
} else if (strcmp(prop->name, "demuxer-cache-duration") == 0) {
|
||||
if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
double duration = *(double*)prop->data;
|
||||
emit cachedDurationChanged(duration);
|
||||
}
|
||||
} else if (strcmp(prop->name, "playlist-pos") == 0) {
|
||||
if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
double pos = *(double*)prop->data;
|
||||
emit playlistPositionChanged(pos);
|
||||
}
|
||||
} else if (strcmp(prop->name, "pause") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
if (mpv::qt::node_to_variant(nod).toBool()) {
|
||||
emit playStatusChanged(Enums::PlayStatus::Paused);
|
||||
// Utils::SetScreensaver(window()->winId(), true);
|
||||
} else {
|
||||
emit playStatusChanged(Enums::PlayStatus::Playing);
|
||||
// Utils::SetScreensaver(window()->winId(), false);
|
||||
}
|
||||
} else if (strcmp(prop->name, "track-list") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit tracksChanged(mpv::qt::node_to_variant(nod).toList());
|
||||
} else if (strcmp(prop->name, "audio-device-list") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit audioDevicesChanged(
|
||||
getAudioDevices(mpv::qt::node_to_variant(nod)));
|
||||
} else if (strcmp(prop->name, "playlist") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit playlistChanged(mpv::qt::node_to_variant(nod).toList());
|
||||
} else if (strcmp(prop->name, "chapter-list") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit chaptersChanged(mpv::qt::node_to_variant(nod).toList());
|
||||
} else if (strcmp(prop->name, "speed") == 0) {
|
||||
double speed = *(double*)prop->data;
|
||||
emit speedChanged(speed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MPV_EVENT_LOG_MESSAGE: {
|
||||
if (m_logging) {
|
||||
struct mpv_event_log_message* msg =
|
||||
(struct mpv_event_log_message*)event->data;
|
||||
QString logMsg = "[" + QString(msg->prefix) + "] " + QString(msg->text);
|
||||
QString msgLevel = QString(msg->level);
|
||||
if (msgLevel.startsWith("d") || msgLevel.startsWith("t")) {
|
||||
mpvLogger->info("{}", logMsg.toStdString());
|
||||
} else if (msgLevel.startsWith("v") || msgLevel.startsWith("i")) {
|
||||
mpvLogger->info("{}", logMsg.toStdString());
|
||||
} else {
|
||||
mpvLogger->debug("{}", logMsg.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_SHUTDOWN: {
|
||||
qApp->exit();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString
|
||||
MPVBackend::getStats()
|
||||
{
|
||||
QString stats;
|
||||
stats =
|
||||
"<style> blockquote { text-indent: 0px; margin-left:40px; margin-top: 0px; "
|
||||
"margin-bottom: 0px; padding-bottom: 0px; padding-top: 0px; padding-left: "
|
||||
"0px; } b span p br { margin-bottom: 0px; margin-top: 0px; padding-top: "
|
||||
"0px; padding-botom: 0px; text-indent: 0px; } </style>";
|
||||
QString filename = getProperty("filename").toString();
|
||||
// File Info
|
||||
stats += "<b>File:</b> " + filename;
|
||||
stats += "<blockquote>";
|
||||
QString title = getProperty("media-title").toString();
|
||||
if (title != filename) {
|
||||
stats += "<b>Title:</b> " + title + "<br>";
|
||||
}
|
||||
QString fileFormat = getProperty("file-format").toString();
|
||||
stats += "<b>Format/Protocol:</b> " + fileFormat + "<br>";
|
||||
QLocale a;
|
||||
// a.formattedDataSize(
|
||||
double cacheUsed = getProperty("cache-used").toDouble();
|
||||
// Utils::createTimestamp(
|
||||
int demuxerSecs = getProperty("demuxer-cache-duration").toInt();
|
||||
QVariantMap demuxerState = getProperty("demuxer-cache-state").toMap();
|
||||
int demuxerCache = demuxerState.value("fw-bytes", QVariant(0)).toInt();
|
||||
|
||||
if (demuxerSecs + demuxerCache + cacheUsed > 0) {
|
||||
QString cacheStats;
|
||||
cacheStats += "<b>Total Cache:</b> ";
|
||||
cacheStats += a.formattedDataSize(demuxerCache + cacheUsed);
|
||||
cacheStats += " (<b>Demuxer:</b> ";
|
||||
|
||||
cacheStats += a.formattedDataSize(demuxerCache);
|
||||
cacheStats += ", ";
|
||||
cacheStats += QString::number(demuxerSecs) + "s) ";
|
||||
double cacheSpeed = getProperty("cache-speed").toDouble();
|
||||
if (cacheSpeed > 0) {
|
||||
cacheStats += "<b>Speed:</b> ";
|
||||
cacheStats += a.formattedDataSize(demuxerSecs);
|
||||
cacheStats += "/s";
|
||||
}
|
||||
cacheStats += "<br>";
|
||||
stats += cacheStats;
|
||||
}
|
||||
QString fileSize =
|
||||
a.formattedDataSize(getProperty("file-size").toInt()).remove("-");
|
||||
stats += "<b>Size:</b> " + fileSize + "<br>";
|
||||
|
||||
stats += "</blockquote>";
|
||||
// Video Info
|
||||
QVariant videoParams = getProperty("video-params");
|
||||
if (videoParams.isNull()) {
|
||||
videoParams = getProperty("video-out-params");
|
||||
}
|
||||
if (!videoParams.isNull()) {
|
||||
stats += "<b>Video:</b> " + getProperty("video-codec").toString();
|
||||
stats += "<blockquote>";
|
||||
QString avsync = QString::number(getProperty("avsync").toDouble(), 'f', 3);
|
||||
stats += "<b>A-V:</b> " + QString(avsync) + "<br>";
|
||||
|
||||
stats += "<b>Dropped Frames:</b> ";
|
||||
int dFDC = getProperty("decoder-frame-drop-count").toInt();
|
||||
if (dFDC > 0) {
|
||||
stats += QString::number(dFDC) + " (decoder) ";
|
||||
}
|
||||
int fDC = getProperty("frame-drop-count").toInt();
|
||||
if (fDC > 0) {
|
||||
stats += QString::number(fDC) + " (output)";
|
||||
}
|
||||
stats += "<br>";
|
||||
|
||||
int dFPS = getProperty("display-fps").toInt();
|
||||
int eDFPS = getProperty("estimated-display-fps").toInt();
|
||||
if ((dFPS + eDFPS) > 0) {
|
||||
stats += "<b>Display FPS:</b> ";
|
||||
|
||||
if (dFPS > 0) {
|
||||
stats += QString::number(dFPS);
|
||||
stats += " (specified) ";
|
||||
}
|
||||
if (eDFPS > 0) {
|
||||
stats += QString::number(eDFPS);
|
||||
stats += " (estimated)";
|
||||
}
|
||||
stats += "<br>";
|
||||
}
|
||||
|
||||
int cFPS = getProperty("container-fps").toInt();
|
||||
int eVFPS = getProperty("estimated-vf-fps").toInt();
|
||||
if ((cFPS + eVFPS) > 0) {
|
||||
stats += "<b>FPS:</b> ";
|
||||
|
||||
if (cFPS > 0) {
|
||||
stats += QString::number(cFPS);
|
||||
stats += " (specified) ";
|
||||
}
|
||||
if (eVFPS > 0) {
|
||||
stats += QString::number(eVFPS);
|
||||
stats += " (estimated)";
|
||||
}
|
||||
stats += "<br>";
|
||||
}
|
||||
QVariantMap vPM = videoParams.toMap();
|
||||
stats += "<b>Native Resolution:</b> ";
|
||||
stats += vPM["w"].toString() + " x " + vPM["h"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Window Scale:</b> ";
|
||||
stats += vPM["window-scale"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Aspect Ratio:</b> ";
|
||||
stats += vPM["aspect"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Pixel Format:</b> ";
|
||||
stats += vPM["pixelformat"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Primaries:</b> ";
|
||||
stats += vPM["primaries"].toString();
|
||||
stats += " <b>Colormatrix:</b> ";
|
||||
stats += vPM["colormatrix"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Levels:</b> ";
|
||||
stats += vPM["colorlevels"].toString();
|
||||
double sigPeak = vPM.value("sig-peak", QVariant(0.0)).toInt();
|
||||
if (sigPeak > 0) {
|
||||
stats += " (HDR Peak: " + QString::number(sigPeak) + ")";
|
||||
}
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Gamma:</b> ";
|
||||
stats += vPM["gamma"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
int pVB = getProperty("packet-video-bitrate").toInt();
|
||||
if (pVB > 0) {
|
||||
stats += "<b>Bitrate:</b> ";
|
||||
stats += a.formattedDataSize(pVB) + "/s";
|
||||
stats += "<br>";
|
||||
}
|
||||
|
||||
stats += "</blockquote>";
|
||||
}
|
||||
QVariant audioParams = getProperty("audio-params");
|
||||
if (audioParams.isNull()) {
|
||||
audioParams = getProperty("audio-out-params");
|
||||
}
|
||||
if (!audioParams.isNull()) {
|
||||
stats += "<b>Audio:</b> " + getProperty("audio-codec").toString();
|
||||
stats += "<blockquote>";
|
||||
QVariantMap aPM = audioParams.toMap();
|
||||
|
||||
stats += "<b>Format:</b> ";
|
||||
stats += aPM["format"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Sample Rate:</b> ";
|
||||
stats += aPM["samplerate"].toString() + " Hz";
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Channels:</b> ";
|
||||
stats += aPM["chanel-count"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
int pAB = getProperty("packet-audio-bitrate").toInt();
|
||||
if (pAB > 0) {
|
||||
stats += "<b>Bitrate:</b> ";
|
||||
stats += a.formattedDataSize(pAB) + "/s";
|
||||
stats += "<br>";
|
||||
}
|
||||
|
||||
stats += "</blockquote>";
|
||||
}
|
||||
|
||||
return stats;
|
||||
MPVCommon::handle_mpv_event(this, event);
|
||||
}
|
||||
|
||||
QQuickFramebufferObject::Renderer*
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
#include "src/enums.hpp"
|
||||
#include "src/utils.hpp"
|
||||
|
||||
extern bool usedirect;
|
||||
|
||||
class MpvRenderer;
|
||||
|
||||
class MPVBackend
|
||||
|
@ -36,11 +34,6 @@ class MPVBackend
|
|||
bool onTop = false;
|
||||
bool m_logging = true;
|
||||
|
||||
int lastTime = 0;
|
||||
double lastSpeed = 0;
|
||||
QString totalDurationString;
|
||||
QString lastPositionString;
|
||||
|
||||
friend class MpvRenderer;
|
||||
|
||||
public:
|
||||
|
@ -58,6 +51,11 @@ public:
|
|||
}
|
||||
bool logging() const { return m_logging; }
|
||||
|
||||
int lastTime = 0;
|
||||
double lastSpeed = 0;
|
||||
QString totalDurationString;
|
||||
QString lastPositionString;
|
||||
|
||||
public slots:
|
||||
QVariant playerCommand(const Enums::Commands& command, const QVariant& args);
|
||||
QVariant playerCommand(const Enums::Commands& command);
|
||||
|
|
504
src/Backends/MPVCommon/MPVCommon.cpp
Normal file
504
src/Backends/MPVCommon/MPVCommon.cpp
Normal file
|
@ -0,0 +1,504 @@
|
|||
#include "src/Backends/MPVCommon/MPVCommon.hpp"
|
||||
#include "src/utils.hpp"
|
||||
#include <QSettings>
|
||||
#include <mpv/qthelper.hpp>
|
||||
#include "src/logger.h"
|
||||
|
||||
|
||||
auto mpvLogger = initLogger("mpv");
|
||||
|
||||
|
||||
namespace MPVCommon {
|
||||
QString getStats(BackendInterface *b) {
|
||||
QString stats;
|
||||
stats =
|
||||
"<style> blockquote { text-indent: 0px; margin-left:40px; margin-top: 0px; "
|
||||
"margin-bottom: 0px; padding-bottom: 0px; padding-top: 0px; padding-left: "
|
||||
"0px; } b span p br { margin-bottom: 0px; margin-top: 0px; padding-top: "
|
||||
"0px; padding-botom: 0px; text-indent: 0px; } </style>";
|
||||
QString filename = b->getProperty("filename").toString();
|
||||
// File Info
|
||||
stats += "<b>File:</b> " + filename;
|
||||
stats += "<blockquote>";
|
||||
QString title = b->getProperty("media-title").toString();
|
||||
if (title != filename) {
|
||||
stats += "<b>Title:</b> " + title + "<br>";
|
||||
}
|
||||
QString fileFormat = b->getProperty("file-format").toString();
|
||||
stats += "<b>Format/Protocol:</b> " + fileFormat + "<br>";
|
||||
QLocale a;
|
||||
// a.formattedDataSize(
|
||||
double cacheUsed = b->getProperty("cache-used").toDouble();
|
||||
// Utils::createTimestamp(
|
||||
int demuxerSecs = b->getProperty("demuxer-cache-duration").toInt();
|
||||
QVariantMap demuxerState = b->getProperty("demuxer-cache-state").toMap();
|
||||
int demuxerCache = demuxerState.value("fw-bytes", QVariant(0)).toInt();
|
||||
|
||||
if (demuxerSecs + demuxerCache + cacheUsed > 0) {
|
||||
QString cacheStats;
|
||||
cacheStats += "<b>Total Cache:</b> ";
|
||||
cacheStats += a.formattedDataSize(demuxerCache + cacheUsed);
|
||||
cacheStats += " (<b>Demuxer:</b> ";
|
||||
|
||||
cacheStats += a.formattedDataSize(demuxerCache);
|
||||
cacheStats += ", ";
|
||||
cacheStats += QString::number(demuxerSecs) + "s) ";
|
||||
double cacheSpeed = b->getProperty("cache-speed").toDouble();
|
||||
if (cacheSpeed > 0) {
|
||||
cacheStats += "<b>Speed:</b> ";
|
||||
cacheStats += a.formattedDataSize(demuxerSecs);
|
||||
cacheStats += "/s";
|
||||
}
|
||||
cacheStats += "<br>";
|
||||
stats += cacheStats;
|
||||
}
|
||||
QString fileSize =
|
||||
a.formattedDataSize(b->getProperty("file-size").toInt()).remove("-");
|
||||
stats += "<b>Size:</b> " + fileSize + "<br>";
|
||||
|
||||
stats += "</blockquote>";
|
||||
// Video Info
|
||||
QVariant videoParams = b->getProperty("video-params");
|
||||
if (videoParams.isNull()) {
|
||||
videoParams = b->getProperty("video-out-params");
|
||||
}
|
||||
if (!videoParams.isNull()) {
|
||||
stats += "<b>Video:</b> " + b->getProperty("video-codec").toString();
|
||||
stats += "<blockquote>";
|
||||
QString avsync = QString::number(b->getProperty("avsync").toDouble(), 'f', 3);
|
||||
stats += "<b>A-V:</b> " + QString(avsync) + "<br>";
|
||||
|
||||
stats += "<b>Dropped Frames:</b> ";
|
||||
int dFDC = b->getProperty("decoder-frame-drop-count").toInt();
|
||||
if (dFDC > 0) {
|
||||
stats += QString::number(dFDC) + " (decoder) ";
|
||||
}
|
||||
int fDC = b->getProperty("frame-drop-count").toInt();
|
||||
if (fDC > 0) {
|
||||
stats += QString::number(fDC) + " (output)";
|
||||
}
|
||||
stats += "<br>";
|
||||
|
||||
int dFPS = b->getProperty("display-fps").toInt();
|
||||
int eDFPS = b->getProperty("estimated-display-fps").toInt();
|
||||
if ((dFPS + eDFPS) > 0) {
|
||||
stats += "<b>Display FPS:</b> ";
|
||||
|
||||
if (dFPS > 0) {
|
||||
stats += QString::number(dFPS);
|
||||
stats += " (specified) ";
|
||||
}
|
||||
if (eDFPS > 0) {
|
||||
stats += QString::number(eDFPS);
|
||||
stats += " (estimated)";
|
||||
}
|
||||
stats += "<br>";
|
||||
}
|
||||
|
||||
int cFPS = b->getProperty("container-fps").toInt();
|
||||
int eVFPS = b->getProperty("estimated-vf-fps").toInt();
|
||||
if ((cFPS + eVFPS) > 0) {
|
||||
stats += "<b>FPS:</b> ";
|
||||
|
||||
if (cFPS > 0) {
|
||||
stats += QString::number(cFPS);
|
||||
stats += " (specified) ";
|
||||
}
|
||||
if (eVFPS > 0) {
|
||||
stats += QString::number(eVFPS);
|
||||
stats += " (estimated)";
|
||||
}
|
||||
stats += "<br>";
|
||||
}
|
||||
QVariantMap vPM = videoParams.toMap();
|
||||
stats += "<b>Native Resolution:</b> ";
|
||||
stats += vPM["w"].toString() + " x " + vPM["h"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Window Scale:</b> ";
|
||||
stats += vPM["window-scale"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Aspect Ratio:</b> ";
|
||||
stats += vPM["aspect"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Pixel Format:</b> ";
|
||||
stats += vPM["pixelformat"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Primaries:</b> ";
|
||||
stats += vPM["primaries"].toString();
|
||||
stats += " <b>Colormatrix:</b> ";
|
||||
stats += vPM["colormatrix"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Levels:</b> ";
|
||||
stats += vPM["colorlevels"].toString();
|
||||
double sigPeak = vPM.value("sig-peak", QVariant(0.0)).toInt();
|
||||
if (sigPeak > 0) {
|
||||
stats += " (HDR Peak: " + QString::number(sigPeak) + ")";
|
||||
}
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Gamma:</b> ";
|
||||
stats += vPM["gamma"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
int pVB = b->getProperty("packet-video-bitrate").toInt();
|
||||
if (pVB > 0) {
|
||||
stats += "<b>Bitrate:</b> ";
|
||||
stats += a.formattedDataSize(pVB) + "/s";
|
||||
stats += "<br>";
|
||||
}
|
||||
|
||||
stats += "</blockquote>";
|
||||
}
|
||||
QVariant audioParams = b->getProperty("audio-params");
|
||||
if (audioParams.isNull()) {
|
||||
audioParams = b->getProperty("audio-out-params");
|
||||
}
|
||||
if (!audioParams.isNull()) {
|
||||
stats += "<b>Audio:</b> " + b->getProperty("audio-codec").toString();
|
||||
stats += "<blockquote>";
|
||||
QVariantMap aPM = audioParams.toMap();
|
||||
|
||||
stats += "<b>Format:</b> ";
|
||||
stats += aPM["format"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Sample Rate:</b> ";
|
||||
stats += aPM["samplerate"].toString() + " Hz";
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Channels:</b> ";
|
||||
stats += aPM["chanel-count"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
int pAB = b->getProperty("packet-audio-bitrate").toInt();
|
||||
if (pAB > 0) {
|
||||
stats += "<b>Bitrate:</b> ";
|
||||
stats += a.formattedDataSize(pAB) + "/s";
|
||||
stats += "<br>";
|
||||
}
|
||||
|
||||
stats += "</blockquote>";
|
||||
}
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
QVariant playerCommand(BackendInterface *b, const Enums::Commands& cmd, const QVariant& args)
|
||||
{
|
||||
switch (cmd) {
|
||||
case Enums::Commands::TogglePlayPause: {
|
||||
b->command(QVariantList() << "cycle"
|
||||
<< "pause");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::ToggleMute: {
|
||||
b->command(QVariantList() << "cycle"
|
||||
<< "mute");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::SetAudioDevice: {
|
||||
b->setProperty("audio-device", args.toString());
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::SetVolume: {
|
||||
b->command(QVariantList() << "set"
|
||||
<< "volume" << args);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::AddVolume: {
|
||||
|
||||
b->command(QVariantList() << "add"
|
||||
<< "volume" << args);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::AddSpeed: {
|
||||
|
||||
QString speedString =
|
||||
QString::number(b->getProperty("speed").toDouble() + args.toDouble());
|
||||
QVariant newSpeed =
|
||||
QVariant(speedString.left(speedString.lastIndexOf('.') + 2));
|
||||
|
||||
b->playerCommand(Enums::Commands::SetSpeed, newSpeed);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SubtractSpeed: {
|
||||
|
||||
QString speedString =
|
||||
QString::number(b->getProperty("speed").toDouble() - args.toDouble());
|
||||
QVariant newSpeed =
|
||||
QVariant(speedString.left(speedString.lastIndexOf('.') + 2));
|
||||
b->playerCommand(Enums::Commands::SetSpeed, newSpeed);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::ChangeSpeed: {
|
||||
|
||||
b->playerCommand(
|
||||
Enums::Commands::SetSpeed,
|
||||
QVariant(b->getProperty("speed").toDouble() * args.toDouble()));
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SetSpeed: {
|
||||
|
||||
b->command(QVariantList() << "set"
|
||||
<< "speed" << args.toString());
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::ToggleStats: {
|
||||
|
||||
b->command(QVariantList() << "script-binding"
|
||||
<< "stats/display-stats-toggle");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextAudioTrack: {
|
||||
|
||||
b->command(QVariantList() << "cycle"
|
||||
<< "audio");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextSubtitleTrack: {
|
||||
|
||||
b->command(QVariantList() << "cycle"
|
||||
<< "sub");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextVideoTrack: {
|
||||
b->command(QVariantList() << "cycle"
|
||||
<< "video");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::PreviousPlaylistItem: {
|
||||
|
||||
b->command(QVariantList() << "playlist-prev");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextPlaylistItem: {
|
||||
|
||||
b->command(QVariantList() << "playlist-next"
|
||||
<< "force");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::LoadFile: {
|
||||
b->command(QVariantList() << "loadfile" << args);
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::AppendFile: {
|
||||
|
||||
b->command(QVariantList() << "loadfile" << args << "append-play");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::Seek: {
|
||||
|
||||
b->command(QVariantList() << "seek" << args);
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::SeekAbsolute: {
|
||||
|
||||
b->command(QVariantList() << "seek" << args << "absolute");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::ForwardFrame: {
|
||||
|
||||
b->command(QVariantList() << "frame-step");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::BackwardFrame: {
|
||||
|
||||
b->command(QVariantList() << "frame-back-step");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SetTrack: {
|
||||
|
||||
b->command(QVariantList() << "set" << args.toList()[0] << args.toList()[1]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SetPlaylistPos: {
|
||||
|
||||
b->command(QVariantList() << "set"
|
||||
<< "playlist-pos" << args);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::ForcePause: {
|
||||
|
||||
b->command(QVariantList() << "set"
|
||||
<< "pause"
|
||||
<< "yes");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
qDebug() << "Command not found: " << cmd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant("NoOutput");
|
||||
}
|
||||
|
||||
void updateDurationString(BackendInterface *b, int numTime, QMetaMethod metaMethod)
|
||||
{
|
||||
QVariant speed = b->getProperty("speed");
|
||||
QSettings settings;
|
||||
if (metaMethod.name() == "positionChanged") {
|
||||
if (speed != b->lastSpeed) {
|
||||
b->lastSpeed = speed.toDouble();
|
||||
} else {
|
||||
if (numTime == b->lastTime) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
b->lastTime = numTime;
|
||||
b->lastPositionString = Utils::createTimestamp(b->lastTime);
|
||||
} else if (metaMethod.name() == "durationChanged") {
|
||||
b->totalDurationString = Utils::createTimestamp(numTime);
|
||||
}
|
||||
QString durationString;
|
||||
durationString += b->lastPositionString;
|
||||
durationString += " / ";
|
||||
durationString += b->totalDurationString;
|
||||
if (b->lastSpeed != 1) {
|
||||
if (settings.value("Appearance/themeName", "").toString() !=
|
||||
"RoosterTeeth") {
|
||||
durationString += " (" + speed.toString() + "x)";
|
||||
}
|
||||
}
|
||||
emit b->durationStringChanged(durationString);
|
||||
}
|
||||
|
||||
void
|
||||
handle_mpv_event(BackendInterface *b, mpv_event* event)
|
||||
{
|
||||
switch (event->event_id) {
|
||||
case MPV_EVENT_PROPERTY_CHANGE: {
|
||||
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;
|
||||
emit b->positionChanged(time);
|
||||
}
|
||||
} else if (strcmp(prop->name, "duration") == 0) {
|
||||
if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
double time = *(double*)prop->data;
|
||||
emit b->durationChanged(time);
|
||||
}
|
||||
} else if (strcmp(prop->name, "mute") == 0 ||
|
||||
strcmp(prop->name, "volume") == 0) {
|
||||
double volume = b->getProperty("volume").toDouble();
|
||||
bool mute = b->getProperty("mute").toBool();
|
||||
if (mute || volume == 0) {
|
||||
emit b->volumeStatusChanged(Enums::VolumeStatus::Muted);
|
||||
} else {
|
||||
if (volume < 25) {
|
||||
emit b->volumeStatusChanged(Enums::VolumeStatus::Low);
|
||||
} else {
|
||||
emit b->volumeStatusChanged(Enums::VolumeStatus::Normal);
|
||||
}
|
||||
}
|
||||
// emit volumeChanged(volume);
|
||||
} else if (strcmp(prop->name, "media-title") == 0) {
|
||||
if (prop->format == MPV_FORMAT_STRING) {
|
||||
char* title = *(char**)prop->data;
|
||||
emit b->titleChanged(QString(title));
|
||||
}
|
||||
} else if (strcmp(prop->name, "sub-text") == 0) {
|
||||
if (prop->format == MPV_FORMAT_STRING) {
|
||||
char* subs = *(char**)prop->data;
|
||||
emit b->subtitlesChanged(QString(subs));
|
||||
}
|
||||
} else if (strcmp(prop->name, "demuxer-cache-duration") == 0) {
|
||||
if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
double duration = *(double*)prop->data;
|
||||
emit b->cachedDurationChanged(duration);
|
||||
}
|
||||
} else if (strcmp(prop->name, "playlist-pos") == 0) {
|
||||
if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
double pos = *(double*)prop->data;
|
||||
emit b->playlistPositionChanged(pos);
|
||||
}
|
||||
} else if (strcmp(prop->name, "pause") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
if (mpv::qt::node_to_variant(nod).toBool()) {
|
||||
emit b->playStatusChanged(Enums::PlayStatus::Paused);
|
||||
// Utils::SetScreensaver(window()->winId(), true);
|
||||
} else {
|
||||
emit b->playStatusChanged(Enums::PlayStatus::Playing);
|
||||
// Utils::SetScreensaver(window()->winId(), false);
|
||||
}
|
||||
} else if (strcmp(prop->name, "track-list") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit b->tracksChanged(mpv::qt::node_to_variant(nod).toList());
|
||||
} else if (strcmp(prop->name, "audio-device-list") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit b->audioDevicesChanged(b->getAudioDevices(mpv::qt::node_to_variant(nod)));
|
||||
} else if (strcmp(prop->name, "playlist") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit b->playlistChanged(mpv::qt::node_to_variant(nod).toList());
|
||||
} else if (strcmp(prop->name, "chapter-list") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit b->chaptersChanged(mpv::qt::node_to_variant(nod).toList());
|
||||
} else if (strcmp(prop->name, "speed") == 0) {
|
||||
double speed = *(double*)prop->data;
|
||||
emit b->speedChanged(speed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MPV_EVENT_LOG_MESSAGE: {
|
||||
struct mpv_event_log_message* msg =
|
||||
(struct mpv_event_log_message*)event->data;
|
||||
QString logMsg = "[" + QString(msg->prefix) + "] " + QString(msg->text);
|
||||
QString msgLevel = QString(msg->level);
|
||||
if (msgLevel.startsWith("d") || msgLevel.startsWith("t")) {
|
||||
mpvLogger->info("{}", logMsg.toStdString());
|
||||
} else if (msgLevel.startsWith("v") || msgLevel.startsWith("i")) {
|
||||
mpvLogger->info("{}", logMsg.toStdString());
|
||||
} else {
|
||||
mpvLogger->debug("{}", logMsg.toStdString());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_SHUTDOWN: {
|
||||
qApp->exit();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariantMap getAudioDevices(const QVariant& drivers)
|
||||
{
|
||||
QVariantMap newDrivers;
|
||||
|
||||
QSequentialIterable iterable = drivers.value<QSequentialIterable>();
|
||||
foreach (const QVariant& v, iterable) {
|
||||
QVariantMap item = v.toMap();
|
||||
newDrivers[item["description"].toString()] = item;
|
||||
}
|
||||
return newDrivers;
|
||||
}
|
||||
|
||||
}
|
19
src/Backends/MPVCommon/MPVCommon.hpp
Normal file
19
src/Backends/MPVCommon/MPVCommon.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef MPVCommon_H
|
||||
#define MPVCommon_H
|
||||
|
||||
#include <QString>
|
||||
#include "src/backendinterface.hpp"
|
||||
#include <mpv/client.h>
|
||||
|
||||
namespace MPVCommon {
|
||||
|
||||
QString getStats(BackendInterface *b);
|
||||
QVariant playerCommand(BackendInterface *b, const Enums::Commands& cmd, const QVariant& args);
|
||||
void updateDurationString(BackendInterface *b, int numTime, QMetaMethod metaMethod);
|
||||
void handle_mpv_event(BackendInterface *b, mpv_event* event);
|
||||
QVariantMap getAudioDevices(const QVariant& drivers);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -14,6 +14,9 @@
|
|||
#include <QSequentialIterable>
|
||||
#include <math.h>
|
||||
|
||||
#include "src/Backends/MPVCommon/MPVCommon.hpp"
|
||||
|
||||
|
||||
void
|
||||
wakeup(void* ctx)
|
||||
{
|
||||
|
@ -232,162 +235,7 @@ QVariant
|
|||
MPVNoFBOBackend::playerCommand(const Enums::Commands& cmd,
|
||||
const QVariant& args)
|
||||
{
|
||||
switch (cmd) {
|
||||
case Enums::Commands::TogglePlayPause: {
|
||||
command(QVariantList() << "cycle"
|
||||
<< "pause");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::ToggleMute: {
|
||||
command(QVariantList() << "cycle"
|
||||
<< "mute");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::SetAudioDevice: {
|
||||
setProperty("audio-device", args.toString());
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SetVolume: {
|
||||
command(QVariantList() << "set"
|
||||
<< "volume" << args);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::AddVolume: {
|
||||
|
||||
command(QVariantList() << "add"
|
||||
<< "volume" << args);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::AddSpeed: {
|
||||
|
||||
QString speedString =
|
||||
QString::number(getProperty("speed").toDouble() + args.toDouble());
|
||||
QVariant newSpeed =
|
||||
QVariant(speedString.left(speedString.lastIndexOf('.') + 2));
|
||||
|
||||
playerCommand(Enums::Commands::SetSpeed, newSpeed);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SubtractSpeed: {
|
||||
|
||||
QString speedString =
|
||||
QString::number(getProperty("speed").toDouble() - args.toDouble());
|
||||
QVariant newSpeed =
|
||||
QVariant(speedString.left(speedString.lastIndexOf('.') + 2));
|
||||
playerCommand(Enums::Commands::SetSpeed, newSpeed);
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::ChangeSpeed: {
|
||||
|
||||
playerCommand(
|
||||
Enums::Commands::SetSpeed,
|
||||
QVariant(getProperty("speed").toDouble() * args.toDouble()));
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SetSpeed: {
|
||||
|
||||
command(QVariantList() << "set"
|
||||
<< "speed" << args.toString());
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::ToggleStats: {
|
||||
|
||||
command(QVariantList() << "script-binding"
|
||||
<< "stats/display-stats-toggle");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextAudioTrack: {
|
||||
|
||||
command(QVariantList() << "cycle"
|
||||
<< "audio");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextSubtitleTrack: {
|
||||
|
||||
command(QVariantList() << "cycle"
|
||||
<< "sub");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextVideoTrack: {
|
||||
command(QVariantList() << "cycle"
|
||||
<< "video");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::PreviousPlaylistItem: {
|
||||
|
||||
command(QVariantList() << "playlist-prev");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::NextPlaylistItem: {
|
||||
|
||||
command(QVariantList() << "playlist-next"
|
||||
<< "force");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::LoadFile: {
|
||||
command(QVariantList() << "loadfile" << args);
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::AppendFile: {
|
||||
|
||||
command(QVariantList() << "loadfile" << args << "append-play");
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::Seek: {
|
||||
|
||||
command(QVariantList() << "seek" << args);
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::SeekAbsolute: {
|
||||
|
||||
command(QVariantList() << "seek" << args << "absolute");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::ForwardFrame: {
|
||||
|
||||
command(QVariantList() << "frame-step");
|
||||
|
||||
break;
|
||||
}
|
||||
case Enums::Commands::BackwardFrame: {
|
||||
|
||||
command(QVariantList() << "frame-back-step");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SetTrack: {
|
||||
|
||||
command(QVariantList() << "set" << args.toList()[0] << args.toList()[1]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Enums::Commands::SetPlaylistPos: {
|
||||
|
||||
command(QVariantList() << "set"
|
||||
<< "playlist-pos" << args);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
qDebug() << "Command not found: " << cmd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant("NoOutput");
|
||||
return MPVCommon::playerCommand(this, cmd, args);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -444,322 +292,26 @@ MPVNoFBOBackend::on_mpv_events()
|
|||
void
|
||||
MPVNoFBOBackend::updateDurationString(int numTime)
|
||||
{
|
||||
QVariant speed = getProperty("speed");
|
||||
QMetaMethod metaMethod = sender()->metaObject()->method(senderSignalIndex());
|
||||
if (metaMethod.name() == "positionChanged") {
|
||||
if (speed != lastSpeed) {
|
||||
lastSpeed = speed.toDouble();
|
||||
} else {
|
||||
if (numTime == lastTime) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
lastTime = numTime;
|
||||
lastPositionString = Utils::createTimestamp(lastTime);
|
||||
} else if (metaMethod.name() == "durationChanged") {
|
||||
totalDurationString = Utils::createTimestamp(numTime);
|
||||
}
|
||||
QString durationString;
|
||||
durationString += lastPositionString;
|
||||
durationString += " / ";
|
||||
durationString += totalDurationString;
|
||||
if (lastSpeed != 1) {
|
||||
if (settings.value("Appearance/themeName", "").toString() !=
|
||||
"RoosterTeeth") {
|
||||
durationString += " (" + speed.toString() + "x)";
|
||||
}
|
||||
}
|
||||
emit durationStringChanged(durationString);
|
||||
MPVCommon::updateDurationString(this, numTime, metaMethod);
|
||||
}
|
||||
|
||||
QVariantMap
|
||||
MPVNoFBOBackend::getAudioDevices() const
|
||||
MPVNoFBOBackend::getAudioDevices(const QVariant& drivers) const
|
||||
{
|
||||
QVariant drivers = getProperty("audio-device-list");
|
||||
QVariant currentDevice = getProperty("audio-device");
|
||||
|
||||
QVariantMap newDrivers;
|
||||
|
||||
QSequentialIterable iterable = drivers.value<QSequentialIterable>();
|
||||
foreach (const QVariant& v, iterable) {
|
||||
QVariantMap item = v.toMap();
|
||||
item["selected"] = currentDevice == item["name"];
|
||||
newDrivers[item["description"].toString()] = item;
|
||||
}
|
||||
QMap<QString, QVariant> pulseItem;
|
||||
pulseItem["name"] = "pulse";
|
||||
pulseItem["description"] = "Default (pulseaudio)";
|
||||
pulseItem["selected"] = currentDevice == "pulse";
|
||||
newDrivers[pulseItem["description"].toString()] = pulseItem;
|
||||
return newDrivers;
|
||||
return MPVCommon::getAudioDevices(drivers);
|
||||
}
|
||||
|
||||
void
|
||||
MPVNoFBOBackend::handle_mpv_event(mpv_event* event)
|
||||
{
|
||||
switch (event->event_id) {
|
||||
case MPV_EVENT_PROPERTY_CHANGE: {
|
||||
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;
|
||||
emit positionChanged(time);
|
||||
}
|
||||
} else if (strcmp(prop->name, "duration") == 0) {
|
||||
if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
double time = *(double*)prop->data;
|
||||
emit durationChanged(time);
|
||||
}
|
||||
} else if (strcmp(prop->name, "mute") == 0 ||
|
||||
strcmp(prop->name, "volume") == 0) {
|
||||
double volume = getProperty("volume").toDouble();
|
||||
bool mute = getProperty("mute").toBool();
|
||||
if (mute || volume == 0) {
|
||||
emit volumeStatusChanged(Enums::VolumeStatus::Muted);
|
||||
} else {
|
||||
if (volume < 25) {
|
||||
emit volumeStatusChanged(Enums::VolumeStatus::Low);
|
||||
} else {
|
||||
emit volumeStatusChanged(Enums::VolumeStatus::Normal);
|
||||
}
|
||||
}
|
||||
// emit volumeChanged(volume);
|
||||
} else if (strcmp(prop->name, "media-title") == 0) {
|
||||
if (prop->format == MPV_FORMAT_STRING) {
|
||||
char* title = *(char**)prop->data;
|
||||
emit titleChanged(QString(title));
|
||||
}
|
||||
} else if (strcmp(prop->name, "sub-text") == 0) {
|
||||
if (prop->format == MPV_FORMAT_STRING) {
|
||||
char* subs = *(char**)prop->data;
|
||||
emit subtitlesChanged(QString(subs));
|
||||
}
|
||||
} else if (strcmp(prop->name, "demuxer-cache-duration") == 0) {
|
||||
if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
double duration = *(double*)prop->data;
|
||||
emit cachedDurationChanged(duration);
|
||||
}
|
||||
} else if (strcmp(prop->name, "playlist-pos") == 0) {
|
||||
if (prop->format == MPV_FORMAT_DOUBLE) {
|
||||
double pos = *(double*)prop->data;
|
||||
emit playlistPositionChanged(pos);
|
||||
}
|
||||
} else if (strcmp(prop->name, "pause") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
if (mpv::qt::node_to_variant(nod).toBool()) {
|
||||
emit playStatusChanged(Enums::PlayStatus::Paused);
|
||||
Utils::SetScreensaver(window()->winId(), true);
|
||||
|
||||
} else {
|
||||
emit playStatusChanged(Enums::PlayStatus::Playing);
|
||||
Utils::SetScreensaver(window()->winId(), true);
|
||||
}
|
||||
} else if (strcmp(prop->name, "track-list") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit tracksChanged(mpv::qt::node_to_variant(nod).toList());
|
||||
} else if (strcmp(prop->name, "audio-device-list") == 0) {
|
||||
emit audioDevicesChanged(getAudioDevices());
|
||||
} else if (strcmp(prop->name, "playlist") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit playlistChanged(mpv::qt::node_to_variant(nod).toList());
|
||||
} else if (strcmp(prop->name, "chapter-list") == 0) {
|
||||
mpv_node* nod = (mpv_node*)prop->data;
|
||||
emit chaptersChanged(mpv::qt::node_to_variant(nod).toList());
|
||||
} else if (strcmp(prop->name, "speed") == 0) {
|
||||
double speed = *(double*)prop->data;
|
||||
emit speedChanged(speed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_SHUTDOWN: {
|
||||
qApp->exit();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
MPVCommon::handle_mpv_event(this, event);
|
||||
}
|
||||
|
||||
QString
|
||||
MPVNoFBOBackend::getStats()
|
||||
{
|
||||
QString stats;
|
||||
stats =
|
||||
"<style> blockquote { text-indent: 0px; margin-left:40px; margin-top: 0px; "
|
||||
"margin-bottom: 0px; padding-bottom: 0px; padding-top: 0px; padding-left: "
|
||||
"0px; } b span p br { margin-bottom: 0px; margin-top: 0px; padding-top: "
|
||||
"0px; padding-botom: 0px; text-indent: 0px; } </style>";
|
||||
QString filename = getProperty("filename").toString();
|
||||
// File Info
|
||||
stats += "<b>File:</b> " + filename;
|
||||
stats += "<blockquote>";
|
||||
QString title = getProperty("media-title").toString();
|
||||
if (title != filename) {
|
||||
stats += "<b>Title:</b> " + title + "<br>";
|
||||
}
|
||||
QString fileFormat = getProperty("file-format").toString();
|
||||
stats += "<b>Format/Protocol:</b> " + fileFormat + "<br>";
|
||||
QLocale a;
|
||||
// a.formattedDataSize(
|
||||
double cacheUsed = getProperty("cache-used").toDouble();
|
||||
// Utils::createTimestamp(
|
||||
int demuxerSecs = getProperty("demuxer-cache-duration").toInt();
|
||||
QVariantMap demuxerState = getProperty("demuxer-cache-state").toMap();
|
||||
int demuxerCache = demuxerState.value("fw-bytes", QVariant(0)).toInt();
|
||||
|
||||
if (demuxerSecs + demuxerCache + cacheUsed > 0) {
|
||||
QString cacheStats;
|
||||
cacheStats += "<b>Total Cache:</b> ";
|
||||
cacheStats += a.formattedDataSize(demuxerCache + cacheUsed);
|
||||
cacheStats += " (<b>Demuxer:</b> ";
|
||||
|
||||
cacheStats += a.formattedDataSize(demuxerCache);
|
||||
cacheStats += ", ";
|
||||
cacheStats += QString::number(demuxerSecs) + "s) ";
|
||||
double cacheSpeed = getProperty("cache-speed").toDouble();
|
||||
if (cacheSpeed > 0) {
|
||||
cacheStats += "<b>Speed:</b> ";
|
||||
cacheStats += a.formattedDataSize(demuxerSecs);
|
||||
cacheStats += "/s";
|
||||
}
|
||||
cacheStats += "<br>";
|
||||
stats += cacheStats;
|
||||
}
|
||||
QString fileSize =
|
||||
a.formattedDataSize(getProperty("file-size").toInt()).remove("-");
|
||||
stats += "<b>Size:</b> " + fileSize + "<br>";
|
||||
|
||||
stats += "</blockquote>";
|
||||
// Video Info
|
||||
QVariant videoParams = getProperty("video-params");
|
||||
if (videoParams.isNull()) {
|
||||
videoParams = getProperty("video-out-params");
|
||||
}
|
||||
if (!videoParams.isNull()) {
|
||||
stats += "<b>Video:</b> " + getProperty("video-codec").toString();
|
||||
stats += "<blockquote>";
|
||||
QString avsync = QString::number(getProperty("avsync").toDouble(), 'f', 3);
|
||||
stats += "<b>A-V:</b> " + QString(avsync) + "<br>";
|
||||
|
||||
stats += "<b>Dropped Frames:</b> ";
|
||||
int dFDC = getProperty("decoder-frame-drop-count").toInt();
|
||||
if (dFDC > 0) {
|
||||
stats += QString::number(dFDC) + " (decoder) ";
|
||||
}
|
||||
int fDC = getProperty("frame-drop-count").toInt();
|
||||
if (fDC > 0) {
|
||||
stats += QString::number(fDC) + " (output)";
|
||||
}
|
||||
stats += "<br>";
|
||||
|
||||
int dFPS = getProperty("display-fps").toInt();
|
||||
int eDFPS = getProperty("estimated-display-fps").toInt();
|
||||
if ((dFPS + eDFPS) > 0) {
|
||||
stats += "<b>Display FPS:</b> ";
|
||||
|
||||
if (dFPS > 0) {
|
||||
stats += QString::number(dFPS);
|
||||
stats += " (specified) ";
|
||||
}
|
||||
if (eDFPS > 0) {
|
||||
stats += QString::number(eDFPS);
|
||||
stats += " (estimated)";
|
||||
}
|
||||
stats += "<br>";
|
||||
}
|
||||
|
||||
int cFPS = getProperty("container-fps").toInt();
|
||||
int eVFPS = getProperty("estimated-vf-fps").toInt();
|
||||
if ((cFPS + eVFPS) > 0) {
|
||||
stats += "<b>FPS:</b> ";
|
||||
|
||||
if (cFPS > 0) {
|
||||
stats += QString::number(cFPS);
|
||||
stats += " (specified) ";
|
||||
}
|
||||
if (eVFPS > 0) {
|
||||
stats += QString::number(eVFPS);
|
||||
stats += " (estimated)";
|
||||
}
|
||||
stats += "<br>";
|
||||
}
|
||||
QVariantMap vPM = videoParams.toMap();
|
||||
stats += "<b>Native Resolution:</b> ";
|
||||
stats += vPM["w"].toString() + " x " + vPM["h"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Window Scale:</b> ";
|
||||
stats += vPM["window-scale"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Aspect Ratio:</b> ";
|
||||
stats += vPM["aspect"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Pixel Format:</b> ";
|
||||
stats += vPM["pixelformat"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Primaries:</b> ";
|
||||
stats += vPM["primaries"].toString();
|
||||
stats += " <b>Colormatrix:</b> ";
|
||||
stats += vPM["colormatrix"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Levels:</b> ";
|
||||
stats += vPM["colorlevels"].toString();
|
||||
double sigPeak = vPM.value("sig-peak", QVariant(0.0)).toInt();
|
||||
if (sigPeak > 0) {
|
||||
stats += " (HDR Peak: " + QString::number(sigPeak) + ")";
|
||||
}
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Gamma:</b> ";
|
||||
stats += vPM["gamma"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
int pVB = getProperty("packet-video-bitrate").toInt();
|
||||
if (pVB > 0) {
|
||||
stats += "<b>Bitrate:</b> ";
|
||||
stats += a.formattedDataSize(pVB) + "/s";
|
||||
stats += "<br>";
|
||||
}
|
||||
|
||||
stats += "</blockquote>";
|
||||
}
|
||||
QVariant audioParams = getProperty("audio-params");
|
||||
if (audioParams.isNull()) {
|
||||
audioParams = getProperty("audio-out-params");
|
||||
}
|
||||
if (!audioParams.isNull()) {
|
||||
stats += "<b>Audio:</b> " + getProperty("audio-codec").toString();
|
||||
stats += "<blockquote>";
|
||||
QVariantMap aPM = audioParams.toMap();
|
||||
|
||||
stats += "<b>Format:</b> ";
|
||||
stats += aPM["format"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Sample Rate:</b> ";
|
||||
stats += aPM["samplerate"].toString() + " Hz";
|
||||
stats += "<br>";
|
||||
|
||||
stats += "<b>Channels:</b> ";
|
||||
stats += aPM["chanel-count"].toString();
|
||||
stats += "<br>";
|
||||
|
||||
int pAB = getProperty("packet-audio-bitrate").toInt();
|
||||
if (pAB > 0) {
|
||||
stats += "<b>Bitrate:</b> ";
|
||||
stats += a.formattedDataSize(pAB) + "/s";
|
||||
stats += "<br>";
|
||||
}
|
||||
|
||||
stats += "</blockquote>";
|
||||
}
|
||||
|
||||
return stats;
|
||||
return MPVCommon::getStats(this);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -44,11 +44,7 @@ class MPVNoFBOBackend
|
|||
mpv_opengl_cb_context* mpv_gl;
|
||||
MPVNoFBORenderer* renderer;
|
||||
bool onTop = false;
|
||||
int lastTime = 0;
|
||||
double lastSpeed = 0;
|
||||
bool m_logging = true;
|
||||
QString totalDurationString;
|
||||
QString lastPositionString;
|
||||
QSettings settings;
|
||||
|
||||
public:
|
||||
|
@ -65,6 +61,11 @@ public:
|
|||
MPVNoFBOBackend(QQuickItem* parent = 0);
|
||||
virtual ~MPVNoFBOBackend();
|
||||
|
||||
int lastTime = 0;
|
||||
double lastSpeed = 0;
|
||||
QString totalDurationString;
|
||||
QString lastPositionString;
|
||||
|
||||
public slots:
|
||||
QVariant playerCommand(const Enums::Commands& command, const QVariant& args);
|
||||
QVariant playerCommand(const Enums::Commands& command);
|
||||
|
@ -82,7 +83,9 @@ public slots:
|
|||
void cleanup();
|
||||
|
||||
// Just used for adding missing audio devices to list.
|
||||
QVariantMap getAudioDevices() const;
|
||||
QVariantMap getAudioDevices(const QVariant& drivers) const;
|
||||
|
||||
|
||||
bool event(QEvent* event);
|
||||
|
||||
signals:
|
||||
|
|
|
@ -11,6 +11,10 @@ class BackendInterface
|
|||
{
|
||||
public:
|
||||
virtual ~BackendInterface(){};
|
||||
int lastTime = 0;
|
||||
double lastSpeed = 0;
|
||||
QString totalDurationString;
|
||||
QString lastPositionString;
|
||||
|
||||
public slots:
|
||||
// All 5 required for Player API
|
||||
|
@ -23,6 +27,8 @@ public slots:
|
|||
virtual void setProperty(const QString& name, const QVariant& value) = 0;
|
||||
virtual void setOption(const QString& name, const QVariant& value) = 0;
|
||||
virtual QVariant getProperty(const QString& name) const = 0;
|
||||
virtual QVariantMap getAudioDevices(const QVariant& drivers) const = 0;
|
||||
|
||||
|
||||
signals:
|
||||
// All below required for Player API
|
||||
|
|
|
@ -52,7 +52,8 @@ Window {
|
|||
id: backendSettings
|
||||
category: "Backend"
|
||||
property string backend: "mpv"
|
||||
property bool checkForUpdatesOnLaunch: true
|
||||
property bool fbo: true
|
||||
property bool direct: false
|
||||
}
|
||||
|
||||
Settings {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <QtCore>
|
||||
#include <QtNetwork>
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
#ifdef ENABLE_X11
|
||||
#include <QX11Info>
|
||||
#include <X11/Xlib.h>
|
||||
|
@ -83,7 +83,7 @@ SetScreensaver(WId wid, bool on)
|
|||
void
|
||||
SetDPMS(bool on)
|
||||
{
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
if (getPlatformName() != "xcb") {
|
||||
return;
|
||||
}
|
||||
|
@ -112,13 +112,13 @@ SetDPMS(bool on)
|
|||
void
|
||||
AlwaysOnTop(WId wid, bool on)
|
||||
{
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
#ifdef ENABLE_X11
|
||||
Display* display = QX11Info::display();
|
||||
XEvent event;
|
||||
event.xclient.type = ClientMessage;
|
||||
event.xclient.serial = 0;
|
||||
event.xclient.send_event = True;
|
||||
event.xclient.send_event = true;
|
||||
event.xclient.display = display;
|
||||
event.xclient.window = wid;
|
||||
event.xclient.message_type = XInternAtom(display, "_NET_WM_STATE", False);
|
||||
|
|
Loading…
Reference in a new issue