Compare commits
56 Commits
Author | SHA1 | Date |
---|---|---|
prpr | b7ebf6861e | |
prpr | b0eb6d5fb6 | |
prpr | 09b1fc7466 | |
prpr | edf589944c | |
prpr | e8b6d30585 | |
prpr | f0ff884255 | |
prpr | 3ccb5332d2 | |
prpr | be6a274dd0 | |
prpr | 869d4d24d2 | |
prpr | 179834a5f5 | |
HummyPkg | 44e991b36e | |
hummypkg | 708b081168 | |
hummypkg | 000c750b19 | |
hummypkg | abe92a3135 | |
hummypkg | 2ffb32bcb4 | |
hummypkg | 792ac397f4 | |
hummypkg | 2b0eeebc30 | |
hummypkg | 18e2ae9938 | |
hummypkg | 0af5061493 | |
hummypkg | ede8b85152 | |
hummypkg | f31cfea03b | |
hummypkg | e8232ddc86 | |
hummypkg | 109e0992ab | |
hummypkg | 8992053f18 | |
hummypkg | 19c33c6566 | |
hummypkg | 26f0a4cf64 | |
hummypkg | fba5a52e92 | |
hummypkg | 56825f0502 | |
hummypkg | dcac532f26 | |
hummypkg | a21b64b158 | |
hummypkg | 9ec88c235a | |
hummypkg | 88180e7473 | |
hummypkg | cba368128d | |
hummypkg | c31dc7166f | |
hummypkg | 5b98b8e21a | |
hummypkg | bb729d2802 | |
hummypkg | 874e8bb6b8 | |
hummypkg | e6e681a43a | |
hummypkg | 603cbd81e5 | |
hummypkg | f0557c57e2 | |
hummypkg | b18b52df1c | |
hummypkg | 1d428500bc | |
hummypkg | 63f96d33e4 | |
hummypkg | d25851546c | |
hummypkg | 8dc3016a79 | |
hummypkg | da83a21b67 | |
hummypkg | 48eec1f3ba | |
hummypkg | 246860b7ec | |
hummypkg | 6b516bf434 | |
hummypkg | d39e1c32b1 | |
hummypkg | 2c021920a3 | |
hummypkg | 68d977c2ba | |
hummypkg | 372759652d | |
hummypkg | c156fc493f | |
hummypkg | 18b82bf36f | |
hummypkg | 1ce97801b6 |
|
@ -0,0 +1,2 @@
|
|||
*.o
|
||||
epg
|
25
Makefile
25
Makefile
|
@ -1,36 +1,43 @@
|
|||
|
||||
MAKE=gmake
|
||||
|
||||
DEFS=-DFOXSATPLATFORM -DFOXSATFILE
|
||||
#DEFS= -DFOXSATFILE
|
||||
DEFS=
|
||||
|
||||
SRCS= descriptor.c \
|
||||
epg.c \
|
||||
file.c \
|
||||
huffman.c \
|
||||
main.c \
|
||||
util.c \
|
||||
epgsql.c
|
||||
util.c
|
||||
|
||||
HDRS= descriptor.h \
|
||||
epg.h \
|
||||
lint.h \
|
||||
util.h \
|
||||
epgsql.h
|
||||
xgetopt.h
|
||||
|
||||
OBJS= $(SRCS:.c=.o)
|
||||
#CC=gcc
|
||||
CC=gcc
|
||||
#CC=mipsel-linux-gcc
|
||||
CC=mips-linux-gcc
|
||||
CFLAGS=-g -pthread
|
||||
CFLAGS=-g
|
||||
INCS=
|
||||
LIBS=-lsqlite3 -ldl
|
||||
LIBS=
|
||||
#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
|
||||
|
||||
PLATFORM=$(shell uname -s | cut -d- -f1)
|
||||
ifeq ($(PLATFORM),Linux)
|
||||
DEFS=-DHAVE_SQLITE3
|
||||
LIBS=-lsqlite3 -lxconv
|
||||
endif
|
||||
|
||||
all: tags epg
|
||||
|
||||
install: epg
|
||||
strip epg
|
||||
cp epg /mod/bin/epg
|
||||
|
||||
epg: ${OBJS}
|
||||
@echo "Linking..."
|
||||
@-[ -f $@ ] && mv $@ $@~ || exit 0
|
||||
|
|
89
descriptor.c
89
descriptor.c
|
@ -19,7 +19,7 @@ read_descriptor_header(struct epg *epg)
|
|||
{
|
||||
struct descriptor *d;
|
||||
|
||||
d = (struct descriptor *)malloc(sizeof(struct descriptor));
|
||||
d = (struct descriptor *)calloc(sizeof(struct descriptor), 1);
|
||||
d->loaded = 0;
|
||||
|
||||
if (epg->binsize - epg->offset < 2)
|
||||
|
@ -55,9 +55,16 @@ string_to_end(struct epg *epg, struct descriptor *d, int sofar,
|
|||
static char *
|
||||
read_lstring(struct epg *epg, unsigned int *len)
|
||||
{
|
||||
int l = epg->bin[epg->offset++];
|
||||
unsigned int l = epg->bin[epg->offset++];
|
||||
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);
|
||||
memcpy(c, epg->bin + epg->offset, l);
|
||||
c[l] = '\0';
|
||||
|
@ -86,6 +93,31 @@ read_descriptor(struct epg *epg, struct descriptor *d)
|
|||
|
||||
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:
|
||||
memcpy(&d->content.d80, epg->bin + epg->offset, 6);
|
||||
epg->offset += 6;
|
||||
|
@ -95,15 +127,37 @@ read_descriptor(struct epg *epg, struct descriptor *d)
|
|||
break;
|
||||
|
||||
case DS_USER_DEFINED:
|
||||
d->content.d137.text =
|
||||
read_lstring(epg, &d->content.d137.textlen);
|
||||
{
|
||||
int sofar = 0;
|
||||
|
||||
/* 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);
|
||||
epg->offset += 3;
|
||||
d->content.d137.warning = string_to_end(epg, d,
|
||||
4 + d->content.d137.textlen,
|
||||
sofar += 3;
|
||||
d->content.d137.warning = string_to_end(epg, d, sofar,
|
||||
&d->content.d137.warninglen);
|
||||
break;
|
||||
}
|
||||
|
||||
case DS_LINKAGE:
|
||||
memcpy(&d->content.d74, epg->bin + epg->offset,
|
||||
|
@ -216,14 +270,17 @@ free_descriptor(struct descriptor *d)
|
|||
free(d->content.d77.text);
|
||||
break;
|
||||
|
||||
case DS_EXTENDED_EVENT:
|
||||
if (d->content.d78.text)
|
||||
free(d->content.d78.text);
|
||||
break;
|
||||
|
||||
case DS_COMPONENT:
|
||||
if (d->content.d80.text)
|
||||
free(d->content.d80.text);
|
||||
break;
|
||||
|
||||
case DS_USER_DEFINED:
|
||||
if (d->content.d137.text)
|
||||
free(d->content.d137.text);
|
||||
if (d->content.d137.warning)
|
||||
free(d->content.d137.warning);
|
||||
break;
|
||||
|
@ -268,7 +325,6 @@ descriptor_name(struct descriptor *d)
|
|||
case DS_CONTENT_IDENTIFIER: return "content id";
|
||||
case DS_FTA_CONTENT_MGMT: return "content mgmt";
|
||||
case DS_USER_DEFINED: return "user defined";
|
||||
default: return "Unknown";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
@ -300,10 +356,8 @@ content_type(struct descriptor *d)
|
|||
return "Leisure";
|
||||
case 0xf:
|
||||
return "Drama";
|
||||
default:
|
||||
return "Undefined";
|
||||
}
|
||||
return "Unknown";
|
||||
return "Undefined";
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -327,6 +381,13 @@ dump_descriptor(struct descriptor *d, int content)
|
|||
DUMPHEX(d, content.d77.text, d->content.d77.textlen);
|
||||
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:
|
||||
DUMPINT(d, content.d80.stream_content);
|
||||
DUMPINT(d, content.d80.reserved);
|
||||
|
@ -338,9 +399,9 @@ dump_descriptor(struct descriptor *d, int content)
|
|||
break;
|
||||
|
||||
case DS_USER_DEFINED:
|
||||
DUMPINT(d, content.d137.textlen);
|
||||
DUMPINT(d, content.d137.guidance_type);
|
||||
DUMPINT(d, content.d137.guidance_mode);
|
||||
DUMPNSTR(d, content.d137.lang, 3);
|
||||
DUMPHEX(d, content.d137.text, d->content.d137.textlen);
|
||||
DUMPHEX(d, content.d137.warning, d->content.d137.warninglen);
|
||||
break;
|
||||
|
||||
|
|
65
descriptor.h
65
descriptor.h
|
@ -3,18 +3,15 @@
|
|||
* by af123, 2011
|
||||
*/
|
||||
|
||||
#define DS_LINKAGE 74
|
||||
#define DS_SHORT_EVENT 77
|
||||
#define DS_COMPONENT 80
|
||||
#define DS_CONTENT 84
|
||||
#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 DS_LINKAGE 74 /* 0x4a */
|
||||
#define DS_SHORT_EVENT 77 /* 0x4d */
|
||||
#define DS_EXTENDED_EVENT 78 /* 0x4e */
|
||||
#define DS_COMPONENT 80 /* 0x50 */
|
||||
#define DS_CONTENT 84 /* 0x54 */
|
||||
#define DS_PRIVATE_DATA_SPECIFIER 95 /* 0x5f */
|
||||
#define DS_CONTENT_IDENTIFIER 118 /* 0x76 */
|
||||
#define DS_FTA_CONTENT_MGMT 126 /* 0x7e */
|
||||
#define DS_USER_DEFINED 137 /* 0x89 */
|
||||
|
||||
#define PARSER_SHORT_EVENT 0
|
||||
#define PARSER_USER_DEFINED 1
|
||||
|
@ -22,7 +19,9 @@
|
|||
#define PARSER_CRID_EVENT 3
|
||||
#define PARSER_CRID_SERIES 4
|
||||
#define PARSER_CRID_REC 5
|
||||
#define PARSER_MAX 6
|
||||
#define PARSER_EXTENDED_EVENT 6
|
||||
#define PARSER_FTA_CONTENT_MGMT 7
|
||||
#define PARSER_MAX 8
|
||||
|
||||
#define CRIDT_EVENT '1'
|
||||
#define CRIDT_SERIES '2'
|
||||
|
@ -30,13 +29,8 @@
|
|||
|
||||
#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;
|
||||
|
@ -54,13 +48,14 @@ struct descriptor {
|
|||
char *text;
|
||||
} d77; /* SHORT_EVENT */
|
||||
struct {
|
||||
#ifdef FOXSATPLATFORM
|
||||
unsigned int reserved:4;
|
||||
unsigned int stream_content:4;
|
||||
#else
|
||||
char lang[3];
|
||||
unsigned int items;
|
||||
unsigned int textlen;
|
||||
char *text;
|
||||
} d78; /* EXTENDED_EVENT */
|
||||
struct {
|
||||
unsigned int stream_content:4;
|
||||
unsigned int reserved:4;
|
||||
#endif
|
||||
unsigned int type:8;
|
||||
unsigned int tag:8;
|
||||
char lang[3];
|
||||
|
@ -68,22 +63,17 @@ 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 {
|
||||
unsigned int textlen;
|
||||
char *text;
|
||||
unsigned int guidance_type;
|
||||
unsigned int guidance_mode;
|
||||
char lang[3];
|
||||
char *warning;
|
||||
unsigned int warninglen;
|
||||
} d137; /* USER_DEFINED - content warnings? */
|
||||
} d137; /* USER_DEFINED - content warnings */
|
||||
struct {
|
||||
unsigned int no_revocation:1;
|
||||
unsigned int control_remote_access:2;
|
||||
|
@ -97,29 +87,16 @@ 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 */
|
||||
|
|
145
epg.c
145
epg.c
|
@ -23,7 +23,7 @@ read_section(struct epg *epg)
|
|||
return NULL;
|
||||
|
||||
memcpy(&h, epg->bin + epg->offset, sizeof(h));
|
||||
if (memcmp(h.magic, SECTION_MAGIC, sizeof(h.magic)))
|
||||
if (memcmp(h.magic, SECTION_MAGIC, sizeof(h.magic) - 1))
|
||||
{
|
||||
printf("Section header magic mismatch.\n");
|
||||
hexdump(epg->bin + epg->offset, 64, 0);
|
||||
|
@ -111,6 +111,28 @@ dump_data(struct data *d)
|
|||
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
|
||||
check_filter_range(struct epgfilter *f, enum epgfiltertype type,
|
||||
unsigned long idl, unsigned long idh)
|
||||
|
@ -120,7 +142,14 @@ check_filter_range(struct epgfilter *f, enum epgfiltertype type,
|
|||
|
||||
for (; f; f = f->next)
|
||||
{
|
||||
if (f->type == type && (f->num < idl || f->num > idh))
|
||||
if (f->type != type)
|
||||
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 1;
|
||||
|
@ -149,7 +178,7 @@ check_filter(struct epgfilter *f, enum epgfiltertype type,
|
|||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
parse(char *epgpath,
|
||||
void (*callback)(struct epg *, struct section *, struct data *,
|
||||
struct descriptor **, void *), void *val, struct epgfilter *filter)
|
||||
|
@ -159,7 +188,7 @@ parse(char *epgpath,
|
|||
int i;
|
||||
|
||||
if (!(epg = open_file(epgpath)))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
while (epg->offset < epg->binsize)
|
||||
{
|
||||
|
@ -177,11 +206,8 @@ 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
|
||||
while (epg->offset < epg->binsize &&
|
||||
epg->bin[epg->offset] == 'U')
|
||||
epg->offset++;
|
||||
continue;
|
||||
}
|
||||
|
@ -207,10 +233,10 @@ parse(char *epgpath,
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((filterflags & FILTER_TIMESTAMP))
|
||||
if ((filterflags &
|
||||
(FILTER_TIMESTAMP | FILTER_TIMERANGE)))
|
||||
{
|
||||
time_t tm;
|
||||
int dur;
|
||||
time_t tm, dur;
|
||||
|
||||
tm = mjd(d->start_date, d->start_hour,
|
||||
d->start_min, d->start_sec);
|
||||
|
@ -218,12 +244,29 @@ parse(char *epgpath,
|
|||
dur = d->dur_hour * 3600 + d->dur_min * 60 +
|
||||
d->dur_sec;
|
||||
|
||||
if (!check_filter_range(filter,
|
||||
FILTER_TIMESTAMP, tm, tm + dur))
|
||||
if ((filterflags & FILTER_TIMESTAMP))
|
||||
{
|
||||
/* Skip this event. */
|
||||
epg->offset = dend;
|
||||
continue;
|
||||
if (!check_filter_range(filter,
|
||||
FILTER_TIMESTAMP,
|
||||
(unsigned long) tm,
|
||||
(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -248,6 +291,14 @@ parse(char *epgpath,
|
|||
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)
|
||||
{
|
||||
case DS_SHORT_EVENT:
|
||||
|
@ -257,6 +308,13 @@ parse(char *epgpath,
|
|||
dslist[PARSER_SHORT_EVENT] = ds;
|
||||
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:
|
||||
if (!(ds = read_descriptor_header(epg)))
|
||||
break;
|
||||
|
@ -289,13 +347,15 @@ parse(char *epgpath,
|
|||
dslist[PARSER_CONTENT] = ds;
|
||||
break;
|
||||
|
||||
/*
|
||||
case DS_FTA_CONTENT_MGMT:
|
||||
if (!(ds = read_descriptor_header(epg)))
|
||||
break;
|
||||
read_descriptor(epg, ds);
|
||||
dump_descriptor(ds, 1);
|
||||
free_descriptor(ds);
|
||||
dslist[PARSER_FTA_CONTENT_MGMT] = ds;
|
||||
break;
|
||||
|
||||
/*
|
||||
|
||||
case DS_LINKAGE:
|
||||
read_descriptor(epg, ds);
|
||||
dump_descriptor(ds, 1);
|
||||
|
@ -304,11 +364,39 @@ parse(char *epgpath,
|
|||
*/
|
||||
|
||||
default:
|
||||
if (debug > 2)
|
||||
printf("! Unhandled.\n");
|
||||
epg->offset += dslen + 2;
|
||||
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 (
|
||||
(
|
||||
!(filterflags & FILTER_CRID) ||
|
||||
|
@ -328,6 +416,13 @@ parse(char *epgpath,
|
|||
check_filter(filter, FILTER_CONTENT,
|
||||
dslist[PARSER_CONTENT]->content.d84.level1,
|
||||
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);
|
||||
|
@ -336,19 +431,19 @@ 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
|
||||
while (epg->offset < epg->binsize &&
|
||||
epg->bin[epg->offset] == 'U')
|
||||
epg->offset++;
|
||||
}
|
||||
|
||||
close_file(epg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
42
epg.h
42
epg.h
|
@ -5,11 +5,7 @@
|
|||
|
||||
#include <sys/param.h>
|
||||
|
||||
#ifdef FOXSATFILE
|
||||
#define DEFAULT_EPG_FILE "/mnt/hd2/fsatepg/epg.dat"
|
||||
#else
|
||||
#define DEFAULT_EPG_FILE "/mnt/hd1/dvbepg/epg.dat"
|
||||
#endif
|
||||
#define DEFAULT_EPG_FILE "/mnt/hd1/dvbepg/epg.dat"
|
||||
|
||||
struct epg {
|
||||
char fname[MAXPATHLEN + 1];
|
||||
|
@ -19,50 +15,26 @@ struct epg {
|
|||
uint32_t binsize;
|
||||
};
|
||||
|
||||
#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
|
||||
#define SECTION_MAGIC "(Gq\x87\x00\x00\x00\x00\x02\x00\x00\x00\x00\x01"
|
||||
|
||||
#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;
|
||||
|
@ -83,15 +55,9 @@ 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;
|
||||
|
@ -104,7 +70,9 @@ enum epgfiltertype {
|
|||
FILTER_TIMESTAMP = 0x8,
|
||||
FILTER_CRID = 0x10,
|
||||
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 };
|
||||
|
|
193
epgsql.c
193
epgsql.c
|
@ -1,193 +0,0 @@
|
|||
#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
11
epgsql.h
|
@ -1,11 +0,0 @@
|
|||
#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
33
file.c
|
@ -23,7 +23,27 @@ struct epg *
|
|||
open_file(char *filename)
|
||||
{
|
||||
struct epg *epg;
|
||||
struct stat st;
|
||||
struct stat st, st2;
|
||||
|
||||
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))))
|
||||
{
|
||||
|
@ -31,18 +51,7 @@ open_file(char *filename)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (debug)
|
||||
printf("Opening file '%s'\n", filename);
|
||||
|
||||
strcpy(epg->fname, filename);
|
||||
|
||||
if (stat(epg->fname, &st) == -1)
|
||||
{
|
||||
perror(epg->fname);
|
||||
free(epg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
epg->binsize = st.st_size;
|
||||
|
||||
if (debug)
|
||||
|
|
18
huffman.c
18
huffman.c
|
@ -1,6 +1,14 @@
|
|||
/*
|
||||
* Humax EPG Tool
|
||||
* by af123, 2011
|
||||
* 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.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>
|
||||
|
@ -14,12 +22,6 @@
|
|||
|
||||
#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;
|
||||
|
@ -5744,7 +5746,7 @@ static unsigned fsat_index_2[] = {
|
|||
#define ESCAPE '\1'
|
||||
|
||||
unsigned char *
|
||||
freeview_huffman_to_string(const unsigned char *src, uint size,
|
||||
freeview_huffman_to_string(const unsigned char *src, unsigned int size,
|
||||
unsigned int *len)
|
||||
{
|
||||
struct fsattab *fsat_table;
|
||||
|
|
7
lint.h
7
lint.h
|
@ -20,9 +20,10 @@ inline uint32_t read_uint32(uint8_t *, int);
|
|||
void hexdump(uint8_t *, uint32_t, uint32_t);
|
||||
char *hexstr(uint8_t *, uint32_t);
|
||||
char *ctime_nl(time_t *);
|
||||
time_t mjd(uint16_t, int, int, int);
|
||||
time_t mjd(unsigned int, unsigned int, unsigned int, unsigned int);
|
||||
void safeprintf(char *, ...);
|
||||
void uncompress_epg(char **, unsigned int *);
|
||||
void iso6937_convert(char **, unsigned int *);
|
||||
|
||||
struct epg *open_file(char *);
|
||||
void close_file(struct epg *);
|
||||
|
@ -35,7 +36,7 @@ void dump_section(struct section *);
|
|||
struct data *read_data(struct epg *);
|
||||
void dump_data(struct data *);
|
||||
|
||||
void parse(char *,
|
||||
int parse(char *,
|
||||
void (*)(struct epg *, struct section *, struct data *,
|
||||
struct descriptor **, void *), void *, struct epgfilter *);
|
||||
|
||||
|
@ -46,7 +47,7 @@ void dump_descriptor(struct descriptor *, int);
|
|||
void free_descriptor(struct descriptor *);
|
||||
const char *content_type(struct descriptor *);
|
||||
|
||||
unsigned char *freeview_huffman_to_string(const unsigned char *, uint,
|
||||
unsigned char *freeview_huffman_to_string(const unsigned char *, unsigned int,
|
||||
unsigned int *);
|
||||
|
||||
int is_bst(time_t);
|
||||
|
|
31
util.c
31
util.c
|
@ -13,25 +13,42 @@
|
|||
#include <time.h>
|
||||
#include <strings.h>
|
||||
#include <stdarg.h>
|
||||
#include <xconv.h>
|
||||
|
||||
#include "lint.h"
|
||||
|
||||
void
|
||||
uncompress_epg(char **epg, unsigned int *epglen)
|
||||
{
|
||||
char *new;
|
||||
char *newepg;
|
||||
unsigned int newlen;
|
||||
|
||||
if ((new = (char *)
|
||||
if ((newepg = (char *)
|
||||
freeview_huffman_to_string((unsigned char *)(*epg),
|
||||
*epglen, &newlen)))
|
||||
{
|
||||
free(*epg);
|
||||
*epg = new;
|
||||
*epg = newepg;
|
||||
*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
|
||||
char *
|
||||
strcasestr (char *h, char *n)
|
||||
|
@ -82,16 +99,16 @@ safeprintf(char *fmt, ...)
|
|||
}
|
||||
|
||||
time_t
|
||||
mjd(uint16_t day, int h, int m, int s)
|
||||
mjd(unsigned int day, unsigned int h, unsigned int m, unsigned int s)
|
||||
{
|
||||
time_t tm;
|
||||
struct tm *t;
|
||||
|
||||
tm = MJD_TO_UNIX(day);
|
||||
t = gmtime(&tm);
|
||||
t->tm_hour = h;
|
||||
t->tm_min = m;
|
||||
t->tm_sec = s;
|
||||
t->tm_hour = (int) h;
|
||||
t->tm_min = (int) m;
|
||||
t->tm_sec = (int) s;
|
||||
|
||||
return mktime(t);
|
||||
}
|
||||
|
|
6
util.h
6
util.h
|
@ -6,11 +6,7 @@
|
|||
/* Works for modern dates, 1970 - 2038 */
|
||||
#define MJD_TO_UNIX(xx) (((xx) - 40587) * 86400)
|
||||
|
||||
#ifdef FOXSATPLATFORM
|
||||
#define _swap16(v) (v)
|
||||
#else
|
||||
#define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8))
|
||||
#endif
|
||||
#define _swap16(v) ((((v) >> 8) & 0xff) | (((v) & 0xff) << 8))
|
||||
|
||||
#define bcd(v) (((((v) >> 4) & 0xf) * 10) + ((v) & 0xf))
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
#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)
|
||||
|
Loading…
Reference in New Issue