Compare commits
4 Commits
Author | SHA1 | Date |
---|---|---|
adrianf36 | b55c134eed | |
MofTot | b3ea751561 | |
HummyPkg | 5e468f5857 | |
adrianf36 | 222797837c |
|
@ -0,0 +1,19 @@
|
|||
Copyright 2019 af123
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
16
Makefile
16
Makefile
|
@ -1,26 +1,30 @@
|
|||
|
||||
MAKE=gmake
|
||||
|
||||
DEFS=
|
||||
DEFS=-DFOXSATPLATFORM -DFOXSATFILE
|
||||
#DEFS= -DFOXSATFILE
|
||||
|
||||
SRCS= descriptor.c \
|
||||
epg.c \
|
||||
file.c \
|
||||
huffman.c \
|
||||
main.c \
|
||||
util.c
|
||||
util.c \
|
||||
epgsql.c
|
||||
|
||||
HDRS= descriptor.h \
|
||||
epg.h \
|
||||
lint.h \
|
||||
util.h
|
||||
util.h \
|
||||
epgsql.h
|
||||
|
||||
OBJS= $(SRCS:.c=.o)
|
||||
CC=gcc
|
||||
#CC=gcc
|
||||
#CC=mipsel-linux-gcc
|
||||
CFLAGS=-g
|
||||
CC=mips-linux-gcc
|
||||
CFLAGS=-g -pthread
|
||||
INCS=
|
||||
LIBS=
|
||||
LIBS=-lsqlite3 -ldl
|
||||
#CFLAGS=-g -O3 -fno-strict-aliasing
|
||||
#WARN=-pedantic -Wall -Wnested-externs -Wpointer-arith -Werror -Wno-unused
|
||||
WARN=-pedantic -Wall -W -Wnested-externs -Wpointer-arith -Wno-long-long
|
||||
|
|
|
@ -298,6 +298,8 @@ content_type(struct descriptor *d)
|
|||
return "Education/Science/Factual";
|
||||
case 0xa:
|
||||
return "Leisure";
|
||||
case 0xf:
|
||||
return "Drama";
|
||||
default:
|
||||
return "Undefined";
|
||||
}
|
||||
|
|
32
descriptor.h
32
descriptor.h
|
@ -10,7 +10,11 @@
|
|||
#define DS_PRIVATE_DATA_SPECIFIER 95
|
||||
#define DS_CONTENT_IDENTIFIER 118
|
||||
#define DS_FTA_CONTENT_MGMT 126
|
||||
#ifdef FOXSATPLATFORM
|
||||
#define DS_USER_DEFINED 218
|
||||
#else
|
||||
#define DS_USER_DEFINED 137
|
||||
#endif
|
||||
|
||||
#define PARSER_SHORT_EVENT 0
|
||||
#define PARSER_USER_DEFINED 1
|
||||
|
@ -26,8 +30,13 @@
|
|||
|
||||
#pragma pack(1)
|
||||
struct crid {
|
||||
#ifdef FOXSATPLATFORM
|
||||
unsigned int type:6;
|
||||
unsigned int location:2;
|
||||
#else
|
||||
unsigned int location:2;
|
||||
unsigned int type:6;
|
||||
#endif
|
||||
unsigned int cridlen;
|
||||
char *crid;
|
||||
unsigned int ref:16;
|
||||
|
@ -45,8 +54,13 @@ struct descriptor {
|
|||
char *text;
|
||||
} d77; /* SHORT_EVENT */
|
||||
struct {
|
||||
#ifdef FOXSATPLATFORM
|
||||
unsigned int reserved:4;
|
||||
unsigned int stream_content:4;
|
||||
#else
|
||||
unsigned int stream_content:4;
|
||||
unsigned int reserved:4;
|
||||
#endif
|
||||
unsigned int type:8;
|
||||
unsigned int tag:8;
|
||||
char lang[3];
|
||||
|
@ -54,8 +68,13 @@ struct descriptor {
|
|||
unsigned int textlen;
|
||||
} d80; /* COMPONENT */
|
||||
struct {
|
||||
#ifdef FOXSATPLATFORM
|
||||
unsigned int level1:4;
|
||||
unsigned int level2:4;
|
||||
#else
|
||||
unsigned int level2:4;
|
||||
unsigned int level1:4;
|
||||
#endif
|
||||
unsigned int user:8;
|
||||
} d84; /* CONTENT */
|
||||
struct {
|
||||
|
@ -78,16 +97,29 @@ struct descriptor {
|
|||
unsigned int linkage_type:8;
|
||||
union {
|
||||
struct {
|
||||
#ifdef FOXSATPLATFORM
|
||||
unsigned int handover_type:4;
|
||||
unsigned int reserved:3;
|
||||
unsigned int origin_type:1;
|
||||
unsigned int id:16;
|
||||
#else
|
||||
unsigned int origin_type:1;
|
||||
unsigned int reserved:3;
|
||||
unsigned int handover_type:4;
|
||||
unsigned int id:16;
|
||||
#endif
|
||||
} l8;
|
||||
struct {
|
||||
unsigned int event_id:16;
|
||||
#ifdef FOXSATPLATFORM
|
||||
unsigned int listed:1;
|
||||
unsigned int simulcast:1;
|
||||
unsigned int reserved:6;
|
||||
#else
|
||||
unsigned int reserved:6;
|
||||
unsigned int simulcast:1;
|
||||
unsigned int listed:1;
|
||||
#endif
|
||||
} ld;
|
||||
} l;
|
||||
} d74; /* DS_LINKAGE */
|
||||
|
|
9
epg.c
9
epg.c
|
@ -177,7 +177,11 @@ parse(char *epgpath,
|
|||
/* Skip this service. */
|
||||
epg->offset += s->total_length - 14;
|
||||
/* Skip padding bytes... */
|
||||
#ifdef FOXSATFILE
|
||||
while ((epg->offset % 4) != 0)
|
||||
#else
|
||||
while (epg->bin[epg->offset] == 'U')
|
||||
#endif
|
||||
epg->offset++;
|
||||
continue;
|
||||
}
|
||||
|
@ -332,12 +336,15 @@ parse(char *epgpath,
|
|||
if (dslist[i])
|
||||
free_descriptor(dslist[i]);
|
||||
}
|
||||
|
||||
/* Skip CRC */
|
||||
epg->offset += 4;
|
||||
|
||||
/* Skip padding bytes... */
|
||||
#ifdef FOXSATFILE
|
||||
while ((epg->offset % 4) != 0)
|
||||
#else
|
||||
while (epg->bin[epg->offset] == 'U')
|
||||
#endif
|
||||
epg->offset++;
|
||||
}
|
||||
|
||||
|
|
38
epg.h
38
epg.h
|
@ -5,7 +5,11 @@
|
|||
|
||||
#include <sys/param.h>
|
||||
|
||||
#define DEFAULT_EPG_FILE "/mnt/hd1/dvbepg/epg.dat"
|
||||
#ifdef FOXSATFILE
|
||||
#define DEFAULT_EPG_FILE "/mnt/hd2/fsatepg/epg.dat"
|
||||
#else
|
||||
#define DEFAULT_EPG_FILE "/mnt/hd1/dvbepg/epg.dat"
|
||||
#endif
|
||||
|
||||
struct epg {
|
||||
char fname[MAXPATHLEN + 1];
|
||||
|
@ -15,26 +19,50 @@ struct epg {
|
|||
uint32_t binsize;
|
||||
};
|
||||
|
||||
#define SECTION_MAGIC "(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01"
|
||||
#ifdef FOXSATFILE
|
||||
#define SECTION_MAGIC "\x19\x77\x09\x29\xff\xff"
|
||||
#else
|
||||
#define SECTION_MAGIC "(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01"
|
||||
#endif
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
|
||||
struct section {
|
||||
#ifdef FOXSATFILE
|
||||
char magic[6];
|
||||
#else
|
||||
char magic[14];
|
||||
#endif
|
||||
unsigned int total_length:16;
|
||||
#ifndef FOXSATFILE
|
||||
unsigned int magic2:32;
|
||||
#endif
|
||||
unsigned int table_id:8;
|
||||
union {
|
||||
struct {
|
||||
#ifdef FOXSATPLATFORM
|
||||
unsigned int syntax_indicator:1;
|
||||
unsigned int reserved:3;
|
||||
unsigned int length:12;
|
||||
#else
|
||||
unsigned int length:12;
|
||||
unsigned int reserved:3;
|
||||
unsigned int syntax_indicator:1;
|
||||
#endif
|
||||
} u;
|
||||
unsigned int comp:16;
|
||||
} u1;
|
||||
unsigned int service_id:16;
|
||||
#ifdef FOXSATPLATFORM
|
||||
unsigned int reserved2:2;
|
||||
unsigned int version_number:5;
|
||||
unsigned int current_next_indicator:1;
|
||||
#else
|
||||
unsigned int current_next_indicator:1;
|
||||
unsigned int version_number:5;
|
||||
unsigned int reserved2:2;
|
||||
#endif
|
||||
unsigned int section_number:8;
|
||||
unsigned int last_section_number:8;
|
||||
unsigned int transport_stream_id:16;
|
||||
|
@ -55,9 +83,15 @@ struct data {
|
|||
unsigned int dur_sec:8;
|
||||
union {
|
||||
struct {
|
||||
#ifdef FOXSATPLATFORM
|
||||
unsigned int running_status:3;
|
||||
unsigned int free_CA_mode:1;
|
||||
unsigned int descriptors_loop_length:12;
|
||||
#else
|
||||
unsigned int descriptors_loop_length:12;
|
||||
unsigned int free_CA_mode:1;
|
||||
unsigned int running_status:3;
|
||||
#endif
|
||||
} u;
|
||||
unsigned int comp:16;
|
||||
} u1;
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "epgsql.h"
|
||||
#include <sqlite3.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
|
||||
int i;
|
||||
for(i=0; i<argc; i++){
|
||||
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OpenCreateDB(char * DBFile, sqlite3 **db){
|
||||
/* Open the Database file -> Create it if it doesn't exist
|
||||
Return the Success/Failure status of the Open command
|
||||
and the pointer to the opened DB */
|
||||
int rc;
|
||||
|
||||
rc = sqlite3_open_v2(DBFile, &*db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
|
||||
|
||||
if( rc != SQLITE_OK){
|
||||
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(*db));
|
||||
sqlite3_close(*db);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CloseDB(sqlite3 *db) {
|
||||
/* Close the database and return the result */
|
||||
return sqlite3_close(db);
|
||||
}
|
||||
|
||||
int InitDB(char * InitScript, sqlite3 *db) {
|
||||
/* Use the database initialisation script to initialise the DB
|
||||
Script should create tables if they don't already exist
|
||||
And delete any data that will be replaced */
|
||||
int fp;
|
||||
char *zErrMsg = 0;
|
||||
int rc;
|
||||
char * SQLStatement;
|
||||
uint32_t SQLStatementSize;
|
||||
struct stat st;
|
||||
|
||||
/* Get the size of the init file */
|
||||
if (stat(InitScript, &st) == -1)
|
||||
{
|
||||
fprintf(stderr, "Error getting size of DB Creation/Initialisation File : %s\n", InitScript);
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
SQLStatementSize = st.st_size;
|
||||
|
||||
if ((fp = open(InitScript, O_RDONLY, 0)) == -1)
|
||||
{
|
||||
fprintf(stderr, "Failed to open DB Creation/Initialisation File : %s\n", InitScript);
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
SQLStatement = (char *)mmap(NULL, SQLStatementSize, PROT_READ, MAP_SHARED, fp, 0);
|
||||
if (SQLStatement == MAP_FAILED)
|
||||
{
|
||||
fprintf(stderr, "Failed to MMAP the DB Creation File : %s\n", InitScript);
|
||||
fprintf(stderr, "SQLStatement : %s, Map_failed : %i\n", SQLStatement, MAP_FAILED);
|
||||
|
||||
close(fp);
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rc = sqlite3_exec(db, SQLStatement, 0, 0, &zErrMsg);
|
||||
|
||||
munmap((void *)SQLStatement, SQLStatementSize);
|
||||
if (fp > 0)
|
||||
close(fp);
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stderr, "SQL error executing DB Init script : %s\n", zErrMsg);
|
||||
fprintf(stderr, "RC = %i\n", rc);
|
||||
sqlite3_free(zErrMsg);
|
||||
sqlite3_close(db);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExecSQLStatement(char *SQL, sqlite3 *db)
|
||||
{
|
||||
int rc;
|
||||
char *zErrMsg = 0;
|
||||
|
||||
rc = sqlite3_exec(db, SQL, 0, 0, &zErrMsg);
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stderr, "SQL error executing script : %s\n", zErrMsg);
|
||||
fprintf(stderr, "RC : %i\n", rc);
|
||||
fprintf(stderr, "SQL : %s\n", SQL);
|
||||
sqlite3_free(zErrMsg);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExecSQLStatementRowCount(char *SQL, sqlite3 *db)
|
||||
{
|
||||
int rc;
|
||||
char *zErrMsg = 0;
|
||||
|
||||
rc = sqlite3_exec(db, SQL, 0, 0, &zErrMsg);
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stderr, "SQL error executing script : %s\n", zErrMsg);
|
||||
fprintf(stderr, "RC : %i\n", rc);
|
||||
fprintf(stderr, "SQL : %s\n", SQL);
|
||||
sqlite3_free(zErrMsg);
|
||||
return -1;
|
||||
}
|
||||
return sqlite3_changes(db);
|
||||
}
|
||||
|
||||
/*int GetFileTimestamp(sqlite3 *db, char *res)*/
|
||||
void GetFileTimestamp(unsigned int * TS)
|
||||
{
|
||||
sqlite3_stmt *pStmt;
|
||||
char sql[256]={0};
|
||||
int rc;
|
||||
int i;
|
||||
sqlite3 *db1;
|
||||
int KeepGoing=1;
|
||||
|
||||
*TS = 0;
|
||||
|
||||
rc = sqlite3_open_v2("/opt/epg/epg.db", &db1, SQLITE_OPEN_READWRITE, 0);
|
||||
if( rc ){
|
||||
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db1));
|
||||
sqlite3_close(db1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
sprintf(sql, "select lastfileprocessed from epgtimestamp limit 1;");
|
||||
|
||||
if (sqlite3_prepare_v2(db1, sql, strlen(sql), &pStmt, NULL) != SQLITE_OK) {
|
||||
fprintf(stderr, "Error Preparing Statement : %s\n", sqlite3_errmsg(db1));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (KeepGoing==1) {
|
||||
rc = sqlite3_step(pStmt);
|
||||
|
||||
switch (rc) {
|
||||
case SQLITE_ROW:
|
||||
/* know it will be one column and one row (due to the query) so
|
||||
stuff the result into the result string */
|
||||
for (i=0; i<(sqlite3_column_count(pStmt)); i++)
|
||||
*TS = strtoul((char*)sqlite3_column_text(pStmt, i), NULL, 10);
|
||||
break;
|
||||
case SQLITE_DONE:
|
||||
KeepGoing=0;
|
||||
break;
|
||||
case SQLITE_ERROR:
|
||||
fprintf(stderr, "Error Executing Statement : %s\n", sqlite3_errmsg(db1));
|
||||
KeepGoing=0;
|
||||
break;
|
||||
case SQLITE_BUSY:
|
||||
case SQLITE_LOCKED:
|
||||
fprintf(stderr, "In waiting loop ... %i\n", rc);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error Condition ... %i\n", rc);
|
||||
fprintf(stderr, "Error Executing Statement : %s\n", sqlite3_errmsg(db1));
|
||||
KeepGoing=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_close(db1);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#include <sqlite3.h>
|
||||
|
||||
static int callback(void *NotUsed, int argc, char **argv, char **azColName);
|
||||
int OpenCreateDB(char * DBFile, sqlite3 **db);
|
||||
int CloseDB(sqlite3 *db);
|
||||
int InitDB(char * InitScript, sqlite3 *db);
|
||||
int ExecSQLStatement(char *SQL, sqlite3 *db);
|
||||
int ExecSQLStatementRowCount(char *SQL, sqlite3 *db);
|
||||
void GetFileTimestamp(unsigned int *);
|
||||
|
||||
|
16
huffman.c
16
huffman.c
|
@ -1,14 +1,6 @@
|
|||
/*
|
||||
* Humax EPG Tool
|
||||
* by af123, 2011 - 2018
|
||||
*
|
||||
* These tables and the decompression code are derived from MythTV
|
||||
* https://github.com/MythTV/mythtv/tree/master/mythtv/libs/libmythtv/mpeg
|
||||
* freesat_tables.h and freesat_huffman.cpp
|
||||
*
|
||||
* MythTV is released as free open source software under version 2 or later
|
||||
* of the GPL (GNU General Public License) a copy of which can be viewed at
|
||||
* https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
|
||||
* by af123, 2011
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -22,6 +14,12 @@
|
|||
|
||||
#include "lint.h"
|
||||
|
||||
/*
|
||||
* These tables and the decompression code are taken/derived from MythTV
|
||||
* https://github.com/MythTV/mythtv/tree/master/mythtv/libs/libmythtv/mpeg
|
||||
* freesat_tables.h and freesat_huffman.cpp
|
||||
*/
|
||||
|
||||
struct fsattab {
|
||||
unsigned int value;
|
||||
short bits;
|
||||
|
|
355
main.c
355
main.c
|
@ -15,16 +15,22 @@
|
|||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include "lint.h"
|
||||
#include <sqlite3.h>
|
||||
#include "epgsql.h"
|
||||
#include "sys/stat.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
int debug = 0;
|
||||
const char *version = "1.0.2";
|
||||
const char *version = "1.9";
|
||||
unsigned long sysopts = 0;
|
||||
unsigned long filterflags = 0;
|
||||
|
||||
int
|
||||
syntax()
|
||||
{
|
||||
fprintf(stderr, "Humax EPG Tool v%s, by af123, 2011.\n\n", version);
|
||||
fprintf(stderr, "Humax Foxsat EPG Tool v%s, by adrianf36, 2011-2016, MofTot 2018-20.\n", version);
|
||||
fprintf(stderr, "based on the Humax (T2) EPG Tool from af123 v1.0.2, 2011.\n\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"Syntax: epg [options] [filters] <command>...\n\n");
|
||||
fprintf(stderr,
|
||||
|
@ -51,6 +57,11 @@ syntax()
|
|||
" Commands:\n"
|
||||
" dump Show a parsed summary of the EPG.\n"
|
||||
" dumpraw Show raw data from the EPG.\n"
|
||||
" dumpsql Process the EPG file into a Sqlite Database\n"
|
||||
" dumpsqlcont As 'dumpsql' but run continuously\n"
|
||||
" Check for updated data every hour and process if necessary\n"
|
||||
);
|
||||
fprintf(stderr,
|
||||
" now Show what is currently on.\n"
|
||||
" parse Parse the EPG, no output.\n"
|
||||
" search <text> Search programme names for text.\n"
|
||||
|
@ -62,7 +73,126 @@ syntax()
|
|||
}
|
||||
|
||||
#define DECOMPRESS(str, len) \
|
||||
if (*(str) == 0x1f) uncompress_epg(&(str), &(len))
|
||||
if (str && *(str) == 0x1f) uncompress_epg(&(str), &(len))
|
||||
|
||||
int
|
||||
copy_freesat_to_non_freesat(sqlite3 * db)
|
||||
{
|
||||
int rc;
|
||||
|
||||
ExecSQLStatement(
|
||||
"attach database '/opt/webif/plugin/epg/epgsettings.db' as epgsettings",
|
||||
db
|
||||
);
|
||||
|
||||
ExecSQLStatement("BEGIN;", db);
|
||||
|
||||
rc = ExecSQLStatementRowCount(
|
||||
"insert into epg "
|
||||
"select epgmappings.nonfreesatserviceid, "
|
||||
"eventid, "
|
||||
"starttime, "
|
||||
"duration, "
|
||||
"encrypted, "
|
||||
"name, "
|
||||
"descr, "
|
||||
"warning, "
|
||||
"contentcode, "
|
||||
"contenttype, "
|
||||
"ECRID, "
|
||||
"SCRID, "
|
||||
"RCRID "
|
||||
"from epgsettings.epgmappings join epg on epg.serviceid = epgsettings.epgmappings.freesatserviceid "
|
||||
"except "
|
||||
"select epg.* "
|
||||
"from epgsettings.epgmappings join epg on epg.serviceid = epgsettings.epgmappings.freesatserviceid",
|
||||
db
|
||||
);
|
||||
|
||||
ExecSQLStatement("COMMIT;", db);
|
||||
|
||||
printf("%d EPG event(s) copied from Freesat to non-Freesat\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
unsigned int NeedToProcess (char * epgFile)
|
||||
{
|
||||
struct stat epgstat;
|
||||
unsigned int FileTS;
|
||||
unsigned int DBTS;
|
||||
FILE * fp;
|
||||
|
||||
/* Get the timestamp of the epg file to be processed */
|
||||
if ((fp = fopen(epgFile, "r"))) {
|
||||
if (!stat(epgFile, &epgstat))
|
||||
{
|
||||
FileTS = (unsigned int) (epgstat.st_mtime);
|
||||
} else {
|
||||
fprintf(stderr, "Error getting epg file modified date\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Input file (%s) does not exist!\n", epgFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the timestamp of the last file processed from the DB */
|
||||
GetFileTimestamp(&DBTS);
|
||||
|
||||
/*
|
||||
printf("File Timestamp : %i\n", FileTS);
|
||||
printf("DB Timestamp : %i\n", DBTS);
|
||||
*/
|
||||
if (FileTS==DBTS)
|
||||
return 0;
|
||||
else
|
||||
return FileTS;
|
||||
}
|
||||
|
||||
void SwapEPGFiles()
|
||||
{
|
||||
/*
|
||||
Having built the new EPG file as epgnew.db delete the old one
|
||||
and replace it with the new one. Handle the case where the old
|
||||
one can't be deleted because it's being accessed
|
||||
|
||||
First thing make sure that the size of the new file looks sensible.
|
||||
Expect this to be > 10MB ..... usually it's about 12MB
|
||||
*/
|
||||
|
||||
struct stat epgstat;
|
||||
off_t fsize;
|
||||
FILE * fp;
|
||||
|
||||
if ((fp = fopen("/opt/epg/epgnew.db", "r"))) {
|
||||
if (!stat("/opt/epg/epgnew.db", &epgstat))
|
||||
{
|
||||
fsize = epgstat.st_size;
|
||||
if (fsize > (10 * 1024 * 1024)) {
|
||||
while (remove("/opt/epg/epg.db") == -1)
|
||||
{
|
||||
sleep(5);
|
||||
}
|
||||
|
||||
while (rename("/opt/epg/epgnew.db", "/opt/epg/epg.db") != 0)
|
||||
{
|
||||
sleep(5);
|
||||
}
|
||||
} else {
|
||||
/* epgnew.db is smaller than we expected and is probably incomplete.
|
||||
Delete it and output a warning.
|
||||
*/
|
||||
fprintf(stderr, "Error. epgnew.db file size too small. Probably corrupt.\n");
|
||||
remove("/opt/epg/epgnew.db");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error getting epgnew.db file size\n");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Can't open epgnew.db\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pass(struct epg *epg __attribute__((unused)),
|
||||
|
@ -99,6 +229,217 @@ dumpraw(struct epg *epg __attribute__((unused)),
|
|||
/* Strings should all be safe now the huffman module is in place... */
|
||||
#define safeprintf printf
|
||||
|
||||
void EscapeChars(char ** InString, unsigned int *Len)
|
||||
{
|
||||
/* Escape String for inserting into SQLite */
|
||||
/* Replace single quote ' with two single quotes '' */
|
||||
char * new;
|
||||
unsigned int i,j;
|
||||
int charcount=0;
|
||||
char * originalstring;
|
||||
|
||||
if (*Len != 0)
|
||||
{
|
||||
originalstring=*InString;
|
||||
if (strchr(*InString, '\'')!=NULL) {
|
||||
/* at least one ' character - process string */
|
||||
/* count them so we know how much space to allocate */
|
||||
for (i=0; i<*Len; i++) {
|
||||
if (originalstring[i]==0x27) {
|
||||
charcount++;
|
||||
}
|
||||
}
|
||||
new = (char *) malloc(sizeof(char) * (*Len + charcount + 1));
|
||||
j=0;
|
||||
for (i=0; i<*Len; i++) {
|
||||
new[j++]=originalstring[i];
|
||||
if (originalstring[i]==0x27)
|
||||
new[j++]=0x27;
|
||||
}
|
||||
new[j]='\0';
|
||||
|
||||
free(*InString);
|
||||
*InString = new;
|
||||
*Len = strlen(new);
|
||||
}
|
||||
} else {
|
||||
new = (char *) malloc(1);
|
||||
new[0] = '\0';
|
||||
free(*InString);
|
||||
*InString = new;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dumpsql(struct epg *epg __attribute__((unused)),
|
||||
struct section *s, struct data *d, struct descriptor **ds,
|
||||
void *var)
|
||||
{
|
||||
time_t tm;
|
||||
char SQLStatement[5000];
|
||||
sqlite3 * db = (sqlite3 *)var;
|
||||
int rc;
|
||||
|
||||
tm = mjd(d->start_date, d->start_hour, d->start_min, d->start_sec);
|
||||
|
||||
if (ds[PARSER_SHORT_EVENT])
|
||||
{
|
||||
struct descriptor *d77 = ds[PARSER_SHORT_EVENT];
|
||||
DECOMPRESS(d77->content.d77.name, d77->content.d77.namelen);
|
||||
DECOMPRESS(d77->content.d77.text, d77->content.d77.textlen);
|
||||
EscapeChars(&d77->content.d77.name, &d77->content.d77.namelen);
|
||||
EscapeChars(&d77->content.d77.text, &d77->content.d77.textlen);
|
||||
}
|
||||
if (ds[PARSER_USER_DEFINED])
|
||||
{
|
||||
struct descriptor *d = ds[PARSER_USER_DEFINED];
|
||||
DECOMPRESS(d->content.d137.warning, d->content.d137.warninglen);
|
||||
EscapeChars(&d->content.d137.warning, &d->content.d137.warninglen);
|
||||
}
|
||||
|
||||
/* service_id, event_id, start, duration, encrypted, name, text
|
||||
* warning, content code, content type,
|
||||
* event CRID, series CRID, rec CRID
|
||||
*/
|
||||
sprintf(SQLStatement,"insert into epg (serviceid, eventid, starttime, duration, encrypted, name,"\
|
||||
"descr, warning, contentcode, contenttype, ECRID, SCRID, RCRID) values (");
|
||||
sprintf(SQLStatement, "%s%d,%d,%ld,%d,%d,", SQLStatement,
|
||||
s->service_id, d->event_id, tm,
|
||||
d->dur_hour * 3600 + d->dur_min * 60 + d->dur_sec,
|
||||
d->u1.u.free_CA_mode);
|
||||
if (ds[PARSER_SHORT_EVENT])
|
||||
{
|
||||
struct descriptor *d77 = ds[PARSER_SHORT_EVENT];
|
||||
sprintf(SQLStatement,"%s'%.*s',", SQLStatement, d77->content.d77.namelen, d77->content.d77.name);
|
||||
sprintf(SQLStatement,"%s'%.*s',", SQLStatement, d77->content.d77.textlen, d77->content.d77.text);
|
||||
}
|
||||
else
|
||||
sprintf(SQLStatement,"%s'','',",SQLStatement);
|
||||
|
||||
if (ds[PARSER_USER_DEFINED])
|
||||
{
|
||||
struct descriptor *d137 = ds[PARSER_USER_DEFINED];
|
||||
EscapeChars(&d137->content.d137.warning, &d137->content.d137.warninglen);
|
||||
sprintf(SQLStatement,"%s'%.*s',", SQLStatement, d137->content.d137.warninglen, d137->content.d137.warning);
|
||||
}
|
||||
else
|
||||
sprintf(SQLStatement,"%s'',",SQLStatement);
|
||||
|
||||
if (ds[PARSER_CONTENT])
|
||||
{
|
||||
sprintf(SQLStatement,"%s%d,", SQLStatement, ds[PARSER_CONTENT]->content.d84.level1);
|
||||
sprintf(SQLStatement,"%s'%s',", SQLStatement, content_type(ds[PARSER_CONTENT]));
|
||||
}
|
||||
else
|
||||
sprintf(SQLStatement,"%s0,'',",SQLStatement);
|
||||
|
||||
if (ds[PARSER_CRID_EVENT])
|
||||
{
|
||||
struct descriptor *d = ds[PARSER_CRID_EVENT];
|
||||
EscapeChars(&d->content.d118.crids[0].crid, &d->content.d118.crids[0].cridlen);
|
||||
sprintf(SQLStatement,"%s'%.*s',", SQLStatement, d->content.d118.crids[0].cridlen,
|
||||
d->content.d118.crids[0].crid);
|
||||
}
|
||||
else
|
||||
sprintf(SQLStatement,"%s'',",SQLStatement);
|
||||
|
||||
if (ds[PARSER_CRID_SERIES])
|
||||
{
|
||||
struct descriptor *d = ds[PARSER_CRID_SERIES];
|
||||
EscapeChars(&d->content.d118.crids[0].crid, &d->content.d118.crids[0].cridlen);
|
||||
sprintf(SQLStatement,"%s'%.*s',", SQLStatement, d->content.d118.crids[0].cridlen,
|
||||
d->content.d118.crids[0].crid);
|
||||
}
|
||||
else
|
||||
sprintf(SQLStatement,"%s'',",SQLStatement);
|
||||
|
||||
if (ds[PARSER_CRID_REC])
|
||||
{
|
||||
struct descriptor *d = ds[PARSER_CRID_REC];
|
||||
EscapeChars(&d->content.d118.crids[0].crid, &d->content.d118.crids[0].cridlen);
|
||||
sprintf(SQLStatement,"%s'%.*s'", SQLStatement, d->content.d118.crids[0].cridlen,
|
||||
d->content.d118.crids[0].crid);
|
||||
}
|
||||
else
|
||||
sprintf(SQLStatement,"%s''",SQLStatement);
|
||||
|
||||
sprintf(SQLStatement,"%s)",SQLStatement);
|
||||
rc = ExecSQLStatement(SQLStatement, db);
|
||||
return;
|
||||
}
|
||||
|
||||
void dosqldump(char * epgpath,struct epgfilter *filter, int Continuous)
|
||||
{
|
||||
sqlite3 * db;
|
||||
int rc;
|
||||
unsigned int FileTS;
|
||||
char SQL [500] = {0};
|
||||
|
||||
if (Continuous==1) {
|
||||
while (1) {
|
||||
FileTS = NeedToProcess(epgpath);
|
||||
if (FileTS !=0) {
|
||||
/* Delete any old epgnew SQLite files before trying to open a new one */
|
||||
/* Don't worry about error handling - just need to make sure they're gone! */
|
||||
remove("/opt/epg/epgnew.db");
|
||||
remove("/opt/epg/epgnew.db-journal");
|
||||
rc = OpenCreateDB("/opt/epg/epgnew.db", &db);
|
||||
|
||||
rc = ExecSQLStatement("pragma journal_mode = off;", db);
|
||||
rc = ExecSQLStatement("pragma synchronous = off;", db);
|
||||
|
||||
InitDB("/opt/epg/epgDBinit.sql", db);
|
||||
|
||||
rc = ExecSQLStatement("BEGIN;", db);
|
||||
|
||||
parse(epgpath, dumpsql, (void *)db, filter);
|
||||
|
||||
rc = ExecSQLStatement("COMMIT;", db);
|
||||
|
||||
copy_freesat_to_non_freesat(db);
|
||||
|
||||
sprintf(SQL, "replace into epgtimestamp (lastfileprocessed) values (%i);", FileTS);
|
||||
rc = ExecSQLStatement("Delete from epgtimestamp;", db);
|
||||
rc = ExecSQLStatement(SQL, db);
|
||||
|
||||
if (db != NULL) CloseDB(db);
|
||||
SwapEPGFiles();
|
||||
}
|
||||
|
||||
sleep(3600);
|
||||
}
|
||||
} else {
|
||||
|
||||
FileTS = NeedToProcess(epgpath);
|
||||
|
||||
if (FileTS != 0) {
|
||||
|
||||
/* Delete any old epgnew SQLite files before trying to open a new one */
|
||||
/* Don't worry about error handling - just need to make sure they're gone! */
|
||||
remove("/opt/epg/epgnew.db");
|
||||
remove("/opt/epg/epgnew.db-journal");
|
||||
rc = OpenCreateDB("/opt/epg/epgnew.db", &db);
|
||||
|
||||
InitDB("/opt/epg/epgDBinit.sql", db);
|
||||
|
||||
rc = ExecSQLStatement("BEGIN;", db);
|
||||
|
||||
parse(epgpath, dumpsql, (void *)db, filter);
|
||||
|
||||
rc = ExecSQLStatement("COMMIT;", db);
|
||||
|
||||
copy_freesat_to_non_freesat(db);
|
||||
|
||||
sprintf(SQL, "replace into epgtimestamp (lastfileprocessed) values (%i);", FileTS);
|
||||
rc = ExecSQLStatement("Delete from epgtimestamp;", db);
|
||||
rc = ExecSQLStatement(SQL, db);
|
||||
|
||||
if (db != NULL) CloseDB(db);
|
||||
SwapEPGFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
dump(struct epg *epg __attribute__((unused)),
|
||||
struct section *s, struct data *d, struct descriptor **ds,
|
||||
|
@ -453,6 +794,8 @@ nextopt:
|
|||
parse(epgpath, pass, NULL, filter);
|
||||
else if (!strcmp(argv[0], "dumpraw"))
|
||||
parse(epgpath, dumpraw, NULL, filter);
|
||||
else if (!strcmp(argv[0], "dumpsql"))
|
||||
dosqldump(epgpath, filter, 0);
|
||||
else if (!strcmp(argv[0], "now"))
|
||||
{
|
||||
time_t tm;
|
||||
|
@ -465,9 +808,13 @@ nextopt:
|
|||
parse(epgpath, search, (void *)argv[1], filter);
|
||||
else if (!strcmp(argv[0], "searchall") && argc > 1)
|
||||
parse(epgpath, searchall, (void *)argv[1], filter);
|
||||
else if (!strcmp(argv[0], "dumpsqlcont"))
|
||||
{
|
||||
dosqldump(epgpath, filter, 1);
|
||||
|
||||
}
|
||||
else
|
||||
syntax();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
6
util.h
6
util.h
|
@ -6,7 +6,11 @@
|
|||
/* Works for modern dates, 1970 - 2038 */
|
||||
#define MJD_TO_UNIX(xx) (((xx) - 40587) * 86400)
|
||||
|
||||
#define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8))
|
||||
#ifdef FOXSATPLATFORM
|
||||
#define _swap16(v) (v)
|
||||
#else
|
||||
#define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8))
|
||||
#endif
|
||||
|
||||
#define bcd(v) (((((v) >> 4) & 0xf) * 10) + ((v) & 0xf))
|
||||
|
||||
|
|
Loading…
Reference in New Issue