initial commit

This commit is contained in:
louis
2014-04-12 17:10:43 +02:00
commit 801610d259
31 changed files with 9104 additions and 0 deletions

7
lib/Makefile Normal file
View File

@@ -0,0 +1,7 @@
all:
g++ -ggdb -DPLGDIR='"."' test.c common.c config.c db.c tabledef.c -lrt -lz -lmysqlclient -o t
clean:
rm -f *.o *.a *~ core

812
lib/common.c Normal file
View File

@@ -0,0 +1,812 @@
/*
* common.c:
*
* See the README file for copyright information and how to reach the author.
*
*/
#include <sys/stat.h>
#ifdef USEUUID
# include <uuid/uuid.h>
#endif
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <zlib.h>
#ifdef USELIBARCHIVE
# include <archive.h>
# include <archive_entry.h>
#endif
#ifdef VDR_PLUGIN
# include <vdr/thread.h>
#endif
#include "common.h"
#include "config.h"
#ifdef VDR_PLUGIN
cMutex logMutex;
#endif
//***************************************************************************
// Debug
//***************************************************************************
void tell(int eloquence, const char* format, ...)
{
if (EPG2VDRConfig.loglevel < eloquence)
return ;
const int sizeBuffer = 100000;
char t[sizeBuffer+100]; *t = 0;
va_list ap;
#ifdef VDR_PLUGIN
cMutexLock lock(&logMutex);
#endif
va_start(ap, format);
#ifdef VDR_PLUGIN
snprintf(t, sizeBuffer, "scraper2vdr: ");
#endif
vsnprintf(t+strlen(t), sizeBuffer-strlen(t), format, ap);
if (EPG2VDRConfig.logstdout)
{
char buf[50+TB];
time_t now;
time(&now);
strftime(buf, 50, "%y.%m.%d %H:%M:%S", localtime(&now));
printf("%s %s\n", buf, t);
}
else
syslog(LOG_ERR, "%s", t);
va_end(ap);
}
//***************************************************************************
// Host ID
//***************************************************************************
unsigned int getHostId()
{
static unsigned int id = gethostid() & 0xFFFFFFFF;
return id;
}
//***************************************************************************
// String Operations
//***************************************************************************
void toUpper(std::string& str)
{
const char* s = str.c_str();
int lenSrc = str.length();
char* dest = (char*)malloc(lenSrc+TB); *dest = 0;
char* d = dest;
int csSrc; // size of character
for (int ps = 0; ps < lenSrc; ps += csSrc)
{
csSrc = max(mblen(&s[ps], lenSrc-ps), 1);
if (csSrc == 1)
*d++ = toupper(s[ps]);
else if (csSrc == 2 && s[ps] == (char)0xc3 && s[ps+1] >= (char)0xa0)
{
*d++ = s[ps];
*d++ = s[ps+1] - 32;
}
else
{
for (int i = 0; i < csSrc; i++)
*d++ = s[ps+i];
}
}
*d = 0;
str = dest;
free(dest);
}
void removeChars(std::string& str, const char* ignore)
{
const char* s = str.c_str();
int lenSrc = str.length();
int lenIgn = strlen(ignore);
char* dest = (char*)malloc(lenSrc+TB); *dest = 0;
char* d = dest;
int csSrc; // size of character
int csIgn; //
for (int ps = 0; ps < lenSrc; ps += csSrc)
{
int skip = no;
csSrc = max(mblen(&s[ps], lenSrc-ps), 1);
for (int pi = 0; pi < lenIgn; pi += csIgn)
{
csIgn = max(mblen(&ignore[pi], lenIgn-pi), 1);
if (csSrc == csIgn && strncmp(&s[ps], &ignore[pi], csSrc) == 0)
{
skip = yes;
break;
}
}
if (!skip)
{
for (int i = 0; i < csSrc; i++)
*d++ = s[ps+i];
}
}
*d = 0;
str = dest;
free(dest);
}
void removeCharsExcept(std::string& str, const char* except)
{
const char* s = str.c_str();
int lenSrc = str.length();
int lenIgn = strlen(except);
char* dest = (char*)malloc(lenSrc+TB); *dest = 0;
char* d = dest;
int csSrc; // size of character
int csIgn; //
for (int ps = 0; ps < lenSrc; ps += csSrc)
{
int skip = yes;
csSrc = max(mblen(&s[ps], lenSrc-ps), 1);
for (int pi = 0; pi < lenIgn; pi += csIgn)
{
csIgn = max(mblen(&except[pi], lenIgn-pi), 1);
if (csSrc == csIgn && strncmp(&s[ps], &except[pi], csSrc) == 0)
{
skip = no;
break;
}
}
if (!skip)
{
for (int i = 0; i < csSrc; i++)
*d++ = s[ps+i];
}
}
*d = 0;
str = dest;
free(dest);
}
void removeWord(std::string& pattern, std::string word)
{
size_t pos;
if ((pos = pattern.find(word)) != std::string::npos)
pattern.swap(pattern.erase(pos, word.length()));
}
//***************************************************************************
// String Manipulation
//***************************************************************************
void prepareCompressed(std::string& pattern)
{
// const char* ignore = " (),.;:-_+*!#?=&%$<>§/'`´@~\"[]{}";
const char* notignore = "ABCDEFGHIJKLMNOPQRSTUVWXYZßÖÄÜöäü0123456789";
toUpper(pattern);
removeWord(pattern, " TEIL ");
removeWord(pattern, " FOLGE ");
removeCharsExcept(pattern, notignore);
}
//***************************************************************************
// Left Trim
//***************************************************************************
char* lTrim(char* buf)
{
if (buf)
{
char *tp = buf;
while (*tp && strchr("\n\r\t ",*tp))
tp++;
memmove(buf, tp, strlen(tp) +1);
}
return buf;
}
//*************************************************************************
// Right Trim
//*************************************************************************
char* rTrim(char* buf)
{
if (buf)
{
char *tp = buf + strlen(buf);
while (tp >= buf && strchr("\n\r\t ",*tp))
tp--;
*(tp+1) = 0;
}
return buf;
}
//*************************************************************************
// All Trim
//*************************************************************************
char* allTrim(char* buf)
{
return lTrim(rTrim(buf));
}
//***************************************************************************
// Number to String
//***************************************************************************
std::string num2Str(int num)
{
char txt[16];
snprintf(txt, sizeof(txt), "%d", num);
return std::string(txt);
}
//***************************************************************************
// Long to Pretty Time
//***************************************************************************
std::string l2pTime(time_t t)
{
char txt[30];
tm* tmp = localtime(&t);
strftime(txt, sizeof(txt), "%d.%m.%Y %T", tmp);
return std::string(txt);
}
//***************************************************************************
// MS to Duration
//***************************************************************************
std::string ms2Dur(uint64_t t)
{
char txt[30];
int s = t / 1000;
int ms = t % 1000;
snprintf(txt, sizeof(txt), "%d.%03d seconds", s, ms);
return std::string(txt);
}
//***************************************************************************
// Char to Char-String
//***************************************************************************
const char* c2s(char c, char* buf)
{
sprintf(buf, "%c", c);
return buf;
}
//***************************************************************************
// TOOLS
//***************************************************************************
int isEmpty(const char* str)
{
return !str || !*str;
}
char* sstrcpy(char* dest, const char* src, int max)
{
if (!dest || !src)
return 0;
strncpy(dest, src, max);
dest[max-1] = 0;
return dest;
}
int isLink(const char* path)
{
struct stat sb;
if (lstat(path, &sb) == 0)
return S_ISLNK(sb.st_mode);
tell(0, "Error: Detecting state for '%s' failed, error was '%m'", path);
return false;
}
int fileSize(const char* path)
{
struct stat sb;
if (lstat(path, &sb) == 0)
return sb.st_size;
tell(0, "Error: Detecting state for '%s' failed, error was '%m'", path);
return false;
}
int fileExists(const char* path)
{
return access(path, F_OK) == 0;
}
int createLink(const char* link, const char* dest, int force)
{
if (!fileExists(link) || force)
{
// may be the link exists and point to a wrong or already deleted destination ...
// .. therefore we delete the link at first
unlink(link);
if (symlink(dest, link) != 0)
{
tell(0, "Failed to create symlink '%s', error was '%m'", link);
return fail;
}
}
return success;
}
//***************************************************************************
// Remove File
//***************************************************************************
int removeFile(const char* filename)
{
int lnk = isLink(filename);
if (unlink(filename) != 0)
{
tell(0, "Can't remove file '%s', '%m'", filename);
return 1;
}
tell(3, "Removed %s '%s'", lnk ? "link" : "file", filename);
return 0;
}
//***************************************************************************
// Check Dir
//***************************************************************************
int chkDir(const char* path)
{
struct stat fs;
if (stat(path, &fs) != 0 || !S_ISDIR(fs.st_mode))
{
tell(0, "Creating directory '%s'", path);
if (mkdir(path, ACCESSPERMS) == -1)
{
tell(0, "Can't create directory '%m'");
return fail;
}
}
return success;
}
#ifdef USELIBXML
//***************************************************************************
// Load XSLT
//***************************************************************************
xsltStylesheetPtr loadXSLT(const char* name, const char* path, int utf8)
{
xsltStylesheetPtr stylesheet;
char* xsltfile;
asprintf(&xsltfile, "%s/%s-%s.xsl", path, name, utf8 ? "utf-8" : "iso-8859-1");
if ((stylesheet = xsltParseStylesheetFile((const xmlChar*)xsltfile)) == 0)
tell(0, "Error: Can't load xsltfile %s", xsltfile);
else
tell(0, "Info: Stylesheet '%s' loaded", xsltfile);
free(xsltfile);
return stylesheet;
}
#endif
//***************************************************************************
// Gnu Unzip
//***************************************************************************
int gunzip(MemoryStruct* zippedData, MemoryStruct* unzippedData)
{
const int growthStep = 1024;
z_stream stream = {0,0,0,0,0,0,0,0,0,0,0,Z_NULL,Z_NULL,Z_NULL};
unsigned int resultSize = 0;
int res = 0;
unzippedData->clear();
// determining the size in this way is taken from the sources of the gzip utility.
memcpy(&unzippedData->size, zippedData->memory + zippedData->size -4, 4);
unzippedData->memory = (char*)malloc(unzippedData->size);
// zlib initialisation
stream.avail_in = zippedData->size;
stream.next_in = (Bytef*)zippedData->memory;
stream.avail_out = unzippedData->size;
stream.next_out = (Bytef*)unzippedData->memory;
// The '+ 32' tells zlib to process zlib&gzlib headers
res = inflateInit2(&stream, MAX_WBITS + 32);
if (res != Z_OK)
{
tellZipError(res, " during zlib initialisation", stream.msg);
inflateEnd(&stream);
return fail;
}
// skip the header
res = inflate(&stream, Z_BLOCK);
if (res != Z_OK)
{
tellZipError(res, " while skipping the header", stream.msg);
inflateEnd(&stream);
return fail;
}
while (res == Z_OK)
{
if (stream.avail_out == 0)
{
unzippedData->size += growthStep;
unzippedData->memory = (char*)realloc(unzippedData->memory, unzippedData->size);
// Set the stream pointers to the potentially changed buffer!
stream.avail_out = resultSize - stream.total_out;
stream.next_out = (Bytef*)(unzippedData + stream.total_out);
}
res = inflate(&stream, Z_SYNC_FLUSH);
resultSize = stream.total_out;
}
if (res != Z_STREAM_END)
{
tellZipError(res, " during inflating", stream.msg);
inflateEnd(&stream);
return fail;
}
unzippedData->size = resultSize;
inflateEnd(&stream);
return success;
}
//*************************************************************************
// tellZipError
//*************************************************************************
void tellZipError(int errorCode, const char* op, const char* msg)
{
if (!op) op = "";
if (!msg) msg = "None";
switch (errorCode)
{
case Z_OK: return;
case Z_STREAM_END: return;
case Z_MEM_ERROR: tell(0, "Error: Not enough memory to unzip file%s!\n", op); return;
case Z_BUF_ERROR: tell(0, "Error: Couldn't unzip data due to output buffer size problem%s!\n", op); return;
case Z_DATA_ERROR: tell(0, "Error: Zipped input data corrupted%s! Details: %s\n", op, msg); return;
case Z_STREAM_ERROR: tell(0, "Error: Invalid stream structure%s. Details: %s\n", op, msg); return;
default: tell(0, "Error: Couldn't unzip data for unknown reason (%6d)%s!\n", errorCode, op); return;
}
}
//*************************************************************************
// Host Data
//*************************************************************************
#include <sys/utsname.h>
#include <netdb.h>
#include <ifaddrs.h>
static struct utsname info;
const char* getHostName()
{
// get info from kernel
if (uname(&info) == -1)
return "";
return info.nodename;
}
const char* getFirstIp()
{
struct ifaddrs *ifaddr, *ifa;
static char host[NI_MAXHOST] = "";
if (getifaddrs(&ifaddr) == -1)
{
tell(0, "getifaddrs() failed");
return "";
}
// walk through linked interface list
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next)
{
if (!ifa->ifa_addr)
continue;
// For an AF_INET interfaces
if (ifa->ifa_addr->sa_family == AF_INET) // || ifa->ifa_addr->sa_family == AF_INET6)
{
int res = getnameinfo(ifa->ifa_addr,
(ifa->ifa_addr->sa_family == AF_INET) ? sizeof(struct sockaddr_in) :
sizeof(struct sockaddr_in6),
host, NI_MAXHOST, 0, 0, NI_NUMERICHOST);
if (res)
{
tell(0, "getnameinfo() failed: %s", gai_strerror(res));
return "";
}
// skip loopback interface
if (strcmp(host, "127.0.0.1") == 0)
continue;
tell(5, "%-8s %-15s %s", ifa->ifa_name, host,
ifa->ifa_addr->sa_family == AF_INET ? " (AF_INET)" :
ifa->ifa_addr->sa_family == AF_INET6 ? " (AF_INET6)" : "");
}
}
freeifaddrs(ifaddr);
return host;
}
#ifdef USELIBARCHIVE
//***************************************************************************
// unzip <file> and get data of first content which name matches <filter>
//***************************************************************************
int unzip(const char* file, const char* filter, char*& buffer, int& size, char* entryName)
{
const int step = 1024*10;
int bufSize = 0;
int r;
int res;
struct archive_entry* entry;
struct archive* a = archive_read_new();
*entryName = 0;
buffer = 0;
size = 0;
archive_read_support_filter_all(a);
archive_read_support_format_all(a);
r = archive_read_open_filename(a, file, 10204);
if (r != ARCHIVE_OK)
{
tell(0, "Error: Open '%s' failed - %m", file);
return 1;
}
while (archive_read_next_header(a, &entry) == ARCHIVE_OK)
{
strcpy(entryName, archive_entry_pathname(entry));
if (strstr(entryName, filter))
{
bufSize = step;
buffer = (char*)malloc(bufSize+1);
while ((res = archive_read_data(a, buffer+size, step)) > 0)
{
size += res;
bufSize += step;
buffer = (char*)realloc(buffer, bufSize+1);
}
buffer[size] = 0;
break;
}
}
r = archive_read_free(a);
if (r != ARCHIVE_OK)
{
size = 0;
free(buffer);
return fail;
}
return size > 0 ? success : fail;
}
#endif
//***************************************************************************
// Class LogDuration
//***************************************************************************
#ifdef VDR_PLUGIN
# include <vdr/plugin.h>
LogDuration::LogDuration(const char* aMessage, int aLogLevel)
{
logLevel = aLogLevel;
strcpy(message, aMessage);
// at last !
durationStart = cTimeMs::Now();
}
LogDuration::~LogDuration()
{
tell(logLevel, "duration '%s' was (%dms)",
message, cTimeMs::Now() - durationStart);
}
void LogDuration::show(const char* label)
{
tell(logLevel, "elapsed '%s' at '%s' was (%dms)",
message, label, cTimeMs::Now() - durationStart);
}
#endif
//***************************************************************************
// Get Unique ID
//***************************************************************************
#ifdef USEUUID
const char* getUniqueId()
{
static char uuid[sizeUuid+TB] = "";
uuid_t id;
uuid_generate(id);
uuid_unparse_upper(id, uuid);
return uuid;
}
#endif // USEUUID
//***************************************************************************
// Create MD5
//***************************************************************************
#ifdef USEMD5
int createMd5(const char* buf, md5* md5)
{
MD5_CTX c;
unsigned char out[MD5_DIGEST_LENGTH];
MD5_Init(&c);
MD5_Update(&c, buf, strlen(buf));
MD5_Final(out, &c);
for (int n = 0; n < MD5_DIGEST_LENGTH; n++)
sprintf(md5+2*n, "%02x", out[n]);
md5[sizeMd5] = 0;
return done;
}
int createMd5OfFile(const char* path, const char* name, md5* md5)
{
FILE* f;
char buffer[1000];
int nread = 0;
MD5_CTX c;
unsigned char out[MD5_DIGEST_LENGTH];
char* file = 0;
asprintf(&file, "%s/%s", path, name);
if (!(f = fopen(file, "r")))
{
tell(0, "Fatal: Can't access '%s'; %m", file);
free(file);
return fail;
}
free(file);
MD5_Init(&c);
while ((nread = fread(buffer, 1, 1000, f)) > 0)
MD5_Update(&c, buffer, nread);
fclose(f);
MD5_Final(out, &c);
for (int n = 0; n < MD5_DIGEST_LENGTH; n++)
sprintf(md5+2*n, "%02x", out[n]);
md5[sizeMd5] = 0;
return success;
}
#endif // USEMD5

179
lib/common.h Normal file
View File

@@ -0,0 +1,179 @@
/*
* common.h: EPG2VDR plugin for the Video Disk Recorder
*
* See the README file for copyright information and how to reach the author.
*
*/
#ifndef __COMMON_H
#define __COMMON_H
#include <stdint.h> // uint_64_t
#include <stdlib.h>
#include <string>
#include <openssl/md5.h> // MD5_*
#ifdef VDR_PLUGIN
# include <vdr/tools.h>
#endif
#ifdef USELIBXML
# include <libxslt/transform.h>
# include <libxslt/xsltutils.h>
# include <libexslt/exslt.h>
#endif
//***************************************************************************
//
//***************************************************************************
#ifndef VDR_PLUGIN
inline long min(long a, long b) { return a < b ? a : b; }
inline long max(long a, long b) { return a > b ? a : b; }
#endif
enum Misc
{
success = 0,
done = success,
fail = -1,
na = -1,
ignore = -2,
all = -3,
abrt = -4,
yes = 1,
on = 1,
off = 0,
no = 0,
TB = 1,
sizeMd5 = 2 * MD5_DIGEST_LENGTH,
sizeUuid = 36,
tmeSecondsPerMinute = 60,
tmeSecondsPerHour = tmeSecondsPerMinute * 60,
tmeSecondsPerDay = 24 * tmeSecondsPerHour
};
//***************************************************************************
// Tell
//***************************************************************************
void tell(int eloquence, const char* format, ...);
//***************************************************************************
// MemoryStruct for curl callbacks
//***************************************************************************
struct MemoryStruct
{
MemoryStruct() { memory = 0; clear(); }
~MemoryStruct() { clear(); }
// data
char* memory;
size_t size;
// tag attribute
char tag[100]; // the tag to be compared
char name[100]; // content name (filename)
int headerOnly;
int isEmpty() { return memory == 0; }
void clear()
{
free(memory);
memory = 0;
size = 0;
*tag = 0;
*name = 0;
headerOnly = no;
}
};
//***************************************************************************
// Tools
//***************************************************************************
unsigned int getHostId();
const char* getHostName();
const char* getFirstIp();
#ifdef USEUUID
const char* getUniqueId();
#endif
void removeChars(std::string& str, const char* ignore);
void removeCharsExcept(std::string& str, const char* except);
void removeWord(std::string& pattern, std::string word);
void prepareCompressed(std::string& pattern);
char* rTrim(char* buf);
char* lTrim(char* buf);
char* allTrim(char* buf);
char* sstrcpy(char* dest, const char* src, int max);
std::string num2Str(int num);
std::string l2pTime(time_t t);
std::string ms2Dur(uint64_t t);
const char* c2s(char c, char* buf);
int fileExists(const char* path);
int fileSize(const char* path);
int createLink(const char* link, const char* dest, int force);
int isLink(const char* path);
int isEmpty(const char* str);
int removeFile(const char* filename);
int chkDir(const char* path);
#ifdef USELIBXML
xsltStylesheetPtr loadXSLT(const char* name, const char* path, int utf8);
#endif
#ifdef USEMD5
typedef char md5Buf[sizeMd5+TB];
typedef char md5;
int createMd5(const char* buf, md5* md5);
int createMd5OfFile(const char* path, const char* name, md5* md5);
#endif
//***************************************************************************
// Zip
//***************************************************************************
int gunzip(MemoryStruct* zippedData, MemoryStruct* unzippedData);
void tellZipError(int errorCode, const char* op, const char* msg);
#ifdef USELIBARCHIVE
int unzip(const char* file, const char* filter, char*& buffer,
int& size, char* entryName);
#endif
#ifdef VDR_PLUGIN
//***************************************************************************
// Log Duration
//***************************************************************************
class LogDuration
{
public:
LogDuration(const char* aMessage, int aLogLevel = 2);
~LogDuration();
void show(const char* label = "");
protected:
char message[1000];
uint64_t durationStart;
int logLevel;
};
#endif
//***************************************************************************
#endif //___COMMON_H

63
lib/config.c Normal file
View File

@@ -0,0 +1,63 @@
/*
* config.c:
*
* See the README file for copyright information and how to reach the author.
*
*/
#include <string.h>
#include "common.h"
#include "config.h"
cEPG2VDRConfig EPG2VDRConfig;
cEPG2VDRConfig::cEPG2VDRConfig(void)
{
mainmenuVisible = yes;
mainmenuFullupdate = 0;
useproxy = no;
sstrcpy(httpproxy, "127.0.0.1:8000", sizeof(httpproxy));
sstrcpy(username, "", sizeof(username));
sstrcpy(password, "", sizeof(password));
checkInitial = yes;
updatetime = 6; // hours
days = 8;
upddays = 2;
storeXmlToFs = no;
blacklist = no;
masterMode = 0;
getepgimages = yes;
maximagesperevent = 1;
epgImageSize = 2;
seriesEnabled = yes;
sstrcpy(seriesUrl, "eplists.constabel.net", sizeof(seriesUrl));
seriesPort = 2006;
storeSeriesToFs = no;
#ifdef VDR_PLUGIN
activeOnEpgd = no;
scheduleBoot = no;
#else
sstrcpy(cachePath, "/var/cache/epgd", sizeof(cachePath));
sstrcpy(pluginPath, PLGDIR, sizeof(pluginPath));
sstrcpy(epgView, "eventsview.sql", sizeof(epgView));
updateThreshold = 200;
maintanance = no;
#endif
sstrcpy(dbHost, "localhost", sizeof(dbHost));
dbPort = 3306;
sstrcpy(dbName, "epg2vdr", sizeof(dbName));
sstrcpy(dbUser, "epg2vdr", sizeof(dbUser));
sstrcpy(dbPass, "epg", sizeof(dbPass));
logstdout = no;
loglevel = 1;
uuid[0] = 0;
}

73
lib/config.h Normal file
View File

@@ -0,0 +1,73 @@
/*
* config.h:
*
* See the README file for copyright information and how to reach the author.
*
* $Id: config.h,v 1.2 2012/10/26 08:44:13 wendel Exp $
*/
#ifndef __EPG2VDR_CONFIG_H
#define __EPG2VDR_CONFIG_H
#include "common.h"
//***************************************************************************
// Config
//***************************************************************************
struct cEPG2VDRConfig
{
public:
cEPG2VDRConfig(void);
int useproxy;
char httpproxy[256+TB];
char username[100+TB];
char password[100+TB];
int checkInitial;
int updatetime;
int days;
int upddays;
int storeXmlToFs;
int blacklist; // to enable noepg feature
int getepgimages;
int maximagesperevent;
int epgImageSize;
int seriesEnabled;
char seriesUrl[500+TB];
int seriesPort;
int storeSeriesToFs;
#ifdef VDR_PLUGIN
int activeOnEpgd;
int scheduleBoot;
#else
char cachePath[256+TB];
char pluginPath[256+TB];
char epgView[100+TB];
int updateThreshold;
int maintanance;
#endif
char dbHost[100+TB];
int dbPort;
char dbName[100+TB];
char dbUser[100+TB];
char dbPass[100+TB];
int logstdout;
int loglevel;
int mainmenuVisible;
int mainmenuFullupdate;
int masterMode;
char uuid[sizeUuid+TB];
};
extern cEPG2VDRConfig EPG2VDRConfig;
#endif // __EPG2VDR_CONFIG_H

1086
lib/db.c Normal file

File diff suppressed because it is too large Load Diff

1030
lib/db.h Normal file

File diff suppressed because it is too large Load Diff

856
lib/tabledef.c Normal file
View File

@@ -0,0 +1,856 @@
/*
* tabledef.c
*
* See the README file for copyright information and how to reach the author.
*
*/
#include "tabledef.h"
//***************************************************************************
// cEpgdState
//***************************************************************************
const char* cEpgdState::states[] =
{
"init",
"standby",
"stopped",
"busy (events)",
"busy (match)",
"busy (images)",
"busy (scraping)",
0
};
const char* cEpgdState::toName(cEpgdState::State s)
{
if (!isValid(s))
return "unknown";
return states[s];
}
cEpgdState::State cEpgdState::toState(const char* name)
{
for (int i = 0; i < esCount; i++)
if (strcmp(states[i], name) == 0)
return (State)i;
return esUnknown;
}
//***************************************************************************
// Event Fields
//***************************************************************************
//***************************************************************************
// Fields
//***************************************************************************
cDbService::FieldDef cTableEvents::fields[] =
{
// name format size index type
// primary key
{ "eventid", ffUInt, 0, fiEventId, ftPrimary },
{ "channelid", ffAscii, 50, fiChannelId, ftPrimary },
{ "masterid", ffUInt, 0, fiMasterId, ftAutoinc },
{ "useid", ffUInt, 0, fiUseId, ftData },
// meta
{ "source", ffAscii, 10, fiSource, ftMeta },
{ "fileref", ffAscii, 50, fiFileRef, ftMeta },
{ "inssp", ffInt, 10, fiInsSp, ftMeta },
{ "updsp", ffInt, 10, fiUpdSp, ftMeta },
{ "updflg", ffAscii, 1, fiUpdFlg, ftMeta },
{ "delflg", ffAscii, 1, fiDelFlg, ftMeta },
// vdr event data
{ "tableid", ffInt, 2, fiTableId, ftData },
{ "version", ffInt, 3, fiVersion, ftData },
{ "title", ffAscii, 200, fiTitle, ftData },
{ "comptitle", ffAscii, 200, fiCompTitle, ftData },
{ "shorttext", ffAscii, 300, fiShortText, ftData },
{ "compshorttext", ffAscii, 300, fiCompShortText, ftData },
{ "longdescription", ffText, 25000, fiLongDescription, ftData },
{ "starttime", ffInt, 10, fiStartTime, ftData },
{ "duration", ffInt, 5, fiDuration, ftData },
{ "parentalrating", ffInt, 2, fiParentalRating, ftData },
{ "vps", ffInt, 10, fiVps, ftData },
{ "description", ffText, 50000, fiDescription, ftCalc },
// additional external data
{ "shortdescription", ffAscii, 3000, fiShortDescription, ftData },
{ "actor", ffAscii, 3000, fiActor, ftData },
{ "audio", ffAscii, 50, fiAudio, ftData },
{ "category", ffAscii, 50, fiCategory, ftData },
{ "country", ffAscii, 50, fiCountry, ftData },
{ "director", ffAscii, 250, fiDirector, ftData },
{ "flags", ffAscii, 100, fiFlags, ftData },
{ "genre", ffAscii, 100, fiGenre, ftData },
{ "info", ffText, 10000, fiInfo, ftData },
{ "music", ffAscii, 250, fiMusic, ftData },
{ "producer", ffText, 1000, fiProducer, ftData },
{ "screenplay", ffAscii, 500, fiScreenplay, ftData },
{ "shortreview", ffAscii, 500, fiShortreview, ftData },
{ "tipp", ffAscii, 250, fiTipp, ftData },
{ "topic", ffAscii, 500, fiTopic, ftData },
{ "year", ffAscii, 10, fiYear, ftData },
{ "rating", ffAscii, 250, fiRating, ftData },
{ "fsk", ffAscii, 2, fiFsk, ftData },
{ "movieid", ffAscii, 20, fiMovieid, ftData },
{ "moderator", ffAscii, 250, fiModerator, ftData },
{ "other", ffText, 2000, fiOther, ftData },
{ "guest", ffText, 1000, fiGuest, ftData },
{ "camera", ffText, 1000, fiCamera, ftData },
{ "extepnum", ffInt, 4, fiExtEpNum, ftData },
{ "imagecount", ffInt, 2, fiImageCount, ftData },
// episodes (constable)
{ "episode", ffAscii, 250, fiEpisode, ftData },
{ "episodepart", ffAscii, 250, fiEpisodePart, ftData },
{ "episodelang", ffAscii, 3, fiEpisodeLang, ftData },
// tv scraper
{ "scrseriesid", ffInt, 11, fiScrSeriesId, ftData },
{ "scrseriesepisode", ffInt, 11, fiScrSeriesEpisode, ftData },
{ "scrmovieid", ffInt, 11, fiScrMovieId, ftData },
{ "scrsp", ffInt, 11, fiScrSp, ftData },
{ 0 }
};
cDbService::FieldDef* cTableEvents::toField(const char* name)
{
for (int i = 0; i < fiCount; i++)
if (strcmp(fields[i].name, name) == 0)
return &fields[i];
tell(0, "Request for unexpected field '%s', ignoring", name);
return 0;
}
cDbService::IndexDef cTableEvents::indices[] =
{
// index fields
{ "comptitle", { fiCompTitle, na }, 0 },
{ "source", { fiSource, na }, 0 },
{ "FilerefSource", { fiFileRef, fiSource, na }, 0 },
{ "channelid", { fiChannelId, na }, 0 },
{ "useid", { fiUseId, na }, 0 },
{ "useidchannelid", { fiUseId, fiChannelId, na }, 0 },
{ "updflgupdsp", { fiUpdFlg, fiUpdSp, na }, 0 },
{ "idxsourcechannelid", { fiSource, fiChannelId, na }, 0 },
{ 0 }
};
//***************************************************************************
// Components
//***************************************************************************
cDbService::FieldDef cTableComponents::fields[] =
{
// name format size index type
{ "eventid", ffUInt, 0, fiEventId, ftPrimary },
{ "channelid", ffAscii, 50, fiChannelId, ftPrimary },
{ "stream", ffInt, 3, fiStream, ftPrimary },
{ "type", ffInt, 3, fiType, ftPrimary },
{ "lang", ffAscii, 8, fiLang, ftPrimary },
{ "description", ffAscii, 100, fiDescription, ftPrimary },
{ "inssp", ffInt, 0, fiInsSp, ftMeta },
{ "updsp", ffInt, 0, fiUpdSp, ftMeta },
{ 0 }
};
//***************************************************************************
// File References
//***************************************************************************
cDbService::FieldDef cTableFileRefs::fields[] =
{
// name format size index type
{ "name", ffAscii, 100, fiName, ftPrimary },
{ "source", ffAscii, 10, fiSource, ftPrimary },
{ "inssp", ffInt, 0, fiInsSp, ftMeta },
{ "updsp", ffInt, 0, fiUpdSp, ftMeta },
{ "extid", ffAscii, 10, fiExternalId, ftData },
{ "fileref", ffAscii, 100, fiFileRef, ftData }, // name + '-' + tag
{ "tag", ffAscii, 100, fiTag, ftData },
{ 0 }
};
cDbService::IndexDef cTableFileRefs::indices[] =
{
// index fields
{ "SourceFileref", { fiSource, fiFileRef, na }, 0 },
{ "Fileref", { fiFileRef, na }, 0 },
{ 0 }
};
//***************************************************************************
// Image Ref Fields
//***************************************************************************
cDbService::FieldDef cTableImageRefs::fields[] =
{
// name format size index type
{ "eventid", ffUInt, 0, fiEventId, ftPrimary },
{ "lfn", ffInt, 0, fiLfn, ftPrimary },
{ "inssp", ffInt, 0, fiInsSp, ftMeta },
{ "updsp", ffInt, 0, fiUpdSp, ftMeta },
{ "source", ffAscii, 10, fiSource, ftMeta },
{ "fileref", ffAscii, 100, fiFileRef, ftData },
{ "imagename", ffAscii, 100, fiImgName, ftData },
{ 0 }
};
cDbService::IndexDef cTableImageRefs::indices[] =
{
// index fields
{ "lfn", { fiLfn, na }, 0 },
{ "name", { fiImgName, na }, 0 },
{ 0 }
};
//***************************************************************************
// Image Fields
//***************************************************************************
cDbService::FieldDef cTableImages::fields[] =
{
// name format size index type
{ "imagename", ffAscii, 100, fiImgName, ftPrimary },
{ "inssp", ffInt, 0, fiInsSp, ftMeta },
{ "updsp", ffInt, 0, fiUpdSp, ftMeta },
{ "image", ffMlob, 200000, fiImage, ftData },
{ 0 }
};
//***************************************************************************
// Series Episode Fields
//***************************************************************************
cDbService::FieldDef cTableEpisodes::fields[] =
{
// name format size index type
// primary key
{ "compname", ffAscii, 100, fiCompName, ftPrimary }, // episode name compressed
{ "comppartname", ffAscii, 200, fiCompPartName, ftPrimary }, // part name compressed
{ "lang", ffAscii, 10, fiLang, ftPrimary },
{ "inssp", ffInt, 0, fiInsSp, ftMeta },
{ "updsp", ffInt, 0, fiUpdSp, ftMeta },
{ "link", ffInt, 0, fiLink, ftData },
// episode data
{ "shortname", ffAscii, 100, fiShortName, ftData },
{ "episodename", ffAscii, 100, fiEpisodeName, ftData }, // episode name
// part data
{ "partname", ffAscii, 300, fiPartName, ftData }, // part name
{ "season", ffInt, 0, fiSeason, ftData },
{ "part", ffInt, 0, fiPart, ftData },
{ "parts", ffInt, 0, fiParts, ftData },
{ "number", ffInt, 0, fiNumber, ftData },
{ "extracol1", ffAscii, 250, fiExtraCol1, ftData },
{ "extracol2", ffAscii, 250, fiExtraCol2, ftData },
{ "extracol3", ffAscii, 250, fiExtraCol3, ftData },
{ "comment", ffAscii, 250, fiComment, ftData },
{ 0 }
};
cDbService::IndexDef cTableEpisodes::indices[] =
{
// index fields
{ "updsp", { fiUpdSp, na }, 0 },
{ 0 }
};
//***************************************************************************
// Channel Map Fields
//***************************************************************************
cDbService::FieldDef cTableChannelMap::fields[] =
{
// name format size index type
{ "extid", ffAscii, 10, fiExternalId, ftPrimary },
{ "channelid", ffAscii, 50, fiChannelId, ftPrimary },
{ "source", ffAscii, 20, fiSource, ftPrimary },
{ "channelname", ffAscii, 100, fiChannelName, ftData },
{ "vps", ffInt, 0, fiVps, ftData },
{ "merge", ffInt, 0, fiMerge, ftData },
{ "mergesp", ffInt, 0, fiMergeSp, ftData },
{ "inssp", ffInt, 0, fiInsSp, ftMeta },
{ "updsp", ffInt, 0, fiUpdSp, ftMeta },
{ "updflg", ffAscii, 1, fiUpdFlg, ftMeta },
{ 0 }
};
cDbService::IndexDef cTableChannelMap::indices[] =
{
// index fields
{ "sourceExtid", { fiSource, fiExternalId, na }, 0 },
{ "source", { fiSource, na }, 0 },
{ "updflg", { fiUpdFlg, na }, 0 },
{ "idxsourcechannelid", { fiSource, fiChannelId, na }, 0 },
{ 0 }
};
//***************************************************************************
// VDRs Fields
//***************************************************************************
cDbService::FieldDef cTableVdrs::fields[] =
{
// name format size index type
{ "uuid", ffAscii, 40, fiUuid, ftPrimary },
{ "inssp", ffInt, 0, fiInsSp, ftMeta },
{ "updsp", ffInt, 0, fiUpdSp, ftMeta },
{ "name", ffAscii, 100, fiName, ftData },
{ "version", ffAscii, 100, fiVersion, ftData },
{ "dbapi", ffUInt, 0, fiDbApi, ftData },
{ "lastupd", ffInt, 0, fiLastUpdate, ftData },
{ "nextupd", ffInt, 0, fiNextUpdate, ftData },
{ "state", ffAscii, 20, fiState, ftData },
{ "master", ffAscii, 1, fiMaster, ftData },
{ "ip", ffAscii, 20, fiIp, ftData },
{ 0 }
};
//***************************************************************************
// Parameter Fields
//***************************************************************************
cDbService::FieldDef cTableParameters::fields[] =
{
// name format size index type
{ "owner", ffAscii, 40, fiOwner, ftPrimary },
{ "name", ffAscii, 40, fiName, ftPrimary },
{ "inssp", ffInt, 0, fiInsSp, ftMeta },
{ "updsp", ffInt, 0, fiUpdSp, ftMeta },
{ "value", ffAscii, 100, fiValue, ftData },
{ 0 }
};
//***************************************************************************
// Analyse
//***************************************************************************
cDbService::FieldDef cTableAnalyse::fields[] =
{
// name format size index type
{ "channelid", ffAscii, 50, fiChannelId, ftPrimary },
{ "vdr_masterid", ffUInt, 0, fiVdrMasterId, ftData },
{ "vdr_eventid", ffUInt, 0, fiVdrEventId, ftPrimary },
{ "vdr_starttime", ffInt, 10, fiVdrStartTime, ftData },
{ "vdr_duration", ffInt, 5, fiVdrDuration, ftData },
{ "vdr_title", ffAscii, 200, fiVdrTitle, ftData },
{ "vdr_shorttext", ffAscii, 300, fiVdrShortText, ftData },
{ "ext_masterid", ffUInt, 0, fiExtMasterId, ftData },
{ "ext_eventid", ffUInt, 0, fiExtEventId, ftData },
{ "ext_starttime", ffInt, 10, fiExtStartTime, ftData },
{ "ext_duration", ffInt, 5, fiExtDuration, ftData },
{ "ext_title", ffAscii, 200, fiExtTitle, ftData },
{ "ext_shorttext", ffAscii, 300, fiExtShortText, ftData },
{ "ext_episode", ffAscii, 1, fiExtEpisode, ftData },
{ "ext_merge", ffInt, 11, fiExtMerge, ftData },
{ "ext_images", ffAscii, 1, fiExiImages, ftData },
{ "lvmin", ffInt, 3, fiLvMin, ftData },
{ "rank", ffInt, 5, fiRank, ftData },
{ 0 }
};
cDbService::IndexDef cTableAnalyse::indices[] =
{
// index fields
{ "vdr_masterid", { fiVdrMasterId, na }, 0 },
{ 0 }
};
//***************************************************************************
// Snapshot
//***************************************************************************
cDbService::FieldDef cTableSnapshot::fields[] =
{
// name format size index type
{ "channelid", ffAscii, 50, fiChannelId, ftData },
{ "source", ffAscii, 10, fiSource, ftData },
{ "masterid", ffUInt, 0, fiVdrMasterId, ftData },
{ "eventid", ffUInt, 0, fiEventId, ftData },
{ "useid", ffUInt, 0, fiUseId, ftData },
{ "starttime", ffInt, 10, fiStartTime, ftData },
{ "duration", ffInt, 5, fiDuration, ftData },
{ "title", ffAscii, 200, fiTitle, ftData },
{ "comptitle", ffAscii, 200, fiCompTitle, ftData },
{ "shorttext", ffAscii, 300, fiShortText, ftData },
{ "compshorttext", ffAscii, 300, fiCompShortText, ftData },
{ "updsp", ffInt, 10, fiUpdsp, ftData },
{ "episode", ffAscii, 1, fiEpisode, ftData },
{ "merge", ffInt, 0, fiMerge, ftData },
{ "images", ffAscii, 1, fiImages, ftData },
{ 0 }
};
cDbService::IndexDef cTableSnapshot::indices[] =
{
// index fields
{ "channelid", { fiChannelId, na }, 0 },
{ "starttimeSource", { fiStartTime, fiSource, na }, 0 },
{ 0 }
};
//***************************************************************************
// Series Fields
//***************************************************************************
cDbService::FieldDef cTableSeries::fields[] =
{
// name format size index type
// primary key
{ "series_id", ffUInt, 0, fiSeriesId, ftPrimary },
//Data
{ "series_name", ffAscii, 200, fiSeriesName, ftData },
{ "series_last_scraped", ffUInt, 0, fiSeriesLastScraped, ftData },
{ "series_last_updated", ffUInt, 0, fiSeriesLastUpdated, ftData },
{ "series_overview", ffText, 10000, fiSeriesOverview, ftData },
{ "series_firstaired", ffAscii, 50, fiSeriesFirstAired, ftData },
{ "series_network", ffAscii, 100, fiSeriesNetwork, ftData },
{ "series_imdb_id", ffAscii, 20, fiSeriesIMDBId, ftData },
{ "series_genre", ffAscii, 100, fiSeriesGenre, ftData },
{ "series_rating", ffFloat, 31, fiSeriesRating, ftData },
{ "series_status", ffAscii, 50, fiSeriesStatus, ftData },
{ 0 }
};
cDbService::FieldDef* cTableSeries::toField(const char* name)
{
for (int i = 0; i < fiCount; i++)
if (strcmp(fields[i].name, name) == 0)
return &fields[i];
tell(0, "Request for unexpected field '%s', ignoring", name);
return 0;
}
cDbService::IndexDef cTableSeries::indices[] =
{
// index fields
{ 0 }
};
//***************************************************************************
// SeriesEpisode Fields
//***************************************************************************
cDbService::FieldDef cTableSeriesEpisode::fields[] =
{
// name format size index type
// primary key
{ "episode_id", ffUInt, 0, fiEpisodeId, ftPrimary },
//Data
{ "episode_number", ffUInt, 0, fiEpisodeNumber, ftData },
{ "season_number", ffUInt, 0, fiSeasonNumber, ftData },
{ "episode_name", ffAscii, 300, fiEpisodeName, ftData },
{ "episode_overview", ffText, 10000, fiEpisodeOverview, ftData },
{ "episode_firstaired", ffAscii, 20, fiEpisodeFirstAired, ftData },
{ "episode_gueststars", ffAscii, 1000, fiEpisodeGuestStars, ftData },
{ "episode_rating", ffFloat, 31, fiEpisodeRating, ftData },
{ "episode_last_updated", ffUInt, 0, fiEpisodeLastUpdated, ftData },
{ "series_id", ffUInt, 0, fiSeriesId, ftData },
{ 0 }
};
cDbService::FieldDef* cTableSeriesEpisode::toField(const char* name)
{
for (int i = 0; i < fiCount; i++)
if (strcmp(fields[i].name, name) == 0)
return &fields[i];
tell(0, "Request for unexpected field '%s', ignoring", name);
return 0;
}
cDbService::IndexDef cTableSeriesEpisode::indices[] =
{
// index fields
{ "series_id", { fiSeriesId, na }, 0 },
{ 0 }
};
//***************************************************************************
// SeriesMedia Fields
//***************************************************************************
cDbService::FieldDef cTableSeriesMedia::fields[] =
{
// name format size index type
// primary key
{ "series_id", ffUInt, 0, fiSeriesId, ftPrimary },
{ "season_number", ffUInt, 0, fiSeasonNumber, ftPrimary },
{ "episode_id", ffUInt, 0, fiEpisodeId, ftPrimary },
{ "actor_id", ffUInt, 0, fiActorId, ftPrimary },
{ "media_type", ffUInt, 0, fiMediaType, ftPrimary },
//Data
{ "media_url", ffAscii, 100, fiMediaUrl, ftData },
{ "media_width", ffUInt, 0, fiMediaWidth, ftData },
{ "media_height", ffUInt, 0, fiMediaHeight, ftData },
{ "media_rating", ffFloat, 31, fiMediaRating, ftData },
{ "media_content", ffMlob, 1000000, fiMediaContent, ftData },
{ 0 }
};
cDbService::FieldDef* cTableSeriesMedia::toField(const char* name)
{
for (int i = 0; i < fiCount; i++)
if (strcmp(fields[i].name, name) == 0)
return &fields[i];
tell(0, "Request for unexpected field '%s', ignoring", name);
return 0;
}
cDbService::IndexDef cTableSeriesMedia::indices[] =
{
// index fields
{ "series_id", { fiSeriesId, na }, 0 },
{ "season_number", { fiSeasonNumber, na }, 0 },
{ "episode_id", { fiEpisodeId, na }, 0 },
{ "actor_id", { fiActorId, na }, 0 },
{ 0 }
};
//***************************************************************************
// SeriesActor Fields
//***************************************************************************
cDbService::FieldDef cTableSeriesActor::fields[] =
{
// name format size index type
// primary key
{ "actor_id", ffUInt, 0, fiActorId, ftPrimary },
//Data
{ "actor_name", ffAscii, 100, fiActorName, ftData },
{ "actor_role", ffAscii, 500, fiActorRole, ftData },
{ "actor_sortorder", ffUInt, 0, fiSortOrder, ftData },
{ 0 }
};
cDbService::FieldDef* cTableSeriesActor::toField(const char* name)
{
for (int i = 0; i < fiCount; i++)
if (strcmp(fields[i].name, name) == 0)
return &fields[i];
tell(0, "Request for unexpected field '%s', ignoring", name);
return 0;
}
cDbService::IndexDef cTableSeriesActor::indices[] =
{
// index fields
{ 0 }
};
//***************************************************************************
// Movie Fields
//***************************************************************************
cDbService::FieldDef cTableMovies::fields[] =
{
// name format size index type
// primary key
{ "movie_id", ffUInt, 0, fiMovieId, ftPrimary },
//Data
{ "movie_title", ffAscii, 300, fiTitle, ftData },
{ "movie_original_title", ffAscii, 300, fiOriginalTitle, ftData },
{ "movie_tagline", ffAscii, 1000, fiTagline, ftData },
{ "movie_overview", ffText, 5000, fiOverview, ftData },
{ "movie_adult", ffUInt, 0, fiIsAdult, ftData },
{ "movie_collection_id", ffUInt, 0, fiCollectionId, ftData },
{ "movie_collection_name", ffAscii, 300, fiCollectionName, ftData },
{ "movie_budget", ffUInt, 0, fiBudget, ftData },
{ "movie_revenue", ffUInt, 0, fiRevenue, ftData },
{ "movie_genres", ffAscii, 500, fiGenres, ftData },
{ "movie_homepage", ffAscii, 300, fiHomepage, ftData },
{ "movie_release_date", ffAscii, 20, fiReleaaseDate, ftData },
{ "movie_runtime", ffUInt, 0, fiRuntime, ftData },
{ "movie_popularity", ffFloat, 31, fiPopularity, ftData },
{ "movie_vote_average", ffFloat, 31, fiVoteAverage, ftData },
{ 0 }
};
cDbService::FieldDef* cTableMovies::toField(const char* name)
{
for (int i = 0; i < fiCount; i++)
if (strcmp(fields[i].name, name) == 0)
return &fields[i];
tell(0, "Request for unexpected field '%s', ignoring", name);
return 0;
}
cDbService::IndexDef cTableMovies::indices[] =
{
// index fields
{ "movie_id", { fiMovieId, na }, 0 },
{ 0 }
};
//***************************************************************************
// MovieActor Fields
//***************************************************************************
cDbService::FieldDef cTableMovieActor::fields[] =
{
// name format size index type
// primary key
{ "actor_id", ffUInt, 0, fiActorId, ftPrimary },
//Data
{ "actor_name", ffAscii, 300, fiActorName, ftData },
{ 0 }
};
cDbService::FieldDef* cTableMovieActor::toField(const char* name)
{
for (int i = 0; i < fiCount; i++)
if (strcmp(fields[i].name, name) == 0)
return &fields[i];
tell(0, "Request for unexpected field '%s', ignoring", name);
return 0;
}
cDbService::IndexDef cTableMovieActor::indices[] =
{
// index fields
{ "actor_id", { fiActorId, na }, 0 },
{ 0 }
};
//***************************************************************************
// MovieActors Fields
//***************************************************************************
cDbService::FieldDef cTableMovieActors::fields[] =
{
// name format size index type
// primary key
{ "movie_id", ffUInt, 0, fiMovieId, ftPrimary },
{ "actor_id", ffUInt, 0, fiActorId, ftPrimary },
//Data
{ "actor_role", ffAscii, 300, fiRole, ftData },
{ 0 }
};
cDbService::FieldDef* cTableMovieActors::toField(const char* name)
{
for (int i = 0; i < fiCount; i++)
if (strcmp(fields[i].name, name) == 0)
return &fields[i];
tell(0, "Request for unexpected field '%s', ignoring", name);
return 0;
}
cDbService::IndexDef cTableMovieActors::indices[] =
{
// index fields
{ "movie_id", { fiMovieId, na }, 0 },
{ "actor_id", { fiActorId, na }, 0 },
{ 0 }
};
//***************************************************************************
// cTableMovieMedia Fields
//***************************************************************************
cDbService::FieldDef cTableMovieMedia::fields[] =
{
// name format size index type
// primary key
{ "movie_id", ffUInt, 0, fiMovieId, ftPrimary },
{ "actor_id", ffUInt, 0, fiActorId, ftPrimary },
{ "media_type", ffUInt, 0, fiMediaType, ftPrimary },
//Data
{ "media_url", ffAscii, 100, fiMediaUrl, ftData },
{ "media_width", ffUInt, 0, fiMediaWidth, ftData },
{ "media_height", ffUInt, 0, fiMediaHeight, ftData },
{ "media_content", ffMlob, 1000000, fiMediaContent, ftData },
{ 0 }
};
cDbService::FieldDef* cTableMovieMedia::toField(const char* name)
{
for (int i = 0; i < fiCount; i++)
if (strcmp(fields[i].name, name) == 0)
return &fields[i];
tell(0, "Request for unexpected field '%s', ignoring", name);
return 0;
}
cDbService::IndexDef cTableMovieMedia::indices[] =
{
// index fields
{ "movie_id", { fiMovieId, na }, 0 },
{ "actor_id", { fiActorId, na }, 0 },
{ 0 }
};
//***************************************************************************
// cTableRecordings Fields
//***************************************************************************
cDbService::FieldDef cTableRecordings::fields[] =
{
// name format size index type
// primary key
{ "uuid", ffAscii, 40, fiUuid, ftPrimary },
{ "rec_path", ffAscii, 200, fiRecPath, ftPrimary },
{ "rec_start", ffUInt, 0, fiRecStart, ftPrimary },
//Data
{ "event_id", ffUInt, 0, fiEventId, ftData },
{ "channel_id", ffAscii, 50, fiChannelId, ftData },
{ "scrapinfo_movie_id", ffUInt, 0, fiScrapInfoMovieId, ftData },
{ "scrapinfo_series_id", ffUInt, 0, fiScrapInfoSeriesId, ftData },
{ "scrapinfo_episode_id", ffUInt, 0, fiScrapInfoEpisodeId, ftData },
{ "scrap_new", ffUInt, 0, fiScrapNew, ftData },
{ "rec_title", ffAscii, 200, fiRecTitle, ftData },
{ "rec_subtitle", ffAscii, 500, fiRecSubTitle, ftData },
{ "rec_duration", ffUInt, 0, fiRecDuration, ftData },
{ "movie_id", ffUInt, 0, fiMovieId, ftData },
{ "series_id", ffUInt, 0, fiSeriesId, ftData },
{ "episode_id", ffUInt, 0, fiEpisodeId, ftData },
{ 0 }
};
cDbService::FieldDef* cTableRecordings::toField(const char* name)
{
for (int i = 0; i < fiCount; i++)
if (strcmp(fields[i].name, name) == 0)
return &fields[i];
tell(0, "Request for unexpected field '%s', ignoring", name);
return 0;
}
cDbService::IndexDef cTableRecordings::indices[] =
{
// index fields
{ "uuid", { fiUuid, na }, 0 },
{ "rec_path", { fiRecPath, na }, 0 },
{ "rec_start", { fiRecStart, na }, 0 },
{ 0 }
};

832
lib/tabledef.h Normal file
View File

@@ -0,0 +1,832 @@
/*
* tabledef.h
*
* See the README file for copyright information and how to reach the author.
*
*/
#ifndef __TABLEDEF_H
#define __TABLEDEF_H
#include "db.h"
//***************************************************************************
// cEpgdState
//***************************************************************************
class cEpgdState
{
public:
enum State
{
esUnknown = na,
esInit,
esStandby,
esStopped,
esBusy,
esBusyEvents = esBusy,
esBusyMatch,
esBusyImages,
esBusyScraping,
esCount
};
static const char* toName(State s);
static State toState(const char* name);
static int isValid(State s) { return s > esUnknown && s < esCount; }
static const char* states[];
};
typedef cEpgdState Es;
//***************************************************************************
// cUpdateState
//***************************************************************************
class cUpdateState
{
public:
enum State
{
// add to VDRs EPG
usActive = 'A',
usLink = 'L',
usPassthrough = 'P',
// remove from VDRs EPG
usChanged = 'C',
usDelete = 'D',
usRemove = 'R',
// don't care for VDRs EPG
usInactive = 'I',
usTarget = 'T'
};
// get lists for SQL 'in' statements
static const char* getDeletable() { return "'A','L','P','R','I'"; }
static const char* getNeeded() { return "'A','L','P','C','D','R'"; }
// checks fpr c++ code
static int isNeeded(char c) { return strchr("ALPCDR", c) != 0; }
static int isRemove(char c) { return strchr("CDR", c) != 0; }
};
typedef cUpdateState Us;
//***************************************************************************
// class cTableFileRef
//***************************************************************************
class cTableFileRefs : public cDbTable
{
public:
cTableFileRefs(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "fileref"; }
enum FieldIndex
{
fiName,
fiSource,
fiInsSp,
fiUpdSp,
fiExternalId,
fiFileRef,
fiTag,
fiCount
};
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableImageRef
//***************************************************************************
class cTableImageRefs : public cDbTable
{
public:
cTableImageRefs(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "imagerefs"; }
enum FieldIndex
{
fiEventId,
fiLfn,
fiInsSp,
fiUpdSp,
fiSource,
fiFileRef,
fiImgName,
fiCount
};
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableImage
//***************************************************************************
class cTableImages : public cDbTable
{
public:
cTableImages(cDbConnection* aConnection)
: cDbTable(aConnection, fields) { }
virtual const char* TableName() { return "images"; }
enum FieldIndex
{
fiImgName,
fiInsSp,
fiUpdSp,
fiImage,
fiCount
};
static FieldDef fields[];
};
//***************************************************************************
// class cTableEvent
//***************************************************************************
class cTableEvents : public cDbTable
{
public:
cTableEvents(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "events"; }
enum FieldIndex
{
fiEventId,
fiChannelId,
fiMasterId,
fiUseId,
fiSource,
fiFileRef,
fiInsSp,
fiUpdSp,
fiUpdFlg, // update flag
fiDelFlg, // deletion flag
fiTableId,
fiVersion,
fiTitle,
fiCompTitle, // compressed (without whitespace and special characters)
fiShortText,
fiCompShortText, // compressed (without whitespace and special characters)
fiLongDescription,
fiStartTime,
fiDuration,
fiParentalRating,
fiVps,
fiDescription, // view field, not stored!
fiShortDescription,
fiActor,
fiAudio,
fiCategory,
fiCountry,
fiDirector,
fiFlags,
fiGenre,
fiInfo,
fiMusic,
fiProducer,
fiScreenplay,
fiShortreview,
fiTipp,
fiTopic,
fiYear,
fiRating,
fiFsk,
fiMovieid,
fiModerator,
fiOther,
fiGuest,
fiCamera,
fiExtEpNum,
fiImageCount,
fiEpisode,
fiEpisodePart,
fiEpisodeLang,
fiScrSeriesId,
fiScrSeriesEpisode,
fiScrMovieId,
fiScrSp,
fiCount
};
static FieldDef* toField(const char* name);
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableComponent
//***************************************************************************
class cTableComponents : public cDbTable
{
public:
cTableComponents(cDbConnection* aConnection)
: cDbTable(aConnection, fields) { }
virtual const char* TableName() { return "components"; }
enum FieldIndex
{
fiEventId,
fiChannelId,
fiStream,
fiType,
fiLang,
fiDescription,
fiInsSp,
fiUpdSp
};
static FieldDef fields[];
};
//***************************************************************************
// class cTableEpisode
//***************************************************************************
class cTableEpisodes : public cDbTable
{
public:
cTableEpisodes(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "episodes"; }
enum FieldIndex
{
// primary key
fiCompName, // compressed name (without whitespace and special characters)
fiCompPartName, // " " "
fiLang, // "de", "en", ...
fiInsSp,
fiUpdSp,
fiLink,
// episode data
fiShortName,
fiEpisodeName, // episode name (fielname without path and suffix)
// part data
fiPartName, // part name
fiSeason,
fiPart,
fiParts,
fiNumber,
fiExtraCol1,
fiExtraCol2,
fiExtraCol3,
fiComment,
fiCount
};
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableChannelMap
//***************************************************************************
class cTableChannelMap : public cDbTable
{
public:
cTableChannelMap(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "channelmap"; }
enum FieldIndex
{
fiExternalId, //
fiChannelId, //
fiSource,
fiChannelName,
fiVps,
fiMerge,
fiMergeSp,
fiInsSp,
fiUpdSp,
fiUpdFlg,
fiCount
};
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableVdr
//***************************************************************************
class cTableVdrs : public cDbTable
{
public:
cTableVdrs(cDbConnection* aConnection)
: cDbTable(aConnection, fields) { }
virtual const char* TableName() { return "vdrs"; }
enum FieldIndex
{
fiUuid,
fiInsSp,
fiUpdSp,
fiName,
fiVersion,
fiDbApi,
fiLastUpdate,
fiNextUpdate,
fiState,
fiMaster,
fiIp,
fiCount
};
static FieldDef fields[];
};
//***************************************************************************
// class cTableParameters
//***************************************************************************
class cTableParameters : public cDbTable
{
public:
cTableParameters(cDbConnection* aConnection)
: cDbTable(aConnection, fields) { }
virtual const char* TableName() { return "parameters"; }
enum FieldIndex
{
fiOwner,
fiName,
fiInsSp,
fiUpdSp,
fiValue,
fiCount
};
static FieldDef fields[];
};
//***************************************************************************
// cTableAnalyse
//***************************************************************************
class cTableAnalyse : public cDbTable
{
public:
cTableAnalyse(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "analyse"; }
enum FieldIndex
{
fiChannelId,
fiVdrMasterId,
fiVdrEventId,
fiVdrStartTime,
fiVdrDuration,
fiVdrTitle,
fiVdrShortText,
fiExtMasterId,
fiExtEventId,
fiExtStartTime,
fiExtDuration,
fiExtTitle,
fiExtShortText,
fiExtEpisode,
fiExtMerge,
fiExiImages,
fiLvMin,
fiRank,
fiCount
};
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// cTableSnapshot
//***************************************************************************
class cTableSnapshot : public cDbTable
{
public:
cTableSnapshot(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "snapshot"; }
enum FieldIndex
{
fiChannelId,
fiSource,
fiVdrMasterId,
fiEventId,
fiUseId,
fiStartTime,
fiDuration,
fiTitle,
fiCompTitle,
fiShortText,
fiCompShortText,
fiUpdsp,
fiEpisode,
fiMerge,
fiImages,
fiCount
};
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableSeries
//***************************************************************************
class cTableSeries : public cDbTable
{
public:
cTableSeries(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "series"; }
enum FieldIndex
{
fiSeriesId,
fiSeriesName,
fiSeriesLastScraped,
fiSeriesLastUpdated,
fiSeriesOverview,
fiSeriesFirstAired,
fiSeriesNetwork,
fiSeriesIMDBId,
fiSeriesGenre,
fiSeriesRating,
fiSeriesStatus,
fiCount
};
static FieldDef* toField(const char* name);
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableSeriesEpisode
//***************************************************************************
class cTableSeriesEpisode : public cDbTable
{
public:
cTableSeriesEpisode(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "series_episode"; }
enum FieldIndex
{
fiEpisodeId,
fiEpisodeNumber,
fiSeasonNumber,
fiEpisodeName,
fiEpisodeOverview,
fiEpisodeFirstAired,
fiEpisodeGuestStars,
fiEpisodeRating,
fiEpisodeLastUpdated,
fiSeriesId,
fiCount
};
static FieldDef* toField(const char* name);
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableSeriesMedia
//***************************************************************************
class cTableSeriesMedia : public cDbTable
{
public:
cTableSeriesMedia(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "series_media"; }
enum FieldIndex
{
fiSeriesId,
fiSeasonNumber,
fiEpisodeId,
fiActorId,
fiMediaType,
fiMediaUrl,
fiMediaWidth,
fiMediaHeight,
fiMediaRating,
fiMediaContent,
fiCount
};
static FieldDef* toField(const char* name);
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableSeriesActor
//***************************************************************************
class cTableSeriesActor : public cDbTable
{
public:
cTableSeriesActor(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "series_actor"; }
enum FieldIndex
{
fiActorId,
fiActorName,
fiActorRole,
fiSortOrder,
fiCount
};
static FieldDef* toField(const char* name);
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableMovies
//***************************************************************************
class cTableMovies : public cDbTable
{
public:
cTableMovies(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "movie"; }
enum FieldIndex
{
fiMovieId,
fiTitle,
fiOriginalTitle,
fiTagline,
fiOverview,
fiIsAdult,
fiCollectionId,
fiCollectionName,
fiBudget,
fiRevenue,
fiGenres,
fiHomepage,
fiReleaaseDate,
fiRuntime,
fiPopularity,
fiVoteAverage,
fiCount
};
static FieldDef* toField(const char* name);
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableMovieActor
//***************************************************************************
class cTableMovieActor : public cDbTable
{
public:
cTableMovieActor(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "movie_actor"; }
enum FieldIndex
{
fiActorId,
fiActorName,
fiCount
};
static FieldDef* toField(const char* name);
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableMovieActors
//***************************************************************************
class cTableMovieActors : public cDbTable
{
public:
cTableMovieActors(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "movie_actors"; }
enum FieldIndex
{
fiMovieId,
fiActorId,
fiRole,
fiCount
};
static FieldDef* toField(const char* name);
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableMovieMedia
//***************************************************************************
class cTableMovieMedia : public cDbTable
{
public:
cTableMovieMedia(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "movie_media"; }
enum FieldIndex
{
fiMovieId,
fiActorId,
fiMediaType,
fiMediaUrl,
fiMediaWidth,
fiMediaHeight,
fiMediaContent,
fiCount
};
static FieldDef* toField(const char* name);
static FieldDef fields[];
static IndexDef indices[];
};
//***************************************************************************
// class cTableRecordings
//***************************************************************************
class cTableRecordings : public cDbTable
{
public:
cTableRecordings(cDbConnection* aConnection)
: cDbTable(aConnection, fields, indices) { }
virtual const char* TableName() { return "recordings"; }
enum FieldIndex
{
fiUuid,
fiRecPath,
fiRecStart,
fiEventId,
fiChannelId,
fiScrapInfoMovieId,
fiScrapInfoSeriesId,
fiScrapInfoEpisodeId,
fiScrapNew,
fiRecTitle,
fiRecSubTitle,
fiRecDuration,
fiMovieId,
fiSeriesId,
fiEpisodeId,
fiCount
};
static FieldDef* toField(const char* name);
static FieldDef fields[];
static IndexDef indices[];
};
#endif //__TABLEDEF_H