Compare commits

..

4 Commits

Author SHA1 Message Date
adrianf36 b55c134eed Handle empty warning descriptors 2022-08-28 16:53:21 +01:00
MofTot b3ea751561 Copy freesat to non-freesat database 2020-04-22 14:43:58 +01:00
HummyPkg 5e468f5857 Add licence 2019-03-29 12:53:35 +00:00
adrianf36 222797837c Changes for Foxsat platform 2019-03-29 12:39:35 +00:00
15 changed files with 771 additions and 1037 deletions

2
.gitignore vendored
View File

@ -1,2 +0,0 @@
*.o
epg

View File

@ -1,43 +1,36 @@
MAKE=gmake MAKE=gmake
DEFS= DEFS=-DFOXSATPLATFORM -DFOXSATFILE
#DEFS= -DFOXSATFILE
SRCS= descriptor.c \ SRCS= descriptor.c \
epg.c \ epg.c \
file.c \ file.c \
huffman.c \ huffman.c \
main.c \ main.c \
util.c util.c \
epgsql.c
HDRS= descriptor.h \ HDRS= descriptor.h \
epg.h \ epg.h \
lint.h \ lint.h \
util.h \ util.h \
xgetopt.h epgsql.h
OBJS= $(SRCS:.c=.o) OBJS= $(SRCS:.c=.o)
CC=gcc #CC=gcc
#CC=mipsel-linux-gcc #CC=mipsel-linux-gcc
CFLAGS=-g CC=mips-linux-gcc
CFLAGS=-g -pthread
INCS= INCS=
LIBS= LIBS=-lsqlite3 -ldl
#CFLAGS=-g -O3 -fno-strict-aliasing #CFLAGS=-g -O3 -fno-strict-aliasing
#WARN=-pedantic -Wall -Wnested-externs -Wpointer-arith -Werror -Wno-unused #WARN=-pedantic -Wall -Wnested-externs -Wpointer-arith -Werror -Wno-unused
WARN=-pedantic -Wall -W -Wnested-externs -Wpointer-arith -Wno-long-long WARN=-pedantic -Wall -W -Wnested-externs -Wpointer-arith -Wno-long-long
PLATFORM=$(shell uname -s | cut -d- -f1)
ifeq ($(PLATFORM),Linux)
DEFS=-DHAVE_SQLITE3
LIBS=-lsqlite3 -lxconv
endif
all: tags epg all: tags epg
install: epg
strip epg
cp epg /mod/bin/epg
epg: ${OBJS} epg: ${OBJS}
@echo "Linking..." @echo "Linking..."
@-[ -f $@ ] && mv $@ $@~ || exit 0 @-[ -f $@ ] && mv $@ $@~ || exit 0

View File

@ -19,7 +19,7 @@ read_descriptor_header(struct epg *epg)
{ {
struct descriptor *d; struct descriptor *d;
d = (struct descriptor *)calloc(sizeof(struct descriptor), 1); d = (struct descriptor *)malloc(sizeof(struct descriptor));
d->loaded = 0; d->loaded = 0;
if (epg->binsize - epg->offset < 2) if (epg->binsize - epg->offset < 2)
@ -55,16 +55,9 @@ string_to_end(struct epg *epg, struct descriptor *d, int sofar,
static char * static char *
read_lstring(struct epg *epg, unsigned int *len) read_lstring(struct epg *epg, unsigned int *len)
{ {
unsigned int l = epg->bin[epg->offset++]; int l = epg->bin[epg->offset++];
char *c; char *c;
/* Check that there is enough file left. */
if (epg->binsize - epg->offset < l)
l = epg->binsize - epg->offset;
if (l < 1)
return strdup("Short file");
c = malloc(l + 1); c = malloc(l + 1);
memcpy(c, epg->bin + epg->offset, l); memcpy(c, epg->bin + epg->offset, l);
c[l] = '\0'; c[l] = '\0';
@ -93,31 +86,6 @@ read_descriptor(struct epg *epg, struct descriptor *d)
break; break;
case DS_EXTENDED_EVENT:
{
unsigned int i;
epg->offset++; /* Skip descriptor number and last descriptor */
memcpy(d->content.d78.lang, epg->bin + epg->offset, 3);
epg->offset += 3;
d->content.d78.items = epg->bin[epg->offset++];
if (debug > 1 && d->content.d78.items > 0)
printf("Extended event items: %d\n",
d->content.d78.items);
/* Skip items. */
for (i = 0; i < d->content.d78.items; i++)
{
int l = epg->bin[epg->offset++];
epg->offset += l;
}
d->content.d78.text =
read_lstring(epg, &d->content.d78.textlen);
break;
}
case DS_COMPONENT: case DS_COMPONENT:
memcpy(&d->content.d80, epg->bin + epg->offset, 6); memcpy(&d->content.d80, epg->bin + epg->offset, 6);
epg->offset += 6; epg->offset += 6;
@ -127,37 +95,15 @@ read_descriptor(struct epg *epg, struct descriptor *d)
break; break;
case DS_USER_DEFINED: case DS_USER_DEFINED:
{ d->content.d137.text =
int sofar = 0; read_lstring(epg, &d->content.d137.textlen);
/* reserved:6 guidance_type:2 */
d->content.d137.guidance_type = epg->bin[epg->offset++] & 0x3;
sofar++;
switch (d->content.d137.guidance_type)
{
case 0:
/* guidance_type 0 means unsuitable for broadcast
* prior to the watershed so set mode to 1. */
d->content.d137.guidance_mode = 1;
break;
case 1:
/* reserved:7 guidance_mode:1 */
d->content.d137.guidance_mode =
epg->bin[epg->offset++] & 0x1;
sofar++;
break;
default:
/* Unknown guidance type.. */
break;
}
memcpy(d->content.d137.lang, epg->bin + epg->offset, 3); memcpy(d->content.d137.lang, epg->bin + epg->offset, 3);
epg->offset += 3; epg->offset += 3;
sofar += 3; d->content.d137.warning = string_to_end(epg, d,
d->content.d137.warning = string_to_end(epg, d, sofar, 4 + d->content.d137.textlen,
&d->content.d137.warninglen); &d->content.d137.warninglen);
break; break;
}
case DS_LINKAGE: case DS_LINKAGE:
memcpy(&d->content.d74, epg->bin + epg->offset, memcpy(&d->content.d74, epg->bin + epg->offset,
@ -270,17 +216,14 @@ free_descriptor(struct descriptor *d)
free(d->content.d77.text); free(d->content.d77.text);
break; break;
case DS_EXTENDED_EVENT:
if (d->content.d78.text)
free(d->content.d78.text);
break;
case DS_COMPONENT: case DS_COMPONENT:
if (d->content.d80.text) if (d->content.d80.text)
free(d->content.d80.text); free(d->content.d80.text);
break; break;
case DS_USER_DEFINED: case DS_USER_DEFINED:
if (d->content.d137.text)
free(d->content.d137.text);
if (d->content.d137.warning) if (d->content.d137.warning)
free(d->content.d137.warning); free(d->content.d137.warning);
break; break;
@ -325,6 +268,7 @@ descriptor_name(struct descriptor *d)
case DS_CONTENT_IDENTIFIER: return "content id"; case DS_CONTENT_IDENTIFIER: return "content id";
case DS_FTA_CONTENT_MGMT: return "content mgmt"; case DS_FTA_CONTENT_MGMT: return "content mgmt";
case DS_USER_DEFINED: return "user defined"; case DS_USER_DEFINED: return "user defined";
default: return "Unknown";
} }
return "Unknown"; return "Unknown";
} }
@ -356,8 +300,10 @@ content_type(struct descriptor *d)
return "Leisure"; return "Leisure";
case 0xf: case 0xf:
return "Drama"; return "Drama";
default:
return "Undefined";
} }
return "Undefined"; return "Unknown";
} }
void void
@ -381,13 +327,6 @@ dump_descriptor(struct descriptor *d, int content)
DUMPHEX(d, content.d77.text, d->content.d77.textlen); DUMPHEX(d, content.d77.text, d->content.d77.textlen);
break; break;
case DS_EXTENDED_EVENT:
DUMPNSTR(d, content.d78.lang, 3);
DUMPINT(d, content.d78.items);
DUMPINT(d, content.d78.textlen);
DUMPHEX(d, content.d78.text, d->content.d78.textlen);
break;
case DS_COMPONENT: case DS_COMPONENT:
DUMPINT(d, content.d80.stream_content); DUMPINT(d, content.d80.stream_content);
DUMPINT(d, content.d80.reserved); DUMPINT(d, content.d80.reserved);
@ -399,9 +338,9 @@ dump_descriptor(struct descriptor *d, int content)
break; break;
case DS_USER_DEFINED: case DS_USER_DEFINED:
DUMPINT(d, content.d137.guidance_type); DUMPINT(d, content.d137.textlen);
DUMPINT(d, content.d137.guidance_mode);
DUMPNSTR(d, content.d137.lang, 3); DUMPNSTR(d, content.d137.lang, 3);
DUMPHEX(d, content.d137.text, d->content.d137.textlen);
DUMPHEX(d, content.d137.warning, d->content.d137.warninglen); DUMPHEX(d, content.d137.warning, d->content.d137.warninglen);
break; break;

View File

@ -3,15 +3,18 @@
* by af123, 2011 * by af123, 2011
*/ */
#define DS_LINKAGE 74 /* 0x4a */ #define DS_LINKAGE 74
#define DS_SHORT_EVENT 77 /* 0x4d */ #define DS_SHORT_EVENT 77
#define DS_EXTENDED_EVENT 78 /* 0x4e */ #define DS_COMPONENT 80
#define DS_COMPONENT 80 /* 0x50 */ #define DS_CONTENT 84
#define DS_CONTENT 84 /* 0x54 */ #define DS_PRIVATE_DATA_SPECIFIER 95
#define DS_PRIVATE_DATA_SPECIFIER 95 /* 0x5f */ #define DS_CONTENT_IDENTIFIER 118
#define DS_CONTENT_IDENTIFIER 118 /* 0x76 */ #define DS_FTA_CONTENT_MGMT 126
#define DS_FTA_CONTENT_MGMT 126 /* 0x7e */ #ifdef FOXSATPLATFORM
#define DS_USER_DEFINED 137 /* 0x89 */ #define DS_USER_DEFINED 218
#else
#define DS_USER_DEFINED 137
#endif
#define PARSER_SHORT_EVENT 0 #define PARSER_SHORT_EVENT 0
#define PARSER_USER_DEFINED 1 #define PARSER_USER_DEFINED 1
@ -19,9 +22,7 @@
#define PARSER_CRID_EVENT 3 #define PARSER_CRID_EVENT 3
#define PARSER_CRID_SERIES 4 #define PARSER_CRID_SERIES 4
#define PARSER_CRID_REC 5 #define PARSER_CRID_REC 5
#define PARSER_EXTENDED_EVENT 6 #define PARSER_MAX 6
#define PARSER_FTA_CONTENT_MGMT 7
#define PARSER_MAX 8
#define CRIDT_EVENT '1' #define CRIDT_EVENT '1'
#define CRIDT_SERIES '2' #define CRIDT_SERIES '2'
@ -29,8 +30,13 @@
#pragma pack(1) #pragma pack(1)
struct crid { struct crid {
#ifdef FOXSATPLATFORM
unsigned int type:6;
unsigned int location:2;
#else
unsigned int location:2; unsigned int location:2;
unsigned int type:6; unsigned int type:6;
#endif
unsigned int cridlen; unsigned int cridlen;
char *crid; char *crid;
unsigned int ref:16; unsigned int ref:16;
@ -48,14 +54,13 @@ struct descriptor {
char *text; char *text;
} d77; /* SHORT_EVENT */ } d77; /* SHORT_EVENT */
struct { struct {
char lang[3]; #ifdef FOXSATPLATFORM
unsigned int items; unsigned int reserved:4;
unsigned int textlen; unsigned int stream_content:4;
char *text; #else
} d78; /* EXTENDED_EVENT */
struct {
unsigned int stream_content:4; unsigned int stream_content:4;
unsigned int reserved:4; unsigned int reserved:4;
#endif
unsigned int type:8; unsigned int type:8;
unsigned int tag:8; unsigned int tag:8;
char lang[3]; char lang[3];
@ -63,17 +68,22 @@ struct descriptor {
unsigned int textlen; unsigned int textlen;
} d80; /* COMPONENT */ } d80; /* COMPONENT */
struct { struct {
#ifdef FOXSATPLATFORM
unsigned int level1:4;
unsigned int level2:4;
#else
unsigned int level2:4; unsigned int level2:4;
unsigned int level1:4; unsigned int level1:4;
#endif
unsigned int user:8; unsigned int user:8;
} d84; /* CONTENT */ } d84; /* CONTENT */
struct { struct {
unsigned int guidance_type; unsigned int textlen;
unsigned int guidance_mode; char *text;
char lang[3]; char lang[3];
char *warning; char *warning;
unsigned int warninglen; unsigned int warninglen;
} d137; /* USER_DEFINED - content warnings */ } d137; /* USER_DEFINED - content warnings? */
struct { struct {
unsigned int no_revocation:1; unsigned int no_revocation:1;
unsigned int control_remote_access:2; unsigned int control_remote_access:2;
@ -87,16 +97,29 @@ struct descriptor {
unsigned int linkage_type:8; unsigned int linkage_type:8;
union { union {
struct { 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 origin_type:1;
unsigned int reserved:3; unsigned int reserved:3;
unsigned int handover_type:4; unsigned int handover_type:4;
unsigned int id:16; unsigned int id:16;
#endif
} l8; } l8;
struct { struct {
unsigned int event_id:16; 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 reserved:6;
unsigned int simulcast:1; unsigned int simulcast:1;
unsigned int listed:1; unsigned int listed:1;
#endif
} ld; } ld;
} l; } l;
} d74; /* DS_LINKAGE */ } d74; /* DS_LINKAGE */

149
epg.c
View File

@ -23,7 +23,7 @@ read_section(struct epg *epg)
return NULL; return NULL;
memcpy(&h, epg->bin + epg->offset, sizeof(h)); memcpy(&h, epg->bin + epg->offset, sizeof(h));
if (memcmp(h.magic, SECTION_MAGIC, sizeof(h.magic) - 1)) if (memcmp(h.magic, SECTION_MAGIC, sizeof(h.magic)))
{ {
printf("Section header magic mismatch.\n"); printf("Section header magic mismatch.\n");
hexdump(epg->bin + epg->offset, 64, 0); hexdump(epg->bin + epg->offset, 64, 0);
@ -111,28 +111,6 @@ dump_data(struct data *d)
DUMPINT(d, u1.u.descriptors_loop_length); DUMPINT(d, u1.u.descriptors_loop_length);
} }
static inline int
check_filter_timerange(struct epgfilter *f, enum epgfiltertype type,
unsigned long idl, unsigned long idh)
{
if (!f)
return 1;
for (; f; f = f->next)
{
if (f->type != type)
continue;
if (!(
(idl > f->num && idl < f->num2) ||
(idh > f->num && idh < f->num2) ||
(idl < f->num && idh > f->num))
)
return 0;
}
return 1;
}
static inline int static inline int
check_filter_range(struct epgfilter *f, enum epgfiltertype type, check_filter_range(struct epgfilter *f, enum epgfiltertype type,
unsigned long idl, unsigned long idh) unsigned long idl, unsigned long idh)
@ -142,14 +120,7 @@ check_filter_range(struct epgfilter *f, enum epgfiltertype type,
for (; f; f = f->next) for (; f; f = f->next)
{ {
if (f->type != type) if (f->type == type && (f->num < idl || f->num > idh))
continue;
if (f->match == FT_RANGE)
{
if (idl < f->num || idl > f->num2)
return 0;
}
else if (f->num < idl || f->num > idh)
return 0; return 0;
} }
return 1; return 1;
@ -178,7 +149,7 @@ check_filter(struct epgfilter *f, enum epgfiltertype type,
return 1; return 1;
} }
int void
parse(char *epgpath, parse(char *epgpath,
void (*callback)(struct epg *, struct section *, struct data *, void (*callback)(struct epg *, struct section *, struct data *,
struct descriptor **, void *), void *val, struct epgfilter *filter) struct descriptor **, void *), void *val, struct epgfilter *filter)
@ -188,7 +159,7 @@ parse(char *epgpath,
int i; int i;
if (!(epg = open_file(epgpath))) if (!(epg = open_file(epgpath)))
return 0; return;
while (epg->offset < epg->binsize) while (epg->offset < epg->binsize)
{ {
@ -206,8 +177,11 @@ parse(char *epgpath,
/* Skip this service. */ /* Skip this service. */
epg->offset += s->total_length - 14; epg->offset += s->total_length - 14;
/* Skip padding bytes... */ /* Skip padding bytes... */
while (epg->offset < epg->binsize && #ifdef FOXSATFILE
epg->bin[epg->offset] == 'U') while ((epg->offset % 4) != 0)
#else
while (epg->bin[epg->offset] == 'U')
#endif
epg->offset++; epg->offset++;
continue; continue;
} }
@ -233,10 +207,10 @@ parse(char *epgpath,
continue; continue;
} }
if ((filterflags & if ((filterflags & FILTER_TIMESTAMP))
(FILTER_TIMESTAMP | FILTER_TIMERANGE)))
{ {
time_t tm, dur; time_t tm;
int dur;
tm = mjd(d->start_date, d->start_hour, tm = mjd(d->start_date, d->start_hour,
d->start_min, d->start_sec); d->start_min, d->start_sec);
@ -244,29 +218,12 @@ parse(char *epgpath,
dur = d->dur_hour * 3600 + d->dur_min * 60 + dur = d->dur_hour * 3600 + d->dur_min * 60 +
d->dur_sec; d->dur_sec;
if ((filterflags & FILTER_TIMESTAMP)) if (!check_filter_range(filter,
FILTER_TIMESTAMP, tm, tm + dur))
{ {
if (!check_filter_range(filter, /* Skip this event. */
FILTER_TIMESTAMP, epg->offset = dend;
(unsigned long) tm, continue;
(unsigned long) (tm + dur)))
{
/* Skip this event. */
epg->offset = dend;
continue;
}
}
if ((filterflags & FILTER_TIMERANGE))
{
if (!check_filter_timerange(filter,
FILTER_TIMERANGE,
(unsigned long) tm,
(unsigned long) (tm + dur)))
{
/* Skip this event. */
epg->offset = dend;
continue;
}
} }
} }
@ -291,14 +248,6 @@ parse(char *epgpath,
continue; continue;
} }
if (debug)
printf("Checking descriptor: "
"%d/%#x (%d)\n",
dstag, dstag, dslen);
if (debug > 3)
hexdump(epg->bin + epg->offset,
dslen + 2, 0);
switch (dstag) switch (dstag)
{ {
case DS_SHORT_EVENT: case DS_SHORT_EVENT:
@ -308,13 +257,6 @@ parse(char *epgpath,
dslist[PARSER_SHORT_EVENT] = ds; dslist[PARSER_SHORT_EVENT] = ds;
break; break;
case DS_EXTENDED_EVENT:
if (!(ds = read_descriptor_header(epg)))
break;
read_descriptor(epg, ds);
dslist[PARSER_EXTENDED_EVENT] = ds;
break;
case DS_CONTENT_IDENTIFIER: case DS_CONTENT_IDENTIFIER:
if (!(ds = read_descriptor_header(epg))) if (!(ds = read_descriptor_header(epg)))
break; break;
@ -347,14 +289,12 @@ parse(char *epgpath,
dslist[PARSER_CONTENT] = ds; dslist[PARSER_CONTENT] = ds;
break; break;
case DS_FTA_CONTENT_MGMT:
if (!(ds = read_descriptor_header(epg)))
break;
read_descriptor(epg, ds);
dslist[PARSER_FTA_CONTENT_MGMT] = ds;
break;
/* /*
case DS_FTA_CONTENT_MGMT:
read_descriptor(epg, ds);
dump_descriptor(ds, 1);
free_descriptor(ds);
break;
case DS_LINKAGE: case DS_LINKAGE:
read_descriptor(epg, ds); read_descriptor(epg, ds);
@ -364,39 +304,11 @@ parse(char *epgpath,
*/ */
default: default:
if (debug > 2)
printf("! Unhandled.\n");
epg->offset += dslen + 2; epg->offset += dslen + 2;
break; break;
} }
} }
/* Move synopsis from extended event descriptor into
* short description if appropriate. */
if (dslist[PARSER_SHORT_EVENT] &&
dslist[PARSER_EXTENDED_EVENT] &&
dslist[PARSER_EXTENDED_EVENT]->content.d78.textlen
> 0 &&
dslist[PARSER_SHORT_EVENT]->content.d77.textlen
== 2 &&
dslist[PARSER_SHORT_EVENT]->content.d77.text[1]
== '\0')
{
if (debug > 3)
printf("Moving event text from "
"extended to short event.\n");
free(dslist[PARSER_SHORT_EVENT]
->content.d77.text);
dslist[PARSER_SHORT_EVENT]->content.d77.text
= dslist[PARSER_EXTENDED_EVENT]->
content.d78.text;
dslist[PARSER_SHORT_EVENT]->content.d77.textlen
= dslist[PARSER_EXTENDED_EVENT]->
content.d78.textlen;
dslist[PARSER_EXTENDED_EVENT]->content.d78.text
= (char *)NULL;
}
if ( if (
( (
!(filterflags & FILTER_CRID) || !(filterflags & FILTER_CRID) ||
@ -416,13 +328,6 @@ parse(char *epgpath,
check_filter(filter, FILTER_CONTENT, check_filter(filter, FILTER_CONTENT,
dslist[PARSER_CONTENT]->content.d84.level1, dslist[PARSER_CONTENT]->content.d84.level1,
NULL)) NULL))
) && (
!(filterflags & FILTER_GUIDETYPE) ||
(dslist[PARSER_USER_DEFINED] &&
check_filter(filter, FILTER_GUIDETYPE,
dslist[PARSER_USER_DEFINED]->
content.d137.guidance_type,
NULL))
) )
) )
callback(epg, s, d, dslist, val); callback(epg, s, d, dslist, val);
@ -431,19 +336,19 @@ parse(char *epgpath,
if (dslist[i]) if (dslist[i])
free_descriptor(dslist[i]); free_descriptor(dslist[i]);
} }
/* Skip CRC */ /* Skip CRC */
epg->offset += 4; epg->offset += 4;
/* Skip padding bytes... */ /* Skip padding bytes... */
while (epg->offset < epg->binsize && #ifdef FOXSATFILE
epg->bin[epg->offset] == 'U') while ((epg->offset % 4) != 0)
#else
while (epg->bin[epg->offset] == 'U')
#endif
epg->offset++; epg->offset++;
} }
close_file(epg); close_file(epg);
return 1;
} }
void void

42
epg.h
View File

@ -5,7 +5,11 @@
#include <sys/param.h> #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 { struct epg {
char fname[MAXPATHLEN + 1]; char fname[MAXPATHLEN + 1];
@ -15,26 +19,50 @@ struct epg {
uint32_t binsize; 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) #pragma pack(1)
struct section { struct section {
#ifdef FOXSATFILE
char magic[6];
#else
char magic[14]; char magic[14];
#endif
unsigned int total_length:16; unsigned int total_length:16;
#ifndef FOXSATFILE
unsigned int magic2:32; unsigned int magic2:32;
#endif
unsigned int table_id:8; unsigned int table_id:8;
union { union {
struct { struct {
#ifdef FOXSATPLATFORM
unsigned int syntax_indicator:1;
unsigned int reserved:3;
unsigned int length:12;
#else
unsigned int length:12; unsigned int length:12;
unsigned int reserved:3; unsigned int reserved:3;
unsigned int syntax_indicator:1; unsigned int syntax_indicator:1;
#endif
} u; } u;
unsigned int comp:16; unsigned int comp:16;
} u1; } u1;
unsigned int service_id:16; 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 current_next_indicator:1;
unsigned int version_number:5; unsigned int version_number:5;
unsigned int reserved2:2; unsigned int reserved2:2;
#endif
unsigned int section_number:8; unsigned int section_number:8;
unsigned int last_section_number:8; unsigned int last_section_number:8;
unsigned int transport_stream_id:16; unsigned int transport_stream_id:16;
@ -55,9 +83,15 @@ struct data {
unsigned int dur_sec:8; unsigned int dur_sec:8;
union { union {
struct { 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 descriptors_loop_length:12;
unsigned int free_CA_mode:1; unsigned int free_CA_mode:1;
unsigned int running_status:3; unsigned int running_status:3;
#endif
} u; } u;
unsigned int comp:16; unsigned int comp:16;
} u1; } u1;
@ -70,9 +104,7 @@ enum epgfiltertype {
FILTER_TIMESTAMP = 0x8, FILTER_TIMESTAMP = 0x8,
FILTER_CRID = 0x10, FILTER_CRID = 0x10,
FILTER_SCRID = 0x20, FILTER_SCRID = 0x20,
FILTER_CONTENT = 0x40, FILTER_CONTENT = 0x40
FILTER_TIMERANGE = 0x80,
FILTER_GUIDETYPE = 0x100
}; };
enum matchtype { FT_EQUAL, FT_RANGE, FT_GREATER, FT_LESS }; enum matchtype { FT_EQUAL, FT_RANGE, FT_GREATER, FT_LESS };

193
epgsql.c Normal file
View File

@ -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);
}

11
epgsql.h Normal file
View File

@ -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 *);

33
file.c
View File

@ -23,27 +23,7 @@ struct epg *
open_file(char *filename) open_file(char *filename)
{ {
struct epg *epg; struct epg *epg;
struct stat st, st2; struct stat st;
if (debug)
printf("Opening file '%s'\n", filename);
if (stat(filename, &st) == -1)
{
perror(filename);
return NULL;
}
sleep(1);
if (stat(filename, &st2) == -1)
{
perror(filename);
return NULL;
}
if (st.st_size != st2.st_size)
{
printf("EPG data file is updating, try later.\n");
return NULL;
}
if (!(epg = malloc(sizeof(struct epg)))) if (!(epg = malloc(sizeof(struct epg))))
{ {
@ -51,7 +31,18 @@ open_file(char *filename)
return NULL; return NULL;
} }
if (debug)
printf("Opening file '%s'\n", filename);
strcpy(epg->fname, filename); strcpy(epg->fname, filename);
if (stat(epg->fname, &st) == -1)
{
perror(epg->fname);
free(epg);
return NULL;
}
epg->binsize = st.st_size; epg->binsize = st.st_size;
if (debug) if (debug)

View File

@ -1,14 +1,6 @@
/* /*
* Humax EPG Tool * Humax EPG Tool
* by af123, 2011 - 2018 * by af123, 2011
*
* These tables and the decompression code are derived from MythTV
* https://github.com/MythTV/mythtv/tree/master/mythtv/libs/libmythtv/mpeg/
* freesat_tables.cpp 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
*/ */
#include <stdio.h> #include <stdio.h>
@ -22,6 +14,12 @@
#include "lint.h" #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 { struct fsattab {
unsigned int value; unsigned int value;
short bits; short bits;
@ -5746,7 +5744,7 @@ static unsigned fsat_index_2[] = {
#define ESCAPE '\1' #define ESCAPE '\1'
unsigned char * unsigned char *
freeview_huffman_to_string(const unsigned char *src, unsigned int size, freeview_huffman_to_string(const unsigned char *src, uint size,
unsigned int *len) unsigned int *len)
{ {
struct fsattab *fsat_table; struct fsattab *fsat_table;

7
lint.h
View File

@ -20,10 +20,9 @@ inline uint32_t read_uint32(uint8_t *, int);
void hexdump(uint8_t *, uint32_t, uint32_t); void hexdump(uint8_t *, uint32_t, uint32_t);
char *hexstr(uint8_t *, uint32_t); char *hexstr(uint8_t *, uint32_t);
char *ctime_nl(time_t *); char *ctime_nl(time_t *);
time_t mjd(unsigned int, unsigned int, unsigned int, unsigned int); time_t mjd(uint16_t, int, int, int);
void safeprintf(char *, ...); void safeprintf(char *, ...);
void uncompress_epg(char **, unsigned int *); void uncompress_epg(char **, unsigned int *);
void iso6937_convert(char **, unsigned int *);
struct epg *open_file(char *); struct epg *open_file(char *);
void close_file(struct epg *); void close_file(struct epg *);
@ -36,7 +35,7 @@ void dump_section(struct section *);
struct data *read_data(struct epg *); struct data *read_data(struct epg *);
void dump_data(struct data *); void dump_data(struct data *);
int parse(char *, void parse(char *,
void (*)(struct epg *, struct section *, struct data *, void (*)(struct epg *, struct section *, struct data *,
struct descriptor **, void *), void *, struct epgfilter *); struct descriptor **, void *), void *, struct epgfilter *);
@ -47,7 +46,7 @@ void dump_descriptor(struct descriptor *, int);
void free_descriptor(struct descriptor *); void free_descriptor(struct descriptor *);
const char *content_type(struct descriptor *); const char *content_type(struct descriptor *);
unsigned char *freeview_huffman_to_string(const unsigned char *, unsigned int, unsigned char *freeview_huffman_to_string(const unsigned char *, uint,
unsigned int *); unsigned int *);
int is_bst(time_t); int is_bst(time_t);

1097
main.c

File diff suppressed because it is too large Load Diff

31
util.c
View File

@ -13,42 +13,25 @@
#include <time.h> #include <time.h>
#include <strings.h> #include <strings.h>
#include <stdarg.h> #include <stdarg.h>
#include <xconv.h>
#include "lint.h" #include "lint.h"
void void
uncompress_epg(char **epg, unsigned int *epglen) uncompress_epg(char **epg, unsigned int *epglen)
{ {
char *newepg; char *new;
unsigned int newlen; unsigned int newlen;
if ((newepg = (char *) if ((new = (char *)
freeview_huffman_to_string((unsigned char *)(*epg), freeview_huffman_to_string((unsigned char *)(*epg),
*epglen, &newlen))) *epglen, &newlen)))
{ {
free(*epg); free(*epg);
*epg = newepg; *epg = new;
*epglen = newlen; *epglen = newlen;
} }
} }
void
iso6937_convert(char **str, unsigned int *len)
{
char dst[0x200];
int newlen;
newlen = xconv(*str, dst, sizeof(dst));
if (newlen)
{
free(*str);
*str = strdup(dst);
*len = newlen;
}
}
#ifdef sun #ifdef sun
char * char *
strcasestr (char *h, char *n) strcasestr (char *h, char *n)
@ -99,16 +82,16 @@ safeprintf(char *fmt, ...)
} }
time_t time_t
mjd(unsigned int day, unsigned int h, unsigned int m, unsigned int s) mjd(uint16_t day, int h, int m, int s)
{ {
time_t tm; time_t tm;
struct tm *t; struct tm *t;
tm = MJD_TO_UNIX(day); tm = MJD_TO_UNIX(day);
t = gmtime(&tm); t = gmtime(&tm);
t->tm_hour = (int) h; t->tm_hour = h;
t->tm_min = (int) m; t->tm_min = m;
t->tm_sec = (int) s; t->tm_sec = s;
return mktime(t); return mktime(t);
} }

6
util.h
View File

@ -6,7 +6,11 @@
/* Works for modern dates, 1970 - 2038 */ /* Works for modern dates, 1970 - 2038 */
#define MJD_TO_UNIX(xx) (((xx) - 40587) * 86400) #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)) #define bcd(v) (((((v) >> 4) & 0xf) * 10) + ((v) & 0xf))

View File

@ -1,40 +0,0 @@
#define GETOPTOPT \
do { \
if (*++cp == '\0' && argc > 1) \
{ \
argc--, argv++; \
cp = argv[0]; \
} \
while (*cp != '\0' && isspace((int)*cp)) \
cp++; \
} while (0)
#define GETOPTINTOPT \
do { \
if (*++cp == '\0' && argc > 1 && atoi(argv[1]) > 0) \
{ \
argc--, argv++; \
cp = argv[0]; \
} \
while (*cp != '\0' && isspace((int)*cp)) \
cp++; \
} while (0)
#define GETOPT \
do { \
if (*++cp == '\0' && argc < 2) \
{ \
fprintf(stderr, \
"No argument supplied for -%c\n", opt); \
exit(1); \
} \
else if (*cp == '\0') \
{ \
argc--, argv++; \
cp = argv[0]; \
} \
while (isspace((int)*cp)) \
cp++; \
} while (0)