* [gentoo-commits] repo/proj/guru:master commit in: media-video/kikoplay/files/, media-video/kikoplay/
@ 2020-04-18 18:39 Andrew Ammerlaan
0 siblings, 0 replies; 3+ messages in thread
From: Andrew Ammerlaan @ 2020-04-18 18:39 UTC (permalink / raw
To: gentoo-commits
commit: 11f4549a67d2a005f0c5108d4759b152775d54f4
Author: Huang Rui <vowstar <AT> gmail <DOT> com>
AuthorDate: Fri Apr 17 19:34:59 2020 +0000
Commit: Andrew Ammerlaan <andrewammerlaan <AT> riseup <DOT> net>
CommitDate: Fri Apr 17 19:46:27 2020 +0000
URL: https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=11f4549a
media-video/kikoplay: new package
A Full-Featured Danmu Player based on mpv.
NOTE: this package is blocked by lua 5.3,
However, Gentoo is using the old 5.1.
It depends on gentoo slotted dev-lang/lua
versions and dependencies.
See also https://bugs.gentoo.org/657722
See also https://bugs.gentoo.org/671248
It takes many years.
Package-Manager: Portage-2.3.99, Repoman-2.3.22
Signed-off-by: Huang Rui <vowstar <AT> gmail.com>
media-video/kikoplay/Manifest | 1 +
.../kikoplay/files/kikoplay-0.6.0-desktop.patch | 16 +
.../kikoplay/files/kikoplay-0.6.0-home.patch | 97 ++
.../kikoplay/files/kikoplay-0.6.0-install.patch | 1003 ++++++++++++++++++++
media-video/kikoplay/kikoplay-0.6.0.ebuild | 78 ++
media-video/kikoplay/metadata.xml | 38 +
6 files changed, 1233 insertions(+)
diff --git a/media-video/kikoplay/Manifest b/media-video/kikoplay/Manifest
new file mode 100644
index 0000000..b7a4138
--- /dev/null
+++ b/media-video/kikoplay/Manifest
@@ -0,0 +1 @@
+DIST kikoplay-0.6.0.tar.gz 7497254 BLAKE2B a23106151782477194d15712e9458171a0bc1dd53f8b6c8dbed12663be1c2c76204674c23eba61f2b8828be7acbd10449f51c766ab57be86cf21844591430b18 SHA512 9d8801f7c9b091f097d1edf9496a389718e81399a8d380d7763c1d12eafd1d4ce444e4df22a0e4a6c8eebbc7f1176e58a3cbac6bea60e87ccd44a5890927bf21
diff --git a/media-video/kikoplay/files/kikoplay-0.6.0-desktop.patch b/media-video/kikoplay/files/kikoplay-0.6.0-desktop.patch
new file mode 100644
index 0000000..86b4382
--- /dev/null
+++ b/media-video/kikoplay/files/kikoplay-0.6.0-desktop.patch
@@ -0,0 +1,16 @@
+diff --git a/kikoplay.desktop b/kikoplay.desktop
+new file mode 100644
+index 0000000..6171559
+--- /dev/null
++++ b/kikoplay.desktop
+@@ -0,0 +1,10 @@
++[Desktop Entry]
++Type=Application
++Name=KikoPlay
++Comment=KikoPlay is a full-featured danmu player!
++TryExec=KikoPlay
++Exec=KikoPlay
++Icon=/usr/share/pixmaps/kikoplay.png
++Terminal=false
++StartupNotify=true
++Categories=Qt;AudioVideo;Video;
diff --git a/media-video/kikoplay/files/kikoplay-0.6.0-home.patch b/media-video/kikoplay/files/kikoplay-0.6.0-home.patch
new file mode 100644
index 0000000..ec2eae5
--- /dev/null
+++ b/media-video/kikoplay/files/kikoplay-0.6.0-home.patch
@@ -0,0 +1,97 @@
+diff --git a/Download/Script/scriptmanager.cpp b/Download/Script/scriptmanager.cpp
+index f99c261..8ede8e3 100644
+--- a/Download/Script/scriptmanager.cpp
++++ b/Download/Script/scriptmanager.cpp
+@@ -163,7 +163,11 @@ QString ScriptManager::search(QString sid, const QString &keyword, int page, int
+ {
+ if(s.id==sid)
+ {
++#ifndef CONFIG_HOME_DATA
+ scriptPath=QCoreApplication::applicationDirPath()+"/script/"+s.fileName;
++#else
++ scriptPath=QDir::homePath()+"/.config/kikoplay/script/"+s.fileName;
++#endif
+ break;
+ }
+ }
+@@ -270,7 +274,11 @@ void ScriptManager::removeScript(const QModelIndex &index)
+ else
+ normalScriptId="";
+ }
++#ifndef CONFIG_HOME_DATA
+ QFileInfo fi(QCoreApplication::applicationDirPath()+"/script/"+script.fileName);
++#else
++ QFileInfo fi(QDir::homePath()+"/.config/kikoplay/script/"+script.fileName);
++#endif
+ if(fi.exists()) fi.dir().remove(fi.fileName());
+ beginRemoveRows(QModelIndex(),index.row(),index.row());
+ scriptList.removeAt(index.row());
+@@ -319,7 +327,11 @@ QVariant ScriptManager::headerData(int section, Qt::Orientation orientation, int
+
+ void ScriptWorker::refreshScriptList()
+ {
++#ifndef CONFIG_HOME_DATA
+ QString scriptPath(QCoreApplication::applicationDirPath()+"/script/");
++#else
++ QString scriptPath(QDir::homePath()+"/.config/kikoplay/script/");
++#endif
+ QDir folder(scriptPath);
+ QList<ScriptInfo> sList;
+ for (QFileInfo fileInfo : folder.entryInfoList())
+diff --git a/Download/aria2jsonrpc.cpp b/Download/aria2jsonrpc.cpp
+index 7999128..43bc63d 100644
+--- a/Download/aria2jsonrpc.cpp
++++ b/Download/aria2jsonrpc.cpp
+@@ -1,4 +1,5 @@
+ #include "aria2jsonrpc.h"
++#include <QFileInfo>
+ #include <QNetworkAccessManager>
+ #include <QNetworkRequest>
+ #include <QNetworkReply>
+@@ -19,7 +20,13 @@ Aria2JsonRPC::Aria2JsonRPC(QObject *parent) : QObject(parent)
+ #ifdef Q_OS_WIN
+ process->start(QCoreApplication::applicationDirPath()+"\\aria2c.exe", args);
+ #else
+- process->start(QCoreApplication::applicationDirPath()+"/aria2c", args);
++ QFileInfo check_file(QCoreApplication::applicationDirPath()+"/aria2c");
++ /* check if file exists and if yes: Is it really a file and no directory? */
++ if (check_file.exists() && check_file.isFile()) {
++ process->start(QCoreApplication::applicationDirPath()+"/aria2c", args);
++ } else {
++ process->start("aria2c", args);
++ }
+
+ #endif
+ process->waitForStarted(-1);
+diff --git a/LANServer/httpserver.cpp b/LANServer/httpserver.cpp
+index 5b3fa08..d66a6ee 100644
+--- a/LANServer/httpserver.cpp
++++ b/LANServer/httpserver.cpp
+@@ -127,7 +127,11 @@ namespace
+ HttpServer::HttpServer(QObject *parent) : QObject(parent)
+ {
+ MediaFileHandler *handler=new MediaFileHandler(&mediaHash,this);
++#ifndef CONFIG_HOME_DATA
+ handler->setDocumentRoot(QCoreApplication::applicationDirPath()+"/web");
++#else
++ handler->setDocumentRoot(QDir::homePath()+"/.config/kikoplay/web");
++#endif
+ handler->addRedirect(QRegExp("^$"), "/index.html");
+
+ QHttpEngine::QObjectHandler *apiHandler=new QHttpEngine::QObjectHandler(this);
+diff --git a/globalobjects.cpp b/globalobjects.cpp
+index 07bf674..32b82a2 100644
+--- a/globalobjects.cpp
++++ b/globalobjects.cpp
+@@ -42,7 +42,11 @@ namespace {
+ }
+ void GlobalObjects::init()
+ {
++#ifndef CONFIG_HOME_DATA
+ dataPath=QCoreApplication::applicationDirPath()+"/data/";
++#else
++ dataPath=QDir::homePath()+"/.config/kikoplay/data/";
++#endif
+ QDir dir;
+ if(!dir.exists(dataPath))
+ {
diff --git a/media-video/kikoplay/files/kikoplay-0.6.0-install.patch b/media-video/kikoplay/files/kikoplay-0.6.0-install.patch
new file mode 100644
index 0000000..0b90d54
--- /dev/null
+++ b/media-video/kikoplay/files/kikoplay-0.6.0-install.patch
@@ -0,0 +1,1003 @@
+diff --git a/Common/network.cpp b/Common/network.cpp
+index c9bf952..ec62f69 100644
+--- a/Common/network.cpp
++++ b/Common/network.cpp
+@@ -139,6 +139,25 @@ QByteArray Network::httpPost(const QString &url, QByteArray &data, const QString
+ request.setRawHeader(header[i].toUtf8(),header[i+1].toUtf8());
+ }
+ request.setUrl(queryUrl);
++ QList<QNetworkCookie> cookies;
++ QNetworkAccessManager *manager = getManager();
++ if(request.hasRawHeader("Cookie"))
++ {
++ auto cookieBytes = request.rawHeader("Cookie");
++ auto rawList = cookieBytes.split(';');
++ for (auto &bytes:rawList)
++ {
++ int pos =bytes.indexOf('=');
++ if(pos<=0) continue;
++ auto name = bytes.left(pos);
++ auto value = bytes.mid(pos+1);
++ QNetworkCookie cookie(name, value);
++ cookie.setDomain(queryUrl.host());
++ cookie.setPath(queryUrl.path());
++ cookies<<cookie;
++ manager->cookieJar()->insertCookie(cookie);
++ }
++ }
+
+ bool hasError=false;
+ QString errorInfo;
+@@ -147,7 +166,11 @@ QByteArray Network::httpPost(const QString &url, QByteArray &data, const QString
+ QTimer timer;
+ timer.setInterval(timeout);
+ timer.setSingleShot(true);
+- QNetworkReply *reply = getManager()->post(request, data);
++ QNetworkReply *reply = manager->post(request, data);
++ for(auto &cookie:cookies)
++ {
++ manager->cookieJar()->deleteCookie(cookie);
++ }
+ QEventLoop eventLoop;
+ QObject::connect(&timer, &QTimer::timeout, &eventLoop, &QEventLoop::quit);
+ QObject::connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
+diff --git a/Play/Danmu/Provider/acfunprovider.cpp b/Play/Danmu/Provider/acfunprovider.cpp
+index 6c1b371..7053c73 100644
+--- a/Play/Danmu/Provider/acfunprovider.cpp
++++ b/Play/Danmu/Provider/acfunprovider.cpp
+@@ -110,7 +110,7 @@ QString AcfunProvider::downloadDanmu(DanmuSourceItem *item, QList<DanmuComment *
+ try
+ {
+ QString replyStr(Network::httpGet(baseUrl, QUrlQuery()));
+- QRegExp re("\"videoId\":([0-9]+)");
++ QRegExp re("\"(current)?(V|v)ideoId\":([0-9]+)");
+ int pos = re.indexIn(replyStr);
+ if (pos == -1)
+ {
+@@ -119,8 +119,16 @@ QString AcfunProvider::downloadDanmu(DanmuSourceItem *item, QList<DanmuComment *
+ else
+ {
+ QStringList captured = re.capturedTexts();
+- item->id = captured[1].toInt();
++ item->id = captured[3].toInt();
+ downloadAllDanmu(danmuList, item->id);
++ QRegExp reDuration("\"durationMillis\":([0-9]+)");
++ int pos = reDuration.indexIn(replyStr);
++ if (pos != -1)
++ {
++ item->extra=reDuration.capturedTexts()[1].toInt()/1000;
++ }
++
++
+ }
+ }
+ catch (Network::NetworkError &error)
+@@ -308,6 +316,42 @@ void AcfunProvider::downloadAllDanmu(QList<DanmuComment *> &danmuList, int video
+ {
+ try
+ {
++ QString baseUrl="https://www.acfun.cn/rest/pc-direct/new-danmaku/poll";
++ QByteArray data(QString("videoId=%1&lastFetchTime=0").arg(videoId).toUtf8());
++
++ QString replyStr(Network::httpPost(baseUrl,data,{"Cookie","_did=web;"}));
++ QJsonDocument document(Network::toJson(replyStr));
++
++ QJsonArray added_dms(document.object().value("added").toArray());
++ for(auto iter=added_dms.begin();iter!=added_dms.end();++iter)
++ {
++ QJsonObject dmObj=(*iter).toObject();
++ DanmuComment *danmu=new DanmuComment();
++ danmu->text=dmObj.value("body").toString();
++ danmu->time =dmObj.value("position").toInt();
++ danmu->originTime=danmu->time;
++ danmu->color=dmObj.value("color").toInt();
++ danmu->setType(dmObj.value("mode").toInt());
++ danmu->date = 0;
++ danmu->sender="[Acfun]"+QString::number(dmObj.value("userId").toInt());
++ switch (dmObj.value("size").toInt())
++ {
++ case 25:
++ danmu->fontSizeLevel=DanmuComment::Normal;
++ break;
++ case 18:
++ danmu->fontSizeLevel=DanmuComment::Small;
++ break;
++ case 36:
++ danmu->fontSizeLevel=DanmuComment::Large;
++ break;
++ default:
++ danmu->fontSizeLevel=DanmuComment::Normal;
++ }
++ if(danmu->type!=DanmuComment::UNKNOW)danmuList.append(danmu);
++ else delete danmu;
++ }
++ /*
+ int downloadCount=0;
+ QString timeStamp("4073558400000");
+ do
+@@ -350,6 +394,7 @@ void AcfunProvider::downloadAllDanmu(QList<DanmuComment *> &danmuList, int video
+ timeStamp=QString::number(danmuList.last()->date);
+
+ }while(downloadCount>=1000);
++ */
+ }
+ catch(Network::NetworkError &)
+ {
+diff --git a/Play/Danmu/Provider/iqiyiprovider.cpp b/Play/Danmu/Provider/iqiyiprovider.cpp
+index cc1f8f6..c6bc46c 100644
+--- a/Play/Danmu/Provider/iqiyiprovider.cpp
++++ b/Play/Danmu/Provider/iqiyiprovider.cpp
+@@ -69,7 +69,7 @@ QString IqiyiProvider::downloadDanmu(DanmuSourceItem *item, QList<DanmuComment *
+ try
+ {
+ QString replyStr(Network::httpGet(item->strId,QUrlQuery()));
+- QRegExp re("playPageInfo.*(\\{.*\\});");
++ QRegExp re("playPageInfo\\s*=\\s*(\\{.*\\})");
+ re.setMinimal(true);
+ int pos=re.indexIn(replyStr);
+ if(pos==-1)
+@@ -114,56 +114,46 @@ QString IqiyiProvider::downloadBySourceURL(const QString &url, QList<DanmuCommen
+
+ void IqiyiProvider::handleSearchReply(QString &reply, DanmuAccessResult *result)
+ {
+- QRegExp re("(<ul class=\"mod_result_list\">)(.*)(<div class=\"mod-page\")");
++ QRegExp re("<div class=\"layout-main\">(.*)<div class=\"layout-side j-search-aside\">");
+ int pos=re.indexIn(reply);
+ if(pos!=-1)
+ {
+ QStringList list = re.capturedTexts();
+- HTMLParserSax parser(list.at(2));
++ HTMLParserSax parser(list.at(1));
+ DanmuSourceItem item;
+ item.extra=0;
+ bool itemStart=false;
+- bool epStart=false;
+ while(!parser.atEnd())
+ {
+- if(parser.currentNodeProperty("class")=="list_item")
++ if(parser.currentNodeProperty("class")=="qy-search-result-tit")
+ {
+- if(!itemStart)itemStart=true;
+- else
++ do{
++ parser.readNext();
++ }while(parser.currentNodeProperty("class")!="main-tit");
++ if(itemStart)
+ {
+- if (!epStart && !item.title.trimmed().isEmpty())result->list.append(item);
++ result->list.append(item);
+ }
+- epStart=false;
+- item.title=parser.currentNodeProperty("data-widget-searchlist-tvname");
+- }
+- else if(parser.currentNodeProperty("class")=="result_title")
+- {
+- parser.readNext();
+- item.strId=parser.currentNodeProperty("href");
+- }
+- else if(parser.currentNodeProperty("class")=="info_play_btn")
+- {
++ itemStart=true;
++ item.title=parser.currentNodeProperty("title");
+ item.strId=parser.currentNodeProperty("href");
+ }
+- else if(parser.currentNodeProperty("class")=="result_info_txt")
+- {
+- item.description=parser.readContentText();
+- }
+- else if(parser.currentNodeProperty("class")=="result_album clearfix" &&
+- parser.currentNodeProperty("data-tvlist-elem")=="list")
+- {
+- epStart=true;
+- }
+- else if(epStart && parser.currentNodeProperty("class")=="album_link")
++ else if(parser.currentNodeProperty("class")=="qy-search-result-album")
+ {
+- if(!parser.currentNodeProperty("href").isEmpty())
++ while(parser.currentNode()!="ul" || parser.isStartNode())
+ {
+- DanmuSourceItem epItem;
+- epItem.title=item.title + " " + parser.currentNodeProperty("title");
+- epItem.strId=parser.currentNodeProperty("href");
+- epItem.extra=0;
+- result->list.append(epItem);
++ parser.readNext();
++ if(parser.currentNode()=="li" && parser.currentNodeProperty("class")=="album-item")
++ {
++ parser.readNext();
++ DanmuSourceItem epItem;
++ epItem.title=item.title + " " + parser.currentNodeProperty("title");
++ epItem.strId=parser.currentNodeProperty("href");
++ epItem.extra=0;
++ result->list.append(epItem);
++ }
+ }
++ itemStart = false;
+ }
+ parser.readNext();
+ }
+diff --git a/Play/Video/mpv/client.h b/Play/Video/mpv/client.h
+index 39df20a..2e8dcdc 100644
+--- a/Play/Video/mpv/client.h
++++ b/Play/Video/mpv/client.h
+@@ -107,8 +107,11 @@ extern "C" {
+ * careful not accidentally interpret the mpv_event->reply_userdata if an
+ * event is not a reply. (For non-replies, this field is set to 0.)
+ *
+- * Currently, asynchronous calls are always strictly ordered (even with
+- * synchronous calls) for each client, although that may change in the future.
++ * Asynchronous calls may be reordered in arbitrarily with other synchronous
++ * and asynchronous calls. If you want a guaranteed order, you need to wait
++ * until asynchronous calls report completion before doing the next call.
++ *
++ * See also the section "Asynchronous command details" in the manpage.
+ *
+ * Multithreading
+ * --------------
+@@ -164,14 +167,14 @@ extern "C" {
+ * Embedding the video window
+ * --------------------------
+ *
+- * Using the opengl-cb API (in opengl_cb.h) is recommended. This API requires
++ * Using the render API (in render_cb.h) is recommended. This API requires
+ * you to create and maintain an OpenGL context, to which you can render
+ * video using a specific API call. This API does not include keyboard or mouse
+ * input directly.
+ *
+ * There is an older way to embed the native mpv window into your own. You have
+ * to get the raw window handle, and set it as "wid" option. This works on X11,
+- * win32, and OSX only. It's much easier to use than the opengl-cb API, but
++ * win32, and OSX only. It's much easier to use than the render API, but
+ * also has various problems.
+ *
+ * Also see client API examples and the mpv manpage. There is an extensive
+@@ -195,6 +198,20 @@ extern "C" {
+ * or change the underlying datatypes. It might be a good idea to prefer
+ * MPV_FORMAT_STRING over other types to decouple your code from potential
+ * mpv changes.
++ *
++ * Also see: DOCS/compatibility.rst
++ *
++ * Future changes
++ * --------------
++ *
++ * This are the planned changes that will most likely be done on the next major
++ * bump of the library:
++ *
++ * - remove all symbols and include files that are marked as deprecated
++ * - reassign enum numerical values to remove gaps
++ * - remove the mpv_opengl_init_params.extra_exts field
++ * - change the type of mpv_event_end_file.reason
++ * - disabling all events by default
+ */
+
+ /**
+@@ -210,7 +227,7 @@ extern "C" {
+ * relational operators (<, >, <=, >=).
+ */
+ #define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL)
+-#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 102)
++#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 107)
+
+ /**
+ * The API user is allowed to "#define MPV_ENABLE_DEPRECATED 0" before
+@@ -427,12 +444,12 @@ mpv_handle *mpv_create(void);
+
+ /**
+ * Initialize an uninitialized mpv instance. If the mpv instance is already
+- * running, an error is retuned.
++ * running, an error is returned.
+ *
+ * This function needs to be called to make full use of the client API if the
+ * client API handle was created with mpv_create().
+ *
+- * Only the following options require to be set _before_ mpv_initialize():
++ * Only the following options are required to be set _before_ mpv_initialize():
+ * - options which are only read at initialization time:
+ * - config
+ * - config-dir
+@@ -928,10 +945,25 @@ int mpv_command(mpv_handle *ctx, const char **args);
+ *
+ * Does not use OSD and string expansion by default.
+ *
+- * @param[in] args mpv_node with format set to MPV_FORMAT_NODE_ARRAY; each entry
+- * is an argument using an arbitrary format (the format must be
+- * compatible to the used command). Usually, the first item is
+- * the command name (as MPV_FORMAT_STRING).
++ * The args argument can have one of the following formats:
++ *
++ * MPV_FORMAT_NODE_ARRAY:
++ * Positional arguments. Each entry is an argument using an arbitrary
++ * format (the format must be compatible to the used command). Usually,
++ * the first item is the command name (as MPV_FORMAT_STRING). The order
++ * of arguments is as documented in each command description.
++ *
++ * MPV_FORMAT_NODE_MAP:
++ * Named arguments. This requires at least an entry with the key "name"
++ * to be present, which must be a string, and contains the command name.
++ * The special entry "_flags" is optional, and if present, must be an
++ * array of strings, each being a command prefix to apply. All other
++ * entries are interpreted as arguments. They must use the argument names
++ * as documented in each command description. Some commands do not
++ * support named arguments at all, and must use MPV_FORMAT_NODE_ARRAY.
++ *
++ * @param[in] args mpv_node with format set to one of the values documented
++ * above (see there for details)
+ * @param[out] result Optional, pass NULL if unused. If not NULL, and if the
+ * function succeeds, this is set to command-specific return
+ * data. You must call mpv_free_node_contents() to free it
+@@ -941,6 +973,22 @@ int mpv_command(mpv_handle *ctx, const char **args);
+ */
+ int mpv_command_node(mpv_handle *ctx, mpv_node *args, mpv_node *result);
+
++/**
++ * This is essentially identical to mpv_command() but it also returns a result.
++ *
++ * Does not use OSD and string expansion by default.
++ *
++ * @param[in] args NULL-terminated list of strings. Usually, the first item
++ * is the command, and the following items are arguments.
++ * @param[out] result Optional, pass NULL if unused. If not NULL, and if the
++ * function succeeds, this is set to command-specific return
++ * data. You must call mpv_free_node_contents() to free it
++ * (again, only if the command actually succeeds).
++ * Not many commands actually use this at all.
++ * @return error code (the result parameter is not set on error)
++ */
++int mpv_command_ret(mpv_handle *ctx, const char **args, mpv_node *result);
++
+ /**
+ * Same as mpv_command, but use input.conf parsing for splitting arguments.
+ * This is slightly simpler, but also more error prone, since arguments may
+@@ -954,14 +1002,11 @@ int mpv_command_string(mpv_handle *ctx, const char *args);
+ * Same as mpv_command, but run the command asynchronously.
+ *
+ * Commands are executed asynchronously. You will receive a
+- * MPV_EVENT_COMMAND_REPLY event. (This event will also have an
+- * error code set if running the command failed.)
++ * MPV_EVENT_COMMAND_REPLY event. This event will also have an
++ * error code set if running the command failed. For commands that
++ * return data, the data is put into mpv_event_command.result.
+ *
+- * This has nothing to do with the "async" command prefix, although they might
+- * be unified in the future. For now, calling this API means that the command
+- * will be synchronously executed on the core, without blocking the API user.
+- *
+- * * Safe to be called from mpv render API threads.
++ * Safe to be called from mpv render API threads.
+ *
+ * @param reply_userdata the value mpv_event.reply_userdata of the reply will
+ * be set to (see section about asynchronous calls)
+@@ -976,8 +1021,7 @@ int mpv_command_async(mpv_handle *ctx, uint64_t reply_userdata,
+ * function is to mpv_command_node() what mpv_command_async() is to
+ * mpv_command().
+ *
+- * See mpv_command_async() for details. Retrieving the result is not
+- * supported yet.
++ * See mpv_command_async() for details.
+ *
+ * Safe to be called from mpv render API threads.
+ *
+@@ -989,6 +1033,38 @@ int mpv_command_async(mpv_handle *ctx, uint64_t reply_userdata,
+ int mpv_command_node_async(mpv_handle *ctx, uint64_t reply_userdata,
+ mpv_node *args);
+
++/**
++ * Signal to all async requests with the matching ID to abort. This affects
++ * the following API calls:
++ *
++ * mpv_command_async
++ * mpv_command_node_async
++ *
++ * All of these functions take a reply_userdata parameter. This API function
++ * tells all requests with the matching reply_userdata value to try to return
++ * as soon as possible. If there are multiple requests with matching ID, it
++ * aborts all of them.
++ *
++ * This API function is mostly asynchronous itself. It will not wait until the
++ * command is aborted. Instead, the command will terminate as usual, but with
++ * some work not done. How this is signaled depends on the specific command (for
++ * example, the "subprocess" command will indicate it by "killed_by_us" set to
++ * true in the result). How long it takes also depends on the situation. The
++ * aborting process is completely asynchronous.
++ *
++ * Not all commands may support this functionality. In this case, this function
++ * will have no effect. The same is true if the request using the passed
++ * reply_userdata has already terminated, has not been started yet, or was
++ * never in use at all.
++ *
++ * You have to be careful of race conditions: the time during which the abort
++ * request will be effective is _after_ e.g. mpv_command_async() has returned,
++ * and before the command has signaled completion with MPV_EVENT_COMMAND_REPLY.
++ *
++ * @param reply_userdata ID of the request to be aborted (see above)
++ */
++void mpv_abort_async_command(mpv_handle *ctx, uint64_t reply_userdata);
++
+ /**
+ * Set a property to a given value. Properties are essentially variables which
+ * can be queried or set at runtime. For example, writing to the pause property
+@@ -1121,6 +1197,9 @@ int mpv_get_property_async(mpv_handle *ctx, uint64_t reply_userdata,
+ * event queue becomes empty (e.g. mpv_wait_event() would block or return
+ * MPV_EVENT_NONE), and then only one event per changed property is returned.
+ *
++ * You always get an initial change notification. This is meant to initialize
++ * the user's state to the current value of the property.
++ *
+ * Normally, change events are sent only if the property value changes according
+ * to the requested format. mpv_event_property will contain the property value
+ * as data member.
+@@ -1133,7 +1212,7 @@ int mpv_get_property_async(mpv_handle *ctx, uint64_t reply_userdata,
+ * If the property is observed with the format parameter set to MPV_FORMAT_NONE,
+ * you get low-level notifications whether the property _may_ have changed, and
+ * the data member in mpv_event_property will be unset. With this mode, you
+- * will have to determine yourself whether the property really changd. On the
++ * will have to determine yourself whether the property really changed. On the
+ * other hand, this mechanism can be faster and uses less resources.
+ *
+ * Observing a property that doesn't exist is allowed. (Although it may still
+@@ -1202,7 +1281,8 @@ typedef enum mpv_event_id {
+ */
+ MPV_EVENT_SET_PROPERTY_REPLY = 4,
+ /**
+- * Reply to a mpv_command_async() request.
++ * Reply to a mpv_command_async() or mpv_command_node_async() request.
++ * See also mpv_event and mpv_event_command.
+ */
+ MPV_EVENT_COMMAND_REPLY = 5,
+ /**
+@@ -1276,15 +1356,16 @@ typedef enum mpv_event_id {
+ * removed in the far future.
+ */
+ MPV_EVENT_UNPAUSE = 13,
+-#endif
+ /**
+ * Sent every time after a video frame is displayed. Note that currently,
+ * this will be sent in lower frequency if there is no video, or playback
+ * is paused - but that will be removed in the future, and it will be
+ * restricted to video frames only.
++ *
++ * @deprecated Use mpv_observe_property() with relevant properties instead
++ * (such as "playback-time").
+ */
+ MPV_EVENT_TICK = 14,
+-#if MPV_ENABLE_DEPRECATED
+ /**
+ * @deprecated This was used internally with the internal "script_dispatch"
+ * command to dispatch keyboard and mouse input for the OSC.
+@@ -1416,7 +1497,6 @@ typedef struct mpv_event_property {
+ *
+ * Note that this is set to NULL if retrieving the property failed (the
+ * format will be MPV_FORMAT_NONE).
+- * See mpv_event.error for the status.
+ */
+ void *data;
+ } mpv_event_property;
+@@ -1549,6 +1629,17 @@ typedef struct mpv_event_hook {
+ uint64_t id;
+ } mpv_event_hook;
+
++// Since API version 1.102.
++typedef struct mpv_event_command {
++ /**
++ * Result data of the command. Note that success/failure is signaled
++ * separately via mpv_event.error. This field is only for result data
++ * in case of success. Most commands leave it at MPV_FORMAT_NONE. Set
++ * to MPV_FORMAT_NONE on failure.
++ */
++ mpv_node result;
++} mpv_event_command;
++
+ typedef struct mpv_event {
+ /**
+ * One of mpv_event. Keep in mind that later ABI compatible releases might
+@@ -1575,6 +1666,7 @@ typedef struct mpv_event {
+ * MPV_EVENT_SET_PROPERTY_REPLY
+ * MPV_EVENT_COMMAND_REPLY
+ * MPV_EVENT_PROPERTY_CHANGE
++ * MPV_EVENT_HOOK
+ */
+ uint64_t reply_userdata;
+ /**
+@@ -1584,6 +1676,8 @@ typedef struct mpv_event {
+ * MPV_EVENT_LOG_MESSAGE: mpv_event_log_message*
+ * MPV_EVENT_CLIENT_MESSAGE: mpv_event_client_message*
+ * MPV_EVENT_END_FILE: mpv_event_end_file*
++ * MPV_EVENT_HOOK: mpv_event_hook*
++ * MPV_EVENT_COMMAND_REPLY* mpv_event_command*
+ * other: NULL
+ *
+ * Note: future enhancements might add new event structs for existing or new
+diff --git a/Play/Video/mpv/render.h b/Play/Video/mpv/render.h
+index 304a21a..293de3c 100644
+--- a/Play/Video/mpv/render.h
++++ b/Play/Video/mpv/render.h
+@@ -94,6 +94,18 @@ extern "C" {
+ * - if the mpv_handle parameter refers to a different mpv core than the one
+ * you're rendering for (very obscure, but allowed)
+ *
++ * Note about old libmpv version:
++ *
++ * Before API version 1.105 (basically in mpv 0.29.x), simply enabling
++ * MPV_RENDER_PARAM_ADVANCED_CONTROL could cause deadlock issues. This can
++ * be worked around by setting the "vd-lavc-dr" option to "no".
++ * In addition, you were required to call all mpv_render*() API functions
++ * from the same thread on which mpv_render_context_create() was originally
++ * run (for the same the mpv_render_context). Not honoring it led to UB
++ * (deadlocks, use of invalid pthread_t handles), even if you moved your GL
++ * context to a different thread correctly.
++ * These problems were addressed in API version 1.105 (mpv 0.30.0).
++ *
+ * Context and handle lifecycle
+ * ----------------------------
+ *
+@@ -227,6 +239,13 @@ typedef enum mpv_render_param_type {
+ * - Rendering screenshots with the GPU API if supported by the backend
+ * (instead of using a suboptimal software fallback via libswscale).
+ *
++ * Warning: do not just add this without reading the "Threading" section
++ * above, and then wondering that deadlocks happen. The
++ * requirements are tricky. But also note that even if advanced
++ * control is disabled, not adhering to the rules will lead to
++ * playback problems. Enabling advanced controls simply makes
++ * violating these rules fatal.
++ *
+ * Type: int*: 0 for disable (default), 1 for enable
+ */
+ MPV_RENDER_PARAM_ADVANCED_CONTROL = 10,
+@@ -277,8 +296,7 @@ typedef enum mpv_render_param_type {
+ */
+ MPV_RENDER_PARAM_SKIP_RENDERING = 13,
+ /**
+- * DRM display, contains drm display handles.
+- * Valid for mpv_render_context_create().
++ * Deprecated. Not supported. Use MPV_RENDER_PARAM_DRM_DISPLAY_V2 instead.
+ * Type : struct mpv_opengl_drm_params*
+ */
+ MPV_RENDER_PARAM_DRM_DISPLAY = 14,
+@@ -288,6 +306,12 @@ typedef enum mpv_render_param_type {
+ * Type : struct mpv_opengl_drm_draw_surface_size*
+ */
+ MPV_RENDER_PARAM_DRM_DRAW_SURFACE_SIZE = 15,
++ /**
++ * DRM display, contains drm display handles.
++ * Valid for mpv_render_context_create().
++ * Type : struct mpv_opengl_drm_params_v2*
++ */
++ MPV_RENDER_PARAM_DRM_DISPLAY_V2 = 16,
+ } mpv_render_param_type;
+
+ /**
+diff --git a/Play/Video/mpv/render_gl.h b/Play/Video/mpv/render_gl.h
+index 690b126..cb141df 100644
+--- a/Play/Video/mpv/render_gl.h
++++ b/Play/Video/mpv/render_gl.h
+@@ -107,11 +107,13 @@ typedef struct mpv_opengl_init_params {
+ /**
+ * This retrieves OpenGL function pointers, and will use them in subsequent
+ * operation.
+- * Usually, GL context APIs do this for you (e.g. with glXGetProcAddressARB
+- * or wglGetProcAddress), but some APIs do not always return pointers for
+- * all standard functions (even if present); in this case you have to
+- * compensate by looking up these functions yourself and returning them
+- * from this callback.
++ * Usually, you can simply call the GL context APIs from this callback (e.g.
++ * glXGetProcAddressARB or wglGetProcAddress), but some APIs do not always
++ * return pointers for all standard functions (even if present); in this
++ * case you have to compensate by looking up these functions yourself when
++ * libmpv wants to resolve them through this callback.
++ * libmpv will not normally attempt to resolve GL functions on its own, nor
++ * does it link to GL libraries directly.
+ */
+ void *(*get_proc_address)(void *ctx, const char *name);
+ /**
+@@ -147,9 +149,33 @@ typedef struct mpv_opengl_fbo {
+ int internal_format;
+ } mpv_opengl_fbo;
+
++/**
++ * Deprecated. For MPV_RENDER_PARAM_DRM_DISPLAY.
++ */
+ typedef struct mpv_opengl_drm_params {
++ int fd;
++ int crtc_id;
++ int connector_id;
++ struct _drmModeAtomicReq **atomic_request_ptr;
++ int render_fd;
++} mpv_opengl_drm_params;
++
++/**
++ * For MPV_RENDER_PARAM_DRM_DRAW_SURFACE_SIZE.
++ */
++typedef struct mpv_opengl_drm_draw_surface_size {
+ /**
+- * DRM fd (int). Set to a negative number if invalid.
++ * size of the draw plane surface in pixels.
++ */
++ int width, height;
++} mpv_opengl_drm_draw_surface_size;
++
++/**
++ * For MPV_RENDER_PARAM_DRM_DISPLAY_V2.
++ */
++typedef struct mpv_opengl_drm_params_v2 {
++ /**
++ * DRM fd (int). Set to -1 if invalid.
+ */
+ int fd;
+
+@@ -172,17 +198,11 @@ typedef struct mpv_opengl_drm_params {
+
+ /**
+ * DRM render node. Used for VAAPI interop.
+- * Set to a negative number if invalid.
++ * Set to -1 if invalid.
+ */
+ int render_fd;
+-} mpv_opengl_drm_params;
++} mpv_opengl_drm_params_v2;
+
+-typedef struct mpv_opengl_drm_draw_surface_size {
+- /**
+- * size of the draw plane surface in pixels.
+- */
+- int width, height;
+-} mpv_opengl_drm_draw_surface_size;
+
+ /**
+ * For backwards compatibility with the old naming of mpv_opengl_drm_draw_surface_size
+diff --git a/Play/Video/mpv/stream_cb.h b/Play/Video/mpv/stream_cb.h
+index 01de470..63593d7 100644
+--- a/Play/Video/mpv/stream_cb.h
++++ b/Play/Video/mpv/stream_cb.h
+@@ -91,7 +91,7 @@ extern "C" {
+ * Read callback used to implement a custom stream. The semantics of the
+ * callback match read(2) in blocking mode. Short reads are allowed (you can
+ * return less bytes than requested, and libmpv will retry reading the rest
+- * with a nother call). If no data can be immediately read, the callback must
++ * with another call). If no data can be immediately read, the callback must
+ * block until there is new data. A return of 0 will be interpreted as final
+ * EOF, although libmpv might retry the read, or seek to a different position.
+ *
+@@ -112,7 +112,7 @@ typedef int64_t (*mpv_stream_cb_read_fn)(void *cookie, char *buf, uint64_t nbyte
+ * is used to test whether the stream is seekable (since seekability might
+ * depend on the URI contents, not just the protocol). Return
+ * MPV_ERROR_UNSUPPORTED if seeking is not implemented for this stream. This
+- * seek also servies to establish the fact that streams start at position 0.
++ * seek also serves to establish the fact that streams start at position 0.
+ *
+ * This callback can be NULL, in which it behaves as if always returning
+ * MPV_ERROR_UNSUPPORTED.
+@@ -147,6 +147,22 @@ typedef int64_t (*mpv_stream_cb_size_fn)(void *cookie);
+ */
+ typedef void (*mpv_stream_cb_close_fn)(void *cookie);
+
++/**
++ * Cancel callback used to implement a custom stream.
++ *
++ * This callback is used to interrupt any current or future read and seek
++ * operations. It will be called from a separate thread than the demux
++ * thread, and should not block.
++ *
++ * This callback can be NULL.
++ *
++ * Available since API 1.106.
++ *
++ * @param cookie opaque cookie identifying the stream,
++ * returned from mpv_stream_cb_open_fn
++ */
++typedef void (*mpv_stream_cb_cancel_fn)(void *cookie);
++
+ /**
+ * See mpv_stream_cb_open_ro_fn callback.
+ */
+@@ -170,6 +186,7 @@ typedef struct mpv_stream_cb_info {
+ mpv_stream_cb_seek_fn seek_fn;
+ mpv_stream_cb_size_fn size_fn;
+ mpv_stream_cb_close_fn close_fn;
++ mpv_stream_cb_cancel_fn cancel_fn; /* since API 1.106 */
+ } mpv_stream_cb_info;
+
+ /**
+diff --git a/Play/Video/mpvplayer.cpp b/Play/Video/mpvplayer.cpp
+index 0e82958..4be26b4 100644
+--- a/Play/Video/mpvplayer.cpp
++++ b/Play/Video/mpvplayer.cpp
+@@ -4,6 +4,8 @@
+ #include <QOpenGLFramebufferObject>
+ #include <QOpenGLPaintDevice>
+ #include <QCoreApplication>
++#include <QApplication>
++#include <QDesktopWidget>
+ #include <QDebug>
+ #include <QMap>
+ #include <clocale>
+@@ -59,12 +61,36 @@ const char *fShaderDanmu_Old =
+ " gl_FragColor.rgba = texture2D(u_SamplerD, v_vTexCoord).bgra;\n"
+ " gl_FragColor.a *= alpha;\n"
+ "}\n";
++#ifdef Q_OS_WIN
++#pragma comment (lib,"user32.lib")
++#pragma comment (lib,"gdi32.lib")
++static QString get_color_profile(HWND hwnd)
++{
++ HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
++ MONITORINFOEXW mi;
++ mi.cbSize = sizeof mi;
++ GetMonitorInfo(monitor, (MONITORINFO*)&mi);
++ QString name;
++
++ HDC ic = CreateICW(mi.szDevice, nullptr, nullptr, nullptr);
++ if(ic)
++ {
++ wchar_t wname[MAX_PATH + 1];
++ DWORD bufSize(MAX_PATH);
++ if (GetICMProfile(ic, &bufSize, wname))
++ name = QString::fromWCharArray(wname);
++ }
++ if (ic)
++ DeleteDC(ic);
++ return name;
++}
++#endif
+ }
+ MPVPlayer::MPVPlayer(QWidget *parent) : QOpenGLWidget(parent),state(PlayState::Stop),
+ mute(false),danmuHide(false),oldOpenGLVersion(false),currentDuration(0)
+ {
+ std::setlocale(LC_NUMERIC, "C");
+- mpv = mpv::qt::Handle::FromRawHandle(mpv_create());
++ mpv = mpv_create();
+ if (!mpv)
+ throw std::runtime_error("could not create mpv context");
+
+@@ -83,8 +109,12 @@ MPVPlayer::MPVPlayer(QWidget *parent) : QOpenGLWidget(parent),state(PlayState::S
+ QString opt(option.trimmed());
+ if(opt.startsWith('#'))continue;
+ int eqPos=opt.indexOf('=');
+- mpv::qt::set_option_variant(mpv, opt.left(eqPos), opt.mid(eqPos+1));
++ if(eqPos==-1) eqPos = opt.length();
++ QString key(opt.left(eqPos)), val(opt.mid(eqPos+1));
++ mpv::qt::set_option_variant(mpv, key, val);
++ optionsMap.insert(key, val);
+ }
++
+ mpv_set_option_string(mpv, "terminal", "yes");
+ mpv_set_option_string(mpv, "keep-open", "yes");
+ // Make use of the MPV_SUB_API_OPENGL_CB API.
+@@ -96,9 +126,6 @@ MPVPlayer::MPVPlayer(QWidget *parent) : QOpenGLWidget(parent),state(PlayState::S
+ mpv::qt::set_option_variant(mpv,"no-resume-playback","");
+ */
+
+- 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, MPVPlayer::on_update, (void *)this);
+ QObject::connect(this, &MPVPlayer::frameSwapped, this,&MPVPlayer::swapped);
+
+ mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_DOUBLE);
+@@ -116,11 +143,8 @@ MPVPlayer::MPVPlayer(QWidget *parent) : QOpenGLWidget(parent),state(PlayState::S
+ MPVPlayer::~MPVPlayer()
+ {
+ makeCurrent();
+- if (mpv_gl) mpv_opengl_cb_set_update_callback(mpv_gl, nullptr, nullptr);
+- // 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);
++ if (mpv_gl) mpv_render_context_free(mpv_gl);
++ mpv_terminate_destroy(mpv);
+ }
+
+ MPVPlayer::VideoSizeInfo MPVPlayer::getVideoSizeInfo()
+@@ -188,6 +212,24 @@ QMap<QString, QMap<QString, QString> > MPVPlayer::getMediaInfo()
+ return mediaInfo;
+ }
+
++void MPVPlayer::setOptions()
++{
++ if(optionsMap.contains("icc-profile-auto"))
++ {
++#ifdef Q_OS_WIN
++ if(this->parent())
++ {
++ QWidget *pWidget = dynamic_cast<QWidget *>(this->parent());
++ if(pWidget)
++ {
++ QString iccProfile(get_color_profile((HWND)pWidget->winId()));
++ mpv::qt::set_option_variant(mpv, "icc-profile",iccProfile);
++ }
++ }
++#endif
++ }
++}
++
+ void MPVPlayer::drawTexture(QList<const DanmuObject *> &objList, float alpha)
+ {
+ static QVector<GLfloat> vtx(6*2*64),tex(6*2*64),texId(6*64);
+@@ -399,9 +441,20 @@ void MPVPlayer::screenshot(QString filename)
+
+ void MPVPlayer::initializeGL()
+ {
+- int r = mpv_opengl_cb_init_gl(mpv_gl, nullptr, MPVPlayer::get_proc_address, nullptr);
+- if (r < 0)
+- throw std::runtime_error("could not initialize OpenGL");
++ mpv_opengl_init_params gl_init_params{get_proc_address, 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(&mpv_gl, mpv, params) < 0)
++ throw std::runtime_error("failed to initialize mpv GL context");
++ mpv_render_context_set_update_callback(mpv_gl, MPVPlayer::on_update, reinterpret_cast<void *>(this));
++
++ //int r = mpv_opengl_cb_init_gl(mpv_gl, nullptr, MPVPlayer::get_proc_address, nullptr);
++ //if (r < 0)
++ // throw std::runtime_error("could not initialize OpenGL");
+
+ QOpenGLFunctions *glFuns=context()->functions();
+ const char *version = reinterpret_cast<const char*>(glFuns->glGetString(GL_VERSION));
+@@ -434,7 +487,17 @@ void MPVPlayer::initializeGL()
+
+ void MPVPlayer::paintGL()
+ {
+- mpv_opengl_cb_draw(mpv_gl, defaultFramebufferObject(), width(), -height());
++ mpv_opengl_fbo mpfbo{static_cast<int>(defaultFramebufferObject()), width(), height(), 0};
++ int flip_y{1};
++
++ mpv_render_param params[] = {
++ {MPV_RENDER_PARAM_OPENGL_FBO, &mpfbo},
++ {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(mpv_gl, params);
+ if(!danmuHide)
+ {
+ QOpenGLFramebufferObject::bindDefault();
+@@ -448,7 +511,6 @@ void MPVPlayer::paintGL()
+
+ void MPVPlayer::swapped()
+ {
+- mpv_opengl_cb_report_flip(mpv_gl, 0);
+ if(state==PlayState::Play)
+ {
+ float step(0.f);
+diff --git a/Play/Video/mpvplayer.h b/Play/Video/mpvplayer.h
+index 1ccc9f9..e9e4d50 100644
+--- a/Play/Video/mpvplayer.h
++++ b/Play/Video/mpvplayer.h
+@@ -5,7 +5,7 @@
+ #include <QtCore>
+ #include <QtGui>
+ #include <mpv/client.h>
+-#include <mpv/opengl_cb.h>
++#include <mpv/render_gl.h>
+ #include <mpv/qthelper.hpp>
+ #include "Play/Danmu/common.h"
+ class DanmuRender;
+@@ -47,6 +47,7 @@ public:
+
+ VideoSizeInfo getVideoSizeInfo();
+ QMap<QString,QMap<QString,QString> > getMediaInfo();
++ void setOptions();
+ void drawTexture(QList<const DanmuObject *> &objList, float alpha);
+ signals:
+ void fileChanged();
+@@ -86,8 +87,8 @@ private:
+ QStringList desc_str;
+ QList<int> ids;
+ };
+- mpv::qt::Handle mpv;
+- mpv_opengl_cb_context *mpv_gl;
++ mpv_handle *mpv;
++ mpv_render_context *mpv_gl;
+ void handle_mpv_event(mpv_event *event);
+ static void on_update(void *ctx);
+ static void wakeup(void *ctx);
+@@ -103,6 +104,7 @@ private:
+ QOpenGLShaderProgram danmuShader;
+ QTimer refreshTimer;
+ QElapsedTimer elapsedTimer;
++ QMap<QString, QString> optionsMap;
+
+ int currentDuration;
+ TrackInfo audioTrack,subtitleTrack;
+diff --git a/UI/about.cpp b/UI/about.cpp
+index 9fbda30..927baef 100644
+--- a/UI/about.cpp
++++ b/UI/about.cpp
+@@ -13,7 +13,7 @@ About::About(QWidget *parent) : CFramelessDialog("",parent)
+ QJsonObject curVersionObj = QJsonDocument::fromJson(version.readAll()).object();
+ QString versionStr=curVersionObj.value("Version").toString();
+ QLabel *info=new QLabel(tr("KikoPlay - A Full-featured Danmu Player<br/>"
+- "%1 (C) 2019 Kikyou <a href=\"https://protostars.github.io/KikoPlay/\">homepage</a> <a href=\"https://github.com/Protostars/KikoPlay\">github</a><br/>"
++ "%1 (C) 2020 Kikyou <a href=\"https://protostars.github.io/KikoPlay/\">homepage</a> <a href=\"https://github.com/Protostars/KikoPlay\">github</a><br/>"
+ "Exchange & BUG Report: 874761809(QQ Group)").arg(versionStr),this);
+ info->setOpenExternalLinks(true);
+ info->setAlignment(Qt::AlignCenter);
+diff --git a/UI/animedetailinfo.h b/UI/animedetailinfo.h
+index 5bab9b7..206f4e4 100644
+--- a/UI/animedetailinfo.h
++++ b/UI/animedetailinfo.h
+@@ -2,6 +2,7 @@
+ #define ANIMEDETAILINFO_H
+
+ #include "framelessdialog.h"
++#include <QMap>
+ struct Anime;
+ struct Character;
+ class CharacterItem : public QWidget
+diff --git a/UI/captureview.cpp b/UI/captureview.cpp
+index 754c70c..15008ae 100644
+--- a/UI/captureview.cpp
++++ b/UI/captureview.cpp
+@@ -7,6 +7,8 @@
+ #include <QApplication>
+ #include <QClipboard>
+ #include <QFileDialog>
++#include <QMouseEvent>
++#include <QWheelEvent>
+ CaptureView::CaptureView(CaptureListModel *captureModel, int curRow, QWidget *parent) : CFramelessDialog("",parent,false,true,false)
+ {
+ this->curRow=curRow;
+diff --git a/UI/mpvlog.cpp b/UI/mpvlog.cpp
+index 155efa1..fee6590 100644
+--- a/UI/mpvlog.cpp
++++ b/UI/mpvlog.cpp
+@@ -8,7 +8,7 @@ MPVLog::MPVLog(QWidget *parent) : CFramelessDialog(tr("MPV Log"),parent,false,tr
+ {
+ QPlainTextEdit *logView=new QPlainTextEdit(this);
+ logView->setReadOnly(true);
+- logView->setMaximumBlockCount(256);
++ logView->setMaximumBlockCount(1024);
+ QObject::connect(GlobalObjects::mpvplayer,&MPVPlayer::showLog,[logView](const QString &log){
+ logView->appendPlainText(log.trimmed());
+ QTextCursor cursor = logView->textCursor();
+diff --git a/UI/player.cpp b/UI/player.cpp
+index 2de7449..1c029d0 100644
+--- a/UI/player.cpp
++++ b/UI/player.cpp
+@@ -213,6 +213,7 @@ PlayerWindow::PlayerWindow(QWidget *parent) : QMainWindow(parent),autoHideContro
+ setCentralWidget(GlobalObjects::mpvplayer);
+ GlobalObjects::mpvplayer->setMouseTracking(true);
+ setContentsMargins(0,0,0,0);
++ GlobalObjects::mpvplayer->setOptions();
+
+ logDialog=new MPVLog(this);
+
+diff --git a/UI/tip.cpp b/UI/tip.cpp
+index a80b5d5..216490a 100644
+--- a/UI/tip.cpp
++++ b/UI/tip.cpp
+@@ -1,6 +1,7 @@
+ #include "tip.h"
+ #include <QLabel>
+ #include <QVBoxLayout>
++#include <QFile>
+ Tip::Tip(QWidget *parent) : CFramelessDialog (tr("Tip"),parent)
+ {
+ QLabel *tipContent=new QLabel(this);
+diff --git a/kikoplay.rc b/kikoplay.rc
+index 48fc00b..608f9a6 100644
+Binary files a/kikoplay.rc and b/kikoplay.rc differ
+diff --git a/lib/x64/libmpv.dll.lib b/lib/x64/libmpv.dll.lib
+index 503fe77..79ead29 100644
+Binary files a/lib/x64/libmpv.dll.lib and b/lib/x64/libmpv.dll.lib differ
+diff --git a/res/about b/res/about
+index 7166e66..1c596bb 100644
+--- a/res/about
++++ b/res/about
+@@ -1,8 +1,8 @@
+ KikoPlay is based on the following projects:
+ Qt 5.12.3
+-libmpv 0.29.1
++libmpv 0.31.0
+ aria2 1.34
+ Qt-Nice-Frameless-Window
+ zlib 1.2.11
+ QHttpEngine 1.01
+-Lua 5.3
+\ No newline at end of file
++Lua 5.3
diff --git a/media-video/kikoplay/kikoplay-0.6.0.ebuild b/media-video/kikoplay/kikoplay-0.6.0.ebuild
new file mode 100644
index 0000000..17438e0
--- /dev/null
+++ b/media-video/kikoplay/kikoplay-0.6.0.ebuild
@@ -0,0 +1,78 @@
+# Copyright 1999-2020 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI=7
+
+GIT_PN="KikoPlay"
+
+inherit qmake-utils xdg
+
+DESCRIPTION="KikoPlay is a full-featured danmu player"
+HOMEPAGE="
+ https://kikoplay.fun
+ https://github.com/Protostars/KikoPlay
+"
+
+if [[ ${PV} == "9999" ]] ; then
+ inherit git-r3
+ EGIT_REPO_URI="https://github.com/Protostars/${GIT_PN}.git"
+else
+ SRC_URI="https://github.com/Protostars/${GIT_PN}/archive/${PV}.tar.gz -> ${P}.tar.gz"
+ KEYWORDS="~amd64 ~arm ~arm64 ~hppa ~m68k ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
+ S="${WORKDIR}/${GIT_PN}-${PV}"
+fi
+
+LICENSE="GPL-3"
+SLOT="0"
+
+RDEPEND="
+ dev-lang/lua:5.3
+ dev-libs/qhttpengine:5
+ dev-qt/qtconcurrent:5
+ dev-qt/qtcore:5
+ dev-qt/qtgui:5
+ dev-qt/qtnetwork:5
+ dev-qt/qtsql:5
+ dev-qt/qtwidgets:5
+ media-video/mpv[libmpv,-luajit]
+ net-misc/aria2
+"
+
+DEPEND="
+ ${RDEPEND}
+"
+
+BDEPEND="
+ media-gfx/imagemagick
+ virtual/pkgconfig
+"
+
+PATCHES=(
+ "${FILESDIR}"/${PN}-0.6.0-install.patch # Fix install problem
+ "${FILESDIR}"/${PN}-0.6.0-desktop.patch # Add a desktop file
+ "${FILESDIR}"/${PN}-0.6.0-home.patch # Add a desktop file
+)
+
+src_prepare() {
+ default
+ # Fix lua link problem, link to lua5.3 to fix bug
+ sed -i "s/-llua/-llua5.3/" KikoPlay.pro || die "Could not fix lua link"
+ echo "target.path += /usr/bin" >> KikoPlay.pro || die "Could not fix install path"
+ echo "INSTALLS += target icons desktop" >> KikoPlay.pro || die "Could not fix install target"
+ echo "unix:icons.path = /usr/share/pixmaps" >> KikoPlay.pro || die "Could not fix install icon PATH"
+ echo "unix:desktop.path = /usr/share/applications" >> KikoPlay.pro || die "Could not fix install desktop PATH"
+ echo "unix:icons.files = kikoplay.png kikoplay.xpm" >> KikoPlay.pro || die "Could not fix install desktop PATH"
+ echo "unix:desktop.files = kikoplay.desktop" >> KikoPlay.pro || die "Could not fix install desktop PATH"
+ echo "DEFINES += CONFIG_HOME_DATA" >> KikoPlay.pro || die "Could not set defines"
+ convert kikoplay.ico kikoplay.png || die "Could not create PNG icon"
+ convert kikoplay.ico kikoplay.xpm || die "Could not create XPM icon"
+}
+
+src_configure() {
+ eqmake5 PREFIX="${D}"/usr
+}
+
+src_install() {
+ # Can't use default, set INSTALL_ROOT
+ emake INSTALL_ROOT="${D}" install
+}
diff --git a/media-video/kikoplay/metadata.xml b/media-video/kikoplay/metadata.xml
new file mode 100644
index 0000000..514daa8
--- /dev/null
+++ b/media-video/kikoplay/metadata.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <maintainer type="person">
+ <email>vowstar@gmail.com</email>
+ <name>Huang Rui</name>
+ </maintainer>
+ <upstream>
+ <remote-id type="github">Protostars/KikoPlay</remote-id>
+ </upstream>
+ <longdescription>
+ KikoPlay - A Full-Featured Danmu Player.
+ OpenGL rendering, smooth barrage experience. The libmpv playback kernel
+ supports multiple media file formats, retaining flexible parameter settings
+ for mpv.
+ Tree playlist, you can organize your fan play at will.
+ Support all major video sites for barrage search and download:
+ AcFun, Bilibili, Tucao, 5dm, Bahamut, iQiyi, Youku, Tencent Video, PPTV
+ Flexible barrage shielding rule setting, support for automatically merging
+ similar barrage and barrage event analysis annotations to enhance the
+ viewing experience.
+ Support batch management of the barrage pool, support the adjustment of the
+ barrage timeline, and better handle the inconsistency between the local
+ video and the video on the website.
+ The database can record and organize the dramas you have watched, and you
+ can get detailed information from Bangumi LAN service, you can watch it on
+ other devices through the webpage, and now there is an Android side to
+ choose from.
+ Integrated aria2 download function. Daily broadcast function: you can
+ quickly browse the new fan list and add followers.
+ Based on the resource search function of Lua script, you can also write
+ scripts for KikoPlay, script repository.
+ Support automatic downloading, by setting rules, KikoPlay can automatically
+ search for download resources.
+ Unique KikoPlay resource code and barrage pool code, can directly share
+ resource links containing barrage pool information.
+ </longdescription>
+</pkgmetadata>
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [gentoo-commits] repo/proj/guru:master commit in: media-video/kikoplay/files/, media-video/kikoplay/
@ 2020-04-20 9:47 Andrew Ammerlaan
0 siblings, 0 replies; 3+ messages in thread
From: Andrew Ammerlaan @ 2020-04-20 9:47 UTC (permalink / raw
To: gentoo-commits
commit: 86bfe4207d923ab72f8baa642a6e350df3dfcb9f
Author: Huang Rui <vowstar <AT> gmail <DOT> com>
AuthorDate: Sun Apr 19 19:25:55 2020 +0000
Commit: Andrew Ammerlaan <andrewammerlaan <AT> riseup <DOT> net>
CommitDate: Sun Apr 19 19:25:55 2020 +0000
URL: https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=86bfe420
media-video/kikoplay: drop 0.6.0
The patches have been merged to upstream into 0.6.1
Package-Manager: Portage-2.3.99, Repoman-2.3.22
Signed-off-by: Huang Rui <vowstar <AT> gmail.com>
media-video/kikoplay/Manifest | 1 -
.../kikoplay/files/kikoplay-0.6.0-desktop.patch | 16 -
.../kikoplay/files/kikoplay-0.6.0-home.patch | 97 --
.../kikoplay/files/kikoplay-0.6.0-install.patch | 1003 --------------------
media-video/kikoplay/kikoplay-0.6.0.ebuild | 78 --
5 files changed, 1195 deletions(-)
diff --git a/media-video/kikoplay/Manifest b/media-video/kikoplay/Manifest
index e2b9453..c9500fe 100644
--- a/media-video/kikoplay/Manifest
+++ b/media-video/kikoplay/Manifest
@@ -1,2 +1 @@
-DIST kikoplay-0.6.0.tar.gz 7497254 BLAKE2B a23106151782477194d15712e9458171a0bc1dd53f8b6c8dbed12663be1c2c76204674c23eba61f2b8828be7acbd10449f51c766ab57be86cf21844591430b18 SHA512 9d8801f7c9b091f097d1edf9496a389718e81399a8d380d7763c1d12eafd1d4ce444e4df22a0e4a6c8eebbc7f1176e58a3cbac6bea60e87ccd44a5890927bf21
DIST kikoplay-0.6.1.tar.gz 7528741 BLAKE2B 92ec99bc64661688509fe1ec951e90a28cbdd9c06999ba8574d23ffec4628e7ad4e2ac60c955009beb2ea9023e9d18faa35ae9f0b9f63d5a098aa4ad15315bd5 SHA512 4e304c5f1b0592ce5eb4b22745e73f4a9446843002cb8f050433be33137c660ef41b71c7a80055bff86f21381bad5b1be2088b621feb6e86e6575ecf6acc16ed
diff --git a/media-video/kikoplay/files/kikoplay-0.6.0-desktop.patch b/media-video/kikoplay/files/kikoplay-0.6.0-desktop.patch
deleted file mode 100644
index 86b4382..0000000
--- a/media-video/kikoplay/files/kikoplay-0.6.0-desktop.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-diff --git a/kikoplay.desktop b/kikoplay.desktop
-new file mode 100644
-index 0000000..6171559
---- /dev/null
-+++ b/kikoplay.desktop
-@@ -0,0 +1,10 @@
-+[Desktop Entry]
-+Type=Application
-+Name=KikoPlay
-+Comment=KikoPlay is a full-featured danmu player!
-+TryExec=KikoPlay
-+Exec=KikoPlay
-+Icon=/usr/share/pixmaps/kikoplay.png
-+Terminal=false
-+StartupNotify=true
-+Categories=Qt;AudioVideo;Video;
diff --git a/media-video/kikoplay/files/kikoplay-0.6.0-home.patch b/media-video/kikoplay/files/kikoplay-0.6.0-home.patch
deleted file mode 100644
index ec2eae5..0000000
--- a/media-video/kikoplay/files/kikoplay-0.6.0-home.patch
+++ /dev/null
@@ -1,97 +0,0 @@
-diff --git a/Download/Script/scriptmanager.cpp b/Download/Script/scriptmanager.cpp
-index f99c261..8ede8e3 100644
---- a/Download/Script/scriptmanager.cpp
-+++ b/Download/Script/scriptmanager.cpp
-@@ -163,7 +163,11 @@ QString ScriptManager::search(QString sid, const QString &keyword, int page, int
- {
- if(s.id==sid)
- {
-+#ifndef CONFIG_HOME_DATA
- scriptPath=QCoreApplication::applicationDirPath()+"/script/"+s.fileName;
-+#else
-+ scriptPath=QDir::homePath()+"/.config/kikoplay/script/"+s.fileName;
-+#endif
- break;
- }
- }
-@@ -270,7 +274,11 @@ void ScriptManager::removeScript(const QModelIndex &index)
- else
- normalScriptId="";
- }
-+#ifndef CONFIG_HOME_DATA
- QFileInfo fi(QCoreApplication::applicationDirPath()+"/script/"+script.fileName);
-+#else
-+ QFileInfo fi(QDir::homePath()+"/.config/kikoplay/script/"+script.fileName);
-+#endif
- if(fi.exists()) fi.dir().remove(fi.fileName());
- beginRemoveRows(QModelIndex(),index.row(),index.row());
- scriptList.removeAt(index.row());
-@@ -319,7 +327,11 @@ QVariant ScriptManager::headerData(int section, Qt::Orientation orientation, int
-
- void ScriptWorker::refreshScriptList()
- {
-+#ifndef CONFIG_HOME_DATA
- QString scriptPath(QCoreApplication::applicationDirPath()+"/script/");
-+#else
-+ QString scriptPath(QDir::homePath()+"/.config/kikoplay/script/");
-+#endif
- QDir folder(scriptPath);
- QList<ScriptInfo> sList;
- for (QFileInfo fileInfo : folder.entryInfoList())
-diff --git a/Download/aria2jsonrpc.cpp b/Download/aria2jsonrpc.cpp
-index 7999128..43bc63d 100644
---- a/Download/aria2jsonrpc.cpp
-+++ b/Download/aria2jsonrpc.cpp
-@@ -1,4 +1,5 @@
- #include "aria2jsonrpc.h"
-+#include <QFileInfo>
- #include <QNetworkAccessManager>
- #include <QNetworkRequest>
- #include <QNetworkReply>
-@@ -19,7 +20,13 @@ Aria2JsonRPC::Aria2JsonRPC(QObject *parent) : QObject(parent)
- #ifdef Q_OS_WIN
- process->start(QCoreApplication::applicationDirPath()+"\\aria2c.exe", args);
- #else
-- process->start(QCoreApplication::applicationDirPath()+"/aria2c", args);
-+ QFileInfo check_file(QCoreApplication::applicationDirPath()+"/aria2c");
-+ /* check if file exists and if yes: Is it really a file and no directory? */
-+ if (check_file.exists() && check_file.isFile()) {
-+ process->start(QCoreApplication::applicationDirPath()+"/aria2c", args);
-+ } else {
-+ process->start("aria2c", args);
-+ }
-
- #endif
- process->waitForStarted(-1);
-diff --git a/LANServer/httpserver.cpp b/LANServer/httpserver.cpp
-index 5b3fa08..d66a6ee 100644
---- a/LANServer/httpserver.cpp
-+++ b/LANServer/httpserver.cpp
-@@ -127,7 +127,11 @@ namespace
- HttpServer::HttpServer(QObject *parent) : QObject(parent)
- {
- MediaFileHandler *handler=new MediaFileHandler(&mediaHash,this);
-+#ifndef CONFIG_HOME_DATA
- handler->setDocumentRoot(QCoreApplication::applicationDirPath()+"/web");
-+#else
-+ handler->setDocumentRoot(QDir::homePath()+"/.config/kikoplay/web");
-+#endif
- handler->addRedirect(QRegExp("^$"), "/index.html");
-
- QHttpEngine::QObjectHandler *apiHandler=new QHttpEngine::QObjectHandler(this);
-diff --git a/globalobjects.cpp b/globalobjects.cpp
-index 07bf674..32b82a2 100644
---- a/globalobjects.cpp
-+++ b/globalobjects.cpp
-@@ -42,7 +42,11 @@ namespace {
- }
- void GlobalObjects::init()
- {
-+#ifndef CONFIG_HOME_DATA
- dataPath=QCoreApplication::applicationDirPath()+"/data/";
-+#else
-+ dataPath=QDir::homePath()+"/.config/kikoplay/data/";
-+#endif
- QDir dir;
- if(!dir.exists(dataPath))
- {
diff --git a/media-video/kikoplay/files/kikoplay-0.6.0-install.patch b/media-video/kikoplay/files/kikoplay-0.6.0-install.patch
deleted file mode 100644
index 0b90d54..0000000
--- a/media-video/kikoplay/files/kikoplay-0.6.0-install.patch
+++ /dev/null
@@ -1,1003 +0,0 @@
-diff --git a/Common/network.cpp b/Common/network.cpp
-index c9bf952..ec62f69 100644
---- a/Common/network.cpp
-+++ b/Common/network.cpp
-@@ -139,6 +139,25 @@ QByteArray Network::httpPost(const QString &url, QByteArray &data, const QString
- request.setRawHeader(header[i].toUtf8(),header[i+1].toUtf8());
- }
- request.setUrl(queryUrl);
-+ QList<QNetworkCookie> cookies;
-+ QNetworkAccessManager *manager = getManager();
-+ if(request.hasRawHeader("Cookie"))
-+ {
-+ auto cookieBytes = request.rawHeader("Cookie");
-+ auto rawList = cookieBytes.split(';');
-+ for (auto &bytes:rawList)
-+ {
-+ int pos =bytes.indexOf('=');
-+ if(pos<=0) continue;
-+ auto name = bytes.left(pos);
-+ auto value = bytes.mid(pos+1);
-+ QNetworkCookie cookie(name, value);
-+ cookie.setDomain(queryUrl.host());
-+ cookie.setPath(queryUrl.path());
-+ cookies<<cookie;
-+ manager->cookieJar()->insertCookie(cookie);
-+ }
-+ }
-
- bool hasError=false;
- QString errorInfo;
-@@ -147,7 +166,11 @@ QByteArray Network::httpPost(const QString &url, QByteArray &data, const QString
- QTimer timer;
- timer.setInterval(timeout);
- timer.setSingleShot(true);
-- QNetworkReply *reply = getManager()->post(request, data);
-+ QNetworkReply *reply = manager->post(request, data);
-+ for(auto &cookie:cookies)
-+ {
-+ manager->cookieJar()->deleteCookie(cookie);
-+ }
- QEventLoop eventLoop;
- QObject::connect(&timer, &QTimer::timeout, &eventLoop, &QEventLoop::quit);
- QObject::connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
-diff --git a/Play/Danmu/Provider/acfunprovider.cpp b/Play/Danmu/Provider/acfunprovider.cpp
-index 6c1b371..7053c73 100644
---- a/Play/Danmu/Provider/acfunprovider.cpp
-+++ b/Play/Danmu/Provider/acfunprovider.cpp
-@@ -110,7 +110,7 @@ QString AcfunProvider::downloadDanmu(DanmuSourceItem *item, QList<DanmuComment *
- try
- {
- QString replyStr(Network::httpGet(baseUrl, QUrlQuery()));
-- QRegExp re("\"videoId\":([0-9]+)");
-+ QRegExp re("\"(current)?(V|v)ideoId\":([0-9]+)");
- int pos = re.indexIn(replyStr);
- if (pos == -1)
- {
-@@ -119,8 +119,16 @@ QString AcfunProvider::downloadDanmu(DanmuSourceItem *item, QList<DanmuComment *
- else
- {
- QStringList captured = re.capturedTexts();
-- item->id = captured[1].toInt();
-+ item->id = captured[3].toInt();
- downloadAllDanmu(danmuList, item->id);
-+ QRegExp reDuration("\"durationMillis\":([0-9]+)");
-+ int pos = reDuration.indexIn(replyStr);
-+ if (pos != -1)
-+ {
-+ item->extra=reDuration.capturedTexts()[1].toInt()/1000;
-+ }
-+
-+
- }
- }
- catch (Network::NetworkError &error)
-@@ -308,6 +316,42 @@ void AcfunProvider::downloadAllDanmu(QList<DanmuComment *> &danmuList, int video
- {
- try
- {
-+ QString baseUrl="https://www.acfun.cn/rest/pc-direct/new-danmaku/poll";
-+ QByteArray data(QString("videoId=%1&lastFetchTime=0").arg(videoId).toUtf8());
-+
-+ QString replyStr(Network::httpPost(baseUrl,data,{"Cookie","_did=web;"}));
-+ QJsonDocument document(Network::toJson(replyStr));
-+
-+ QJsonArray added_dms(document.object().value("added").toArray());
-+ for(auto iter=added_dms.begin();iter!=added_dms.end();++iter)
-+ {
-+ QJsonObject dmObj=(*iter).toObject();
-+ DanmuComment *danmu=new DanmuComment();
-+ danmu->text=dmObj.value("body").toString();
-+ danmu->time =dmObj.value("position").toInt();
-+ danmu->originTime=danmu->time;
-+ danmu->color=dmObj.value("color").toInt();
-+ danmu->setType(dmObj.value("mode").toInt());
-+ danmu->date = 0;
-+ danmu->sender="[Acfun]"+QString::number(dmObj.value("userId").toInt());
-+ switch (dmObj.value("size").toInt())
-+ {
-+ case 25:
-+ danmu->fontSizeLevel=DanmuComment::Normal;
-+ break;
-+ case 18:
-+ danmu->fontSizeLevel=DanmuComment::Small;
-+ break;
-+ case 36:
-+ danmu->fontSizeLevel=DanmuComment::Large;
-+ break;
-+ default:
-+ danmu->fontSizeLevel=DanmuComment::Normal;
-+ }
-+ if(danmu->type!=DanmuComment::UNKNOW)danmuList.append(danmu);
-+ else delete danmu;
-+ }
-+ /*
- int downloadCount=0;
- QString timeStamp("4073558400000");
- do
-@@ -350,6 +394,7 @@ void AcfunProvider::downloadAllDanmu(QList<DanmuComment *> &danmuList, int video
- timeStamp=QString::number(danmuList.last()->date);
-
- }while(downloadCount>=1000);
-+ */
- }
- catch(Network::NetworkError &)
- {
-diff --git a/Play/Danmu/Provider/iqiyiprovider.cpp b/Play/Danmu/Provider/iqiyiprovider.cpp
-index cc1f8f6..c6bc46c 100644
---- a/Play/Danmu/Provider/iqiyiprovider.cpp
-+++ b/Play/Danmu/Provider/iqiyiprovider.cpp
-@@ -69,7 +69,7 @@ QString IqiyiProvider::downloadDanmu(DanmuSourceItem *item, QList<DanmuComment *
- try
- {
- QString replyStr(Network::httpGet(item->strId,QUrlQuery()));
-- QRegExp re("playPageInfo.*(\\{.*\\});");
-+ QRegExp re("playPageInfo\\s*=\\s*(\\{.*\\})");
- re.setMinimal(true);
- int pos=re.indexIn(replyStr);
- if(pos==-1)
-@@ -114,56 +114,46 @@ QString IqiyiProvider::downloadBySourceURL(const QString &url, QList<DanmuCommen
-
- void IqiyiProvider::handleSearchReply(QString &reply, DanmuAccessResult *result)
- {
-- QRegExp re("(<ul class=\"mod_result_list\">)(.*)(<div class=\"mod-page\")");
-+ QRegExp re("<div class=\"layout-main\">(.*)<div class=\"layout-side j-search-aside\">");
- int pos=re.indexIn(reply);
- if(pos!=-1)
- {
- QStringList list = re.capturedTexts();
-- HTMLParserSax parser(list.at(2));
-+ HTMLParserSax parser(list.at(1));
- DanmuSourceItem item;
- item.extra=0;
- bool itemStart=false;
-- bool epStart=false;
- while(!parser.atEnd())
- {
-- if(parser.currentNodeProperty("class")=="list_item")
-+ if(parser.currentNodeProperty("class")=="qy-search-result-tit")
- {
-- if(!itemStart)itemStart=true;
-- else
-+ do{
-+ parser.readNext();
-+ }while(parser.currentNodeProperty("class")!="main-tit");
-+ if(itemStart)
- {
-- if (!epStart && !item.title.trimmed().isEmpty())result->list.append(item);
-+ result->list.append(item);
- }
-- epStart=false;
-- item.title=parser.currentNodeProperty("data-widget-searchlist-tvname");
-- }
-- else if(parser.currentNodeProperty("class")=="result_title")
-- {
-- parser.readNext();
-- item.strId=parser.currentNodeProperty("href");
-- }
-- else if(parser.currentNodeProperty("class")=="info_play_btn")
-- {
-+ itemStart=true;
-+ item.title=parser.currentNodeProperty("title");
- item.strId=parser.currentNodeProperty("href");
- }
-- else if(parser.currentNodeProperty("class")=="result_info_txt")
-- {
-- item.description=parser.readContentText();
-- }
-- else if(parser.currentNodeProperty("class")=="result_album clearfix" &&
-- parser.currentNodeProperty("data-tvlist-elem")=="list")
-- {
-- epStart=true;
-- }
-- else if(epStart && parser.currentNodeProperty("class")=="album_link")
-+ else if(parser.currentNodeProperty("class")=="qy-search-result-album")
- {
-- if(!parser.currentNodeProperty("href").isEmpty())
-+ while(parser.currentNode()!="ul" || parser.isStartNode())
- {
-- DanmuSourceItem epItem;
-- epItem.title=item.title + " " + parser.currentNodeProperty("title");
-- epItem.strId=parser.currentNodeProperty("href");
-- epItem.extra=0;
-- result->list.append(epItem);
-+ parser.readNext();
-+ if(parser.currentNode()=="li" && parser.currentNodeProperty("class")=="album-item")
-+ {
-+ parser.readNext();
-+ DanmuSourceItem epItem;
-+ epItem.title=item.title + " " + parser.currentNodeProperty("title");
-+ epItem.strId=parser.currentNodeProperty("href");
-+ epItem.extra=0;
-+ result->list.append(epItem);
-+ }
- }
-+ itemStart = false;
- }
- parser.readNext();
- }
-diff --git a/Play/Video/mpv/client.h b/Play/Video/mpv/client.h
-index 39df20a..2e8dcdc 100644
---- a/Play/Video/mpv/client.h
-+++ b/Play/Video/mpv/client.h
-@@ -107,8 +107,11 @@ extern "C" {
- * careful not accidentally interpret the mpv_event->reply_userdata if an
- * event is not a reply. (For non-replies, this field is set to 0.)
- *
-- * Currently, asynchronous calls are always strictly ordered (even with
-- * synchronous calls) for each client, although that may change in the future.
-+ * Asynchronous calls may be reordered in arbitrarily with other synchronous
-+ * and asynchronous calls. If you want a guaranteed order, you need to wait
-+ * until asynchronous calls report completion before doing the next call.
-+ *
-+ * See also the section "Asynchronous command details" in the manpage.
- *
- * Multithreading
- * --------------
-@@ -164,14 +167,14 @@ extern "C" {
- * Embedding the video window
- * --------------------------
- *
-- * Using the opengl-cb API (in opengl_cb.h) is recommended. This API requires
-+ * Using the render API (in render_cb.h) is recommended. This API requires
- * you to create and maintain an OpenGL context, to which you can render
- * video using a specific API call. This API does not include keyboard or mouse
- * input directly.
- *
- * There is an older way to embed the native mpv window into your own. You have
- * to get the raw window handle, and set it as "wid" option. This works on X11,
-- * win32, and OSX only. It's much easier to use than the opengl-cb API, but
-+ * win32, and OSX only. It's much easier to use than the render API, but
- * also has various problems.
- *
- * Also see client API examples and the mpv manpage. There is an extensive
-@@ -195,6 +198,20 @@ extern "C" {
- * or change the underlying datatypes. It might be a good idea to prefer
- * MPV_FORMAT_STRING over other types to decouple your code from potential
- * mpv changes.
-+ *
-+ * Also see: DOCS/compatibility.rst
-+ *
-+ * Future changes
-+ * --------------
-+ *
-+ * This are the planned changes that will most likely be done on the next major
-+ * bump of the library:
-+ *
-+ * - remove all symbols and include files that are marked as deprecated
-+ * - reassign enum numerical values to remove gaps
-+ * - remove the mpv_opengl_init_params.extra_exts field
-+ * - change the type of mpv_event_end_file.reason
-+ * - disabling all events by default
- */
-
- /**
-@@ -210,7 +227,7 @@ extern "C" {
- * relational operators (<, >, <=, >=).
- */
- #define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL)
--#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 102)
-+#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 107)
-
- /**
- * The API user is allowed to "#define MPV_ENABLE_DEPRECATED 0" before
-@@ -427,12 +444,12 @@ mpv_handle *mpv_create(void);
-
- /**
- * Initialize an uninitialized mpv instance. If the mpv instance is already
-- * running, an error is retuned.
-+ * running, an error is returned.
- *
- * This function needs to be called to make full use of the client API if the
- * client API handle was created with mpv_create().
- *
-- * Only the following options require to be set _before_ mpv_initialize():
-+ * Only the following options are required to be set _before_ mpv_initialize():
- * - options which are only read at initialization time:
- * - config
- * - config-dir
-@@ -928,10 +945,25 @@ int mpv_command(mpv_handle *ctx, const char **args);
- *
- * Does not use OSD and string expansion by default.
- *
-- * @param[in] args mpv_node with format set to MPV_FORMAT_NODE_ARRAY; each entry
-- * is an argument using an arbitrary format (the format must be
-- * compatible to the used command). Usually, the first item is
-- * the command name (as MPV_FORMAT_STRING).
-+ * The args argument can have one of the following formats:
-+ *
-+ * MPV_FORMAT_NODE_ARRAY:
-+ * Positional arguments. Each entry is an argument using an arbitrary
-+ * format (the format must be compatible to the used command). Usually,
-+ * the first item is the command name (as MPV_FORMAT_STRING). The order
-+ * of arguments is as documented in each command description.
-+ *
-+ * MPV_FORMAT_NODE_MAP:
-+ * Named arguments. This requires at least an entry with the key "name"
-+ * to be present, which must be a string, and contains the command name.
-+ * The special entry "_flags" is optional, and if present, must be an
-+ * array of strings, each being a command prefix to apply. All other
-+ * entries are interpreted as arguments. They must use the argument names
-+ * as documented in each command description. Some commands do not
-+ * support named arguments at all, and must use MPV_FORMAT_NODE_ARRAY.
-+ *
-+ * @param[in] args mpv_node with format set to one of the values documented
-+ * above (see there for details)
- * @param[out] result Optional, pass NULL if unused. If not NULL, and if the
- * function succeeds, this is set to command-specific return
- * data. You must call mpv_free_node_contents() to free it
-@@ -941,6 +973,22 @@ int mpv_command(mpv_handle *ctx, const char **args);
- */
- int mpv_command_node(mpv_handle *ctx, mpv_node *args, mpv_node *result);
-
-+/**
-+ * This is essentially identical to mpv_command() but it also returns a result.
-+ *
-+ * Does not use OSD and string expansion by default.
-+ *
-+ * @param[in] args NULL-terminated list of strings. Usually, the first item
-+ * is the command, and the following items are arguments.
-+ * @param[out] result Optional, pass NULL if unused. If not NULL, and if the
-+ * function succeeds, this is set to command-specific return
-+ * data. You must call mpv_free_node_contents() to free it
-+ * (again, only if the command actually succeeds).
-+ * Not many commands actually use this at all.
-+ * @return error code (the result parameter is not set on error)
-+ */
-+int mpv_command_ret(mpv_handle *ctx, const char **args, mpv_node *result);
-+
- /**
- * Same as mpv_command, but use input.conf parsing for splitting arguments.
- * This is slightly simpler, but also more error prone, since arguments may
-@@ -954,14 +1002,11 @@ int mpv_command_string(mpv_handle *ctx, const char *args);
- * Same as mpv_command, but run the command asynchronously.
- *
- * Commands are executed asynchronously. You will receive a
-- * MPV_EVENT_COMMAND_REPLY event. (This event will also have an
-- * error code set if running the command failed.)
-+ * MPV_EVENT_COMMAND_REPLY event. This event will also have an
-+ * error code set if running the command failed. For commands that
-+ * return data, the data is put into mpv_event_command.result.
- *
-- * This has nothing to do with the "async" command prefix, although they might
-- * be unified in the future. For now, calling this API means that the command
-- * will be synchronously executed on the core, without blocking the API user.
-- *
-- * * Safe to be called from mpv render API threads.
-+ * Safe to be called from mpv render API threads.
- *
- * @param reply_userdata the value mpv_event.reply_userdata of the reply will
- * be set to (see section about asynchronous calls)
-@@ -976,8 +1021,7 @@ int mpv_command_async(mpv_handle *ctx, uint64_t reply_userdata,
- * function is to mpv_command_node() what mpv_command_async() is to
- * mpv_command().
- *
-- * See mpv_command_async() for details. Retrieving the result is not
-- * supported yet.
-+ * See mpv_command_async() for details.
- *
- * Safe to be called from mpv render API threads.
- *
-@@ -989,6 +1033,38 @@ int mpv_command_async(mpv_handle *ctx, uint64_t reply_userdata,
- int mpv_command_node_async(mpv_handle *ctx, uint64_t reply_userdata,
- mpv_node *args);
-
-+/**
-+ * Signal to all async requests with the matching ID to abort. This affects
-+ * the following API calls:
-+ *
-+ * mpv_command_async
-+ * mpv_command_node_async
-+ *
-+ * All of these functions take a reply_userdata parameter. This API function
-+ * tells all requests with the matching reply_userdata value to try to return
-+ * as soon as possible. If there are multiple requests with matching ID, it
-+ * aborts all of them.
-+ *
-+ * This API function is mostly asynchronous itself. It will not wait until the
-+ * command is aborted. Instead, the command will terminate as usual, but with
-+ * some work not done. How this is signaled depends on the specific command (for
-+ * example, the "subprocess" command will indicate it by "killed_by_us" set to
-+ * true in the result). How long it takes also depends on the situation. The
-+ * aborting process is completely asynchronous.
-+ *
-+ * Not all commands may support this functionality. In this case, this function
-+ * will have no effect. The same is true if the request using the passed
-+ * reply_userdata has already terminated, has not been started yet, or was
-+ * never in use at all.
-+ *
-+ * You have to be careful of race conditions: the time during which the abort
-+ * request will be effective is _after_ e.g. mpv_command_async() has returned,
-+ * and before the command has signaled completion with MPV_EVENT_COMMAND_REPLY.
-+ *
-+ * @param reply_userdata ID of the request to be aborted (see above)
-+ */
-+void mpv_abort_async_command(mpv_handle *ctx, uint64_t reply_userdata);
-+
- /**
- * Set a property to a given value. Properties are essentially variables which
- * can be queried or set at runtime. For example, writing to the pause property
-@@ -1121,6 +1197,9 @@ int mpv_get_property_async(mpv_handle *ctx, uint64_t reply_userdata,
- * event queue becomes empty (e.g. mpv_wait_event() would block or return
- * MPV_EVENT_NONE), and then only one event per changed property is returned.
- *
-+ * You always get an initial change notification. This is meant to initialize
-+ * the user's state to the current value of the property.
-+ *
- * Normally, change events are sent only if the property value changes according
- * to the requested format. mpv_event_property will contain the property value
- * as data member.
-@@ -1133,7 +1212,7 @@ int mpv_get_property_async(mpv_handle *ctx, uint64_t reply_userdata,
- * If the property is observed with the format parameter set to MPV_FORMAT_NONE,
- * you get low-level notifications whether the property _may_ have changed, and
- * the data member in mpv_event_property will be unset. With this mode, you
-- * will have to determine yourself whether the property really changd. On the
-+ * will have to determine yourself whether the property really changed. On the
- * other hand, this mechanism can be faster and uses less resources.
- *
- * Observing a property that doesn't exist is allowed. (Although it may still
-@@ -1202,7 +1281,8 @@ typedef enum mpv_event_id {
- */
- MPV_EVENT_SET_PROPERTY_REPLY = 4,
- /**
-- * Reply to a mpv_command_async() request.
-+ * Reply to a mpv_command_async() or mpv_command_node_async() request.
-+ * See also mpv_event and mpv_event_command.
- */
- MPV_EVENT_COMMAND_REPLY = 5,
- /**
-@@ -1276,15 +1356,16 @@ typedef enum mpv_event_id {
- * removed in the far future.
- */
- MPV_EVENT_UNPAUSE = 13,
--#endif
- /**
- * Sent every time after a video frame is displayed. Note that currently,
- * this will be sent in lower frequency if there is no video, or playback
- * is paused - but that will be removed in the future, and it will be
- * restricted to video frames only.
-+ *
-+ * @deprecated Use mpv_observe_property() with relevant properties instead
-+ * (such as "playback-time").
- */
- MPV_EVENT_TICK = 14,
--#if MPV_ENABLE_DEPRECATED
- /**
- * @deprecated This was used internally with the internal "script_dispatch"
- * command to dispatch keyboard and mouse input for the OSC.
-@@ -1416,7 +1497,6 @@ typedef struct mpv_event_property {
- *
- * Note that this is set to NULL if retrieving the property failed (the
- * format will be MPV_FORMAT_NONE).
-- * See mpv_event.error for the status.
- */
- void *data;
- } mpv_event_property;
-@@ -1549,6 +1629,17 @@ typedef struct mpv_event_hook {
- uint64_t id;
- } mpv_event_hook;
-
-+// Since API version 1.102.
-+typedef struct mpv_event_command {
-+ /**
-+ * Result data of the command. Note that success/failure is signaled
-+ * separately via mpv_event.error. This field is only for result data
-+ * in case of success. Most commands leave it at MPV_FORMAT_NONE. Set
-+ * to MPV_FORMAT_NONE on failure.
-+ */
-+ mpv_node result;
-+} mpv_event_command;
-+
- typedef struct mpv_event {
- /**
- * One of mpv_event. Keep in mind that later ABI compatible releases might
-@@ -1575,6 +1666,7 @@ typedef struct mpv_event {
- * MPV_EVENT_SET_PROPERTY_REPLY
- * MPV_EVENT_COMMAND_REPLY
- * MPV_EVENT_PROPERTY_CHANGE
-+ * MPV_EVENT_HOOK
- */
- uint64_t reply_userdata;
- /**
-@@ -1584,6 +1676,8 @@ typedef struct mpv_event {
- * MPV_EVENT_LOG_MESSAGE: mpv_event_log_message*
- * MPV_EVENT_CLIENT_MESSAGE: mpv_event_client_message*
- * MPV_EVENT_END_FILE: mpv_event_end_file*
-+ * MPV_EVENT_HOOK: mpv_event_hook*
-+ * MPV_EVENT_COMMAND_REPLY* mpv_event_command*
- * other: NULL
- *
- * Note: future enhancements might add new event structs for existing or new
-diff --git a/Play/Video/mpv/render.h b/Play/Video/mpv/render.h
-index 304a21a..293de3c 100644
---- a/Play/Video/mpv/render.h
-+++ b/Play/Video/mpv/render.h
-@@ -94,6 +94,18 @@ extern "C" {
- * - if the mpv_handle parameter refers to a different mpv core than the one
- * you're rendering for (very obscure, but allowed)
- *
-+ * Note about old libmpv version:
-+ *
-+ * Before API version 1.105 (basically in mpv 0.29.x), simply enabling
-+ * MPV_RENDER_PARAM_ADVANCED_CONTROL could cause deadlock issues. This can
-+ * be worked around by setting the "vd-lavc-dr" option to "no".
-+ * In addition, you were required to call all mpv_render*() API functions
-+ * from the same thread on which mpv_render_context_create() was originally
-+ * run (for the same the mpv_render_context). Not honoring it led to UB
-+ * (deadlocks, use of invalid pthread_t handles), even if you moved your GL
-+ * context to a different thread correctly.
-+ * These problems were addressed in API version 1.105 (mpv 0.30.0).
-+ *
- * Context and handle lifecycle
- * ----------------------------
- *
-@@ -227,6 +239,13 @@ typedef enum mpv_render_param_type {
- * - Rendering screenshots with the GPU API if supported by the backend
- * (instead of using a suboptimal software fallback via libswscale).
- *
-+ * Warning: do not just add this without reading the "Threading" section
-+ * above, and then wondering that deadlocks happen. The
-+ * requirements are tricky. But also note that even if advanced
-+ * control is disabled, not adhering to the rules will lead to
-+ * playback problems. Enabling advanced controls simply makes
-+ * violating these rules fatal.
-+ *
- * Type: int*: 0 for disable (default), 1 for enable
- */
- MPV_RENDER_PARAM_ADVANCED_CONTROL = 10,
-@@ -277,8 +296,7 @@ typedef enum mpv_render_param_type {
- */
- MPV_RENDER_PARAM_SKIP_RENDERING = 13,
- /**
-- * DRM display, contains drm display handles.
-- * Valid for mpv_render_context_create().
-+ * Deprecated. Not supported. Use MPV_RENDER_PARAM_DRM_DISPLAY_V2 instead.
- * Type : struct mpv_opengl_drm_params*
- */
- MPV_RENDER_PARAM_DRM_DISPLAY = 14,
-@@ -288,6 +306,12 @@ typedef enum mpv_render_param_type {
- * Type : struct mpv_opengl_drm_draw_surface_size*
- */
- MPV_RENDER_PARAM_DRM_DRAW_SURFACE_SIZE = 15,
-+ /**
-+ * DRM display, contains drm display handles.
-+ * Valid for mpv_render_context_create().
-+ * Type : struct mpv_opengl_drm_params_v2*
-+ */
-+ MPV_RENDER_PARAM_DRM_DISPLAY_V2 = 16,
- } mpv_render_param_type;
-
- /**
-diff --git a/Play/Video/mpv/render_gl.h b/Play/Video/mpv/render_gl.h
-index 690b126..cb141df 100644
---- a/Play/Video/mpv/render_gl.h
-+++ b/Play/Video/mpv/render_gl.h
-@@ -107,11 +107,13 @@ typedef struct mpv_opengl_init_params {
- /**
- * This retrieves OpenGL function pointers, and will use them in subsequent
- * operation.
-- * Usually, GL context APIs do this for you (e.g. with glXGetProcAddressARB
-- * or wglGetProcAddress), but some APIs do not always return pointers for
-- * all standard functions (even if present); in this case you have to
-- * compensate by looking up these functions yourself and returning them
-- * from this callback.
-+ * Usually, you can simply call the GL context APIs from this callback (e.g.
-+ * glXGetProcAddressARB or wglGetProcAddress), but some APIs do not always
-+ * return pointers for all standard functions (even if present); in this
-+ * case you have to compensate by looking up these functions yourself when
-+ * libmpv wants to resolve them through this callback.
-+ * libmpv will not normally attempt to resolve GL functions on its own, nor
-+ * does it link to GL libraries directly.
- */
- void *(*get_proc_address)(void *ctx, const char *name);
- /**
-@@ -147,9 +149,33 @@ typedef struct mpv_opengl_fbo {
- int internal_format;
- } mpv_opengl_fbo;
-
-+/**
-+ * Deprecated. For MPV_RENDER_PARAM_DRM_DISPLAY.
-+ */
- typedef struct mpv_opengl_drm_params {
-+ int fd;
-+ int crtc_id;
-+ int connector_id;
-+ struct _drmModeAtomicReq **atomic_request_ptr;
-+ int render_fd;
-+} mpv_opengl_drm_params;
-+
-+/**
-+ * For MPV_RENDER_PARAM_DRM_DRAW_SURFACE_SIZE.
-+ */
-+typedef struct mpv_opengl_drm_draw_surface_size {
- /**
-- * DRM fd (int). Set to a negative number if invalid.
-+ * size of the draw plane surface in pixels.
-+ */
-+ int width, height;
-+} mpv_opengl_drm_draw_surface_size;
-+
-+/**
-+ * For MPV_RENDER_PARAM_DRM_DISPLAY_V2.
-+ */
-+typedef struct mpv_opengl_drm_params_v2 {
-+ /**
-+ * DRM fd (int). Set to -1 if invalid.
- */
- int fd;
-
-@@ -172,17 +198,11 @@ typedef struct mpv_opengl_drm_params {
-
- /**
- * DRM render node. Used for VAAPI interop.
-- * Set to a negative number if invalid.
-+ * Set to -1 if invalid.
- */
- int render_fd;
--} mpv_opengl_drm_params;
-+} mpv_opengl_drm_params_v2;
-
--typedef struct mpv_opengl_drm_draw_surface_size {
-- /**
-- * size of the draw plane surface in pixels.
-- */
-- int width, height;
--} mpv_opengl_drm_draw_surface_size;
-
- /**
- * For backwards compatibility with the old naming of mpv_opengl_drm_draw_surface_size
-diff --git a/Play/Video/mpv/stream_cb.h b/Play/Video/mpv/stream_cb.h
-index 01de470..63593d7 100644
---- a/Play/Video/mpv/stream_cb.h
-+++ b/Play/Video/mpv/stream_cb.h
-@@ -91,7 +91,7 @@ extern "C" {
- * Read callback used to implement a custom stream. The semantics of the
- * callback match read(2) in blocking mode. Short reads are allowed (you can
- * return less bytes than requested, and libmpv will retry reading the rest
-- * with a nother call). If no data can be immediately read, the callback must
-+ * with another call). If no data can be immediately read, the callback must
- * block until there is new data. A return of 0 will be interpreted as final
- * EOF, although libmpv might retry the read, or seek to a different position.
- *
-@@ -112,7 +112,7 @@ typedef int64_t (*mpv_stream_cb_read_fn)(void *cookie, char *buf, uint64_t nbyte
- * is used to test whether the stream is seekable (since seekability might
- * depend on the URI contents, not just the protocol). Return
- * MPV_ERROR_UNSUPPORTED if seeking is not implemented for this stream. This
-- * seek also servies to establish the fact that streams start at position 0.
-+ * seek also serves to establish the fact that streams start at position 0.
- *
- * This callback can be NULL, in which it behaves as if always returning
- * MPV_ERROR_UNSUPPORTED.
-@@ -147,6 +147,22 @@ typedef int64_t (*mpv_stream_cb_size_fn)(void *cookie);
- */
- typedef void (*mpv_stream_cb_close_fn)(void *cookie);
-
-+/**
-+ * Cancel callback used to implement a custom stream.
-+ *
-+ * This callback is used to interrupt any current or future read and seek
-+ * operations. It will be called from a separate thread than the demux
-+ * thread, and should not block.
-+ *
-+ * This callback can be NULL.
-+ *
-+ * Available since API 1.106.
-+ *
-+ * @param cookie opaque cookie identifying the stream,
-+ * returned from mpv_stream_cb_open_fn
-+ */
-+typedef void (*mpv_stream_cb_cancel_fn)(void *cookie);
-+
- /**
- * See mpv_stream_cb_open_ro_fn callback.
- */
-@@ -170,6 +186,7 @@ typedef struct mpv_stream_cb_info {
- mpv_stream_cb_seek_fn seek_fn;
- mpv_stream_cb_size_fn size_fn;
- mpv_stream_cb_close_fn close_fn;
-+ mpv_stream_cb_cancel_fn cancel_fn; /* since API 1.106 */
- } mpv_stream_cb_info;
-
- /**
-diff --git a/Play/Video/mpvplayer.cpp b/Play/Video/mpvplayer.cpp
-index 0e82958..4be26b4 100644
---- a/Play/Video/mpvplayer.cpp
-+++ b/Play/Video/mpvplayer.cpp
-@@ -4,6 +4,8 @@
- #include <QOpenGLFramebufferObject>
- #include <QOpenGLPaintDevice>
- #include <QCoreApplication>
-+#include <QApplication>
-+#include <QDesktopWidget>
- #include <QDebug>
- #include <QMap>
- #include <clocale>
-@@ -59,12 +61,36 @@ const char *fShaderDanmu_Old =
- " gl_FragColor.rgba = texture2D(u_SamplerD, v_vTexCoord).bgra;\n"
- " gl_FragColor.a *= alpha;\n"
- "}\n";
-+#ifdef Q_OS_WIN
-+#pragma comment (lib,"user32.lib")
-+#pragma comment (lib,"gdi32.lib")
-+static QString get_color_profile(HWND hwnd)
-+{
-+ HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
-+ MONITORINFOEXW mi;
-+ mi.cbSize = sizeof mi;
-+ GetMonitorInfo(monitor, (MONITORINFO*)&mi);
-+ QString name;
-+
-+ HDC ic = CreateICW(mi.szDevice, nullptr, nullptr, nullptr);
-+ if(ic)
-+ {
-+ wchar_t wname[MAX_PATH + 1];
-+ DWORD bufSize(MAX_PATH);
-+ if (GetICMProfile(ic, &bufSize, wname))
-+ name = QString::fromWCharArray(wname);
-+ }
-+ if (ic)
-+ DeleteDC(ic);
-+ return name;
-+}
-+#endif
- }
- MPVPlayer::MPVPlayer(QWidget *parent) : QOpenGLWidget(parent),state(PlayState::Stop),
- mute(false),danmuHide(false),oldOpenGLVersion(false),currentDuration(0)
- {
- std::setlocale(LC_NUMERIC, "C");
-- mpv = mpv::qt::Handle::FromRawHandle(mpv_create());
-+ mpv = mpv_create();
- if (!mpv)
- throw std::runtime_error("could not create mpv context");
-
-@@ -83,8 +109,12 @@ MPVPlayer::MPVPlayer(QWidget *parent) : QOpenGLWidget(parent),state(PlayState::S
- QString opt(option.trimmed());
- if(opt.startsWith('#'))continue;
- int eqPos=opt.indexOf('=');
-- mpv::qt::set_option_variant(mpv, opt.left(eqPos), opt.mid(eqPos+1));
-+ if(eqPos==-1) eqPos = opt.length();
-+ QString key(opt.left(eqPos)), val(opt.mid(eqPos+1));
-+ mpv::qt::set_option_variant(mpv, key, val);
-+ optionsMap.insert(key, val);
- }
-+
- mpv_set_option_string(mpv, "terminal", "yes");
- mpv_set_option_string(mpv, "keep-open", "yes");
- // Make use of the MPV_SUB_API_OPENGL_CB API.
-@@ -96,9 +126,6 @@ MPVPlayer::MPVPlayer(QWidget *parent) : QOpenGLWidget(parent),state(PlayState::S
- mpv::qt::set_option_variant(mpv,"no-resume-playback","");
- */
-
-- 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, MPVPlayer::on_update, (void *)this);
- QObject::connect(this, &MPVPlayer::frameSwapped, this,&MPVPlayer::swapped);
-
- mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_DOUBLE);
-@@ -116,11 +143,8 @@ MPVPlayer::MPVPlayer(QWidget *parent) : QOpenGLWidget(parent),state(PlayState::S
- MPVPlayer::~MPVPlayer()
- {
- makeCurrent();
-- if (mpv_gl) mpv_opengl_cb_set_update_callback(mpv_gl, nullptr, nullptr);
-- // 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);
-+ if (mpv_gl) mpv_render_context_free(mpv_gl);
-+ mpv_terminate_destroy(mpv);
- }
-
- MPVPlayer::VideoSizeInfo MPVPlayer::getVideoSizeInfo()
-@@ -188,6 +212,24 @@ QMap<QString, QMap<QString, QString> > MPVPlayer::getMediaInfo()
- return mediaInfo;
- }
-
-+void MPVPlayer::setOptions()
-+{
-+ if(optionsMap.contains("icc-profile-auto"))
-+ {
-+#ifdef Q_OS_WIN
-+ if(this->parent())
-+ {
-+ QWidget *pWidget = dynamic_cast<QWidget *>(this->parent());
-+ if(pWidget)
-+ {
-+ QString iccProfile(get_color_profile((HWND)pWidget->winId()));
-+ mpv::qt::set_option_variant(mpv, "icc-profile",iccProfile);
-+ }
-+ }
-+#endif
-+ }
-+}
-+
- void MPVPlayer::drawTexture(QList<const DanmuObject *> &objList, float alpha)
- {
- static QVector<GLfloat> vtx(6*2*64),tex(6*2*64),texId(6*64);
-@@ -399,9 +441,20 @@ void MPVPlayer::screenshot(QString filename)
-
- void MPVPlayer::initializeGL()
- {
-- int r = mpv_opengl_cb_init_gl(mpv_gl, nullptr, MPVPlayer::get_proc_address, nullptr);
-- if (r < 0)
-- throw std::runtime_error("could not initialize OpenGL");
-+ mpv_opengl_init_params gl_init_params{get_proc_address, 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(&mpv_gl, mpv, params) < 0)
-+ throw std::runtime_error("failed to initialize mpv GL context");
-+ mpv_render_context_set_update_callback(mpv_gl, MPVPlayer::on_update, reinterpret_cast<void *>(this));
-+
-+ //int r = mpv_opengl_cb_init_gl(mpv_gl, nullptr, MPVPlayer::get_proc_address, nullptr);
-+ //if (r < 0)
-+ // throw std::runtime_error("could not initialize OpenGL");
-
- QOpenGLFunctions *glFuns=context()->functions();
- const char *version = reinterpret_cast<const char*>(glFuns->glGetString(GL_VERSION));
-@@ -434,7 +487,17 @@ void MPVPlayer::initializeGL()
-
- void MPVPlayer::paintGL()
- {
-- mpv_opengl_cb_draw(mpv_gl, defaultFramebufferObject(), width(), -height());
-+ mpv_opengl_fbo mpfbo{static_cast<int>(defaultFramebufferObject()), width(), height(), 0};
-+ int flip_y{1};
-+
-+ mpv_render_param params[] = {
-+ {MPV_RENDER_PARAM_OPENGL_FBO, &mpfbo},
-+ {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(mpv_gl, params);
- if(!danmuHide)
- {
- QOpenGLFramebufferObject::bindDefault();
-@@ -448,7 +511,6 @@ void MPVPlayer::paintGL()
-
- void MPVPlayer::swapped()
- {
-- mpv_opengl_cb_report_flip(mpv_gl, 0);
- if(state==PlayState::Play)
- {
- float step(0.f);
-diff --git a/Play/Video/mpvplayer.h b/Play/Video/mpvplayer.h
-index 1ccc9f9..e9e4d50 100644
---- a/Play/Video/mpvplayer.h
-+++ b/Play/Video/mpvplayer.h
-@@ -5,7 +5,7 @@
- #include <QtCore>
- #include <QtGui>
- #include <mpv/client.h>
--#include <mpv/opengl_cb.h>
-+#include <mpv/render_gl.h>
- #include <mpv/qthelper.hpp>
- #include "Play/Danmu/common.h"
- class DanmuRender;
-@@ -47,6 +47,7 @@ public:
-
- VideoSizeInfo getVideoSizeInfo();
- QMap<QString,QMap<QString,QString> > getMediaInfo();
-+ void setOptions();
- void drawTexture(QList<const DanmuObject *> &objList, float alpha);
- signals:
- void fileChanged();
-@@ -86,8 +87,8 @@ private:
- QStringList desc_str;
- QList<int> ids;
- };
-- mpv::qt::Handle mpv;
-- mpv_opengl_cb_context *mpv_gl;
-+ mpv_handle *mpv;
-+ mpv_render_context *mpv_gl;
- void handle_mpv_event(mpv_event *event);
- static void on_update(void *ctx);
- static void wakeup(void *ctx);
-@@ -103,6 +104,7 @@ private:
- QOpenGLShaderProgram danmuShader;
- QTimer refreshTimer;
- QElapsedTimer elapsedTimer;
-+ QMap<QString, QString> optionsMap;
-
- int currentDuration;
- TrackInfo audioTrack,subtitleTrack;
-diff --git a/UI/about.cpp b/UI/about.cpp
-index 9fbda30..927baef 100644
---- a/UI/about.cpp
-+++ b/UI/about.cpp
-@@ -13,7 +13,7 @@ About::About(QWidget *parent) : CFramelessDialog("",parent)
- QJsonObject curVersionObj = QJsonDocument::fromJson(version.readAll()).object();
- QString versionStr=curVersionObj.value("Version").toString();
- QLabel *info=new QLabel(tr("KikoPlay - A Full-featured Danmu Player<br/>"
-- "%1 (C) 2019 Kikyou <a href=\"https://protostars.github.io/KikoPlay/\">homepage</a> <a href=\"https://github.com/Protostars/KikoPlay\">github</a><br/>"
-+ "%1 (C) 2020 Kikyou <a href=\"https://protostars.github.io/KikoPlay/\">homepage</a> <a href=\"https://github.com/Protostars/KikoPlay\">github</a><br/>"
- "Exchange & BUG Report: 874761809(QQ Group)").arg(versionStr),this);
- info->setOpenExternalLinks(true);
- info->setAlignment(Qt::AlignCenter);
-diff --git a/UI/animedetailinfo.h b/UI/animedetailinfo.h
-index 5bab9b7..206f4e4 100644
---- a/UI/animedetailinfo.h
-+++ b/UI/animedetailinfo.h
-@@ -2,6 +2,7 @@
- #define ANIMEDETAILINFO_H
-
- #include "framelessdialog.h"
-+#include <QMap>
- struct Anime;
- struct Character;
- class CharacterItem : public QWidget
-diff --git a/UI/captureview.cpp b/UI/captureview.cpp
-index 754c70c..15008ae 100644
---- a/UI/captureview.cpp
-+++ b/UI/captureview.cpp
-@@ -7,6 +7,8 @@
- #include <QApplication>
- #include <QClipboard>
- #include <QFileDialog>
-+#include <QMouseEvent>
-+#include <QWheelEvent>
- CaptureView::CaptureView(CaptureListModel *captureModel, int curRow, QWidget *parent) : CFramelessDialog("",parent,false,true,false)
- {
- this->curRow=curRow;
-diff --git a/UI/mpvlog.cpp b/UI/mpvlog.cpp
-index 155efa1..fee6590 100644
---- a/UI/mpvlog.cpp
-+++ b/UI/mpvlog.cpp
-@@ -8,7 +8,7 @@ MPVLog::MPVLog(QWidget *parent) : CFramelessDialog(tr("MPV Log"),parent,false,tr
- {
- QPlainTextEdit *logView=new QPlainTextEdit(this);
- logView->setReadOnly(true);
-- logView->setMaximumBlockCount(256);
-+ logView->setMaximumBlockCount(1024);
- QObject::connect(GlobalObjects::mpvplayer,&MPVPlayer::showLog,[logView](const QString &log){
- logView->appendPlainText(log.trimmed());
- QTextCursor cursor = logView->textCursor();
-diff --git a/UI/player.cpp b/UI/player.cpp
-index 2de7449..1c029d0 100644
---- a/UI/player.cpp
-+++ b/UI/player.cpp
-@@ -213,6 +213,7 @@ PlayerWindow::PlayerWindow(QWidget *parent) : QMainWindow(parent),autoHideContro
- setCentralWidget(GlobalObjects::mpvplayer);
- GlobalObjects::mpvplayer->setMouseTracking(true);
- setContentsMargins(0,0,0,0);
-+ GlobalObjects::mpvplayer->setOptions();
-
- logDialog=new MPVLog(this);
-
-diff --git a/UI/tip.cpp b/UI/tip.cpp
-index a80b5d5..216490a 100644
---- a/UI/tip.cpp
-+++ b/UI/tip.cpp
-@@ -1,6 +1,7 @@
- #include "tip.h"
- #include <QLabel>
- #include <QVBoxLayout>
-+#include <QFile>
- Tip::Tip(QWidget *parent) : CFramelessDialog (tr("Tip"),parent)
- {
- QLabel *tipContent=new QLabel(this);
-diff --git a/kikoplay.rc b/kikoplay.rc
-index 48fc00b..608f9a6 100644
-Binary files a/kikoplay.rc and b/kikoplay.rc differ
-diff --git a/lib/x64/libmpv.dll.lib b/lib/x64/libmpv.dll.lib
-index 503fe77..79ead29 100644
-Binary files a/lib/x64/libmpv.dll.lib and b/lib/x64/libmpv.dll.lib differ
-diff --git a/res/about b/res/about
-index 7166e66..1c596bb 100644
---- a/res/about
-+++ b/res/about
-@@ -1,8 +1,8 @@
- KikoPlay is based on the following projects:
- Qt 5.12.3
--libmpv 0.29.1
-+libmpv 0.31.0
- aria2 1.34
- Qt-Nice-Frameless-Window
- zlib 1.2.11
- QHttpEngine 1.01
--Lua 5.3
-\ No newline at end of file
-+Lua 5.3
diff --git a/media-video/kikoplay/kikoplay-0.6.0.ebuild b/media-video/kikoplay/kikoplay-0.6.0.ebuild
deleted file mode 100644
index 7fb835f..0000000
--- a/media-video/kikoplay/kikoplay-0.6.0.ebuild
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 1999-2020 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=7
-
-GIT_PN="KikoPlay"
-
-inherit qmake-utils xdg
-
-DESCRIPTION="KikoPlay is a full-featured danmu player"
-HOMEPAGE="
- https://kikoplay.fun
- https://github.com/Protostars/KikoPlay
-"
-
-if [[ ${PV} == "9999" ]] ; then
- inherit git-r3
- EGIT_REPO_URI="https://github.com/Protostars/${GIT_PN}.git"
-else
- SRC_URI="https://github.com/Protostars/${GIT_PN}/archive/${PV}.tar.gz -> ${P}.tar.gz"
- KEYWORDS="~amd64 ~arm ~arm64 ~hppa ~m68k ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86"
- S="${WORKDIR}/${GIT_PN}-${PV}"
-fi
-
-LICENSE="GPL-3"
-SLOT="0"
-
-RDEPEND="
- dev-lang/lua:5.3
- dev-libs/qhttpengine:5
- dev-qt/qtconcurrent:5
- dev-qt/qtcore:5
- dev-qt/qtgui:5
- dev-qt/qtnetwork:5
- dev-qt/qtsql:5
- dev-qt/qtwidgets:5
- media-video/mpv[libmpv,-luajit]
- net-misc/aria2
-"
-
-DEPEND="
- ${RDEPEND}
-"
-
-BDEPEND="
- media-gfx/imagemagick
- virtual/pkgconfig
-"
-
-PATCHES=(
- "${FILESDIR}"/${PN}-0.6.0-install.patch # Fix install problem
- "${FILESDIR}"/${PN}-0.6.0-desktop.patch # Add a desktop file
- "${FILESDIR}"/${PN}-0.6.0-home.patch # Fix config file path
-)
-
-src_prepare() {
- default
- # Fix lua link problem, link to lua5.3 to fix bug
- sed -i "s/-llua/-llua5.3/" KikoPlay.pro || die "Could not fix lua link"
- echo "target.path += /usr/bin" >> KikoPlay.pro || die "Could not fix install path"
- echo "INSTALLS += target icons desktop" >> KikoPlay.pro || die "Could not fix install target"
- echo "unix:icons.path = /usr/share/pixmaps" >> KikoPlay.pro || die "Could not fix install icon PATH"
- echo "unix:desktop.path = /usr/share/applications" >> KikoPlay.pro || die "Could not fix install desktop PATH"
- echo "unix:icons.files = kikoplay.png kikoplay.xpm" >> KikoPlay.pro || die "Could not fix install desktop PATH"
- echo "unix:desktop.files = kikoplay.desktop" >> KikoPlay.pro || die "Could not fix install desktop PATH"
- echo "DEFINES += CONFIG_HOME_DATA" >> KikoPlay.pro || die "Could not set defines"
- convert kikoplay.ico kikoplay.png || die "Could not create PNG icon"
- convert kikoplay.ico kikoplay.xpm || die "Could not create XPM icon"
-}
-
-src_configure() {
- eqmake5 PREFIX="${D}"/usr
-}
-
-src_install() {
- # Can't use default, set INSTALL_ROOT
- emake INSTALL_ROOT="${D}" install
-}
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [gentoo-commits] repo/proj/guru:master commit in: media-video/kikoplay/files/, media-video/kikoplay/
@ 2020-05-14 9:29 Andrew Ammerlaan
0 siblings, 0 replies; 3+ messages in thread
From: Andrew Ammerlaan @ 2020-05-14 9:29 UTC (permalink / raw
To: gentoo-commits
commit: 6265ccae7e3626895f9134ce786d04a984eedcc1
Author: Huang Rui <vowstar <AT> gmail <DOT> com>
AuthorDate: Wed May 13 17:14:05 2020 +0000
Commit: Andrew Ammerlaan <andrewammerlaan <AT> riseup <DOT> net>
CommitDate: Wed May 13 17:14:19 2020 +0000
URL: https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=6265ccae
media-video/kikoplay: fix data not found bug
enable CONFIG_UNIX_DATA default for linux environment
Applied https://github.com/Protostars/KikoPlay/pull/23
Package-Manager: Portage-2.3.99, Repoman-2.3.22
Signed-off-by: Huang Rui <vowstar <AT> gmail.com>
media-video/kikoplay/files/kikoplay-0.6.2-fix-define.patch | 12 ++++++++++++
media-video/kikoplay/kikoplay-0.6.2.ebuild | 4 ++++
2 files changed, 16 insertions(+)
diff --git a/media-video/kikoplay/files/kikoplay-0.6.2-fix-define.patch b/media-video/kikoplay/files/kikoplay-0.6.2-fix-define.patch
new file mode 100644
index 0000000..eb79d8d
--- /dev/null
+++ b/media-video/kikoplay/files/kikoplay-0.6.2-fix-define.patch
@@ -0,0 +1,12 @@
+diff --git a/KikoPlay.pro b/KikoPlay.pro
+index 7270328..1fe6f8d 100644
+--- a/KikoPlay.pro
++++ b/KikoPlay.pro
+@@ -268,5 +268,6 @@ contains(QT_ARCH, i386){
+ unix:web.files = web/*
+
+ INSTALLS += target icons desktop web
++ DEFINES += CONFIG_UNIX_DATA
+ }
+ }
+
diff --git a/media-video/kikoplay/kikoplay-0.6.2.ebuild b/media-video/kikoplay/kikoplay-0.6.2.ebuild
index 05c327c..edbaf88 100644
--- a/media-video/kikoplay/kikoplay-0.6.2.ebuild
+++ b/media-video/kikoplay/kikoplay-0.6.2.ebuild
@@ -50,6 +50,10 @@ BDEPEND="
virtual/pkgconfig
"
+PATCHES=(
+ "${FILESDIR}"/${PN}-0.6.2-fix-define.patch # fix define problem
+)
+
src_configure() {
eqmake5 PREFIX="${D}"/usr
}
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-05-14 9:29 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-04-20 9:47 [gentoo-commits] repo/proj/guru:master commit in: media-video/kikoplay/files/, media-video/kikoplay/ Andrew Ammerlaan
-- strict thread matches above, loose matches on Subject: below --
2020-05-14 9:29 Andrew Ammerlaan
2020-04-18 18:39 Andrew Ammerlaan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox