properly handle guidance, fix sql field names
This commit is contained in:
parent
fba5a52e92
commit
26f0a4cf64
38
descriptor.c
38
descriptor.c
|
@ -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;
|
||||||
|
|
||||||
|
|
12
descriptor.h
12
descriptor.h
|
@ -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
7
epg.c
|
@ -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
3
epg.h
|
@ -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
75
main.c
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue