add filters
This commit is contained in:
parent
9f637857c8
commit
2e2d35cf7e
58
epg.c
58
epg.c
|
@ -21,6 +21,7 @@ read_section(struct epg *epg)
|
|||
if (memcmp(h.magic, SECTION_MAGIC, sizeof(h.magic)))
|
||||
{
|
||||
printf("Section header magic mismatch.\n");
|
||||
hexdump(epg->bin + epg->offset, 64, 0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -105,10 +106,23 @@ dump_data(struct data *d)
|
|||
DUMPINT(d, u1.u.descriptors_loop_length);
|
||||
}
|
||||
|
||||
static inline int
|
||||
check_filter(struct epgfilter *f, enum epgfiltertype type,
|
||||
unsigned int id, char *str __attribute__((unused)))
|
||||
{
|
||||
if (!f)
|
||||
return 1;
|
||||
|
||||
for (; f; f = f->next)
|
||||
if (f->type == type && f->num != id)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
parse(char *epgpath,
|
||||
void (*callback)(struct epg *, struct section *, struct data *,
|
||||
struct descriptor **, void *), void *val)
|
||||
struct descriptor **, void *), void *val, struct epgfilter *filter)
|
||||
{
|
||||
struct descriptor *dslist[3];
|
||||
struct epg *epg;
|
||||
|
@ -127,6 +141,16 @@ parse(char *epgpath,
|
|||
|
||||
send = epg->offset - 11 + s->u1.u.length - 4;
|
||||
|
||||
if (!check_filter(filter, FILTER_SERVICE, s->service_id, NULL))
|
||||
{
|
||||
/* Skip this service. */
|
||||
epg->offset += s->total_length - 14;
|
||||
/* Skip padding bytes... */
|
||||
while (epg->bin[epg->offset] == 'U')
|
||||
epg->offset++;
|
||||
continue;
|
||||
}
|
||||
|
||||
while (epg->offset < send)
|
||||
{
|
||||
struct data *d;
|
||||
|
@ -135,9 +159,18 @@ parse(char *epgpath,
|
|||
if (!(d = read_data(epg)))
|
||||
break;
|
||||
|
||||
dend = epg->offset + d->u1.u.descriptors_loop_length;
|
||||
|
||||
if (!check_filter(filter, FILTER_EVENT, d->event_id,
|
||||
NULL))
|
||||
{
|
||||
/* Skip this event. */
|
||||
epg->offset = dend;
|
||||
continue;
|
||||
}
|
||||
|
||||
dslist[0] = dslist[1] = dslist[2] = NULL;
|
||||
|
||||
dend = epg->offset + d->u1.u.descriptors_loop_length;
|
||||
while (epg->offset < dend)
|
||||
{
|
||||
struct descriptor *ds;
|
||||
|
@ -145,6 +178,14 @@ parse(char *epgpath,
|
|||
if (!(ds = read_descriptor_header(epg)))
|
||||
continue;
|
||||
|
||||
if (!check_filter(filter, FILTER_DESCRIPTOR,
|
||||
ds->tag, NULL))
|
||||
{
|
||||
skip_descriptor(epg, ds);
|
||||
free_descriptor(ds);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (ds->tag)
|
||||
{
|
||||
case DS_SHORT_EVENT:
|
||||
|
@ -187,3 +228,16 @@ parse(char *epgpath,
|
|||
close_file(epg);
|
||||
}
|
||||
|
||||
void
|
||||
add_epgfilter(struct epgfilter **filter, enum epgfiltertype type,
|
||||
unsigned int num, char *str)
|
||||
{
|
||||
struct epgfilter *f = malloc(sizeof(struct epgfilter));
|
||||
|
||||
f->type = type;
|
||||
f->num = num;
|
||||
f->str = str;
|
||||
f->next = *filter;
|
||||
*filter = f;
|
||||
}
|
||||
|
||||
|
|
14
epg.h
14
epg.h
|
@ -59,3 +59,17 @@ struct data {
|
|||
} u1;
|
||||
};
|
||||
|
||||
enum epgfiltertype {
|
||||
FILTER_SERVICE = 0,
|
||||
FILTER_EVENT,
|
||||
FILTER_DESCRIPTOR
|
||||
};
|
||||
|
||||
struct epgfilter {
|
||||
enum epgfiltertype type;
|
||||
unsigned int num;
|
||||
char *str;
|
||||
|
||||
struct epgfilter *next;
|
||||
};
|
||||
|
||||
|
|
4
lint.h
4
lint.h
|
@ -20,6 +20,8 @@ void safeprintf(char *, ...);
|
|||
|
||||
struct epg *open_file(char *);
|
||||
void close_file(struct epg *);
|
||||
void add_epgfilter(struct epgfilter **, enum epgfiltertype,
|
||||
unsigned int, char *);
|
||||
|
||||
struct section *read_section(struct epg *);
|
||||
void dump_section(struct section *);
|
||||
|
@ -29,7 +31,7 @@ void dump_data(struct data *);
|
|||
|
||||
void parse(char *,
|
||||
void (*)(struct epg *, struct section *, struct data *,
|
||||
struct descriptor **, void *), void *);
|
||||
struct descriptor **, void *), void *, struct epgfilter *);
|
||||
|
||||
struct descriptor *read_descriptor_header(struct epg *);
|
||||
void read_descriptor(struct epg *, struct descriptor *);
|
||||
|
|
77
main.c
77
main.c
|
@ -25,7 +25,7 @@ syntax()
|
|||
{
|
||||
fprintf(stderr, "Humax EPG Tool v%s, by af123, 2011.\n\n", version);
|
||||
fprintf(stderr,
|
||||
"Syntax: epg [options] <command>...\n");
|
||||
"Syntax: epg [options] [filters] <command>...\n\n");
|
||||
fprintf(stderr,
|
||||
" Options:\n"
|
||||
" -b Brief output.\n"
|
||||
|
@ -33,8 +33,15 @@ syntax()
|
|||
" -f<file> Specify alternate EPG data file.\n"
|
||||
" -h Show help text.\n"
|
||||
" -p Parsable output.\n"
|
||||
"\n"
|
||||
);
|
||||
fprintf(stderr,
|
||||
" Filters: (can be specified multiple times, all must be true)\n"
|
||||
" -D<descriptor type> Show only selected descriptor type.\n"
|
||||
" -E<event id> Show only selected event.\n"
|
||||
" -S<service id> Show only selected service.\n"
|
||||
"\n"
|
||||
);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr,
|
||||
" Commands:\n"
|
||||
" dump Show a parsed summary of the EPG.\n"
|
||||
|
@ -219,10 +226,29 @@ now(struct epg *epg __attribute__((unused)),
|
|||
dump(epg, s, d, ds, NULL);
|
||||
}
|
||||
|
||||
#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)
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *epgpath = DEFAULT_EPG_FILE;
|
||||
struct epgfilter *filter = NULL;
|
||||
char *cp;
|
||||
|
||||
argc--, argv++;
|
||||
|
@ -230,7 +256,8 @@ main(int argc, char **argv)
|
|||
{
|
||||
for (cp = &argv[0][1]; *cp; cp++)
|
||||
{
|
||||
switch (*cp)
|
||||
char opt;
|
||||
switch (opt = *cp)
|
||||
{
|
||||
case 'b':
|
||||
sysopts |= SYSOPT_BRIEF;
|
||||
|
@ -244,18 +271,8 @@ main(int argc, char **argv)
|
|||
goto nextopt;
|
||||
|
||||
case 'f':
|
||||
if (*++cp == '\0')
|
||||
{
|
||||
fprintf(stderr,
|
||||
"No argument supplied for -f\n");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (isspace((int)*cp))
|
||||
cp++;
|
||||
epgpath = strdup(cp);
|
||||
}
|
||||
GETOPT;
|
||||
epgpath = strdup(cp);
|
||||
goto nextopt;
|
||||
|
||||
case 'h':
|
||||
|
@ -264,24 +281,42 @@ main(int argc, char **argv)
|
|||
case 'p':
|
||||
sysopts |= SYSOPT_PARSABLE;
|
||||
break;
|
||||
|
||||
/* Filters */
|
||||
case 'D':
|
||||
GETOPT;
|
||||
add_epgfilter(&filter, FILTER_DESCRIPTOR,
|
||||
atoi(cp), NULL);
|
||||
goto nextopt;
|
||||
|
||||
case 'E':
|
||||
GETOPT;
|
||||
add_epgfilter(&filter, FILTER_EVENT,
|
||||
atoi(cp), NULL);
|
||||
goto nextopt;
|
||||
|
||||
case 'S':
|
||||
GETOPT;
|
||||
add_epgfilter(&filter, FILTER_SERVICE,
|
||||
atoi(cp), NULL);
|
||||
goto nextopt;
|
||||
}
|
||||
}
|
||||
nextopt:
|
||||
argc--, argv++;
|
||||
}
|
||||
|
||||
|
||||
if (argc < 1)
|
||||
return syntax();
|
||||
|
||||
if (!strcmp(argv[0], "dump"))
|
||||
parse(epgpath, dump, NULL);
|
||||
if (!strcmp(argv[0], "now"))
|
||||
parse(epgpath, now, NULL);
|
||||
parse(epgpath, dump, NULL, filter);
|
||||
else if (!strcmp(argv[0], "now"))
|
||||
parse(epgpath, now, NULL, filter);
|
||||
else if (!strcmp(argv[0], "search") && argc > 1)
|
||||
parse(epgpath, search, (void *)argv[1]);
|
||||
parse(epgpath, search, (void *)argv[1], filter);
|
||||
else if (!strcmp(argv[0], "searchall") && argc > 1)
|
||||
parse(epgpath, searchall, (void *)argv[1]);
|
||||
parse(epgpath, searchall, (void *)argv[1], filter);
|
||||
else
|
||||
syntax();
|
||||
|
||||
|
|
Loading…
Reference in New Issue