properly handle guidance, fix sql field names

This commit is contained in:
hummypkg 2015-01-04 20:50:50 +00:00 committed by HummyPkg
parent fba5a52e92
commit 26f0a4cf64
5 changed files with 101 additions and 34 deletions

View File

@ -19,7 +19,7 @@ read_descriptor_header(struct epg *epg)
{ {
struct descriptor *d; struct descriptor *d;
d = (struct descriptor *)malloc(sizeof(struct descriptor)); d = (struct descriptor *)calloc(sizeof(struct descriptor), 1);
d->loaded = 0; d->loaded = 0;
if (epg->binsize - epg->offset < 2) if (epg->binsize - epg->offset < 2)
@ -120,15 +120,37 @@ read_descriptor(struct epg *epg, struct descriptor *d)
break; break;
case DS_USER_DEFINED: 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); memcpy(d->content.d137.lang, epg->bin + epg->offset, 3);
epg->offset += 3; epg->offset += 3;
d->content.d137.warning = string_to_end(epg, d, sofar += 3;
4 + d->content.d137.textlen, d->content.d137.warning = string_to_end(epg, d, sofar,
&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,
@ -252,8 +274,6 @@ free_descriptor(struct descriptor *d)
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;
@ -373,9 +393,9 @@ dump_descriptor(struct descriptor *d, int content)
break; break;
case DS_USER_DEFINED: 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); 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

@ -9,9 +9,9 @@
#define DS_COMPONENT 80 /* 0x50 */ #define DS_COMPONENT 80 /* 0x50 */
#define DS_CONTENT 84 /* 0x54 */ #define DS_CONTENT 84 /* 0x54 */
#define DS_PRIVATE_DATA_SPECIFIER 95 /* 0x5f */ #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 */
#define DS_USER_DEFINED 137 #define DS_USER_DEFINED 137 /* 0x89 */
#define PARSER_SHORT_EVENT 0 #define PARSER_SHORT_EVENT 0
#define PARSER_USER_DEFINED 1 #define PARSER_USER_DEFINED 1
@ -67,12 +67,12 @@ struct descriptor {
unsigned int user:8; unsigned int user:8;
} d84; /* CONTENT */ } d84; /* CONTENT */
struct { struct {
unsigned int textlen; unsigned int guidance_type;
char *text; unsigned int guidance_mode;
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;

7
epg.c
View File

@ -410,6 +410,13 @@ 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);

3
epg.h
View File

@ -71,7 +71,8 @@ enum epgfiltertype {
FILTER_CRID = 0x10, FILTER_CRID = 0x10,
FILTER_SCRID = 0x20, FILTER_SCRID = 0x20,
FILTER_CONTENT = 0x40, FILTER_CONTENT = 0x40,
FILTER_TIMERANGE = 0x80 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 };

75
main.c
View File

@ -1,6 +1,6 @@
/* /*
* Humax EPG Tool * Humax EPG Tool
* by af123, 2011 - 2013 * by af123, 2011 - 2015
*/ */
#include <stdio.h> #include <stdio.h>
@ -21,7 +21,7 @@
#include "lint.h" #include "lint.h"
int debug = 0; int debug = 0;
const char *version = "1.0.14"; const char *version = "1.0.15";
unsigned long sysopts = 0; unsigned long sysopts = 0;
unsigned long filterflags = 0; unsigned long filterflags = 0;
static time_t latest_stamp = 0; static time_t latest_stamp = 0;
@ -34,7 +34,7 @@ sqlite3_stmt *stmt;
int int
syntax() syntax()
{ {
fprintf(stderr, "Humax EPG Tool v%s, by af123, 2011-2013.\n\n", fprintf(stderr, "Humax EPG Tool v%s, by af123, 2011-2015.\n\n",
version); version);
fprintf(stderr, fprintf(stderr,
"Syntax: epg [options] [filters] <command>...\n\n"); "Syntax: epg [options] [filters] <command>...\n\n");
@ -44,7 +44,7 @@ syntax()
" -d[level] Set debug level.\n" " -d[level] Set debug level.\n"
" -f<file> Specify alternate EPG data file.\n" " -f<file> Specify alternate EPG data file.\n"
" -h Show help text.\n" " -h Show help text.\n"
" -p Parsable output.\n" " -p Parsable output (see *).\n"
"\n" "\n"
); );
fprintf(stderr, fprintf(stderr,
@ -54,6 +54,8 @@ syntax()
" -E<event id> Show only selected event.\n" " -E<event id> Show only selected event.\n"
" -R<SCRID> Show only events with this Series ID.\n" " -R<SCRID> Show only events with this Series ID.\n"
" -S<service id> Show only selected service.\n" " -S<service id> Show only selected service.\n"
" -G<type> Show only records with this guidance "
"type\n"
); );
fprintf(stderr, fprintf(stderr,
" -T<content type> Show only selected content types.\n" " -T<content type> Show only selected content types.\n"
@ -83,6 +85,14 @@ syntax()
" searchall <text> " " searchall <text> "
"Search programme names/descriptions for text.\n" "Search programme names/descriptions for text.\n"
); );
fprintf(stderr, "\n"
"* Parseable output is tab delimited and contains the following fields:\n"
" Service ID, Event ID, Start, Duration, Encrypted,\n"
" Title, Synopsis, Warning, Content Code, Content Type,\n"
" Event CRID, Series CRID, Recommended CRID, Guidance Mode\n"
);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
return 0; return 0;
} }
@ -249,8 +259,8 @@ sqlitedumpstart(char *file)
"create table epg (" "create table epg ("
"[service_id] integer, [event_id] integer, " "[service_id] integer, [event_id] integer, "
"[start] integer, [end] integer, [duration] integer, " "[start] integer, [end] integer, [duration] integer, "
"[name] text, [text] text, [warning] text, " "[name] text, [text] text, [warning] text, [warning_mode] integer, "
"[content_type] integer, [content] text, " "[content_code] integer, [content_type] text, "
"[event_crid] text, [series_crid] text, [rec_crid] text)" "[event_crid] text, [series_crid] text, [rec_crid] text)"
); );
EXEC("create index tm on epg(start,end)"); EXEC("create index tm on epg(start,end)");
@ -314,33 +324,34 @@ sqlitedump(struct epg *epg __attribute__((unused)),
DECOMPRESS(d->content.d137.warning, d->content.d137.warninglen); DECOMPRESS(d->content.d137.warning, d->content.d137.warninglen);
sqlite3_bind_text(stmt, 8, d->content.d137.warning, -1, NULL); sqlite3_bind_text(stmt, 8, d->content.d137.warning, -1, NULL);
sqlite3_bind_int(stmt, 9, d->content.d137.guidance_mode);
} }
if (ds[PARSER_CONTENT]) if (ds[PARSER_CONTENT])
{ {
sqlite3_bind_int(stmt, 9, sqlite3_bind_int(stmt, 10,
ds[PARSER_CONTENT]->content.d84.level1); ds[PARSER_CONTENT]->content.d84.level1);
sqlite3_bind_text(stmt, 10, content_type(ds[PARSER_CONTENT]), sqlite3_bind_text(stmt, 11, content_type(ds[PARSER_CONTENT]),
-1, NULL); -1, NULL);
} }
if (ds[PARSER_CRID_EVENT]) if (ds[PARSER_CRID_EVENT])
{ {
struct descriptor *d = ds[PARSER_CRID_EVENT]; struct descriptor *d = ds[PARSER_CRID_EVENT];
sqlite3_bind_text(stmt, 11, d->content.d118.crids[0].crid, sqlite3_bind_text(stmt, 12, d->content.d118.crids[0].crid,
-1, NULL); -1, NULL);
} }
if (ds[PARSER_CRID_SERIES]) if (ds[PARSER_CRID_SERIES])
{ {
struct descriptor *d = ds[PARSER_CRID_SERIES]; struct descriptor *d = ds[PARSER_CRID_SERIES];
sqlite3_bind_text(stmt, 12, d->content.d118.crids[0].crid, sqlite3_bind_text(stmt, 13, d->content.d118.crids[0].crid,
-1, NULL); -1, NULL);
} }
if (ds[PARSER_CRID_REC]) if (ds[PARSER_CRID_REC])
{ {
struct descriptor *d = ds[PARSER_CRID_REC]; struct descriptor *d = ds[PARSER_CRID_REC];
sqlite3_bind_text(stmt, 13, d->content.d118.crids[0].crid, sqlite3_bind_text(stmt, 14, d->content.d118.crids[0].crid,
-1, NULL); -1, NULL);
} }
@ -420,12 +431,16 @@ json(struct epg *epg __attribute__((unused)),
printf(",\n \"warning\": \"%s\"", printf(",\n \"warning\": \"%s\"",
json_escape_len(d->content.d137.warninglen, json_escape_len(d->content.d137.warninglen,
d->content.d137.warning)); d->content.d137.warning));
printf(",\n \"guidance_type\": \"%d\"",
d->content.d137.guidance_type);
printf(",\n \"guidance_mode\": \"%d\"",
d->content.d137.guidance_mode);
} }
if (ds[PARSER_CONTENT]) if (ds[PARSER_CONTENT])
{ {
printf(",\n \"content_type\": \"%d\"", printf(",\n \"content_code\": \"%d\"",
ds[PARSER_CONTENT]->content.d84.level1); ds[PARSER_CONTENT]->content.d84.level1);
printf(",\n \"content\": \"%s\"", printf(",\n \"content_type\": \"%s\"",
content_type(ds[PARSER_CONTENT])); content_type(ds[PARSER_CONTENT]));
} }
@ -469,8 +484,9 @@ sqldumpstart()
printf("name varchar(255),\n"); printf("name varchar(255),\n");
printf("text varchar(255),\n"); printf("text varchar(255),\n");
printf("warning varchar(255),\n"); printf("warning varchar(255),\n");
printf("content_type bigint unsigned not null,\n"); printf("guidance_mode tinyint unsigned not null,\n");
printf("content varchar(255),\n"); printf("content_code bigint unsigned not null,\n");
printf("content_type varchar(255),\n");
printf("event_crid varchar(255),\n"); printf("event_crid varchar(255),\n");
printf("series_crid varchar(255),\n"); printf("series_crid varchar(255),\n");
printf("rec_crid varchar(255),\n"); printf("rec_crid varchar(255),\n");
@ -534,12 +550,15 @@ sqldump(struct epg *epg __attribute__((unused)),
printf(",\n warning = '%s'", printf(",\n warning = '%s'",
sql_escape_len(d->content.d137.warninglen, sql_escape_len(d->content.d137.warninglen,
d->content.d137.warning)); d->content.d137.warning));
printf(",\n guidance_mode = '%d'",
d->content.d137.guidance_mode);
} }
if (ds[PARSER_CONTENT]) if (ds[PARSER_CONTENT])
{ {
printf(",\n content_type = %d", printf(",\n content_code = %d",
ds[PARSER_CONTENT]->content.d84.level1); ds[PARSER_CONTENT]->content.d84.level1);
printf(",\n content = '%s'", content_type(ds[PARSER_CONTENT])); printf(",\n content_type = '%s'",
content_type(ds[PARSER_CONTENT]));
} }
if (ds[PARSER_CRID_EVENT]) if (ds[PARSER_CRID_EVENT])
@ -593,7 +612,8 @@ dump(struct epg *epg __attribute__((unused)),
{ {
/* service_id, event_id, start, duration, encrypted, name, text /* service_id, event_id, start, duration, encrypted, name, text
* warning, content code, content type, * warning, content code, content type,
* event CRID, series CRID, rec CRID * event CRID, series CRID, rec CRID,
* guidance mode
*/ */
printf("%d\t%d\t%ld\t%d\t%d\t", printf("%d\t%d\t%ld\t%d\t%d\t",
s->service_id, d->event_id, tm, s->service_id, d->event_id, tm,
@ -656,6 +676,15 @@ dump(struct epg *epg __attribute__((unused)),
else else
printf("\t"); printf("\t");
if (ds[PARSER_USER_DEFINED])
{
struct descriptor *d137 = ds[PARSER_USER_DEFINED];
printf("%d\t", d137->content.d137.guidance_mode);
}
else
printf("\t");
printf("\n"); printf("\n");
return; return;
} }
@ -717,6 +746,10 @@ dump(struct epg *epg __attribute__((unused)),
safeprintf("%30s: %.*s\n", "Warning", safeprintf("%30s: %.*s\n", "Warning",
d137->content.d137.warninglen, d137->content.d137.warning); d137->content.d137.warninglen, d137->content.d137.warning);
printf("%30s: %d\n", "Guidance Type",
d137->content.d137.guidance_type);
printf("%30s: %d\n", "Guidance Mode",
d137->content.d137.guidance_mode);
} }
if (ds[PARSER_CONTENT]) if (ds[PARSER_CONTENT])
@ -920,6 +953,12 @@ main(int argc, char **argv)
add_epgfilter(&filter, FILTER_CONTENT, add_epgfilter(&filter, FILTER_CONTENT,
atoi(cp), 0, NULL, FT_EQUAL); atoi(cp), 0, NULL, FT_EQUAL);
goto nextopt; goto nextopt;
case 'G':
GETOPT;
add_epgfilter(&filter, FILTER_GUIDETYPE,
atoi(cp), 0, NULL, FT_EQUAL);
goto nextopt;
} }
} }
nextopt: nextopt: