diff --git a/media-video/qmplay2/patches/qmplay2-20.07.04.patchset b/media-video/qmplay2/patches/qmplay2-20.07.04.patchset
index 282d8b1f5..8a41f9491 100644
--- a/media-video/qmplay2/patches/qmplay2-20.07.04.patchset
+++ b/media-video/qmplay2/patches/qmplay2-20.07.04.patchset
@@ -1,4 +1,4 @@
-From d9031acc4ae269e8db40b793d9ae974c009055d2 Mon Sep 17 00:00:00 2001
+From b421b98416a2dbb4cea7c3b89c65b2ff66efc752 Mon Sep 17 00:00:00 2001
From: Gerasim Troeglazov <3dEyes@gmail.com>
Date: Sun, 3 May 2020 11:29:15 +1000
Subject: Add haiku support
@@ -733,10 +733,10 @@ index 0000000..24b4ebd
+ MediaKit.png
+
diff --git a/src/qmplay2/QMPlay2Core.cpp b/src/qmplay2/QMPlay2Core.cpp
-index 5cf8f56..4b48fe4 100644
+index 092dcde..bed9ff7 100644
--- a/src/qmplay2/QMPlay2Core.cpp
+++ b/src/qmplay2/QMPlay2Core.cpp
-@@ -210,7 +210,7 @@ void QMPlay2CoreClass::init(bool loadModules, bool modulesInSubdirs, const QStri
+@@ -204,7 +204,7 @@ void QMPlay2CoreClass::init(bool loadModules, bool modulesInSubdirs, const QStri
settingsDir = QCoreApplication::applicationDirPath() + "/settings/";
else
{
@@ -745,7 +745,7 @@ index 5cf8f56..4b48fe4 100644
settingsDir = QFileInfo(QSettings(QSettings::IniFormat, QSettings::UserScope, QString()).fileName()).absolutePath() + "/QMPlay2/";
#elif defined(Q_OS_MACOS)
settingsDir = Functions::cleanPath(QStandardPaths::standardLocations(QStandardPaths::DataLocation).value(0, settingsDir));
-@@ -409,6 +409,11 @@ QStringList QMPlay2CoreClass::getModules(const QString &type, int typeLen) const
+@@ -460,6 +460,11 @@ QStringList QMPlay2CoreClass::getModules(const QString &type, int typeLen) const
#elif defined Q_OS_WIN
if (type == "videoWriters")
defaultModules << "OpenGL 2" << "DirectDraw";
@@ -758,5 +758,277 @@ index 5cf8f56..4b48fe4 100644
if (type == "decoders")
defaultModules << "FFmpeg Decoder";
--
-2.26.0
+2.28.0
+
+
+From 323101a7c0b3ff43ccaabc46027d60ee5311ca1d Mon Sep 17 00:00:00 2001
+From: Gerasim Troeglazov <3dEyes@gmail.com>
+Date: Sat, 5 Dec 2020 11:46:40 +1000
+Subject: YouTube fixes from upstream
+
+
+diff --git a/src/modules/Extensions/YouTube.cpp b/src/modules/Extensions/YouTube.cpp
+index 8f16779..a12ba35 100644
+--- a/src/modules/Extensions/YouTube.cpp
++++ b/src/modules/Extensions/YouTube.cpp
+@@ -18,6 +18,7 @@
+
+ #include
+
++#include
+ #include
+ #include
+
+@@ -754,90 +755,96 @@ void YouTube::setSearchResults(const QByteArray &data)
+ {
+ const auto json = getYtInitialData(data);
+
+- const auto contents = json.object()
++ const auto sectionListRendererContents = json.object()
+ ["contents"].toObject()
+ ["twoColumnSearchResultsRenderer"].toObject()
+ ["primaryContents"].toObject()
+ ["sectionListRenderer"].toObject()
+- ["contents"].toArray().at(0).toObject()
+- ["itemSectionRenderer"].toObject()
+ ["contents"].toArray()
+ ;
+
+- for (auto &&obj : contents)
++ for (auto &&obj : sectionListRendererContents)
+ {
+- const auto videoRenderer = obj.toObject()["videoRenderer"].toObject();
+- const auto playlistRenderer = obj.toObject()["playlistRenderer"].toObject();
+-
+- const bool isVideo = !videoRenderer.isEmpty() && playlistRenderer.isEmpty();
+-
+- QString title, contentId, length, user, publishedTime, viewCount, thumbnail, url;
++ const auto contents = obj.toObject()
++ ["itemSectionRenderer"].toObject()
++ ["contents"].toArray()
++ ;
+
+- if (isVideo)
++ for (auto &&obj : contents)
+ {
+- title = videoRenderer["title"].toObject()["runs"].toArray().at(0).toObject()["text"].toString();
+- contentId = videoRenderer["videoId"].toString();
+- if (title.isEmpty() || contentId.isEmpty())
+- continue;
+-
+- length = videoRenderer["lengthText"].toObject()["simpleText"].toString();
+- user = videoRenderer["ownerText"].toObject()["runs"].toArray().at(0).toObject()["text"].toString();
+- publishedTime = videoRenderer["publishedTimeText"].toObject()["simpleText"].toString();
+- viewCount = videoRenderer["shortViewCountText"].toObject()["simpleText"].toString();
+- thumbnail = videoRenderer["thumbnail"].toObject()["thumbnails"].toArray().at(0).toObject()["url"].toString();
++ const auto videoRenderer = obj.toObject()["videoRenderer"].toObject();
++ const auto playlistRenderer = obj.toObject()["playlistRenderer"].toObject();
+
+- url = YOUTUBE_URL "/watch?v=" + contentId;
+- }
+- else
+- {
+- title = playlistRenderer["title"].toObject()["simpleText"].toString();
+- contentId = playlistRenderer["playlistId"].toString();
+- if (title.isEmpty() || contentId.isEmpty())
+- continue;
++ const bool isVideo = !videoRenderer.isEmpty() && playlistRenderer.isEmpty();
+
+- user = playlistRenderer["longBylineText"].toObject()["runs"].toArray().at(0).toObject()["text"].toString();
+- thumbnail = playlistRenderer
+- ["thumbnailRenderer"].toObject()
+- ["playlistVideoThumbnailRenderer"].toObject()
+- ["thumbnail"].toObject()
+- ["thumbnails"].toArray().at(0).toObject()
+- ["url"].toString()
+- ;
++ QString title, contentId, length, user, publishedTime, viewCount, thumbnail, url;
+
+- url = YOUTUBE_URL "/playlist?list=" + contentId;
+- }
++ if (isVideo)
++ {
++ title = videoRenderer["title"].toObject()["runs"].toArray().at(0).toObject()["text"].toString();
++ contentId = videoRenderer["videoId"].toString();
++ if (title.isEmpty() || contentId.isEmpty())
++ continue;
++
++ length = videoRenderer["lengthText"].toObject()["simpleText"].toString();
++ user = videoRenderer["ownerText"].toObject()["runs"].toArray().at(0).toObject()["text"].toString();
++ publishedTime = videoRenderer["publishedTimeText"].toObject()["simpleText"].toString();
++ viewCount = videoRenderer["shortViewCountText"].toObject()["simpleText"].toString();
++ thumbnail = videoRenderer["thumbnail"].toObject()["thumbnails"].toArray().at(0).toObject()["url"].toString();
++
++ url = YOUTUBE_URL "/watch?v=" + contentId;
++ }
++ else
++ {
++ title = playlistRenderer["title"].toObject()["simpleText"].toString();
++ contentId = playlistRenderer["playlistId"].toString();
++ if (title.isEmpty() || contentId.isEmpty())
++ continue;
++
++ user = playlistRenderer["longBylineText"].toObject()["runs"].toArray().at(0).toObject()["text"].toString();
++ thumbnail = playlistRenderer
++ ["thumbnailRenderer"].toObject()
++ ["playlistVideoThumbnailRenderer"].toObject()
++ ["thumbnail"].toObject()
++ ["thumbnails"].toArray().at(0).toObject()
++ ["url"].toString()
++ ;
++
++ url = YOUTUBE_URL "/playlist?list=" + contentId;
++ }
+
+- auto tWI = new QTreeWidgetItem(resultsW);
++ auto tWI = new QTreeWidgetItem(resultsW);
+
+- tWI->setText(0, title);
+- tWI->setText(1, isVideo ? length : tr("Playlist"));
+- tWI->setText(2, user);
++ tWI->setText(0, title);
++ tWI->setText(1, isVideo ? length : tr("Playlist"));
++ tWI->setText(2, user);
+
+- QString tooltip;
+- tooltip += QString("%1: %2\n").arg(resultsW->headerItem()->text(0), tWI->text(0));
+- tooltip += QString("%1: %2\n").arg(isVideo ? resultsW->headerItem()->text(1) : tr("Playlist"), isVideo ? tWI->text(1) : tr("yes"));
+- tooltip += QString("%1: %2\n").arg(resultsW->headerItem()->text(2), tWI->text(2));
+- tooltip += QString("%1: %2\n").arg(tr("Published time"), publishedTime);
+- tooltip += QString("%1: %2").arg(tr("View count"), viewCount);
+- tWI->setToolTip(0, tooltip);
++ QString tooltip;
++ tooltip += QString("%1: %2\n").arg(resultsW->headerItem()->text(0), tWI->text(0));
++ tooltip += QString("%1: %2\n").arg(isVideo ? resultsW->headerItem()->text(1) : tr("Playlist"), isVideo ? tWI->text(1) : tr("yes"));
++ tooltip += QString("%1: %2\n").arg(resultsW->headerItem()->text(2), tWI->text(2));
++ tooltip += QString("%1: %2\n").arg(tr("Published time"), publishedTime);
++ tooltip += QString("%1: %2").arg(tr("View count"), viewCount);
++ tWI->setToolTip(0, tooltip);
+
+- tWI->setData(0, Qt::UserRole, url);
+- tWI->setData(1, Qt::UserRole, !isVideo);
++ tWI->setData(0, Qt::UserRole, url);
++ tWI->setData(1, Qt::UserRole, !isVideo);
+
+- if (!isVideo)
+- {
+- tWI->setDisabled(true);
++ if (!isVideo)
++ {
++ tWI->setDisabled(true);
+
+- auto linkReply = net.start(url);
+- linkReply->setProperty("tWI", QVariant::fromValue((void *)tWI));
+- linkReplies += linkReply;
+- }
++ auto linkReply = net.start(url);
++ linkReply->setProperty("tWI", QVariant::fromValue((void *)tWI));
++ linkReplies += linkReply;
++ }
+
+- if (!thumbnail.isEmpty())
+- {
+- auto imageReply = net.start(thumbnail);
+- imageReply->setProperty("tWI", QVariant::fromValue((void *)tWI));
+- imageReplies += imageReply;
++ if (!thumbnail.isEmpty())
++ {
++ auto imageReply = net.start(thumbnail);
++ imageReply->setProperty("tWI", QVariant::fromValue((void *)tWI));
++ imageReplies += imageReply;
++ }
+ }
+ }
+
+@@ -1042,7 +1049,7 @@ void YouTube::preparePlaylist(const QByteArray &data, QTreeWidgetItem *tWI)
+ {
+ const auto playlistRenderer = obj.toObject()["playlistVideoRenderer"].toObject();
+
+- const auto title = playlistRenderer["title"].toObject()["simpleText"].toString();
++ const auto title = playlistRenderer["title"].toObject()["runs"].toArray().at(0).toObject()["text"].toString();
+ const auto videoId = playlistRenderer["videoId"].toString();
+ if (title.isEmpty() || videoId.isEmpty())
+ continue;
+@@ -1070,13 +1077,10 @@ QJsonDocument YouTube::getYtInitialData(const QByteArray &data)
+ if (idx < 0)
+ return QJsonDocument();
+
+- int idx2 = data.indexOf("\n", idx);
++ int idx2 = Functions::findJsonEnd(data, idx);
+ if (idx2 < 0)
+ return QJsonDocument();
+
+- auto jsonData = data.mid(idx, idx2 - idx);
+- if (jsonData.endsWith(';'))
+- jsonData.chop(1);
+-
++ const auto jsonData = data.mid(idx, idx2 - idx);
+ return QJsonDocument::fromJson(jsonData);
+ }
+diff --git a/src/qmplay2/Functions.cpp b/src/qmplay2/Functions.cpp
+index 7319a2b..dce416c 100644
+--- a/src/qmplay2/Functions.cpp
++++ b/src/qmplay2/Functions.cpp
+@@ -940,6 +940,46 @@ QByteArray Functions::textWithFallbackEncoding(const QByteArray &data)
+ return data;
+ }
+
++int Functions::findJsonEnd(const QByteArray &data, int idx)
++{
++ const int dataLen = data.length();
++
++ if (dataLen < 1 || idx < 0 || idx >= dataLen || data.at(idx) != '{')
++ return -1;
++
++ int brackets = 1;
++ bool inString = false;
++ char prevChr = '\0';
++
++ for (int i = idx + 1; i < dataLen; ++i)
++ {
++ const char chr = data.at(i);
++
++ if (chr == '"')
++ {
++ if (!inString)
++ inString = true;
++ else if (prevChr != '\\')
++ inString = false;
++ }
++
++ prevChr = chr;
++
++ if (inString)
++ continue;
++
++ if (chr == '{')
++ ++brackets;
++ else if (chr == '}')
++ --brackets;
++
++ if (brackets == 0)
++ return i + 1;
++ }
++
++ return -1;
++}
++
+ Functions::LumaCoefficients Functions::getLumaCoeff(AVColorSpace colorSpace)
+ {
+ switch (colorSpace)
+diff --git a/src/qmplay2/Functions.hpp b/src/qmplay2/Functions.hpp
+index 395b9fd..0187a50 100644
+--- a/src/qmplay2/Functions.hpp
++++ b/src/qmplay2/Functions.hpp
+@@ -149,6 +149,8 @@ namespace Functions
+
+ QMPLAY2SHAREDLIB_EXPORT QByteArray textWithFallbackEncoding(const QByteArray &data);
+
++ QMPLAY2SHAREDLIB_EXPORT int findJsonEnd(const QByteArray &data, int idx = 0);
++
+ struct LumaCoefficients
+ {
+ float cR, cG, cB;
+--
+2.28.0
diff --git a/media-video/qmplay2/qmplay2-20.07.04.recipe b/media-video/qmplay2/qmplay2-20.07.04.recipe
index b698c69a8..2ad6aa2b2 100644
--- a/media-video/qmplay2/qmplay2-20.07.04.recipe
+++ b/media-video/qmplay2/qmplay2-20.07.04.recipe
@@ -6,7 +6,7 @@ MyFreeMP3 browser."
HOMEPAGE="http://zaps166.sourceforge.net"
COPYRIGHT="2010-2020 Błażej Szczygieł"
LICENSE="GNU GPL v3"
-REVISION="1"
+REVISION="2"
SOURCE_URI="https://github.com/zaps166/QMPlay2/archive/$portVersion.tar.gz"
CHECKSUM_SHA256="5f30785e215da6e106304b2a0a94c84e4cb679e51b2119fa2dd9f24e91b740cb"
SOURCE_DIR="QMPlay2-$portVersion"