diff options
author | Mateusz Łukasik <mati75@linuxmint.pl> | 2014-09-10 13:50:41 +0200 |
---|---|---|
committer | Mateusz Łukasik <mati75@linuxmint.pl> | 2014-09-10 13:50:41 +0200 |
commit | 2d547200175bcaefcbca0862f8e0395e42c96224 (patch) | |
tree | d2d8508074c5035a8c5af248e147655cdeb0a1cb /src/youtube | |
parent | 02af8398ac9a1089a7fe9efda615a771e1c13637 (diff) |
Imported Upstream version 14.9.0
Diffstat (limited to 'src/youtube')
-rw-r--r-- | src/youtube/retrieveyoutubeurl.cpp | 140 | ||||
-rw-r--r-- | src/youtube/retrieveyoutubeurl.h | 28 | ||||
-rw-r--r-- | src/youtube/ytsig.cpp | 2 |
3 files changed, 145 insertions, 25 deletions
diff --git a/src/youtube/retrieveyoutubeurl.cpp b/src/youtube/retrieveyoutubeurl.cpp index 47a3650..e289996 100644 --- a/src/youtube/retrieveyoutubeurl.cpp +++ b/src/youtube/retrieveyoutubeurl.cpp @@ -31,6 +31,8 @@ #define USE_PLAYER_NAME QString RetrieveYoutubeUrl::user_agent; +bool RetrieveYoutubeUrl::use_https_main = false; +bool RetrieveYoutubeUrl::use_https_vi = false; RetrieveYoutubeUrl::RetrieveYoutubeUrl( QObject* parent ) : QObject(parent) { @@ -44,12 +46,12 @@ RetrieveYoutubeUrl::~RetrieveYoutubeUrl() { } void RetrieveYoutubeUrl::fetchPage(const QString & url) { - QString agent = user_agent; - if (agent.isEmpty()) agent = "Mozilla/5.0 (X11; Linux x86_64; rv:5.0.1) Gecko/20100101 Firefox/5.0.1"; - qDebug("RetrieveYoutubeUrl::fetchPage: user agent: %s", agent.toLatin1().constData()); + qDebug("RetrieveYoutubeUrl::fetchPage: url: %s", url.toUtf8().constData()); + qDebug("RetrieveYoutubeUrl::fetchPage: user agent: '%s'", user_agent.toLatin1().constData()); QNetworkRequest req(url); - req.setRawHeader("User-Agent", agent.toLatin1()); + req.setRawHeader("User-Agent", user_agent.toLatin1()); + req.setRawHeader("Accept-Language", "en-us,en;q=0.5"); reply = manager->get(req); connect(reply, SIGNAL(finished()), this, SLOT(gotResponse())); orig_url = url; @@ -62,13 +64,19 @@ void RetrieveYoutubeUrl::fetchPage(const QString & url) { } #ifdef YT_GET_VIDEOINFO -void RetrieveYoutubeUrl::fetchVideoInfoPage() { - QString url = QString("http://www.youtube.com/get_video_info?el=detailpage&ps=default&eurl=&gl=US&hl=en&video_id=%1").arg(video_id); - //qDebug("RetrieveYoutubeUrl::fetchVideoInfoPage: url: %s", url.toUtf8().constData()); +void RetrieveYoutubeUrl::fetchVideoInfoPage(QString url) { + if (url.isEmpty()) { + QString scheme = use_https_vi ? "https" : "http"; + url = QString("%2://www.youtube.com/get_video_info?el=detailpage&ps=default&eurl=&gl=US&hl=en&video_id=%1").arg(video_id).arg(scheme); + } + qDebug("RetrieveYoutubeUrl::fetchVideoInfoPage: url: %s...", url.left(20).toUtf8().constData()); + + qDebug("RetrieveYoutubeUrl::fetchPage: user agent: '%s'", user_agent.toLatin1().constData()); YTSig::check(url); QNetworkRequest req(url); req.setRawHeader("User-Agent", user_agent.toLatin1()); + req.setRawHeader("Accept-Language", "en-us,en;q=0.5"); reply = manager->get(req); connect(reply, SIGNAL(finished()), this, SLOT(gotVideoInfoResponse())); @@ -81,6 +89,8 @@ void RetrieveYoutubeUrl::close() { } void RetrieveYoutubeUrl::gotResponse() { + qDebug("RetrieveYoutubeUrl::gotResponse"); + QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); if (reply->error() == QNetworkReply::NoError) { @@ -96,6 +106,7 @@ void RetrieveYoutubeUrl::gotResponse() { return; } } else { + qDebug("RetrieveYoutubeUrl::gotResponse: error %d: '%s'", (int)reply->error(), reply->errorString().toUtf8().constData()); emit errorOcurred((int)reply->error(), reply->errorString()); return; } @@ -108,7 +119,20 @@ void RetrieveYoutubeUrl::gotVideoInfoResponse() { QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); - if (reply->error() != QNetworkReply::NoError) { + if (reply->error() == QNetworkReply::NoError) { + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + qDebug("RetrieveYoutubeUrl::gotVideoInfoResponse: status: %d", status); + switch (status) { + case 301: + case 302: + case 307: + QString r_url = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl().toString(); + //qDebug("RetrieveYoutubeUrl::gotVideoInfoResponse: redirected: %s", r_url.toLatin1().constData()); + fetchVideoInfoPage(r_url); + return; + } + } else { + qDebug("RetrieveYoutubeUrl::gotVideoInfoResponse: error %d: '%s'", (int)reply->error(), reply->errorString().toUtf8().constData()); emit errorOcurred((int)reply->error(), reply->errorString()); return; } @@ -135,15 +159,26 @@ void RetrieveYoutubeUrl::parse(QByteArray text) { //qDebug("RetrieveYoutubeUrl::parse: replyString: %s",replyString.toLatin1().constData()); QString player; - QRegExp rxplayer("html5player-([\\d,\\w,-]+)\\.js"); + QRegExp rxplayer("html5player-([\\d,\\w,-]+)\\\\"); if (rxplayer.indexIn(replyString) != -1) { player = rxplayer.cap(1); qDebug("RetrieveYoutubeUrl::parse: html5player: %s", player.toLatin1().constData()); } + QString fmtArray; QRegExp regex("\\\"url_encoded_fmt_stream_map\\\"\\s*:\\s*\\\"([^\\\"]*)"); - regex.indexIn(replyString); - QString fmtArray = regex.cap(1); + if (regex.indexIn(replyString) != -1) { + fmtArray = regex.cap(1); + } + +#ifdef YT_DASH_SUPPORT + QRegExp regex2("\\\"adaptive_fmts\\\"\\s*:\\s*\\\"([^\\\"]*)"); + if (regex2.indexIn(replyString) != -1) { + if (!fmtArray.isEmpty()) fmtArray += ","; + fmtArray += regex2.cap(1); + } +#endif + fmtArray = sanitizeForUnicodePoint(fmtArray); fmtArray.replace(QRegExp("\\\\(.)"), "\\1"); @@ -215,15 +250,32 @@ void RetrieveYoutubeUrl::parse(QByteArray text) { q->removeAllQueryItems("fallback_host"); q->removeAllQueryItems("type"); + if (!q->hasQueryItem("ratebypass")) q->addQueryItem("ratebypass", "yes"); + if ((q->hasQueryItem("itag")) && (q->hasQueryItem("signature"))) { QString itag = q->queryItemValue("itag"); - q->removeAllQueryItems("itag"); // Remove duplicated itag - q->addQueryItem("itag", itag); + + // Remove duplicated queries + QPair <QString,QString> item; + QList<QPair<QString, QString> > items = q->queryItems(); + foreach(item, items) { + q->removeAllQueryItems(item.first); + q->addQueryItem(item.first, item.second); + } + #if QT_VERSION >= 0x050000 line.setQuery(q->query(QUrl::FullyDecoded)); #endif + + #ifdef YT_GET_VIDEOINFO + if (!line.toString().startsWith("https")) { + urlMap[itag.toInt()] = line.toString(); + } + #else urlMap[itag.toInt()] = line.toString(); - //qDebug("line: %s", line.toString().toLatin1().constData()); + #endif + + //qDebug("itag: %s line: %s", itag.toLatin1().constData(), line.toString().toLatin1().constData()); } } } @@ -254,6 +306,9 @@ void RetrieveYoutubeUrl::parse(QByteArray text) { if (!p_url.isNull()) { emit gotUrls(urlMap); emit gotPreferredUrl(p_url); + #ifdef YT_GET_VIDEOINFO + emit gotVideoInfo(urlMap, url_title, video_id); + #endif } else { emit gotEmptyList(); } @@ -317,7 +372,10 @@ bool RetrieveYoutubeUrl::isUrlSupported(const QString & url) { QString RetrieveYoutubeUrl::fullUrl(const QString & url) { QString r; QString ID = getVideoID(url); - if (!ID.isEmpty()) r = "http://www.youtube.com/watch?v=" + ID; + if (!ID.isEmpty()) { + QString scheme = use_https_main ? "https" : "http"; + r = scheme + "://www.youtube.com/watch?v=" + ID; + } return r; } @@ -328,13 +386,19 @@ void RetrieveYoutubeUrl::parseVideoInfo(QByteArray text) { #if QT_VERSION >= 0x050000 QUrlQuery all; all.setQuery(text); - QByteArray fmtArray = all.queryItemValue("url_encoded_fmt_stream_map").toLatin1(); #else QUrl all; all.setEncodedQuery(text); - QByteArray fmtArray = all.queryItemValue("url_encoded_fmt_stream_map").toLatin1(); #endif + QByteArray fmtArray; + fmtArray = all.queryItemValue("url_encoded_fmt_stream_map").toLatin1(); + +#ifdef YT_DASH_SUPPORT + if (!fmtArray.isEmpty()) fmtArray += ","; + fmtArray += all.queryItemValue("adaptive_fmts").toLatin1(); +#endif + /* qDebug("fmtArray: %s", fmtArray.constData()); return; @@ -399,15 +463,25 @@ void RetrieveYoutubeUrl::parseVideoInfo(QByteArray text) { } q->removeAllQueryItems("fallback_host"); q->removeAllQueryItems("type"); + + if (!q->hasQueryItem("ratebypass")) q->addQueryItem("ratebypass", "yes"); + if ((q->hasQueryItem("itag")) && (q->hasQueryItem("signature"))) { QString itag = q->queryItemValue("itag"); - q->removeAllQueryItems("itag"); // Remove duplicated itag - q->addQueryItem("itag", itag); + + // Remove duplicated queries + QPair <QString,QString> item; + QList<QPair<QString, QString> > items = q->queryItems(); + foreach(item, items) { + q->removeAllQueryItems(item.first); + q->addQueryItem(item.first, item.second); + } + #if QT_VERSION >= 0x050000 line.setQuery(q->query(QUrl::FullyDecoded)); #endif urlMap[itag.toInt()] = line.toString(); - //qDebug("line: %s", line.toString().toLatin1().constData()); + //qDebug("itag: %s line: %s", itag.toLatin1().constData(), line.toString().toLatin1().constData()); } } } @@ -430,6 +504,9 @@ void RetrieveYoutubeUrl::parseVideoInfo(QByteArray text) { if (!p_url.isNull()) { emit gotUrls(urlMap); emit gotPreferredUrl(p_url); + #ifdef YT_GET_VIDEOINFO + emit gotVideoInfo(urlMap, url_title, video_id); + #endif } else { emit gotEmptyList(); } @@ -506,6 +583,29 @@ QString RetrieveYoutubeUrl::findPreferredUrl(const QMap<int, QString>& urlMap, Q return p_url; } +#ifdef YT_DASH_SUPPORT +QString RetrieveYoutubeUrl::findBestAudio(const QMap<int, QString>& urlMap) { + QString url; + + url = urlMap.value(DASH_AUDIO_MP4_256, QString()); + if (!url.isEmpty()) return url; + + url = urlMap.value(DASH_AUDIO_WEBM_192, QString()); + if (!url.isEmpty()) return url; + + url = urlMap.value(DASH_AUDIO_MP4_128, QString()); + if (!url.isEmpty()) return url; + + url = urlMap.value(DASH_AUDIO_WEBM_128, QString()); + if (!url.isEmpty()) return url; + + url = urlMap.value(DASH_AUDIO_MP4_48, QString()); + if (!url.isEmpty()) return url; + + return url; +} +#endif + QString RetrieveYoutubeUrl::sanitizeForUnicodePoint(QString string) { QRegExp rx("\\\\u(\\d{4})"); while (rx.indexIn(string) != -1) { diff --git a/src/youtube/retrieveyoutubeurl.h b/src/youtube/retrieveyoutubeurl.h index d06e45b..c7dfe10 100644 --- a/src/youtube/retrieveyoutubeurl.h +++ b/src/youtube/retrieveyoutubeurl.h @@ -1,5 +1,5 @@ /* smplayer, GUI front-end for mplayer. - Copyright (C) 2006-2014 Ricardo Villalba <rvm@users.sourceforge.net> + Copyright (C) 2006-2013 Ricardo Villalba <rvm@users.sourceforge.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include <QMap> #define YT_GET_VIDEOINFO +//#define YT_DASH_SUPPORT class RetrieveYoutubeUrl : public QObject { @@ -31,8 +32,13 @@ class RetrieveYoutubeUrl : public QObject public: enum Quality { FLV_240p = 5, MP4_360p = 18, MP4_720p = 22, FLV_360p = 34, - FLV_480p = 35, MP4_1080p = 37, WEBM_360p = 43, - WEBM_480p = 44, WEBM_720p = 45, WEBM_1080p = 46 }; + FLV_480p = 35, MP4_1080p = 37, WEBM_360p = 43, + WEBM_480p = 44, WEBM_720p = 45, WEBM_1080p = 46, + DASH_AUDIO_MP4_48 = 139, DASH_AUDIO_MP4_128 = 140, DASH_AUDIO_MP4_256 = 141, + DASH_AUDIO_WEBM_128 = 171, DASH_AUDIO_WEBM_192 = 172, + DASH_VIDEO_1080p = 137, DASH_VIDEO_720p = 136, + DASH_VIDEO_480p = 135, DASH_VIDEO_360p = 134, + DASH_VIDEO_240p = 133 }; RetrieveYoutubeUrl( QObject* parent = 0 ); ~RetrieveYoutubeUrl(); @@ -49,6 +55,10 @@ public: static QString findPreferredUrl(const QMap<int, QString>& urlMap, Quality q); QString findPreferredUrl(); +#ifdef YT_DASH_SUPPORT + static QString findBestAudio(const QMap<int, QString>& urlMap); +#endif + QString urlTitle() { return url_title; } QString latestPreferredUrl() { return latest_preferred_url; } QString origUrl() { return orig_url; } @@ -56,10 +66,18 @@ public: bool isUrlSupported(const QString & url); QString fullUrl(const QString & url); + static void setUseHttpsMain(bool b) { use_https_main = b; }; + static void setUseHttpsVi(bool b) { use_https_vi = b; }; + static bool useHttpsMain() { return use_https_main; }; + static bool useHttpsVi() { return use_https_vi; }; + signals: void gotUrls(const QMap<int, QString>&); void gotPreferredUrl(const QString &); void gotEmptyList(); +#ifdef YT_GET_VIDEOINFO + void gotVideoInfo(const QMap<int, QString>&, QString, QString); +#endif void connecting(QString host); void errorOcurred(int error_number, QString error_str); @@ -72,7 +90,7 @@ protected slots: #ifdef YT_GET_VIDEOINFO void gotVideoInfoResponse(); void parseVideoInfo(QByteArray text); - void fetchVideoInfoPage(); + void fetchVideoInfoPage(QString url = QString::null); #endif protected: @@ -87,6 +105,8 @@ protected: Quality preferred_quality; static QString user_agent; + static bool use_https_main; + static bool use_https_vi; #ifdef YT_GET_VIDEOINFO QString video_id; diff --git a/src/youtube/ytsig.cpp b/src/youtube/ytsig.cpp index d85de43..f0cb3c0 100644 --- a/src/youtube/ytsig.cpp +++ b/src/youtube/ytsig.cpp @@ -86,7 +86,7 @@ void YTSig::reloadScriptFile() { QRegExp rx("D: ([\\d,a-z,A-Z-]+)"); if (rx.indexIn(bytes)) { QByteArray d = rx.cap(1).toLatin1(); - qDebug("YTSig::reloadScriptFile: d: %s", d.constData()); + //qDebug("YTSig::reloadScriptFile: d: %s", d.constData()); parsed_ts = QByteArray::fromBase64(d); } |