#include "ytjsvideo.h"
#include "ytvideo.h"
+#include "variantpromise.h"
+
Video::Video()
- : duration(0), viewCount(-1), license(LicenseYouTube), definitionCode(0),
- loadingThumbnail(false), ytVideo(nullptr), ytjsVideo(nullptr) {}
+ : duration(0), viewCount(-1), license(LicenseYouTube), definitionCode(0), ytVideo(nullptr),
+ ytjsVideo(nullptr) {}
Video::~Video() {
qDebug() << "Deleting" << id;
clone->channelId = channelId;
clone->webpage = webpage;
clone->streamUrl = streamUrl;
- clone->thumbnail = thumbnail;
- clone->thumbnailUrl = thumbnailUrl;
- clone->mediumThumbnailUrl = mediumThumbnailUrl;
+ clone->thumbs = thumbs;
+ clone->thumbsNeedSorting = thumbsNeedSorting;
clone->duration = duration;
clone->formattedDuration = formattedDuration;
clone->published = published;
}
}
-void Video::loadThumbnail() {
- if (thumbnailUrl.isEmpty() || loadingThumbnail) return;
- loadingThumbnail = true;
- QObject *reply = HttpUtils::yt().get(thumbnailUrl);
- connect(reply, SIGNAL(data(QByteArray)), SLOT(setThumbnail(QByteArray)));
-}
-
void Video::setDuration(int value) {
duration = value;
formattedDuration = DataUtils::formatDuration(duration);
formattedPublished = DataUtils::formatDateTime(published);
}
-void Video::setThumbnail(const QByteArray &bytes) {
- qreal ratio = qApp->devicePixelRatio();
- thumbnail.loadFromData(bytes);
- thumbnail.setDevicePixelRatio(ratio);
- const int thumbWidth = PlaylistItemDelegate::thumbWidth * ratio;
- if (thumbnail.width() > thumbWidth)
- thumbnail = thumbnail.scaledToWidth(thumbWidth, Qt::SmoothTransformation);
- emit gotThumbnail();
- loadingThumbnail = false;
-}
-
void Video::streamUrlLoaded(const QString &streamUrl, const QString &audioUrl) {
qDebug() << "Streams loaded";
this->streamUrl = streamUrl;
ytjsVideo = new YTJSVideo(id, this);
connect(ytjsVideo, &YTJSVideo::gotStreamUrl, this, &Video::streamUrlLoaded);
connect(ytjsVideo, &YTJSVideo::errorStreamUrl, this, [this](const QString &msg) {
- emit errorStreamUrl(msg);
+ qDebug() << msg;
ytjsVideo->deleteLater();
ytjsVideo = nullptr;
+ // loadStreamUrlYT();
+ emit errorStreamUrl(msg);
});
ytjsVideo->loadStreamUrl();
}
-void Video::loadStreamUrl() {
- loadStreamUrlJS();
- return;
+void Video::loadStreamUrlYT() {
if (ytVideo) {
qDebug() << "Already loading" << id;
return;
ytVideo = new YTVideo(id, this);
connect(ytVideo, &YTVideo::gotStreamUrl, this, &Video::streamUrlLoaded);
connect(ytVideo, &YTVideo::errorStreamUrl, this, [this](const QString &msg) {
+ qDebug() << msg;
emit errorStreamUrl(msg);
ytVideo->deleteLater();
ytVideo = nullptr;
ytVideo->loadStreamUrl();
}
+void Video::loadStreamUrl() {
+ loadStreamUrlJS();
+}
+
+bool Video::isLoadingStreamUrl() const {
+ return ytVideo != nullptr || ytjsVideo != nullptr;
+}
+
void Video::abortLoadStreamUrl() {
if (ytVideo) {
ytVideo->disconnect(this);
ytVideo->deleteLater();
ytVideo = nullptr;
}
+ if (ytjsVideo) {
+ ytjsVideo->disconnect(this);
+ ytjsVideo->deleteLater();
+ ytjsVideo = nullptr;
+ }
+}
+
+void Video::addThumb(int width, int height, QString url) {
+ thumbs << YTThumb(width, height, url);
+ thumbsNeedSorting = true;
+}
+
+VariantPromise &Video::loadThumb(QSize size, qreal pixelRatio) {
+ if (thumbsNeedSorting) {
+ std::sort(thumbs.begin(), thumbs.end(),
+ [](auto a, auto b) { return a.getWidth() < b.getWidth(); });
+ thumbsNeedSorting = false;
+ }
+
+ auto promise = new VariantPromise(this);
+ if (thumbs.isEmpty()) {
+ QTimer::singleShot(0, promise, [promise] { promise->reject("Empty thumbs"); });
+ return *promise;
+ }
+
+ auto reallyLoad = [this, promise, size, pixelRatio](auto &&self,
+ YTThumb *previous = nullptr) -> void {
+ YTThumb *selected = nullptr;
+
+ static bool fallback = false;
+ if (fallback) {
+ qDebug() << "Doing fallback loop";
+ bool skip = previous != nullptr;
+ for (int i = thumbs.size() - 1; i >= 0; --i) {
+ auto &thumb = thumbs.at(i);
+ if (!skip) {
+ selected = (YTThumb *)&thumb;
+ qDebug() << "selected" << selected->getUrl();
+ break;
+ }
+ if (&thumb == previous) skip = false;
+ }
+ } else {
+ bool skip = previous != nullptr;
+ for (auto &thumb : qAsConst(thumbs)) {
+ if (!skip && thumb.getWidth() * pixelRatio >= size.width() &&
+ thumb.getHeight() * pixelRatio >= size.height()) {
+ selected = (YTThumb *)&thumb;
+ qDebug() << "selected" << selected->getUrl();
+ break;
+ }
+ if (&thumb == previous) skip = false;
+ }
+ }
+ if (!selected && !fallback) {
+ qDebug() << "Falling back";
+ fallback = true;
+ self(self);
+ return;
+ }
+ if (selected) {
+ qDebug() << "Loading" << selected->getUrl();
+ selected->load(promise)
+ .then([promise](auto variant) { promise->resolve(variant); })
+ .onFailed([self, selected] { self(self, selected); });
+ } else
+ promise->reject("No thumb");
+ };
+ reallyLoad(reallyLoad);
+
+ return *promise;
}