vdr-plugin-scraper2vdr/update.c

1373 lines
51 KiB
C
Raw Normal View History

2014-04-12 17:10:43 +02:00
#define __STL_CONFIG_H
#include <locale.h>
#include <vdr/videodir.h>
#include <vdr/tools.h>
#include <vdr/plugin.h>
2014-05-09 01:05:21 +02:00
#include "lib/config.h"
2014-04-12 17:10:43 +02:00
#include "config.h"
#include "tools.h"
#include "update.h"
extern cScraper2VdrConfig config;
cUpdate::cUpdate(cScrapManager *manager) : cThread("update thread started", true) {
2014-04-12 17:10:43 +02:00
connection = NULL;
vdrDb = NULL;
tEvents = NULL;
tSeries = NULL;
tEpisodes = NULL;
tSeriesMedia = NULL;
tSeriesActors = NULL;
tMovies = NULL;
tMovieActor = NULL;
tMovieActors = NULL;
tMovieMedia = NULL;
tRecordings = NULL;
2014-05-09 01:05:21 +02:00
selectReadScrapedEventsInit = 0;
selectReadScrapedEvents = 0;
selectImg = 0;
selectSeasonPoster = 0;
selectActors = 0;
selectActorThumbs = 0;
selectSeriesMedia = 0;
selectMovieActors = 0;
selectMovieActorThumbs = 0;
selectMovieMedia = 0;
selectMediaMovie = 0;
selectRecordings = 0;
selectCleanupRecordings = 0;
2014-04-12 17:10:43 +02:00
scrapManager = manager;
imgPathSeries = config.imageDir + "/series";
imgPathMovies = config.imageDir + "/movies";
lastScrap = 0;
forceUpdate = false;
forceRecordingUpdate = false;
forceVideoDirUpdate = false;
forceScrapInfoUpdate = false;
forceCleanupRecordingDb = false;
char* lang;
lang = setlocale(LC_CTYPE, 0);
if (lang) {
tell(0, "Set locale to '%s'", lang);
if ((strcasestr(lang, "UTF-8") != 0) || (strcasestr(lang, "UTF8") != 0)){
tell(0, "detected UTF-8");
withutf8 = yes;
}
} else {
tell(0, "Reseting locale for LC_CTYPE failed.");
}
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
cDbConnection::setEncoding(withutf8 ? "utf8": "latin1");
cDbConnection::setHost(config.mysqlHost.c_str());
cDbConnection::setPort(config.mysqlPort);
cDbConnection::setName(config.mysqlDBName.c_str());
cDbConnection::setUser(config.mysqlDBUser.c_str());
cDbConnection::setPass(config.mysqlDBPass.c_str());
cDbTable::setConfPath(cPlugin::ConfigDirectory("epg2vdr/"));
2014-05-09 01:05:21 +02:00
EPG2VDRConfig.loglevel = config.debug ? 2 : 1;
2014-04-12 17:10:43 +02:00
}
cUpdate::~cUpdate() {
if (loopActive)
Stop();
exitDb();
}
2014-05-09 01:05:21 +02:00
// global field definitions
cDBS::FieldDef imageSizeDef = { "media_content", cDBS::ffUInt, 0, 999, cDBS::ftData };
2014-04-12 17:10:43 +02:00
int cUpdate::initDb() {
int status = success;
if (!connection)
connection = new cDbConnection();
if (!connection)
return fail;
vdrDb = new cTableVdrs(connection);
if (vdrDb->open() != success)
return fail;
tEvents = new cTableEvents(connection);
if (tEvents->open() != success)
return fail;
tSeries = new cTableSeries(connection);
if (tSeries->open() != success)
return fail;
tEpisodes = new cTableSeriesEpisode(connection);
if (tEpisodes->open() != success)
return fail;
tSeriesMedia = new cTableSeriesMedia(connection);
if (tSeriesMedia->open() != success)
return fail;
tSeriesActors = new cTableSeriesActor(connection);
if (tSeriesActors->open() != success)
return fail;
tMovies = new cTableMovies(connection);
if (tMovies->open() != success)
return fail;
tMovieActor = new cTableMovieActor(connection);
if (tMovieActor->open() != success)
return fail;
tMovieActors = new cTableMovieActors(connection);
if (tMovieActors->open() != success)
return fail;
tMovieMedia = new cTableMovieMedia(connection);
if (tMovieMedia->open() != success)
return fail;
tRecordings = new cTableRecordings(connection);
if (tRecordings->open() != success)
return fail;
2014-05-09 01:05:21 +02:00
// --------------------
// prepare statements
//
selectReadScrapedEventsInit = new cDbStatement(tEvents);
selectReadScrapedEventsInit->build("select ");
selectReadScrapedEventsInit->bind(cTableEvents::fiEventId, cDBS::bndOut);
selectReadScrapedEventsInit->bind(cTableEvents::fiChannelId, cDBS::bndOut, ", ");
selectReadScrapedEventsInit->bind(cTableEvents::fiMasterId, cDBS::bndOut, ", ");
selectReadScrapedEventsInit->bind(cTableEvents::fiScrSeriesId, cDBS::bndOut, ", ");
selectReadScrapedEventsInit->bind(cTableEvents::fiScrSeriesEpisode, cDBS::bndOut, ", ");
selectReadScrapedEventsInit->bind(cTableEvents::fiScrMovieId, cDBS::bndOut, ", ");
selectReadScrapedEventsInit->bind(cTableEvents::fiScrSp, cDBS::bndOut, ", ");
selectReadScrapedEventsInit->build(" from %s where ", tEvents->TableName());
selectReadScrapedEventsInit->build(" ((%s is not null and %s > 0) ",
tEvents->getField(cTableEvents::fiScrSeriesId)->name,
tEvents->getField(cTableEvents::fiScrSeriesId)->name);
selectReadScrapedEventsInit->build(" or (%s is not null and %s > 0)) ",
tEvents->getField(cTableEvents::fiScrMovieId)->name,
tEvents->getField(cTableEvents::fiScrMovieId)->name);
selectReadScrapedEventsInit->build(" order by %s", tEvents->getField(cTableEvents::fiInsSp)->name);
status += selectReadScrapedEventsInit->prepare();
//
selectReadScrapedEvents = new cDbStatement(tEvents);
selectReadScrapedEvents->build("select ");
selectReadScrapedEvents->bind(cTableEvents::fiEventId, cDBS::bndOut);
selectReadScrapedEvents->bind(cTableEvents::fiChannelId, cDBS::bndOut, ", ");
selectReadScrapedEvents->bind(cTableEvents::fiMasterId, cDBS::bndOut, ", ");
selectReadScrapedEvents->bind(cTableEvents::fiScrSeriesId, cDBS::bndOut, ", ");
selectReadScrapedEvents->bind(cTableEvents::fiScrSeriesEpisode, cDBS::bndOut, ", ");
selectReadScrapedEvents->bind(cTableEvents::fiScrMovieId, cDBS::bndOut, ", ");
selectReadScrapedEvents->bind(cTableEvents::fiScrSp, cDBS::bndOut, ", ");
selectReadScrapedEvents->build(" from %s where ", tEvents->TableName());
selectReadScrapedEvents->build(" ((%s is not null and %s > 0) ",
tEvents->getField(cTableEvents::fiScrSeriesId)->name,
tEvents->getField(cTableEvents::fiScrSeriesId)->name);
selectReadScrapedEvents->build(" or (%s is not null and %s > 0)) ",
tEvents->getField(cTableEvents::fiScrMovieId)->name,
tEvents->getField(cTableEvents::fiScrMovieId)->name);
2014-05-10 10:56:47 +02:00
selectReadScrapedEvents->bindCmp(0, cTableEvents::fiScrSp, 0, ">", " and ");
2014-05-09 01:05:21 +02:00
selectReadScrapedEvents->build(" order by %s", tEvents->getField(cTableEvents::fiInsSp)->name);
2014-05-10 10:56:47 +02:00
2014-05-09 01:05:21 +02:00
status += selectReadScrapedEvents->prepare();
// select image
imageSize.setField(&imageSizeDef);
selectImg = new cDbStatement(tSeriesMedia);
selectImg->build("select ");
selectImg->bind(cTableSeriesMedia::fiMediaWidth, cDBS::bndOut);
selectImg->bind(cTableSeriesMedia::fiMediaHeight, cDBS::bndOut, ", ");
selectImg->bind(cTableSeriesMedia::fiMediaContent, cDBS::bndOut, ", ");
selectImg->build(", length(");
selectImg->bind(&imageSize, cDBS::bndOut);
selectImg->build(")");
selectImg->build(" from %s where ", tSeriesMedia->TableName());
selectImg->bind(cTableSeriesMedia::fiSeriesId, cDBS::bndIn | cDBS::bndSet);
selectImg->bind(cTableSeriesMedia::fiEpisodeId, cDBS::bndIn | cDBS::bndSet, " and ");
status += selectImg->prepare();
// select poster image
posterSize.setField(&imageSizeDef);
selectSeasonPoster = new cDbStatement(tSeriesMedia);
selectSeasonPoster->build("select ");
selectSeasonPoster->bind(cTableSeriesMedia::fiMediaWidth, cDBS::bndOut);
selectSeasonPoster->bind(cTableSeriesMedia::fiMediaHeight, cDBS::bndOut, ", ");
selectSeasonPoster->bind(cTableSeriesMedia::fiMediaContent, cDBS::bndOut, ", ");
selectSeasonPoster->build(", length(");
selectSeasonPoster->bind(&posterSize, cDBS::bndOut);
selectSeasonPoster->build(")");
selectSeasonPoster->build(" from %s where ", tSeriesMedia->TableName());
selectSeasonPoster->bind(cTableSeriesMedia::fiSeriesId, cDBS::bndIn | cDBS::bndSet);
selectSeasonPoster->bind(cTableSeriesMedia::fiSeasonNumber, cDBS::bndIn | cDBS::bndSet, " and ");
selectSeasonPoster->bind(cTableSeriesMedia::fiMediaType, cDBS::bndIn | cDBS::bndSet, " and ");
status += selectSeasonPoster->prepare();
// select actor
series_id.setField(tSeriesMedia->getField(cTableSeriesMedia::fiSeriesId));
selectActors = new cDbStatement(tSeriesActors);
selectActors->build("select ");
selectActors->setBindPrefix("series_actor.");
selectActors->bind(cTableSeriesActor::fiActorId, cDBS::bndOut);
selectActors->bind(cTableSeriesActor::fiActorName, cDBS::bndOut, ", ");
selectActors->bind(cTableSeriesActor::fiActorRole, cDBS::bndOut, ", ");
selectActors->clrBindPrefix();
selectActors->build(" from %s, %s where ", tSeriesActors->TableName(), tSeriesMedia->TableName());
selectActors->build(" %s.%s = %s.%s ", tSeriesActors->TableName(),
tSeriesActors->getField(cTableSeriesActor::fiActorId)->name,
tSeriesMedia->TableName(),
tSeriesMedia->getField(cTableSeriesMedia::fiActorId)->name);
selectActors->setBindPrefix("series_media.");
selectActors->bind(&series_id, cDBS::bndIn | cDBS::bndSet, " and ");
selectActors->build(" order by %s, %s asc", tSeriesActors->getField(cTableSeriesActor::fiSortOrder)->name,
tSeriesActors->getField(cTableSeriesActor::fiActorRole)->name);
status += selectActors->prepare();
// select actor thumbs
actorImageSize.setField(&imageSizeDef);
selectActorThumbs = new cDbStatement(tSeriesMedia);
selectActorThumbs->build("select ");
selectActorThumbs->bind(cTableSeriesMedia::fiMediaWidth, cDBS::bndOut);
selectActorThumbs->bind(cTableSeriesMedia::fiMediaHeight, cDBS::bndOut, ", ");
selectActorThumbs->bind(cTableSeriesMedia::fiMediaContent, cDBS::bndOut, ", ");
selectActorThumbs->build(", length(");
selectActorThumbs->bind(&actorImageSize, cDBS::bndOut);
selectActorThumbs->build(")");
selectActorThumbs->build(" from %s where ", tSeriesMedia->TableName());
selectActorThumbs->bind(cTableSeriesMedia::fiActorId, cDBS::bndIn | cDBS::bndSet);
status += selectActorThumbs->prepare();
//
selectSeriesMedia = new cDbStatement(tSeriesMedia);
selectSeriesMedia->build("select ");
selectSeriesMedia->bind(cTableSeriesMedia::fiMediaWidth, cDBS::bndOut);
selectSeriesMedia->bind(cTableSeriesMedia::fiMediaHeight, cDBS::bndOut, ", ");
selectSeriesMedia->bind(cTableSeriesMedia::fiMediaType, cDBS::bndOut, ", ");
selectSeriesMedia->build(" from %s where ", tSeriesMedia->TableName());
selectSeriesMedia->bind(cTableSeriesMedia::fiSeriesId, cDBS::bndIn | cDBS::bndSet);
selectSeriesMedia->build(" and %s in (%d, %d, %d, %d, %d, %d, %d, %d, %d)",
tSeriesMedia->getField(cTableSeriesMedia::fiMediaType)->name,
msPoster1, msPoster2, msPoster3,
msFanart1, msFanart2, msFanart3,
msBanner1, msBanner2, msBanner3);
status += selectSeriesMedia->prepare();
//
actorRole.setField(tMovieActors->getField(cTableMovieActors::fiRole));
actorMovie.setField(tMovieActors->getField(cTableMovieActors::fiMovieId));
thbWidth.setField(tMovieMedia->getField(cTableMovieMedia::fiMediaWidth));
thbHeight.setField(tMovieMedia->getField(cTableMovieMedia::fiMediaHeight));
selectMovieActors = new cDbStatement(tMovieActor);
selectMovieActors->build("select ");
selectMovieActors->setBindPrefix("act.");
selectMovieActors->bind(cTableMovieActor::fiActorId, cDBS::bndOut);
selectMovieActors->bind(cTableMovieActor::fiActorName, cDBS::bndOut, ", ");
selectMovieActors->setBindPrefix("role.");
selectMovieActors->bind(&actorRole, cDBS::bndOut, ", ");
selectMovieActors->setBindPrefix("thumb.");
selectMovieActors->bind(&thbWidth, cDBS::bndOut, ", ");
selectMovieActors->bind(&thbHeight, cDBS::bndOut, ", ");
selectMovieActors->clrBindPrefix();
selectMovieActors->build(" from %s act, %s role, %s thumb where ",
tMovieActor->TableName(), tMovieActors->TableName(), tMovieMedia->TableName());
selectMovieActors->build("act.%s = role.%s ",
tMovieActor->getField(cTableMovieActor::fiActorId)->name,
tMovieActors->getField(cTableMovieActors::fiActorId)->name);
selectMovieActors->build(" and role.%s = thumb.%s ",
tMovieActors->getField(cTableMovieActors::fiActorId)->name,
tMovieMedia->getField(cTableMovieMedia::fiActorId)->name);
selectMovieActors->setBindPrefix("role.");
selectMovieActors->bind(&actorMovie, cDBS::bndIn | cDBS::bndSet, " and ");
status += selectMovieActors->prepare();
//
selectMovieActorThumbs = new cDbStatement(tMovieMedia);
selectMovieActorThumbs->build("select ");
selectMovieActorThumbs->bind(cTableMovieMedia::fiMediaContent, cDBS::bndOut);
selectMovieActorThumbs->build(", length(");
selectMovieActorThumbs->bind(&imageSize, cDBS::bndOut);
selectMovieActorThumbs->build(")");
selectMovieActorThumbs->build(" from %s where ", tMovieMedia->TableName());
selectMovieActorThumbs->bind(cTableMovieMedia::fiActorId, cDBS::bndIn | cDBS::bndSet);
status += selectMovieActorThumbs->prepare();
//
selectMovieMedia = new cDbStatement(tMovieMedia);
selectMovieMedia->build("select ");
selectMovieMedia->bind(cTableMovieMedia::fiMediaWidth, cDBS::bndOut);
selectMovieMedia->bind(cTableMovieMedia::fiMediaHeight, cDBS::bndOut, ", ");
selectMovieMedia->bind(cTableMovieMedia::fiMediaType, cDBS::bndOut, ", ");
selectMovieMedia->build(" from %s where ", tMovieMedia->TableName());
selectMovieMedia->bind(cTableMovieMedia::fiMovieId, cDBS::bndIn | cDBS::bndSet);
selectMovieMedia->build(" and %s in (%d, %d, %d, %d)",
tMovieMedia->getField(cTableMovieMedia::fiMediaType)->name,
mmPoster,
mmFanart,
mmCollectionPoster,
mmCollectionFanart);
status += selectMovieMedia->prepare();
//
selectMediaMovie = new cDbStatement(tMovieMedia);
selectMediaMovie->build("select ");
selectMediaMovie->bind(cTableMovieMedia::fiMediaContent, cDBS::bndOut);
selectMediaMovie->build(", length(");
selectMediaMovie->bind(&imageSize, cDBS::bndOut);
selectMediaMovie->build(")");
selectMediaMovie->build(" from %s where ", tMovieMedia->TableName());
selectMediaMovie->bind(cTableMovieMedia::fiMovieId, cDBS::bndIn | cDBS::bndSet);
selectMediaMovie->bind(cTableMovieMedia::fiMediaType, cDBS::bndIn | cDBS::bndSet, " and ");
status += selectMediaMovie->prepare();
//
selectRecordings = new cDbStatement(tRecordings);
selectRecordings->build("select ");
selectRecordings->bind(cTableRecordings::fiRecPath, cDBS::bndOut);
selectRecordings->bind(cTableRecordings::fiRecStart, cDBS::bndOut, ", ");
selectRecordings->bind(cTableRecordings::fiMovieId, cDBS::bndOut, ", ");
selectRecordings->bind(cTableRecordings::fiSeriesId, cDBS::bndOut, ", ");
selectRecordings->bind(cTableRecordings::fiEpisodeId, cDBS::bndOut, ", ");
selectRecordings->build(" from %s where ", tRecordings->TableName());
selectRecordings->bind(cTableRecordings::fiUuid, cDBS::bndIn | cDBS::bndSet);
selectRecordings->build(" and %s = 0", tRecordings->getField(cTableRecordings::fiScrapNew)->name);
status += selectRecordings->prepare();
//
selectCleanupRecordings = new cDbStatement(tRecordings);
selectCleanupRecordings->build("select ");
selectCleanupRecordings->bind(cTableRecordings::fiRecPath, cDBS::bndOut);
selectCleanupRecordings->bind(cTableRecordings::fiRecStart, cDBS::bndOut, ", ");
selectCleanupRecordings->build(" from %s where ", tRecordings->TableName());
selectCleanupRecordings->bind(cTableRecordings::fiUuid, cDBS::bndIn | cDBS::bndSet);
status += selectCleanupRecordings->prepare();
2014-04-12 17:10:43 +02:00
return status;
}
int cUpdate::exitDb() {
2014-05-09 01:05:21 +02:00
delete selectReadScrapedEvents; selectReadScrapedEvents = 0;
delete selectReadScrapedEventsInit; selectReadScrapedEventsInit = 0;
delete selectImg; selectImg = 0;
delete selectSeasonPoster; selectSeasonPoster = 0;
delete selectActors; selectActors = 0;
delete selectActorThumbs; selectActorThumbs = 0;
delete selectSeriesMedia; selectSeriesMedia = 0;
delete selectMovieActors; selectMovieActors = 0;
delete selectMovieActorThumbs; selectMovieActorThumbs = 0;
delete selectMovieMedia; selectMovieMedia = 0;
delete selectMediaMovie; selectMediaMovie = 0;
delete selectRecordings; selectRecordings = 0;
delete selectCleanupRecordings; selectCleanupRecordings = 0;
delete vdrDb; vdrDb = 0;
delete tEvents; tEvents = 0;
delete tSeries; tSeries = 0;
delete tEpisodes; tEpisodes = 0;
delete tSeriesMedia; tSeriesMedia = 0;
delete tSeriesActors; tSeriesActors = 0;
delete tMovies; tMovies = 0;
delete tMovieActor; tMovieActor = 0;
delete tMovieActors; tMovieActors = 0;
delete tMovieMedia; tMovieMedia = 0;
delete tRecordings; tRecordings = 0;
delete connection; connection = 0;
2014-04-12 17:10:43 +02:00
return done;
}
void cUpdate::Stop() {
loopActive = false;
waitCondition.Broadcast();
2014-04-27 11:06:32 +02:00
Cancel(1);
while (Active())
cCondWait::SleepMs(10);
2014-04-12 17:10:43 +02:00
}
int cUpdate::CheckConnection(int& timeout) {
static int retry = 0;
timeout = retry < 5 ? 10 : 60;
// check connection
if (!dbConnected(yes)) {
// try to connect
tell(0, "Trying to re-connect to database!");
retry++;
if (initDb() != success) {
tell(0, "Retry #%d failed, retrying in %d seconds!", retry, timeout);
exitDb();
return fail;
}
retry = 0;
tell(0, "Connection established successfull!");
}
return success;
}
bool cUpdate::CheckEpgdBusy(void) {
2014-05-09 01:05:21 +02:00
int busy = false;
vdrDb->clear();
vdrDb->setValue(cTableVdrs::fiUuid, EPGDNAME);
if (vdrDb->find()) {
Es::State epgdState = cEpgdState::toState(vdrDb->getStrValue(cTableVdrs::fiState));
// ignore esBusyImages until we don't write this table
if (epgdState >= cEpgdState::esBusy && epgdState < cEpgdState::esBusyImages)
busy = true;
}
vdrDb->reset();
return busy;
2014-04-12 17:10:43 +02:00
}
int cUpdate::ReadScrapedEvents(void) {
int eventId = 0;
int seriesId = 0;
int episodeId = 0;
int movieId = 0;
string channelId = "";
int numNew = 0;
2014-05-09 01:05:21 +02:00
cDbStatement* select = lastScrap > 0 ? selectReadScrapedEvents : selectReadScrapedEventsInit;
tEvents->clear();
tEvents->setValue(cTableEvents::fiScrSp, lastScrap);
2014-04-27 11:06:32 +02:00
for (int res = select->find(); res; res = select->fetch() && Running()) {
eventId = tEvents->getIntValue(cTableEvents::fiMasterId);
2014-04-12 17:10:43 +02:00
channelId = tEvents->getStrValue(cTableEvents::fiChannelId);
seriesId = tEvents->getIntValue(cTableEvents::fiScrSeriesId);
episodeId = tEvents->getIntValue(cTableEvents::fiScrSeriesEpisode);
movieId = tEvents->getIntValue(cTableEvents::fiScrMovieId);
scrapManager->AddEvent(eventId, channelId, seriesId, episodeId, movieId);
lastScrap = max(lastScrap, (int)tEvents->getIntValue(cTableEvents::fiScrSp));
numNew++;
}
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
select->freeResult();
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
return numNew;
}
//***************************************************************************
// SERIES
//***************************************************************************
int cUpdate::ReadSeries(bool isRec) {
scrapManager->InitIterator(isRec);
int seriesId = 0;
int episodeId = 0;
if (!CreateDirectory(config.imageDir))
return 0;
if (!CreateDirectory(imgPathSeries))
return 0;
bool isNew = false;
int numNew = 0;
int i=0;
2014-04-27 11:06:32 +02:00
while (scrapManager->GetNextSeries(isRec, seriesId, episodeId) && Running()) {
2014-04-12 17:10:43 +02:00
cTVDBSeries *series = scrapManager->GetSeries(seriesId);
if (!series) {
tSeries->clear();
tSeries->setValue(cTableSeries::fiSeriesId, seriesId);
int res = tSeries->find();
if (res) {
series = scrapManager->AddSeries(tSeries);
}
isNew = true;
} else {
isNew = false;
}
if (series) {
stringstream sPath("");
2014-04-12 17:10:43 +02:00
sPath << imgPathSeries << "/" << seriesId;
string seriesPath = sPath.str();
if (episodeId) {
ReadEpisode(episodeId, series, seriesPath);
}
if (isNew) {
ReadSeriesActors(series, seriesPath);
LoadSeriesMedia(series, seriesPath);
}
}
waitCondition.TimedWait(mutex, 3);
if (++i % 500 == 0)
tell(0, "Loaded %d series, continuing...", i);
2014-04-12 17:10:43 +02:00
numNew++;
}
return numNew;
}
void cUpdate::ReadEpisode(int episodeId, cTVDBSeries *series, string path) {
tEpisodes->clear();
tEpisodes->setValue(cTableSeriesEpisode::fiEpisodeId, episodeId);
2014-04-18 17:08:11 +02:00
int res = tEpisodes->find();
2014-04-12 17:10:43 +02:00
if (res) {
scrapManager->AddSeriesEpisode(series, tEpisodes);
LoadEpisodeImage(series, episodeId, path);
int season = tEpisodes->getIntValue(cTableSeriesEpisode::fiSeasonNumber);
if (season > 0)
LoadSeasonPoster(series, season, path);
}
return;
}
void cUpdate::LoadEpisodeImage(cTVDBSeries *series, int episodeId, string path) {
2014-05-09 01:05:21 +02:00
stringstream iPath("");
2014-04-12 17:10:43 +02:00
iPath << path << "/" << "episode_" << episodeId << ".jpg";
string imgPath = iPath.str();
bool imgExists = FileExists(imgPath);
2014-04-18 17:08:11 +02:00
if (!imgExists)
if (!CreateDirectory(path))
return;
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
tSeriesMedia->clear();
tSeriesMedia->setValue(cTableSeriesMedia::fiSeriesId, series->id);
tSeriesMedia->setValue(cTableSeriesMedia::fiEpisodeId, episodeId);
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
int res = selectImg->find();
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
if (res) {
if (!imgExists) {
int size = imageSize.getIntValue();
if (FILE* fh = fopen(imgPath.c_str(), "w")) {
fwrite(tSeriesMedia->getStrValue(cTableSeriesMedia::fiMediaContent), 1, size, fh);
fclose(fh);
}
}
int imgWidth = tSeriesMedia->getIntValue(cTableSeriesMedia::fiMediaWidth);
int imgHeight = tSeriesMedia->getIntValue(cTableSeriesMedia::fiMediaHeight);
series->InsertEpisodeImage(episodeId, imgWidth, imgHeight, imgPath);
}
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
selectImg->freeResult();
}
void cUpdate::LoadSeasonPoster(cTVDBSeries *series, int season, string path) {
2014-05-09 01:05:21 +02:00
stringstream iPath("");
2014-04-12 17:10:43 +02:00
iPath << path << "/" << "season_" << season << ".jpg";
2014-05-09 01:05:21 +02:00
stringstream tPath("");
2014-04-12 17:10:43 +02:00
tPath << path << "/" << "season_" << season << "_thumb.jpg";
string imgPath = iPath.str();
string thumbPath = tPath.str();
bool imgExists = FileExists(imgPath);
2014-04-18 17:08:11 +02:00
if (!imgExists)
if (!CreateDirectory(path))
return;
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
tSeriesMedia->clear();
tSeriesMedia->setValue(cTableSeriesMedia::fiSeriesId, series->id);
tSeriesMedia->setValue(cTableSeriesMedia::fiSeasonNumber, season);
tSeriesMedia->setValue(cTableSeriesMedia::fiMediaType, msSeasonPoster);
2014-05-09 01:05:21 +02:00
int res = selectSeasonPoster->find();
2014-04-12 17:10:43 +02:00
if (res) {
if (!imgExists) {
2014-05-09 01:05:21 +02:00
int size = posterSize.getIntValue();
2014-04-12 17:10:43 +02:00
if (FILE* fh = fopen(imgPath.c_str(), "w")) {
fwrite(tSeriesMedia->getStrValue(cTableSeriesMedia::fiMediaContent), 1, size, fh);
fclose(fh);
}
}
int imgWidth = tSeriesMedia->getIntValue(cTableSeriesMedia::fiMediaWidth);
int imgHeight = tSeriesMedia->getIntValue(cTableSeriesMedia::fiMediaHeight);
if (!FileExists(thumbPath)) {
CreateThumbnail(imgPath, thumbPath, imgWidth, imgHeight, 2);
}
series->InsertMedia(msSeasonPoster, imgWidth, imgHeight, imgPath, season);
series->InsertMedia(msSeasonPosterThumb, imgWidth/2, imgHeight/2, thumbPath, season);
}
2014-05-09 01:05:21 +02:00
selectSeasonPoster->freeResult();
2014-04-12 17:10:43 +02:00
}
void cUpdate::ReadSeriesActors(cTVDBSeries *series, string path) {
tSeriesActors->clear();
series_id.setValue(series->id);
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
for (int res = selectActors->find(); res; res = selectActors->fetch()) {
scrapManager->AddSeriesActor(series, tSeriesActors);
LoadSeriesActorThumb(series, tSeriesActors->getIntValue(cTableSeriesActor::fiActorId), path);
}
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
selectActors->freeResult();
}
void cUpdate::LoadSeriesActorThumb(cTVDBSeries *series, int actorId, string path) {
2014-05-09 01:05:21 +02:00
stringstream iPath("");
2014-04-12 17:10:43 +02:00
iPath << path << "/" << "actor_" << actorId << ".jpg";
string imgPath = iPath.str();
bool imgExists = FileExists(imgPath);
2014-04-18 17:08:11 +02:00
if (!imgExists)
if (!CreateDirectory(path))
return;
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
tSeriesMedia->clear();
tSeriesMedia->setValue(cTableSeriesMedia::fiActorId, actorId);
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
int res = selectActorThumbs->find();
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
if (res) {
if (!imgExists) {
2014-05-09 01:05:21 +02:00
int size = actorImageSize.getIntValue();
2014-04-12 17:10:43 +02:00
if (FILE* fh = fopen(imgPath.c_str(), "w")) {
fwrite(tSeriesMedia->getStrValue(cTableSeriesMedia::fiMediaContent), 1, size, fh);
fclose(fh);
}
}
int tmbWidth = tSeriesMedia->getIntValue(cTableSeriesMedia::fiMediaWidth);
int tmbHeight = tSeriesMedia->getIntValue(cTableSeriesMedia::fiMediaHeight);
series->InsertActorThumb(actorId, tmbWidth, tmbHeight, imgPath);
}
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
selectActorThumbs->freeResult();
}
2014-05-09 01:05:21 +02:00
void cUpdate::LoadSeriesMedia(cTVDBSeries *series, string path) {
tSeriesMedia->clear();
tSeriesMedia->setValue(cTableSeriesMedia::fiSeriesId, series->id);
for (int res = selectSeriesMedia->find(); res; res = selectSeriesMedia->fetch()) {
int mediaType = tSeriesMedia->getIntValue(cTableSeriesMedia::fiMediaType);
int mediaWidth = tSeriesMedia->getIntValue(cTableSeriesMedia::fiMediaWidth);
int mediaHeight = tSeriesMedia->getIntValue(cTableSeriesMedia::fiMediaHeight);
string mediaPath = LoadMediaSeries(series->id, mediaType, path, mediaWidth, mediaHeight);
series->InsertMedia(mediaType, mediaWidth, mediaHeight, mediaPath);
if (mediaType == msPoster1) {
string thumbPath = path + "/poster_thumb.jpg";
series->InsertMedia(msPosterThumb, mediaWidth/5, mediaHeight/5, thumbPath);
}
}
selectSeriesMedia->freeResult();
2014-04-12 17:10:43 +02:00
}
string cUpdate::LoadMediaSeries(int seriesId, int mediaType, string path, int width, int height) {
2014-05-09 01:05:21 +02:00
stringstream iPath("");
2014-04-12 17:10:43 +02:00
iPath << path << "/";
bool createThumb = false;
2014-05-09 01:05:21 +02:00
stringstream tPath("");
2014-04-12 17:10:43 +02:00
tPath << path << "/";
switch (mediaType) {
case msPoster1:
iPath << "poster1.jpg";
createThumb = true;
tPath << "poster_thumb.jpg";
break;
case msPoster2:
iPath << "poster2.jpg";
break;
case msPoster3:
iPath << "poster3.jpg";
break;
case msFanart1:
iPath << "fanart1.jpg";
break;
case msFanart2:
iPath << "fanart2.jpg";
break;
case msFanart3:
iPath << "fanart3.jpg";
break;
case msBanner1:
iPath << "banner1.jpg";
break;
case msBanner2:
iPath << "banner2.jpg";
break;
case msBanner3:
iPath << "banner3.jpg";
break;
default:
break;
}
string imgPath = iPath.str();
string thumbPath = tPath.str();
if (FileExists(imgPath)) {
if (createThumb && !FileExists(thumbPath)) {
CreateThumbnail(imgPath, thumbPath, width, height, 5);
}
return imgPath;
}
if (!CreateDirectory(path))
return "";
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
tSeriesMedia->clear();
tSeriesMedia->setValue(cTableSeriesMedia::fiSeriesId, seriesId);
tSeriesMedia->setValue(cTableSeriesMedia::fiMediaType, mediaType);
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
int res = selectImg->find();
if (res) {
int size = imageSize.getIntValue();
if (FILE* fh = fopen(imgPath.c_str(), "w")) {
fwrite(tSeriesMedia->getStrValue(cTableSeriesMedia::fiMediaContent), 1, size, fh);
fclose(fh);
}
if (createThumb && !FileExists(thumbPath)) {
CreateThumbnail(imgPath, thumbPath, width, height, 5);
}
}
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
selectImg->freeResult();
return imgPath;
}
//***************************************************************************
// MOVIES
//***************************************************************************
int cUpdate::ReadMovies(bool isRec) {
scrapManager->InitIterator(isRec);
int movieId = 0;
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
if (!CreateDirectory(config.imageDir))
return 0;
if (!CreateDirectory(imgPathMovies))
return 0;
int numNew = 0;
2014-04-27 11:06:32 +02:00
while (scrapManager->GetNextMovie(isRec, movieId) && Running()) {
2014-04-12 17:10:43 +02:00
cMovieDbMovie *movie = scrapManager->GetMovie(movieId);
if (movie)
continue;
tMovies->clear();
tMovies->setValue(cTableMovies::fiMovieId, movieId);
int res = tMovies->find();
if (!res)
continue;
movie = scrapManager->AddMovie(tMovies);
2014-05-09 01:05:21 +02:00
stringstream mPath("");
2014-04-12 17:10:43 +02:00
mPath << imgPathMovies << "/" << movieId;
string moviePath = mPath.str();
ReadMovieActors(movie);
LoadMovieActorThumbs(movie);
LoadMovieMedia(movie, moviePath);
numNew++;
}
return numNew;
}
void cUpdate::ReadMovieActors(cMovieDbMovie *movie) {
2014-05-09 01:05:21 +02:00
tMovieActor->clear();
tMovieMedia->clear();
2014-04-12 17:10:43 +02:00
actorMovie.setValue(movie->id);
2014-05-09 01:05:21 +02:00
for (int res = selectMovieActors->find(); res; res = selectMovieActors->fetch()) {
2014-04-12 17:10:43 +02:00
scrapManager->AddMovieActor(movie, tMovieActor, actorRole.getStrValue());
int tmbWidth = thbWidth.getIntValue();
int tmbHeight = thbHeight.getIntValue();
movie->SetActorThumbSize(tMovieActor->getIntValue(cTableMovieActor::fiActorId), tmbWidth, tmbHeight);
}
2014-05-09 01:05:21 +02:00
selectMovieActors->freeResult();
2014-04-12 17:10:43 +02:00
}
void cUpdate::LoadMovieActorThumbs(cMovieDbMovie *movie) {
tMovieMedia->clear();
2014-05-09 01:05:21 +02:00
imageSize.setField(&imageSizeDef);
2014-04-12 17:10:43 +02:00
string movieActorsPath = imgPathMovies + "/actors";
if (!CreateDirectory(movieActorsPath))
return;
vector<int> IDs = movie->GetActorIDs();
for (vector<int>::iterator it = IDs.begin(); it != IDs.end(); it++) {
int actorId = (int)*it;
2014-05-09 01:05:21 +02:00
stringstream tName("");
2014-04-12 17:10:43 +02:00
tName << "actor_" << actorId << ".jpg";
string thumbName = tName.str();
string thumbFullPath = movieActorsPath + "/" + thumbName;
if (!FileExists(thumbFullPath)) {
tMovieMedia->setValue(cTableMovieMedia::fiActorId, actorId);
2014-05-09 01:05:21 +02:00
int res = selectMovieActorThumbs->find();
2014-04-12 17:10:43 +02:00
if (res) {
int size = imageSize.getIntValue();
if (FILE* fh = fopen(thumbFullPath.c_str(), "w")) {
fwrite(tMovieMedia->getStrValue(cTableMovieMedia::fiMediaContent), 1, size, fh);
fclose(fh);
}
movie->SetActorPath(actorId, thumbFullPath);
}
} else {
movie->SetActorPath(actorId, thumbFullPath);
}
}
2014-05-09 01:05:21 +02:00
selectMovieActorThumbs->freeResult();
2014-04-12 17:10:43 +02:00
}
void cUpdate::LoadMovieMedia(cMovieDbMovie *movie, string moviePath) {
tMovieMedia->clear();
tMovieMedia->setValue(cTableMovieMedia::fiMovieId, movie->id);
2014-05-09 01:05:21 +02:00
for (int res = selectMovieMedia->find(); res; res = selectMovieMedia->fetch()) {
2014-04-12 17:10:43 +02:00
int mediaType = tMovieMedia->getIntValue(cTableMovieMedia::fiMediaType);
int mediaWidth = tMovieMedia->getIntValue(cTableMovieMedia::fiMediaWidth);
int mediaHeight = tMovieMedia->getIntValue(cTableMovieMedia::fiMediaHeight);
string imgPath = LoadMediaMovie(movie->id, mediaType, moviePath, mediaWidth, mediaHeight);
if (imgPath.size() > 0)
scrapManager->AddMovieMedia(movie, tMovieMedia, imgPath);
if (mediaType == mmPoster) {
cMovieMedia *m = new cMovieMedia();
m->mediaType = mmPosterThumb;
m->width = mediaWidth/4;
m->height = mediaHeight/4;
m->path = moviePath + "/poster_thumb.jpg";
movie->InsertMedia(m);
}
}
2014-05-09 01:05:21 +02:00
selectMovieMedia->freeResult();
2014-04-12 17:10:43 +02:00
}
string cUpdate::LoadMediaMovie(int movieId, int mediaType, string path, int width, int height) {
2014-05-09 01:05:21 +02:00
stringstream iPath("");
2014-04-12 17:10:43 +02:00
iPath << path << "/";
bool createThumb = false;
2014-05-09 01:05:21 +02:00
stringstream tPath("");
2014-04-12 17:10:43 +02:00
tPath << path << "/";
switch (mediaType) {
case mmPoster:
iPath << "poster.jpg";
createThumb = true;
tPath << "poster_thumb.jpg";
break;
case mmFanart:
iPath << "fanart.jpg";
break;
case mmCollectionPoster:
iPath << "collectionPoster.jpg";
break;
case mmCollectionFanart:
iPath << "collectionFanart.jpg";
break;
default:
break;
}
string imgPath = iPath.str();
string thumbPath = tPath.str();
if (FileExists(imgPath)) {
if (createThumb && !FileExists(thumbPath)) {
CreateThumbnail(imgPath, thumbPath, width, height, 4);
}
return imgPath;
}
if (!CreateDirectory(path))
return imgPath;
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
tMovieMedia->clear();
imageSize.setField(&imageSizeDef);
tMovieMedia->setValue(cTableMovieMedia::fiMovieId, movieId);
tMovieMedia->setValue(cTableMovieMedia::fiMediaType, mediaType);
2014-05-09 01:05:21 +02:00
int res = selectMediaMovie->find();
2014-04-12 17:10:43 +02:00
if (res) {
int size = imageSize.getIntValue();
if (FILE* fh = fopen(imgPath.c_str(), "w")) {
fwrite(tMovieMedia->getStrValue(cTableMovieMedia::fiMediaContent), 1, size, fh);
fclose(fh);
}
if (createThumb && !FileExists(thumbPath)) {
CreateThumbnail(imgPath, thumbPath, width, height, 4);
}
}
2014-05-09 01:05:21 +02:00
selectMediaMovie->freeResult();
2014-04-12 17:10:43 +02:00
return imgPath;
}
//***************************************************************************
// RECORDINGS
//***************************************************************************
2014-05-09 01:05:21 +02:00
int cUpdate::ReadRecordings(void) {
2014-04-12 17:10:43 +02:00
tRecordings->clear();
tRecordings->setValue(cTableRecordings::fiUuid, config.uuid.c_str());
int numRecs = 0;
2014-05-09 01:05:21 +02:00
for (int res = selectRecordings->find(); res; res = selectRecordings->fetch()) {
2014-04-12 17:10:43 +02:00
int recStart = tRecordings->getIntValue(cTableRecordings::fiRecStart);
string recPath = tRecordings->getStrValue(cTableRecordings::fiRecPath);
int movieId = tRecordings->getIntValue(cTableRecordings::fiMovieId);
int seriesId = tRecordings->getIntValue(cTableRecordings::fiSeriesId);
int episodeId = tRecordings->getIntValue(cTableRecordings::fiEpisodeId);
bool isNew = scrapManager->AddRecording(recStart, recPath, seriesId, episodeId, movieId);
if (isNew)
numRecs++;
}
2014-05-09 01:05:21 +02:00
selectRecordings->freeResult();
2014-04-12 17:10:43 +02:00
return numRecs;
}
int cUpdate::ScanVideoDir(void) {
int newRecs = 0;
for (cRecording *rec = Recordings.First(); rec; rec = Recordings.Next(rec)) {
string recPath = getRecPath(rec);
2014-04-12 17:10:43 +02:00
int recStart = rec->Start();
if (!scrapManager->RecordingExists(recStart, recPath)) {
newRecs++;
int scrapInfoMovieID = 0;
int scrapInfoSeriesID = 0;
int scrapInfoEpisodeID = 0;
ReadScrapInfo(rec->FileName(), scrapInfoMovieID, scrapInfoSeriesID, scrapInfoEpisodeID);
int eventId = 0;
string channelId = "";
2014-04-13 08:17:00 +02:00
string title = rec->Name();
//remove directory
size_t posDelim = title.find_last_of('~');
if (posDelim != string::npos) {
title = title.substr(posDelim+1);
}
2014-04-12 17:10:43 +02:00
string subTitle = "";
const cRecordingInfo *recInfo = rec->Info();
if (recInfo) {
const cEvent *recEvent = recInfo->GetEvent();
if (recEvent) {
eventId = recEvent->EventID();
channelId = *(recInfo->ChannelID().ToString());
2014-04-13 08:28:02 +02:00
if (recInfo->Title())
title = recInfo->Title();
2014-04-12 17:10:43 +02:00
subTitle = (recInfo->ShortText())?(recInfo->ShortText()):"";
}
}
tRecordings->clear();
tRecordings->setValue(cTableRecordings::fiUuid, config.uuid.c_str());
tRecordings->setValue(cTableRecordings::fiRecPath, recPath.c_str());
tRecordings->setValue(cTableRecordings::fiRecStart, recStart);
tRecordings->setValue(cTableRecordings::fiEventId, eventId);
tRecordings->setValue(cTableRecordings::fiChannelId, channelId.c_str());
tRecordings->setValue(cTableRecordings::fiScrapInfoMovieId, scrapInfoMovieID);
tRecordings->setValue(cTableRecordings::fiScrapInfoSeriesId, scrapInfoSeriesID);
tRecordings->setValue(cTableRecordings::fiScrapInfoEpisodeId, scrapInfoEpisodeID);
tRecordings->setValue(cTableRecordings::fiScrapNew, 1);
tRecordings->setValue(cTableRecordings::fiRecTitle, title.c_str());
tRecordings->setValue(cTableRecordings::fiRecSubTitle, subTitle.c_str());
tRecordings->setValue(cTableRecordings::fiRecDuration, rec->LengthInSeconds()/60);
tRecordings->store();
}
}
return newRecs;
}
int cUpdate::ScanVideoDirScrapInfo(void) {
int numUpdated = 0;
for (cRecording *rec = Recordings.First(); rec; rec = Recordings.Next(rec)) {
int recStart = rec->Start();
string recPath = getRecPath(rec);
2014-05-09 01:05:21 +02:00
/* bool recExists = */ LoadRecording(recStart, recPath);
2014-04-12 17:10:43 +02:00
int scrapInfoMovieID = 0;
int scrapInfoSeriesID = 0;
int scrapInfoEpisodeID = 0;
ReadScrapInfo(rec->FileName(), scrapInfoMovieID, scrapInfoSeriesID, scrapInfoEpisodeID);
if (ScrapInfoChanged(scrapInfoMovieID, scrapInfoSeriesID, scrapInfoEpisodeID)) {
tRecordings->setValue(cTableRecordings::fiScrapNew, 1);
tRecordings->setValue(cTableRecordings::fiScrapInfoMovieId, scrapInfoMovieID);
tRecordings->setValue(cTableRecordings::fiScrapInfoSeriesId, scrapInfoSeriesID);
tRecordings->setValue(cTableRecordings::fiScrapInfoEpisodeId, scrapInfoEpisodeID);
tRecordings->update();
numUpdated++;
}
}
return numUpdated;
}
bool cUpdate::LoadRecording(int recStart, string recPath) {
tRecordings->clear();
tRecordings->setValue(cTableRecordings::fiUuid, config.uuid.c_str());
tRecordings->setValue(cTableRecordings::fiRecStart, recStart);
tRecordings->setValue(cTableRecordings::fiRecPath, recPath.c_str());
int found = tRecordings->find();
if (found == yes) {
return true;
}
return false;
}
bool cUpdate::ScrapInfoChanged(int scrapInfoMovieID, int scrapInfoSeriesID, int scrapInfoEpisodeID) {
int movieIdCurrent = tRecordings->getIntValue(cTableRecordings::fiScrapInfoMovieId);
int seriesIdCurrent = tRecordings->getIntValue(cTableRecordings::fiScrapInfoSeriesId);
int episodeIdCurrent = tRecordings->getIntValue(cTableRecordings::fiScrapInfoEpisodeId);
if ((movieIdCurrent != scrapInfoMovieID) ||
(seriesIdCurrent != scrapInfoSeriesID) ||
(episodeIdCurrent != scrapInfoEpisodeID))
return true;
return false;
}
void cUpdate::ReadScrapInfo(string recDir, int &scrapInfoMovieID, int &scrapInfoSeriesID, int &scrapInfoEpisodeID) {
2014-05-09 01:05:21 +02:00
stringstream sInfoName("");
2014-04-12 17:10:43 +02:00
sInfoName << recDir << "/" << config.recScrapInfoName;
string scrapInfoName = sInfoName.str();
if (!FileExists(scrapInfoName, false)) {
string twoHigher = TwoFoldersHigher(recDir);
if (twoHigher.size() > 0) {
2014-05-09 01:05:21 +02:00
stringstream sInfoNameAlt("");
2014-04-12 17:10:43 +02:00
sInfoNameAlt << twoHigher << "/" << config.recScrapInfoName;
scrapInfoName = sInfoNameAlt.str();
if (!FileExists(scrapInfoName, false)) {
return;
}
} else
return;
}
vector<string> scrapInfoLines;
FILE *f = fopen(scrapInfoName.c_str(), "r");
if (!f)
return;
cReadLine ReadLine;
char *line;
while ((line = ReadLine.Read(f)) != NULL) {
scrapInfoLines.push_back(line);
}
fclose(f);
int numLines = scrapInfoLines.size();
if (numLines < 2) {
tell(0, "invalid scrapinfo file in %s", recDir.c_str());
return;
}
for (int line=0; line < numLines; line++) {
scrapInfoLines[line] = trim(scrapInfoLines[line]);
toLower(scrapInfoLines[line]);
}
bool isMovie = false;
bool isSeries = false;
if (!scrapInfoLines[0].compare("movie"))
isMovie = true;
else if (!scrapInfoLines[0].compare("series"))
isSeries = true;
else
tell(0, "invalid scrapinfo file in %s", recDir.c_str());
int id1 = 0, id2 = 0;
string key = "", value = "";
splitstring s(scrapInfoLines[1].c_str());
vector<string> flds = s.split('=');
if (flds.size() == 2) {
key = trim(flds[0]);
value = trim(flds[1]);
} else {
tell(0, "invalid scrapinfo file in %s", recDir.c_str());
}
if (!key.compare("id")) {
id1 = atoi(value.c_str());
if (numLines > 2) {
splitstring s2(scrapInfoLines[2].c_str());
vector<string> flds2 = s2.split('=');
if (flds2.size() == 2) {
key = trim(flds2[0]);
toLower(key);
value = trim(flds2[1]);
}
if (!key.compare("episode")) {
id2 = atoi(value.c_str());
}
}
} else
tell(0, "invalid scrapinfo file in %s", recDir.c_str());
if (isSeries) {
scrapInfoSeriesID = id1;
scrapInfoEpisodeID = id2;
}
if (isMovie) {
scrapInfoMovieID = id1;
}
}
//***************************************************************************
// Cleanup
//***************************************************************************
int cUpdate::CleanupSeries(void) {
//read existing series in file system
vector<string> storedSeries;
DIR *dir;
struct dirent *entry;
if ((dir = opendir (imgPathSeries.c_str())) != NULL) {
while ((entry = readdir (dir)) != NULL) {
string dirName = entry->d_name;
if (isNumber(dirName)) {
storedSeries.push_back(dirName);
}
}
closedir (dir);
} else return 0;
int deletedSeries = 0;
//aviod complete delete if no series are available
int numSeriesAvailable = scrapManager->GetNumSeries();
if (numSeriesAvailable == 0)
return 0;
for (vector<string>::iterator seriesDir = storedSeries.begin(); seriesDir != storedSeries.end(); seriesDir++) {
int seriesId = atoi(((string)*seriesDir).c_str());
if (!scrapManager->SeriesInUse(seriesId)) {
string delDir = imgPathSeries + "/" + ((string)*seriesDir);
DeleteDirectory(delDir);
deletedSeries++;
}
}
return deletedSeries;
}
int cUpdate::CleanupMovies(void) {
//read existing movies in file system
vector<string> storedMovies;
DIR *dir;
struct dirent *entry;
if ((dir = opendir (imgPathMovies.c_str())) != NULL) {
while ((entry = readdir (dir)) != NULL) {
string dirName = entry->d_name;
if (isNumber(dirName)) {
storedMovies.push_back(dirName);
}
}
closedir (dir);
} else return 0;
int deletedMovies = 0;
//aviod complete delete if no movies are available
int numMoviesAvailable = scrapManager->GetNumMovies();
if (numMoviesAvailable == 0)
return 0;
for (vector<string>::iterator movieDir = storedMovies.begin(); movieDir != storedMovies.end(); movieDir++) {
int movieId = atoi(((string)*movieDir).c_str());
if (!scrapManager->MovieInUse(movieId)) {
string delDir = imgPathMovies + "/" + ((string)*movieDir);
DeleteDirectory(delDir);
deletedMovies++;
}
}
return deletedMovies;
}
int cUpdate::CleanupRecordings(void) {
2014-05-09 01:05:21 +02:00
// delete all not anymore existing recordings in database
2014-04-12 17:10:43 +02:00
tRecordings->clear();
tRecordings->setValue(cTableRecordings::fiUuid, config.uuid.c_str());
int numRecsDeleted = 0;
2014-05-09 01:05:21 +02:00
for (int res = selectCleanupRecordings->find(); res; res = selectCleanupRecordings->fetch()) {
2014-04-12 17:10:43 +02:00
int recStart = tRecordings->getIntValue(cTableRecordings::fiRecStart);
string recPath = tRecordings->getStrValue(cTableRecordings::fiRecPath);
if (!Recordings.GetByName(recPath.c_str())) {
2014-05-09 01:05:21 +02:00
stringstream delWhere("");
2014-04-12 17:10:43 +02:00
delWhere << "uuid = '" << config.uuid << "' and rec_path = '" << recPath << "' and rec_start = " << recStart;
tRecordings->deleteWhere(delWhere.str().c_str());
numRecsDeleted++;
}
}
2014-05-09 01:05:21 +02:00
selectCleanupRecordings->freeResult();
2014-04-12 17:10:43 +02:00
return numRecsDeleted;
}
//***************************************************************************
// Action
//***************************************************************************
2014-05-09 01:05:21 +02:00
void cUpdate::Action()
{
2014-04-12 17:10:43 +02:00
tell(0, "Update thread started (pid=%d)", getpid());
mutex.Lock();
loopActive = yes;
2014-05-09 01:05:21 +02:00
int worked = no;
int sleep = 60;
2014-04-13 07:52:48 +02:00
int scanFreq = 60 * 2;
2014-04-12 17:10:43 +02:00
int scanNewRecFreq = 60 * 5;
int scanNewRecDBFreq = 60 * 5;
2014-04-13 07:52:48 +02:00
int cleanUpFreq = 60 * 10;
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
forceUpdate = true;
forceRecordingUpdate = true;
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
time_t lastScan = time(0);
time_t lastScanNewRec = time(0);
time_t lastScanNewRecDB = time(0);
time_t lastCleanup = time(0);
bool init = true;
2014-05-09 01:05:21 +02:00
while (loopActive && Running())
{
int reconnectTimeout; // set by checkConnection
waitCondition.TimedWait(mutex, init ? sleep*500 : sleep*1000);
if (CheckConnection(reconnectTimeout) != success)
continue;
// auch beim init auf den epgd warten, wenn der gerade busy ist müssen die sich User etwas gedulden ;)
if (CheckEpgdBusy())
{
tell(1, "epgd busy, trying again in %d seconds ...", sleep);
continue;
2014-04-18 17:08:11 +02:00
}
2014-05-09 01:05:21 +02:00
// Update Recordings from Database
if (forceRecordingUpdate || (time(0) - lastScanNewRecDB > scanNewRecDBFreq) && Running())
{
worked++;
int numNewRecs = ReadRecordings();
lastScanNewRecDB = time(0);
if (numNewRecs > 0)
{
int numSeries = ReadSeries(true);
int numMovies = ReadMovies(true);
tell(0, "Loaded %d new Recordings from Database, %d series, %d movies", numNewRecs, numSeries, numMovies);
}
forceRecordingUpdate = false;
2014-04-12 17:10:43 +02:00
}
2014-04-18 17:08:11 +02:00
2014-05-09 01:05:21 +02:00
// Update Events
if (!config.headless && (forceUpdate || (time(0) - lastScan > scanFreq)) && Running())
{
worked++;
int numNewEvents = ReadScrapedEvents();
if (numNewEvents > 0)
{
tell(0, "Loaded %d new scraped Events from Database", numNewEvents);
}
else
{
lastScan = time(0);
forceUpdate = false;
init = false;
continue;
}
tell(0, "Loading new Movies from Database...");
time_t now = time(0);
worked++;
int numNewMovies = ReadMovies(false);
int dur = time(0) - now;
tell(0, "Loaded %d new Movies in %ds from Database", numNewMovies, dur);
tell(0, "Loading new Series and Episodes from Database...");
now = time(0);
worked++;
int numNewSeries = ReadSeries(false);
dur = time(0) - now;
tell(0, "Loaded %d new Series and Episodes in %ds from Database", numNewSeries, dur);
lastScan = time(0);
forceUpdate = false;
2014-04-12 17:10:43 +02:00
}
2014-05-09 01:05:21 +02:00
// Scan new recordings
2014-04-12 17:10:43 +02:00
2014-05-09 01:05:21 +02:00
if ((init || forceVideoDirUpdate || (time(0) - lastScanNewRec > scanNewRecFreq)) && Running())
{
static int recState = 0;
if (Recordings.StateChanged(recState))
{
tell(0, "Searching for new recordings because of Recordings State Change...");
worked++;
int newRecs = ScanVideoDir();
tell(0, "found %d new recordings", newRecs);
}
lastScanNewRec = time(0);
forceVideoDirUpdate = false;
}
2014-04-12 17:10:43 +02:00
init = false;
2014-05-09 01:05:21 +02:00
// Scan Video dir for scrapinfo files
2014-04-12 17:10:43 +02:00
2014-05-09 01:05:21 +02:00
if (forceScrapInfoUpdate)
{
worked++;
tell(0, "Checking for new or updated scrapinfo files in recordings...");
int numUpdated = ScanVideoDirScrapInfo();
tell(0, "found %d new or updated scrapinfo files", numUpdated);
forceScrapInfoUpdate = false;
2014-04-12 17:10:43 +02:00
}
2014-05-09 01:05:21 +02:00
// Cleanup
if ((time(0) - lastCleanup > cleanUpFreq) && Running())
{
worked++;
int seriesDeleted = CleanupSeries();
int moviesDeleted = CleanupMovies();
if (seriesDeleted > 0 || moviesDeleted > 0)
{
tell(0, "Deleted %d outdated series image folders", seriesDeleted);
tell(0, "Deleted %d outdated movie image folders", moviesDeleted);
}
lastCleanup = time(0);
2014-04-12 17:10:43 +02:00
}
2014-05-09 01:05:21 +02:00
// Cleanup Recording DB
if (forceCleanupRecordingDb)
{
worked++;
2014-04-12 17:10:43 +02:00
tell(0, "Cleaning up recordings in database...");
int recsDeleted = CleanupRecordings();
tell(0, "Deleted %d not anymore existing recordings in database", recsDeleted);
forceCleanupRecordingDb = false;
}
2014-05-09 01:05:21 +02:00
if (worked && config.debug)
connection->showStat();
2014-04-12 17:10:43 +02:00
2014-05-09 01:05:21 +02:00
worked = no;
2014-04-12 17:10:43 +02:00
}
loopActive = no;
tell(0, "Update thread ended (pid=%d)", getpid());
}
//***************************************************************************
// External trigggering of Actions
//***************************************************************************
2014-05-09 01:05:21 +02:00
2014-04-12 17:10:43 +02:00
void cUpdate::ForceUpdate(void) {
tell(0, "full update from database forced");
forceUpdate = true;
}
void cUpdate::ForceRecordingUpdate(void) {
tell(0, "scanning of recordings in database triggered");
forceRecordingUpdate = true;
}
void cUpdate::ForceVideoDirUpdate(void) {
tell(0, "scanning for new recordings in video directory triggered");
forceVideoDirUpdate = true;
}
void cUpdate::ForceScrapInfoUpdate(void) {
tell(0, "scanning of recording scrapinfo files triggered");
forceScrapInfoUpdate = true;
}
void cUpdate::TriggerCleanRecordingsDB(void) {
tell(0, "cleanup of recording DB triggered");
forceCleanupRecordingDb = true;
}
2014-04-27 12:39:56 +02:00