mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-neutrino.git
synced 2025-08-28 16:01:10 +02:00
experimental yt cache (currently no gui integration)
Conflicts:
src/gui/moviebrowser.cpp
src/gui/movieinfo.cpp
src/system/Makefile.am
Origin commit data
------------------
Commit: 70e5e66327
Author: martii <m4rtii@gmx.de>
Date: 2013-06-12 (Wed, 12 Jun 2013)
This commit is contained in:
@@ -64,6 +64,7 @@
|
|||||||
#include <gui/customcolor.h>
|
#include <gui/customcolor.h>
|
||||||
#include <driver/record.h>
|
#include <driver/record.h>
|
||||||
#include <system/helpers.h>
|
#include <system/helpers.h>
|
||||||
|
#include <system/ytcache.h>
|
||||||
|
|
||||||
#include <timerdclient/timerdclient.h>
|
#include <timerdclient/timerdclient.h>
|
||||||
#include <system/hddstat.h>
|
#include <system/hddstat.h>
|
||||||
@@ -1084,6 +1085,10 @@ int CMovieBrowser::exec(const char* path)
|
|||||||
TRACE("[mb] stop: %d start:%d \r\n",m_movieSelectionHandler->bookmarks.lastPlayStop,m_movieSelectionHandler->bookmarks.start);
|
TRACE("[mb] stop: %d start:%d \r\n",m_movieSelectionHandler->bookmarks.lastPlayStop,m_movieSelectionHandler->bookmarks.start);
|
||||||
m_currentStartPos = showStartPosSelectionMenu(); // display start menu m_currentStartPos =
|
m_currentStartPos = showStartPosSelectionMenu(); // display start menu m_currentStartPos =
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (show_mode == MB_SHOW_YT)
|
||||||
|
cYTCache::getInstance()->useCachedCopy(m_movieSelectionHandler);
|
||||||
|
|
||||||
if(m_currentStartPos >= 0) {
|
if(m_currentStartPos >= 0) {
|
||||||
playing_info = m_movieSelectionHandler;
|
playing_info = m_movieSelectionHandler;
|
||||||
TRACE("[mb] start pos: %d s\r\n",m_currentStartPos);
|
TRACE("[mb] start pos: %d s\r\n",m_currentStartPos);
|
||||||
@@ -1093,6 +1098,10 @@ int CMovieBrowser::exec(const char* path)
|
|||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ((show_mode == MB_SHOW_YT) && (msg == CRCInput::RC_record) && m_movieSelectionHandler)
|
||||||
|
{
|
||||||
|
cYTCache::getInstance()->addToCache(m_movieSelectionHandler);
|
||||||
|
}
|
||||||
else if (msg == CRCInput::RC_home)
|
else if (msg == CRCInput::RC_home)
|
||||||
{
|
{
|
||||||
loop = false;
|
loop = false;
|
||||||
@@ -1280,8 +1289,8 @@ std::string CMovieBrowser::getScreenshotName(std::string movie)
|
|||||||
std::string ext;
|
std::string ext;
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
|
||||||
size_t found = movie.rfind(".ts");
|
size_t found = movie.find_last_of(".");
|
||||||
if ((found == string::npos) || (found != (movie.length() - 3)))
|
if (found == string::npos)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
vector<std::string>::iterator it = PicExts.begin();
|
vector<std::string>::iterator it = PicExts.begin();
|
||||||
@@ -3692,9 +3701,9 @@ void CMovieBrowser::loadYTitles(int mode, std::string search, std::string id)
|
|||||||
movieInfo.tfile = ylist[i].tfile;
|
movieInfo.tfile = ylist[i].tfile;
|
||||||
movieInfo.ytdate = ylist[i].published;
|
movieInfo.ytdate = ylist[i].published;
|
||||||
movieInfo.ytid = ylist[i].id;
|
movieInfo.ytid = ylist[i].id;
|
||||||
|
|
||||||
movieInfo.file.Name = ylist[i].title;
|
movieInfo.file.Name = ylist[i].title;
|
||||||
movieInfo.file.Url = ylist[i].GetUrl(m_settings.ytquality, false);
|
movieInfo.ytitag = m_settings.ytquality;
|
||||||
|
movieInfo.file.Url = ylist[i].GetUrl(&movieInfo.ytitag, false);
|
||||||
movieInfo.file.Time = toEpoch(movieInfo.ytdate);
|
movieInfo.file.Time = toEpoch(movieInfo.ytdate);
|
||||||
m_vMovieInfo.push_back(movieInfo);
|
m_vMovieInfo.push_back(movieInfo);
|
||||||
}
|
}
|
||||||
@@ -4371,7 +4380,7 @@ static void save_info(CMovieInfo * cmovie, MI_MOVIE_INFO * minfo, char * dpart,
|
|||||||
{
|
{
|
||||||
MI_MOVIE_INFO ninfo;
|
MI_MOVIE_INFO ninfo;
|
||||||
|
|
||||||
cmovie->copy(minfo, &ninfo);
|
ninfo = *minfo;
|
||||||
ninfo.file.Name = dpart;
|
ninfo.file.Name = dpart;
|
||||||
ninfo.file.Size = spos;
|
ninfo.file.Size = spos;
|
||||||
ninfo.length = spos/secsize/60;
|
ninfo.length = spos/secsize/60;
|
||||||
|
@@ -97,24 +97,13 @@ bool CMovieInfo::convertTs2XmlName(char *char_filename, int size)
|
|||||||
************************************************************************/
|
************************************************************************/
|
||||||
bool CMovieInfo::convertTs2XmlName(std::string * filename)
|
bool CMovieInfo::convertTs2XmlName(std::string * filename)
|
||||||
{
|
{
|
||||||
//TRACE("[mi]->convertTs2XmlName\r\n");
|
size_t lastdot = filename->find_last_of(".");
|
||||||
int bytes = filename->find(".ts");
|
if (lastdot != string::npos) {
|
||||||
bool result = false;
|
filename->erase(lastdot + 1);
|
||||||
|
filename->append("xml");
|
||||||
if (bytes != -1) {
|
return true;
|
||||||
if (bytes > 3) {
|
|
||||||
if ((*filename)[bytes - 4] == '.') {
|
|
||||||
bytes = bytes - 4;
|
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
*filename = filename->substr(0, bytes) + ".xml";
|
|
||||||
result = true;
|
|
||||||
} else // not a TS file, return!!!!!
|
|
||||||
{
|
|
||||||
//TRACE(" not a TS file ");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@@ -886,6 +875,7 @@ void CMovieInfo::clearMovieInfo(MI_MOVIE_INFO * movie_info)
|
|||||||
timePlay.tm_mon = 1;
|
timePlay.tm_mon = 1;
|
||||||
|
|
||||||
movie_info->file.Name = "";
|
movie_info->file.Name = "";
|
||||||
|
movie_info->file.Url = "";
|
||||||
movie_info->file.Size = 0; // Megabytes
|
movie_info->file.Size = 0; // Megabytes
|
||||||
movie_info->file.Time = mktime(&timePlay);
|
movie_info->file.Time = mktime(&timePlay);
|
||||||
movie_info->dateOfLastPlay = mktime(&timePlay); // (date, month, year)
|
movie_info->dateOfLastPlay = mktime(&timePlay); // (date, month, year)
|
||||||
@@ -925,6 +915,7 @@ void CMovieInfo::clearMovieInfo(MI_MOVIE_INFO * movie_info)
|
|||||||
movie_info->tfile.clear();
|
movie_info->tfile.clear();
|
||||||
movie_info->ytdate.clear();
|
movie_info->ytdate.clear();
|
||||||
movie_info->ytid.clear();
|
movie_info->ytid.clear();
|
||||||
|
movie_info->ytitag = 0;
|
||||||
movie_info->marked = false;
|
movie_info->marked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1028,52 +1019,57 @@ bool CMovieInfo::saveFile_vlc(const CFile & /*file*/, const char */*text*/, cons
|
|||||||
*
|
*
|
||||||
* */
|
* */
|
||||||
|
|
||||||
void CMovieInfo::copy(MI_MOVIE_INFO * src, MI_MOVIE_INFO * dst)
|
#if 0
|
||||||
|
MI_MOVIE_INFO& MI_MOVIE_INFO::operator=(const MI_MOVIE_INFO& src)
|
||||||
{
|
{
|
||||||
//TRACE("[mi]->clearMovieInfo \r\n");
|
file.Name = src.file.Name;
|
||||||
|
file.Url = src.file.Url;
|
||||||
|
file.Size = src.file.Size;
|
||||||
|
file.Time = src.file.Time;
|
||||||
|
dateOfLastPlay = src.dateOfLastPlay;
|
||||||
|
dirItNr = src.dirItNr;
|
||||||
|
genreMajor = src.genreMajor;
|
||||||
|
genreMinor = src.genreMinor;
|
||||||
|
length = src.length;
|
||||||
|
quality = src.quality;
|
||||||
|
productionDate = src.productionDate;
|
||||||
|
parentalLockAge = src.parentalLockAge;
|
||||||
|
format = src.format;
|
||||||
|
audio = src.audio;
|
||||||
|
|
||||||
dst->file.Name = src->file.Name;
|
epgId = src.epgId;
|
||||||
dst->file.Size = src->file.Size;
|
epgEpgId = src.epgEpgId;
|
||||||
dst->file.Time = src->file.Time;
|
epgMode = src.epgMode;
|
||||||
dst->dateOfLastPlay = src->dateOfLastPlay;
|
epgVideoPid = src.epgVideoPid;
|
||||||
dst->dirItNr = src->dirItNr;
|
VideoType = src.VideoType;
|
||||||
dst->genreMajor = src->genreMajor;
|
epgVTXPID = src.epgVTXPID;
|
||||||
dst->genreMinor = src->genreMinor;
|
|
||||||
dst->length = src->length;
|
|
||||||
dst->quality = src->quality;
|
|
||||||
dst->productionDate = src->productionDate;
|
|
||||||
dst->parentalLockAge = src->parentalLockAge;
|
|
||||||
dst->format = src->format;
|
|
||||||
dst->audio = src->audio;
|
|
||||||
|
|
||||||
dst->epgId = src->epgId;
|
productionCountry = src.productionCountry;
|
||||||
dst->epgEpgId = src->epgEpgId;
|
epgTitle = src.epgTitle;
|
||||||
dst->epgMode = src->epgMode;
|
epgInfo1 = src.epgInfo1;
|
||||||
dst->epgVideoPid = src->epgVideoPid;
|
epgInfo2 = src.epgInfo2;
|
||||||
dst->VideoType = src->VideoType;
|
epgChannel = src.epgChannel;
|
||||||
dst->epgVTXPID = src->epgVTXPID;
|
serieName = src.serieName;
|
||||||
|
bookmarks.end = src.bookmarks.end;
|
||||||
|
bookmarks.start = src.bookmarks.start;
|
||||||
|
bookmarks.lastPlayStop = src.bookmarks.lastPlayStop;
|
||||||
|
|
||||||
dst->productionCountry = src->productionCountry;
|
for (unsigned int i = 0; i < MI_MOVIE_BOOK_USER_MAX; i++) {
|
||||||
dst->epgTitle = src->epgTitle;
|
bookmarks.user[i].pos = src.bookmarks.user[i].pos;
|
||||||
dst->epgInfo1 = src->epgInfo1;
|
bookmarks.user[i].length = src.bookmarks.user[i].length;
|
||||||
dst->epgInfo2 = src->epgInfo2;
|
bookmarks.user[i].name = src.bookmarks.user[i].name;
|
||||||
dst->epgChannel = src->epgChannel;
|
|
||||||
dst->serieName = src->serieName;
|
|
||||||
dst->bookmarks.end = src->bookmarks.end;
|
|
||||||
dst->bookmarks.start = src->bookmarks.start;
|
|
||||||
dst->bookmarks.lastPlayStop = src->bookmarks.lastPlayStop;
|
|
||||||
|
|
||||||
for (int i = 0; i < MI_MOVIE_BOOK_USER_MAX; i++) {
|
|
||||||
dst->bookmarks.user[i].pos = src->bookmarks.user[i].pos;
|
|
||||||
dst->bookmarks.user[i].length = src->bookmarks.user[i].length;
|
|
||||||
dst->bookmarks.user[i].name = src->bookmarks.user[i].name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < src->audioPids.size(); i++) {
|
for (unsigned int i = 0; i < src.audioPids.size(); i++) {
|
||||||
EPG_AUDIO_PIDS audio_pids;
|
EPG_AUDIO_PIDS audio_pids;
|
||||||
audio_pids.epgAudioPid = src->audioPids[i].epgAudioPid;
|
audio_pids.epgAudioPid = src.audioPids[i].epgAudioPid;
|
||||||
audio_pids.epgAudioPidName = src->audioPids[i].epgAudioPidName;
|
audio_pids.epgAudioPidName = src.audioPids[i].epgAudioPidName;
|
||||||
audio_pids.atype = src->audioPids[i].atype;
|
audio_pids.atype = src.audioPids[i].atype;
|
||||||
dst->audioPids.push_back(audio_pids);
|
audioPids.push_back(audio_pids);
|
||||||
}
|
}
|
||||||
|
ytdate = src.ytdate;
|
||||||
|
ytid = src.ytid;
|
||||||
|
ytitag = src.ytitag;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@@ -46,12 +46,15 @@
|
|||||||
#ifndef MOVIEINFO_H_
|
#ifndef MOVIEINFO_H_
|
||||||
#define MOVIEINFO_H_
|
#define MOVIEINFO_H_
|
||||||
|
|
||||||
|
#define __USE_FILE_OFFSET64 1
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <stdint.h>
|
||||||
#include "driver/file.h"
|
#include "driver/file.h"
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
@@ -140,8 +143,10 @@ typedef struct
|
|||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
typedef struct
|
class MI_MOVIE_INFO
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
// MI_MOVIE_INFO &operator=(const MI_MOVIE_INFO& src);
|
||||||
CFile file; // not stored in xml
|
CFile file; // not stored in xml
|
||||||
std::string productionCountry; // user defined Country (not from EPG yet, but might be possible)
|
std::string productionCountry; // user defined Country (not from EPG yet, but might be possible)
|
||||||
std::string epgTitle; // plain movie name, usually filled by EPG
|
std::string epgTitle; // plain movie name, usually filled by EPG
|
||||||
@@ -173,7 +178,8 @@ typedef struct
|
|||||||
std::string tfile; // thumbnail/cover file name
|
std::string tfile; // thumbnail/cover file name
|
||||||
std::string ytdate; // yt published
|
std::string ytdate; // yt published
|
||||||
std::string ytid; // yt published
|
std::string ytid; // yt published
|
||||||
} MI_MOVIE_INFO;
|
int ytitag; // youtube quality profile
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::vector<MI_MOVIE_INFO> MI_MOVIE_LIST;
|
typedef std::vector<MI_MOVIE_INFO> MI_MOVIE_LIST;
|
||||||
typedef std::vector<MI_MOVIE_INFO*> P_MI_MOVIE_LIST;
|
typedef std::vector<MI_MOVIE_INFO*> P_MI_MOVIE_LIST;
|
||||||
@@ -192,7 +198,6 @@ class CMovieInfo
|
|||||||
void printDebugMovieInfo(MI_MOVIE_INFO& movie_info); // print movie info on debug channel (RS232)
|
void printDebugMovieInfo(MI_MOVIE_INFO& movie_info); // print movie info on debug channel (RS232)
|
||||||
void clearMovieInfo(MI_MOVIE_INFO* movie_info); // Set movie info structure to initial values
|
void clearMovieInfo(MI_MOVIE_INFO* movie_info); // Set movie info structure to initial values
|
||||||
bool addNewBookmark(MI_MOVIE_INFO* movie_info,MI_BOOKMARK &new_bookmark); // add a new bookmark to the given movie info. If there is no space false is returned
|
bool addNewBookmark(MI_MOVIE_INFO* movie_info,MI_BOOKMARK &new_bookmark); // add a new bookmark to the given movie info. If there is no space false is returned
|
||||||
void copy(MI_MOVIE_INFO* src, MI_MOVIE_INFO* dst);
|
|
||||||
|
|
||||||
private:// Functions
|
private:// Functions
|
||||||
bool parseXmlTree (char* text, MI_MOVIE_INFO* movie_info); // this is the 'good' function, but it needs the xmllib which is not currently linked within neutrino. Might be to slow as well. If used, add bookmark parsing
|
bool parseXmlTree (char* text, MI_MOVIE_INFO* movie_info); // this is the 'good' function, but it needs the xmllib which is not currently linked within neutrino. Might be to slow as well. If used, add bookmark parsing
|
||||||
|
@@ -44,5 +44,6 @@ libneutrino_system_a_SOURCES = \
|
|||||||
ping.cpp \
|
ping.cpp \
|
||||||
settings.cpp \
|
settings.cpp \
|
||||||
sysload.cpp \
|
sysload.cpp \
|
||||||
|
ytcache.cpp \
|
||||||
ytparser.cpp \
|
ytparser.cpp \
|
||||||
setting_helpers.cpp
|
setting_helpers.cpp
|
||||||
|
@@ -509,7 +509,7 @@ bool CFileHelpers::copyFile(const char *Src, const char *Dst, mode_t mode)
|
|||||||
unlink(Dst);
|
unlink(Dst);
|
||||||
if ((fd1 = open(Src, O_RDONLY)) < 0)
|
if ((fd1 = open(Src, O_RDONLY)) < 0)
|
||||||
return false;
|
return false;
|
||||||
if ((fd2 = open(Dst, O_WRONLY | O_CREAT, 0666)) < 0) {
|
if ((fd2 = open(Dst, O_WRONLY | O_CREAT, mode)) < 0) {
|
||||||
close(fd1);
|
close(fd1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -574,7 +574,6 @@ bool CFileHelpers::copyFile(const char *Src, const char *Dst, mode_t mode)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
chmod(Dst, mode);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
254
src/system/ytcache.cpp
Normal file
254
src/system/ytcache.cpp
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
/*
|
||||||
|
ytcache.cpp -- cache youtube movies
|
||||||
|
|
||||||
|
Copyright (C) 2013 martii
|
||||||
|
|
||||||
|
License: GPL
|
||||||
|
|
||||||
|
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
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ytcache.h"
|
||||||
|
#include <OpenThreads/ScopedLock>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include <curl/easy.h>
|
||||||
|
#if LIBCURL_VERSION_NUM < 0x071507
|
||||||
|
#include <curl/types.h>
|
||||||
|
#endif
|
||||||
|
#define URL_TIMEOUT 60
|
||||||
|
|
||||||
|
#include "helpers.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include <global.h>
|
||||||
|
|
||||||
|
static cYTCache *instance = NULL;
|
||||||
|
|
||||||
|
cYTCache::cYTCache(void)
|
||||||
|
{
|
||||||
|
cancelled = false;
|
||||||
|
thread = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cYTCache::~cYTCache(void)
|
||||||
|
{
|
||||||
|
instance = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cYTCache *cYTCache::getInstance(void)
|
||||||
|
{
|
||||||
|
if (!instance)
|
||||||
|
instance = new cYTCache();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cYTCache::getName(MI_MOVIE_INFO *mi, std::string ext)
|
||||||
|
{
|
||||||
|
char ytitag[10];
|
||||||
|
snprintf(ytitag, sizeof(ytitag), "%d", mi->ytitag);
|
||||||
|
return g_settings.downloadcache_dir + "/" + mi->ytid + "-" + std::string(ytitag) + "." + ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cYTCache::useCachedCopy(MI_MOVIE_INFO *mi)
|
||||||
|
{
|
||||||
|
std::string cache = getName(mi);
|
||||||
|
if (!access(cache.c_str(), R_OK)) {
|
||||||
|
mi->file.Url = cache;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cYTCache::curlProgress(void *clientp, double /*dltotal*/, double /*dlnow*/, double /*ultotal*/, double /*ulnow*/)
|
||||||
|
{
|
||||||
|
cYTCache *caller = (cYTCache *) clientp;
|
||||||
|
if (caller->cancelled)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cYTCache::download(MI_MOVIE_INFO *mi)
|
||||||
|
{
|
||||||
|
std::string file = getName(mi);
|
||||||
|
std::string tmpfile = file + ".tmp";
|
||||||
|
|
||||||
|
if (!access(file.c_str(), R_OK) || !access(tmpfile.c_str(), R_OK))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
FILE * fp = fopen(file.c_str(), "wb");
|
||||||
|
if (!fp) {
|
||||||
|
perror(file.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CURL *curl = curl_easy_init();
|
||||||
|
if (!curl) {
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_easy_setopt(curl, CURLOPT_URL, mi->file.Url.c_str());
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FILE, fp);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_TIMEOUT, URL_TIMEOUT);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, (long)1);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, cYTCache::curlProgress);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, this);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, (long)0);
|
||||||
|
|
||||||
|
char cerror[CURL_ERROR_SIZE];
|
||||||
|
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, cerror);
|
||||||
|
|
||||||
|
CURLcode res = curl_easy_perform(curl);
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
fprintf(stderr, "curl error: %s\n", cerror);
|
||||||
|
unlink(tmpfile.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rename (tmpfile.c_str(), file.c_str());
|
||||||
|
CMovieInfo cMovieInfo;
|
||||||
|
CFile File;
|
||||||
|
File.Name = getName(mi, "xml");
|
||||||
|
cMovieInfo.convertTs2XmlName(&File.Name);
|
||||||
|
cMovieInfo.saveMovieInfo(*mi, &File);
|
||||||
|
std::string thumbnail_dst = getName(mi, "jpg");
|
||||||
|
std::string thumbnail_src = "/tmp/ytparser/" + mi->ytid + ".jpg";
|
||||||
|
CFileHelpers::getInstance()->copyFile(thumbnail_src.c_str(), thumbnail_dst.c_str(), 0644);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cYTCache::downloadThread(void *arg) {
|
||||||
|
cYTCache *caller = (cYTCache *)arg;
|
||||||
|
|
||||||
|
while (caller->thread) {
|
||||||
|
MI_MOVIE_INFO mi;
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(caller->mutex);
|
||||||
|
if (caller->pending.empty()) {
|
||||||
|
caller->cancelled = false;
|
||||||
|
caller->thread = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mi = caller->pending.front();
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "download start: %s\n", mi.file.Url.c_str());
|
||||||
|
|
||||||
|
bool res = caller->download(&mi);
|
||||||
|
|
||||||
|
fprintf(stderr, "download end: %s %s\n", mi.file.Url.c_str(), res ? "succeeded" : "failed");
|
||||||
|
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(caller->mutex);
|
||||||
|
if (res)
|
||||||
|
caller->done.push_front(mi);
|
||||||
|
else
|
||||||
|
caller->failed.push_front(mi);
|
||||||
|
caller->cancelled = false;
|
||||||
|
if (caller->pending.empty())
|
||||||
|
caller->thread = 0;
|
||||||
|
else
|
||||||
|
caller->pending.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cYTCache::addToCache(MI_MOVIE_INFO *mi)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||||
|
pending.push_back(*mi);
|
||||||
|
|
||||||
|
if (!thread) {
|
||||||
|
if (pthread_create(&thread, NULL, downloadThread, this)) {
|
||||||
|
perror("pthread_create");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pthread_detach(thread);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cYTCache::cancel(MI_MOVIE_INFO *mi)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||||
|
if (pending.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (compareMovieInfo(mi, &pending.front())) {
|
||||||
|
cancelled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (std::list<MI_MOVIE_INFO>::iterator it = pending.begin(); it != pending.end(); ++it)
|
||||||
|
if (compareMovieInfo(&(*it), mi)) {
|
||||||
|
pending.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cYTCache::cancelAll(void)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||||
|
if (pending.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
cancelled = true;
|
||||||
|
while (thread)
|
||||||
|
usleep(100000);
|
||||||
|
cancelled = false;
|
||||||
|
pending.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<MI_MOVIE_INFO> cYTCache::getFailed(bool clear)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||||
|
std::list<MI_MOVIE_INFO> res = failed;
|
||||||
|
if (clear)
|
||||||
|
failed.clear();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<MI_MOVIE_INFO> cYTCache::getDone(bool clear)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||||
|
std::list<MI_MOVIE_INFO> res = done;
|
||||||
|
if (clear)
|
||||||
|
done.clear();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cYTCache::clearFailed(void)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||||
|
failed.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cYTCache::clearDone(void)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> m_lock(mutex);
|
||||||
|
done.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cYTCache::compareMovieInfo(MI_MOVIE_INFO *a, MI_MOVIE_INFO *b)
|
||||||
|
{
|
||||||
|
return a->ytid == b->ytid && a->ytitag == b->ytitag;
|
||||||
|
return true;
|
||||||
|
}
|
62
src/system/ytcache.h
Normal file
62
src/system/ytcache.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
ytcache.h -- cache youtube movies
|
||||||
|
|
||||||
|
Copyright (C) 2013 martii
|
||||||
|
|
||||||
|
License: GPL
|
||||||
|
|
||||||
|
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
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __YTCACHE_H__
|
||||||
|
#define __YTCACHE_H__
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/Condition>
|
||||||
|
|
||||||
|
#include <gui/movieinfo.h>
|
||||||
|
|
||||||
|
class cYTCache
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
pthread_t thread;
|
||||||
|
bool cancelled;
|
||||||
|
std::list<MI_MOVIE_INFO> pending;
|
||||||
|
std::list<MI_MOVIE_INFO> done;
|
||||||
|
std::list<MI_MOVIE_INFO> failed;
|
||||||
|
OpenThreads::Mutex mutex;
|
||||||
|
bool download(MI_MOVIE_INFO *mi);
|
||||||
|
std::string getName(MI_MOVIE_INFO *mi, std::string ext = "mp4");
|
||||||
|
static void *downloadThread(void *arg);
|
||||||
|
static int curlProgress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
|
||||||
|
bool compareMovieInfo(MI_MOVIE_INFO *a, MI_MOVIE_INFO *b);
|
||||||
|
public:
|
||||||
|
static cYTCache *getInstance();
|
||||||
|
cYTCache();
|
||||||
|
~cYTCache();
|
||||||
|
bool useCachedCopy(MI_MOVIE_INFO *mi);
|
||||||
|
bool addToCache(MI_MOVIE_INFO *mi);
|
||||||
|
void cancel(MI_MOVIE_INFO *mi);
|
||||||
|
void cancelAll(void);
|
||||||
|
std::list<MI_MOVIE_INFO> getDone(bool clear = false);
|
||||||
|
std::list<MI_MOVIE_INFO> getFailed(bool clear = false);
|
||||||
|
void clearDone(void);
|
||||||
|
void clearFailed(void);
|
||||||
|
};
|
||||||
|
#endif
|
@@ -63,27 +63,29 @@ void cYTVideoInfo::Dump()
|
|||||||
printf("===================================================================\n");
|
printf("===================================================================\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string cYTVideoInfo::GetUrl(int fmt, bool mandatory)
|
std::string cYTVideoInfo::GetUrl(int *fmt, bool mandatory)
|
||||||
{
|
{
|
||||||
|
int default_fmt = 0;
|
||||||
|
if (!*fmt)
|
||||||
|
fmt = &default_fmt;
|
||||||
|
|
||||||
yt_urlmap_iterator_t it;
|
yt_urlmap_iterator_t it;
|
||||||
if (fmt) {
|
if (*fmt) {
|
||||||
if ((it = formats.find(fmt)) != formats.end())
|
if ((it = formats.find(*fmt)) != formats.end()) {
|
||||||
return it->second.GetUrl();
|
return it->second.GetUrl();
|
||||||
if (mandatory)
|
}
|
||||||
|
if (mandatory) {
|
||||||
|
*fmt = 0;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
if ((it = formats.find(37)) != formats.end()) // 1080p MP4
|
}
|
||||||
return it->second.GetUrl();
|
|
||||||
if ((it = formats.find(22)) != formats.end()) // 720p MP4
|
int itags[] = { 37 /* 1080p MP4*/, 22 /* 720p MP4 */, 18 /* 270p/360p MP4 */, 0 };
|
||||||
return it->second.GetUrl();
|
for (int *fmtp = itags; *fmtp; fmtp++)
|
||||||
#if 0
|
if ((it = formats.find(*fmtp)) != formats.end()) {
|
||||||
if ((it = formats.find(35)) != formats.end()) // 480p FLV
|
*fmt = *fmtp;
|
||||||
return it->second.GetUrl();
|
|
||||||
if ((it = formats.find(34)) != formats.end()) // 360p FLV
|
|
||||||
return it->second.GetUrl();
|
|
||||||
#endif
|
|
||||||
if ((it = formats.find(18)) != formats.end()) // 270p/360p MP4
|
|
||||||
return it->second.GetUrl();
|
return it->second.GetUrl();
|
||||||
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -62,7 +62,7 @@ class cYTVideoInfo
|
|||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
void Dump();
|
void Dump();
|
||||||
std::string GetUrl(int fmt = 0, bool mandatory = true);
|
std::string GetUrl(int *fmt = NULL, bool mandatory = true);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user