- ytparser: fix youtube playback; change to APIv3

This commit is contained in:
FlatTV
2015-06-01 12:00:00 +02:00
committed by svenhoefer
parent 76e26c0b98
commit acf3453fcd
6 changed files with 94 additions and 128 deletions

View File

@@ -104,6 +104,7 @@ neutrino_LDADD = \
$(top_builddir)/lib/connection/libtuxbox-connection.a \
$(top_builddir)/lib/libeventserver/libtuxbox-eventserver.a \
$(top_builddir)/lib/xmltree/libtuxbox-xmltree.a \
$(top_builddir)/lib/jsoncpp/libjsoncpp.a \
$(top_builddir)/lib/libnet/libtuxbox-net.a \
$(top_builddir)/lib/libmd5sum/libtuxbox-md5sum.a \
$(top_builddir)/lib/libtuxtxt/libtuxtxt.a \

View File

@@ -795,6 +795,7 @@ int CNeutrinoApp::loadSetup(const char * fname)
//Movie-Player
g_settings.movieplayer_repeat_on = configfile.getInt32("movieplayer_repeat_on", CMoviePlayerGui::REPEAT_OFF);
g_settings.youtube_dev_id = configfile.getString("youtube_dev_id","XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
//Filebrowser
g_settings.filebrowser_showrights = configfile.getInt32("filebrowser_showrights", 1);
@@ -1255,6 +1256,7 @@ void CNeutrinoApp::saveSetup(const char * fname)
//Movie-Player
configfile.setInt32( "movieplayer_repeat_on", g_settings.movieplayer_repeat_on );
configfile.setString( "youtube_dev_id", g_settings.youtube_dev_id );
//Filebrowser
configfile.setInt32("filebrowser_showrights", g_settings.filebrowser_showrights);

View File

@@ -16,6 +16,7 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/lib/libconfigfile \
-I$(top_srcdir)/lib/libmd5sum \
-I$(top_srcdir)/lib/xmltree \
-I$(top_srcdir)/lib/jsoncpp/include \
@SIGC_CFLAGS@ \
@FREETYPE_CFLAGS@

View File

@@ -682,6 +682,7 @@ struct SNeutrinoSettings
//movieplayer
int movieplayer_repeat_on;
std::string youtube_dev_id;
//zapit setup
std::string StartChannelTV;

View File

@@ -27,6 +27,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <fstream>
#include <set>
#include <map>
@@ -39,6 +40,7 @@
#include "helpers.h"
#include "set_threadname.h"
#include <global.h>
#include <json/json.h>
#include "ytparser.h"
#include "ytcache.h"
@@ -50,6 +52,7 @@
#define URL_TIMEOUT 60
static int itags[] = { 37 /* 1080p MP4 */, 22 /* 720p MP4 */, 18 /* 270p/360p MP4 */, 0 };
std::string cYTVideoUrl::GetUrl()
{
std::string fullurl = url;
@@ -133,6 +136,7 @@ bool cYTFeedParser::getUrl(std::string &url, std::string &answer, CURL *_curl_ha
curl_easy_setopt(_curl_handle, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(_curl_handle, CURLOPT_TIMEOUT, URL_TIMEOUT);
curl_easy_setopt(_curl_handle, CURLOPT_NOSIGNAL, (long)1);
curl_easy_setopt(_curl_handle, CURLOPT_SSL_VERIFYPEER, false);
if(!g_settings.softupdate_proxyserver.empty()) {
curl_easy_setopt(_curl_handle, CURLOPT_PROXY, g_settings.softupdate_proxyserver.c_str());
@@ -173,6 +177,7 @@ bool cYTFeedParser::DownloadUrl(std::string &url, std::string &file, CURL *_curl
curl_easy_setopt(_curl_handle, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(_curl_handle, CURLOPT_TIMEOUT, URL_TIMEOUT);
curl_easy_setopt(_curl_handle, CURLOPT_NOSIGNAL, (long)1);
curl_easy_setopt(_curl_handle, CURLOPT_SSL_VERIFYPEER, false);
if(!g_settings.softupdate_proxyserver.empty()) {
curl_easy_setopt(_curl_handle, CURLOPT_PROXY, g_settings.softupdate_proxyserver.c_str());
@@ -276,134 +281,79 @@ std::string cYTFeedParser::getXmlData(xmlNodePtr node)
return result;
}
bool cYTFeedParser::parseFeedXml(std::string &answer)
bool cYTFeedParser::parseFeedJSON(std::string &answer)
{
xmlDocPtr answer_parser = parseXmlFile(curfeedfile.c_str());
if (answer_parser == NULL)
answer_parser = parseXml(answer.c_str());
Json::Value root;
Json::Reader reader;
if (answer_parser == NULL) {
printf("failed to parse xml\n");
std::ostringstream ss;
std::ifstream fh(curfeedfile.c_str(),std::ifstream::in);
ss << fh.rdbuf();
std::string filedata = ss.str();
bool parsedSuccess = reader.parse(filedata,root,false);
if(!parsedSuccess)
{
parsedSuccess = reader.parse(answer,root,false);
}
if(!parsedSuccess)
{
printf("Failed to parse JSON\n");
printf("%s\n", reader.getFormattedErrorMessages().c_str());
return false;
}
next.clear();
prev.clear();
//TODO
total.clear();
start.clear();
xmlNodePtr entry = xmlDocGetRootElement(answer_parser);
entry = xmlChildrenNode(entry);
while (entry) {
std::string name = getXmlName(entry);
#ifdef DEBUG_PARSER
printf("entry: %s\n", name.c_str());
#endif
if (name == "openSearch:startIndex") {
start = getXmlData(entry);
printf("start %s\n", start.c_str());
} else if (name == "openSearch:totalResults") {
total = getXmlData(entry);
printf("total %s\n", total.c_str());
}
else if (name == "link") {
std::string link = getXmlAttr(entry, "rel");
if (link == "next") {
next = getXmlAttr(entry, "href");
printf(" next [%s]\n", next.c_str());
} else if (link == "previous") {
prev = getXmlAttr(entry, "href");
printf(" prev [%s]\n", prev.c_str());
}
}
else if (name != "entry") {
entry = xmlNextNode(entry);
continue;
}
xmlNodePtr node = xmlChildrenNode(entry);
cYTVideoInfo vinfo;
std::string thumbnail;
while (node) {
name = getXmlName(node);
#ifdef DEBUG_PARSER
printf(" node: %s\n", name.c_str());
#endif
if (name == "title") {
#ifdef DEBUG_PARSER
printf(" title [%s]\n", getXmlData(node).c_str());
#endif
vinfo.title = getXmlData(node);
}
else if (name == "published") {
vinfo.published = getXmlData(node).substr(0, 10);
}
else if (name == "author") {
xmlNodePtr author = xmlChildrenNode(node);
while(author) {
name = getXmlName(author);
if (name == "name") {
#ifdef DEBUG_PARSER
printf(" author [%s]\n", getXmlData(author).c_str());
#endif
vinfo.author = getXmlData(author);
}
author = xmlNextNode(author);
}
}
else if (name == "media:group") {
xmlNodePtr media = xmlChildrenNode(node);
while (media) {
name = getXmlName(media);
if (name == "media:description") {
vinfo.description = getXmlData(media).c_str();
}
else if (name == "media:category") {
if (vinfo.category.size() < 3)
vinfo.category = getXmlData(media).c_str();
}
else if (name == "yt:videoid") {
#ifdef DEBUG_PARSER
printf(" id [%s]\n", getXmlData(media).c_str());
#endif
vinfo.id = getXmlData(media).c_str();
}
else if (name == "media:thumbnail") {
/* save first found */
if (thumbnail.empty())
thumbnail = getXmlAttr(media, "url");
/* check wanted quality */
if (tquality == getXmlAttr(media, "yt:name")) {
vinfo.thumbnail = getXmlAttr(media, "url");
next = root.get("nextPageToken", "").asString();
prev = root.get("prevPageToken", "").asString();
cYTVideoInfo vinfo;
Json::Value elements = root["items"];
for(unsigned int i=0; i<elements.size();++i)
{
#ifdef DEBUG_PARSER
printf("vinfo.thumbnail [%s]\n", vinfo.thumbnail.c_str());
printf("=========================================================\n");
printf("Element %d in elements\n", i);
printf("%s\n", elements[i]);
#endif
}
}
else if (name == "yt:duration") {
vinfo.duration = atoi(getXmlAttr(media, "seconds").c_str());
}
#if 0
else if (name == "media:player") {
std::string url = getXmlAttr(media, "url");
printf(" media:player [%s]\n", url.c_str());
}
else if (name == "media:title") {
}
#endif
media = xmlNextNode(media);
}
}
node = xmlNextNode(node);
if(elements[i]["id"].type() == Json::objectValue) {
vinfo.id = elements[i]["id"].get("videoId", "").asString();
}
else if(elements[i]["id"].type() == Json::stringValue) {
vinfo.id = elements[i].get("id", "").asString();
}
vinfo.title = elements[i]["snippet"].get("title", "").asString();
vinfo.description = elements[i]["snippet"].get("description", "").asString();
vinfo.published = elements[i]["snippet"].get("publishedAt", "").asString().substr(0, 10);
std::string thumbnail = elements[i]["snippet"]["thumbnails"]["default"].get("url", "").asString();
// save thumbnail "default", if "high" not found
vinfo.thumbnail = elements[i]["snippet"]["thumbnails"]["high"].get("url", thumbnail).asString();
vinfo.author = elements[i]["snippet"].get("channelTitle", "unkown").asString();
vinfo.category = "";
vinfo.duration = 0;
#ifdef DEBUG_PARSER
printf("prevPageToken: %s\n", prevPageToken.c_str());
printf("nextPageToken: %s\n", nextPageToken.c_str());
printf("vinfo.id: %s\n", vinfo.id.c_str());
printf("vinfo.description: %s\n", vinfo.description.c_str());
printf("vinfo.published: %s\n", vinfo.published.c_str());
printf("vinfo.title: %s\n", vinfo.title.c_str());
printf("vinfo.thumbnail: %s\n", vinfo.thumbnail.c_str());
#endif
if (!vinfo.id.empty()) {
/* save first one, if wanted not found */
if (vinfo.thumbnail.empty())
vinfo.thumbnail = thumbnail;
vinfo.ret = false;
videos.push_back(vinfo);
}
entry = xmlNextNode(entry);
}
xmlFreeDoc(answer_parser);
GetVideoUrls();
@@ -507,46 +457,55 @@ bool cYTFeedParser::ParseFeed(std::string &url)
if (!getUrl(url, answer))
return false;
#endif
return parseFeedXml(answer);
return parseFeedJSON(answer);
}
bool cYTFeedParser::ParseFeed(yt_feed_mode_t mode, std::string search, std::string vid, yt_feed_orderby_t orderby)
{
std::string url = "http://gdata.youtube.com/feeds/api/standardfeeds/";
std::string answer;
std::string key = g_settings.youtube_dev_id;
std::string url = "https://www.googleapis.com/youtube/v3/search?";
bool append_res = true;
std::string trailer;
if (mode < FEED_LAST) {
switch(mode) {
//FIXME APIv3: we dont have the parameter "time".
case MOST_POPULAR:
default:
trailer = "&time=today";
//trailer = "&time=today";
curfeed = "&chart=mostPopular";
case MOST_POPULAR_ALL_TIME:
curfeed = "most_popular";
curfeed = "&chart=mostPopular";
break;
}
url = "https://www.googleapis.com/youtube/v3/videos?part=snippet";
if (!region.empty()) {
url += "&regionCode=";
url += region;
url += "/";
}
url += curfeed;
url += "?";
}
else if (mode == NEXT) {
if (next.empty())
return false;
url = next;
url = nextprevurl;
url += "&pageToken=";
url += next;
append_res = false;
}
else if (mode == PREV) {
if (prev.empty())
return false;
url = prev;
url = nextprevurl;
url += "&pageToken=";
url += prev;
append_res = false;
}
else if (mode == RELATED) {
if (vid.empty())
return false;
url = "http://gdata.youtube.com/feeds/api/videos/";
url = "https://www.googleapis.com/youtube/v3/videos/";
url += vid;
url += "/related?";
}
@@ -554,23 +513,24 @@ bool cYTFeedParser::ParseFeed(yt_feed_mode_t mode, std::string search, std::stri
if (search.empty())
return false;
encodeUrl(search);
url = "http://gdata.youtube.com/feeds/api/videos?q=";
url = "https://www.googleapis.com/youtube/v3/search?q=";
url += search;
url += "&";
const char *orderby_values[] = { "published", "relevance", "viewCount", "rating" };
url += "orderby=" + std::string(orderby_values[orderby & 3]) + "&";
url += "&part=snippet";
//FIXME locale for "title" and "videoCount"
const char *orderby_values[] = { "date","relevance","viewCount","rating","title","videoCount"};
url += "&order=" + std::string(orderby_values[orderby & 3]);
}
feedmode = mode;
if (append_res) {
url += "v=2&max-results=";
url += "&maxResults=";
char res[10];
sprintf(res, "%d", max_results);
url+= res;
url += "&key=" + key;
nextprevurl = url;
}
url += trailer;
return ParseFeed(url);
}

View File

@@ -81,6 +81,7 @@ class cYTFeedParser
std::string prev; // prev results
std::string start; // start index
std::string total; // total results
std::string nextprevurl; // url for next/prev
int feedmode;
int max_results;
@@ -106,7 +107,7 @@ class cYTFeedParser
static bool saveToFile(const char * name, std::string str);
bool getUrl(std::string &url, std::string &answer, CURL *_curl_handle = NULL);
bool DownloadUrl(std::string &url, std::string &file, CURL *_curl_handle = NULL);
bool parseFeedXml(std::string &answer);
bool parseFeedJSON(std::string &answer);
bool decodeVideoInfo(std::string &answer, cYTVideoInfo &vinfo);
bool supportedFormat(int fmt);
bool ParseFeed(std::string &url);