Significant updates to the opentv structure.
This commit is contained in:
parent
567c7be55f
commit
458d6515c4
1 changed files with 238 additions and 176 deletions
|
@ -33,14 +33,20 @@
|
||||||
#include "htsmsg.h"
|
#include "htsmsg.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
|
||||||
|
static epggrab_channel_tree_t _opentv_channels;
|
||||||
|
|
||||||
|
static void _opentv_tune
|
||||||
|
( epggrab_module_t *m, th_dvb_mux_instance_t *tdmi );
|
||||||
|
static int _opentv_enable
|
||||||
|
( epggrab_module_t *m, uint8_t e );
|
||||||
|
|
||||||
/* ************************************************************************
|
/* ************************************************************************
|
||||||
* Configuration
|
* Data structures
|
||||||
* ***********************************************************************/
|
* ***********************************************************************/
|
||||||
|
|
||||||
#define OPENTV_SCAN_MAX 600 // 10min max scan period
|
#define OPENTV_SCAN_MAX 600 // 10min max scan period
|
||||||
#define OPENTV_SCAN_PER 3600 // 1hour interval
|
#define OPENTV_SCAN_PER 3600 // 1hour interval
|
||||||
|
|
||||||
|
|
||||||
/* Data carousel status */
|
/* Data carousel status */
|
||||||
typedef struct opentv_status
|
typedef struct opentv_status
|
||||||
{
|
{
|
||||||
|
@ -61,13 +67,12 @@ typedef struct opentv_dict
|
||||||
huffman_node_t *codes;
|
huffman_node_t *codes;
|
||||||
RB_ENTRY(opentv_dict) h_link;
|
RB_ENTRY(opentv_dict) h_link;
|
||||||
} opentv_dict_t;
|
} opentv_dict_t;
|
||||||
|
int begbat;
|
||||||
|
|
||||||
/* Provider configuration */
|
/* Provider configuration */
|
||||||
typedef struct opentv_prov
|
typedef struct opentv_module_t
|
||||||
{
|
{
|
||||||
char *id;
|
epggrab_module_t ; ///< Base struct
|
||||||
char *name;
|
|
||||||
RB_ENTRY(opentv_prov) h_link;
|
|
||||||
|
|
||||||
int nid;
|
int nid;
|
||||||
int tsid;
|
int tsid;
|
||||||
|
@ -76,37 +81,23 @@ typedef struct opentv_prov
|
||||||
int *title;
|
int *title;
|
||||||
int *summary;
|
int *summary;
|
||||||
opentv_dict_t *dict;
|
opentv_dict_t *dict;
|
||||||
} opentv_prov_t;
|
|
||||||
|
|
||||||
/* Extension of epggrab module to include linked provider */
|
int endbat;
|
||||||
typedef struct opentv_module
|
int begbat;
|
||||||
{
|
LIST_HEAD(, opentv_status) status;
|
||||||
epggrab_module_t ; ///< Base struct
|
|
||||||
opentv_prov_t *prov; ///< Associated provider config
|
|
||||||
pthread_mutex_t mutex;
|
|
||||||
pthread_cond_t cond;
|
|
||||||
time_t updated;
|
|
||||||
LIST_HEAD(,opentv_status) status;
|
|
||||||
} opentv_module_t;
|
} opentv_module_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lists/Comparators
|
* Dictionary list
|
||||||
*/
|
*/
|
||||||
RB_HEAD(opentv_dict_tree, opentv_dict);
|
RB_HEAD(, opentv_dict) _opentv_dicts;
|
||||||
RB_HEAD(opentv_prov_tree, opentv_prov);
|
|
||||||
struct opentv_dict_tree _opentv_dicts;
|
|
||||||
struct opentv_prov_tree _opentv_provs;
|
|
||||||
|
|
||||||
static int _dict_cmp ( void *a, void *b )
|
static int _dict_cmp ( void *a, void *b )
|
||||||
{
|
{
|
||||||
return strcmp(((opentv_dict_t*)a)->id, ((opentv_dict_t*)b)->id);
|
return strcmp(((opentv_dict_t*)a)->id, ((opentv_dict_t*)b)->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _prov_cmp ( void *a, void *b )
|
|
||||||
{
|
|
||||||
return strcmp(((opentv_prov_t*)a)->id, ((opentv_prov_t*)b)->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static opentv_dict_t *_opentv_dict_find ( const char *id )
|
static opentv_dict_t *_opentv_dict_find ( const char *id )
|
||||||
{
|
{
|
||||||
opentv_dict_t skel;
|
opentv_dict_t skel;
|
||||||
|
@ -114,11 +105,28 @@ static opentv_dict_t *_opentv_dict_find ( const char *id )
|
||||||
return RB_FIND(&_opentv_dicts, &skel, h_link, _dict_cmp);
|
return RB_FIND(&_opentv_dicts, &skel, h_link, _dict_cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* ************************************************************************
|
||||||
* Configuration loading
|
* Module functions
|
||||||
*/
|
* ***********************************************************************/
|
||||||
|
|
||||||
static int* _pid_list_to_array ( htsmsg_t *m )
|
static opentv_status_t *_opentv_module_get_status
|
||||||
|
( opentv_module_t *mod, int pid )
|
||||||
|
{
|
||||||
|
opentv_status_t *sta;
|
||||||
|
LIST_FOREACH(sta, &mod->status, link)
|
||||||
|
if (sta->pid == pid) break;
|
||||||
|
if (!sta) {
|
||||||
|
sta = calloc(1, sizeof(opentv_status_t));
|
||||||
|
LIST_INSERT_HEAD(&mod->status, sta, link);
|
||||||
|
}
|
||||||
|
return sta;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************
|
||||||
|
* Configuration loading
|
||||||
|
* ***********************************************************************/
|
||||||
|
|
||||||
|
static int* _pid_list_to_array ( htsmsg_t *m, opentv_module_t *mod )
|
||||||
{
|
{
|
||||||
int i = 1;
|
int i = 1;
|
||||||
int *ret;
|
int *ret;
|
||||||
|
@ -128,17 +136,19 @@ static int* _pid_list_to_array ( htsmsg_t *m )
|
||||||
ret = calloc(i, sizeof(int));
|
ret = calloc(i, sizeof(int));
|
||||||
i = 0;
|
i = 0;
|
||||||
HTSMSG_FOREACH(f, m)
|
HTSMSG_FOREACH(f, m)
|
||||||
if (f->hmf_s64)
|
if (f->hmf_s64) {
|
||||||
|
if (mod) (void)_opentv_module_get_status(mod, ret[i]);
|
||||||
ret[i++] = (int)f->hmf_s64;
|
ret[i++] = (int)f->hmf_s64;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _opentv_dict_load ( const char *id, htsmsg_t *m )
|
static int _opentv_dict_load_one ( const char *id, htsmsg_t *m )
|
||||||
{
|
{
|
||||||
opentv_dict_t *dict = calloc(1, sizeof(opentv_dict_t));
|
opentv_dict_t *dict = calloc(1, sizeof(opentv_dict_t));
|
||||||
dict->id = (char*)id;
|
dict->id = (char*)id;
|
||||||
if (RB_INSERT_SORTED(&_opentv_dicts, dict, h_link, _dict_cmp)) {
|
if (RB_INSERT_SORTED(&_opentv_dicts, dict, h_link, _dict_cmp)) {
|
||||||
tvhlog(LOG_WARNING, "opentv", "ignore duplicate dictionary %s", id);
|
tvhlog(LOG_DEBUG, "opentv", "ignore duplicate dictionary %s", id);
|
||||||
free(dict);
|
free(dict);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -154,43 +164,88 @@ static int _opentv_dict_load ( const char *id, htsmsg_t *m )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _opentv_prov_load ( const char *id, htsmsg_t *m )
|
static void _opentv_dict_load ( htsmsg_t *m )
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
|
htsmsg_t *e;
|
||||||
|
htsmsg_field_t *f;
|
||||||
|
HTSMSG_FOREACH(f, m) {
|
||||||
|
if ((e = htsmsg_get_list(m, f->hmf_name))) {
|
||||||
|
if ((r = _opentv_dict_load_one(f->hmf_name, e))) {
|
||||||
|
if (r > 0)
|
||||||
|
tvhlog(LOG_INFO, "opentv", "dictionary %s loaded", f->hmf_name);
|
||||||
|
else
|
||||||
|
tvhlog(LOG_WARNING, "opentv", "dictionary %s failed", f->hmf_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
htsmsg_destroy(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _opentv_prov_load_one
|
||||||
|
( const char *id, htsmsg_t *m, epggrab_module_list_t *list )
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
htsmsg_t *cl, *tl, *sl;
|
htsmsg_t *cl, *tl, *sl;
|
||||||
uint32_t tsid, sid, nid;
|
uint32_t tsid, sid, nid;
|
||||||
const char *str, *name;
|
const char *str, *name;
|
||||||
opentv_dict_t *dict;
|
opentv_dict_t *dict;
|
||||||
opentv_prov_t *prov;
|
static opentv_module_t *mod = NULL;
|
||||||
|
|
||||||
/* Check config */
|
/* Check config */
|
||||||
if (!(name = htsmsg_get_str(m, "name"))) return -1;
|
if (!(name = htsmsg_get_str(m, "name"))) return -1;
|
||||||
if (!(str = htsmsg_get_str(m, "dict"))) return -1;
|
if (!(str = htsmsg_get_str(m, "dict"))) return -1;
|
||||||
if (!(dict = _opentv_dict_find(str))) return -1;
|
if (!(dict = _opentv_dict_find(str))) return -1;
|
||||||
if (!(cl = htsmsg_get_list(m, "channel"))) return -1;
|
if (!(cl = htsmsg_get_list(m, "channel"))) return -1;
|
||||||
if (!(tl = htsmsg_get_list(m, "title"))) return -5;
|
if (!(tl = htsmsg_get_list(m, "title"))) return -1;
|
||||||
if (!(sl = htsmsg_get_list(m, "summary"))) return -1;
|
if (!(sl = htsmsg_get_list(m, "summary"))) return -1;
|
||||||
if (htsmsg_get_u32(m, "nid", &nid)) return -1;
|
if (htsmsg_get_u32(m, "nid", &nid)) return -1;
|
||||||
if (htsmsg_get_u32(m, "tsid", &tsid)) return -1;
|
if (htsmsg_get_u32(m, "tsid", &tsid)) return -1;
|
||||||
if (htsmsg_get_u32(m, "sid", &sid)) return -1;
|
if (htsmsg_get_u32(m, "sid", &sid)) return -1;
|
||||||
|
|
||||||
prov = calloc(1, sizeof(opentv_prov_t));
|
/* Exists */
|
||||||
prov->id = (char*)id;
|
sprintf(buf, "opentv-%s", id);
|
||||||
if (RB_INSERT_SORTED(&_opentv_provs, prov, h_link, _prov_cmp)) {
|
if (epggrab_module_find_by_id(buf)) return 0;
|
||||||
tvhlog(LOG_WARNING, "opentv", "ignore duplicate provider %s", id);
|
|
||||||
free(prov);
|
/* Create module */
|
||||||
return 0;
|
mod = calloc(1, sizeof(opentv_module_t));
|
||||||
} else {
|
mod->id = strdup(buf);
|
||||||
prov->id = strdup(id);
|
sprintf(buf, "OpenTV: %s", name);
|
||||||
prov->name = strdup(name);
|
mod->name = strdup(buf);
|
||||||
prov->dict = dict;
|
mod->enable = _opentv_enable;
|
||||||
prov->nid = nid;
|
mod->tune = _opentv_tune;
|
||||||
prov->tsid = tsid;
|
mod->channels = &_opentv_channels;
|
||||||
prov->sid = sid;
|
*((uint8_t*)&mod->flags) = EPGGRAB_MODULE_OTA;
|
||||||
prov->channel = _pid_list_to_array(cl);
|
LIST_INSERT_HEAD(list, ((epggrab_module_t*)mod), link);
|
||||||
prov->title = _pid_list_to_array(tl);
|
|
||||||
prov->summary = _pid_list_to_array(sl);
|
/* Add provider details */
|
||||||
|
mod->dict = dict;
|
||||||
|
mod->nid = nid;
|
||||||
|
mod->tsid = tsid;
|
||||||
|
mod->sid = sid;
|
||||||
|
mod->channel = _pid_list_to_array(cl, NULL);
|
||||||
|
mod->title = _pid_list_to_array(tl, mod);
|
||||||
|
mod->summary = _pid_list_to_array(sl, mod);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _opentv_prov_load ( htsmsg_t *m, epggrab_module_list_t *list )
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
htsmsg_t *e;
|
||||||
|
htsmsg_field_t *f;
|
||||||
|
HTSMSG_FOREACH(f, m) {
|
||||||
|
if ((e = htsmsg_get_map_by_field(f))) {
|
||||||
|
if ((r = _opentv_prov_load_one(f->hmf_name, e, list))) {
|
||||||
|
if (r > 0)
|
||||||
|
tvhlog(LOG_INFO, "opentv", "provider %s loaded", f->hmf_name);
|
||||||
|
else
|
||||||
|
tvhlog(LOG_WARNING, "opentv", "provider %s failed", f->hmf_name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
htsmsg_destroy(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************
|
/* ************************************************************************
|
||||||
|
@ -201,7 +256,7 @@ static epggrab_channel_t *_opentv_find_epggrab_channel
|
||||||
( opentv_module_t *mod, int cid, int create, int *save )
|
( opentv_module_t *mod, int cid, int create, int *save )
|
||||||
{
|
{
|
||||||
char chid[32];
|
char chid[32];
|
||||||
sprintf(chid, "%s-%d", mod->prov->id, cid);
|
sprintf(chid, "%s-%d", mod->id, cid);
|
||||||
return epggrab_module_channel_find((epggrab_module_t*)mod, chid, create, save);
|
return epggrab_module_channel_find((epggrab_module_t*)mod, chid, create, save);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +265,7 @@ static epg_season_t *_opentv_find_season
|
||||||
{
|
{
|
||||||
int save = 0;
|
int save = 0;
|
||||||
char uri[64];
|
char uri[64];
|
||||||
sprintf(uri, "%s-%d-%d", mod->prov->id, cid, slink);
|
sprintf(uri, "%s-%d-%d", mod->id, cid, slink);
|
||||||
return epg_season_find_by_uri(uri, 1, &save);
|
return epg_season_find_by_uri(uri, 1, &save);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +334,7 @@ static int _ev_cmp ( void *_a, void *_b )
|
||||||
|
|
||||||
/* Parse huffman encoded string */
|
/* Parse huffman encoded string */
|
||||||
static char *_opentv_parse_string
|
static char *_opentv_parse_string
|
||||||
( opentv_prov_t *prov, uint8_t *buf, int len )
|
( opentv_module_t *prov, uint8_t *buf, int len )
|
||||||
{
|
{
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
char *ret, *tmp;
|
char *ret, *tmp;
|
||||||
|
@ -307,7 +362,7 @@ static char *_opentv_parse_string
|
||||||
|
|
||||||
/* Parse a specific record */
|
/* Parse a specific record */
|
||||||
static int _opentv_parse_event_record
|
static int _opentv_parse_event_record
|
||||||
( opentv_prov_t *prov, opentv_event_t *ev, uint8_t *buf, int len, time_t mjd )
|
( opentv_module_t *prov, opentv_event_t *ev, uint8_t *buf, int len, time_t mjd )
|
||||||
{
|
{
|
||||||
uint8_t rtag = buf[0];
|
uint8_t rtag = buf[0];
|
||||||
uint8_t rlen = buf[1];
|
uint8_t rlen = buf[1];
|
||||||
|
@ -342,7 +397,7 @@ static int _opentv_parse_event_record
|
||||||
|
|
||||||
/* Parse a specific event */
|
/* Parse a specific event */
|
||||||
static int _opentv_parse_event
|
static int _opentv_parse_event
|
||||||
( opentv_prov_t *prov, uint8_t *buf, int len, int cid, time_t mjd,
|
( opentv_module_t *prov, uint8_t *buf, int len, int cid, time_t mjd,
|
||||||
opentv_event_t **ev )
|
opentv_event_t **ev )
|
||||||
{
|
{
|
||||||
static opentv_event_t *skel = NULL;
|
static opentv_event_t *skel = NULL;
|
||||||
|
@ -394,7 +449,7 @@ static int _opentv_parse_event_section
|
||||||
/* Loop around event entries */
|
/* Loop around event entries */
|
||||||
i = 7;
|
i = 7;
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
i += _opentv_parse_event(mod->prov, buf+i, len-i, cid, mjd, &ev);
|
i += _opentv_parse_event(mod, buf+i, len-i, cid, mjd, &ev);
|
||||||
|
|
||||||
/* Error */
|
/* Error */
|
||||||
if (!ev) continue;
|
if (!ev) continue;
|
||||||
|
@ -453,57 +508,95 @@ static int _opentv_parse_event_section
|
||||||
* OpenTV channel processing
|
* OpenTV channel processing
|
||||||
* ***********************************************************************/
|
* ***********************************************************************/
|
||||||
|
|
||||||
// TODO: bouqets are ignored, what useful info can we get from them?
|
static void _opentv_parse_sky_channels
|
||||||
static int _opentv_bat_section
|
( opentv_module_t *mod, uint8_t *buf, int len, uint16_t tsid )
|
||||||
( opentv_module_t *mod, uint8_t *buf, int len )
|
|
||||||
{
|
{
|
||||||
epggrab_channel_t *ec;
|
epggrab_channel_t *ec;
|
||||||
int tsid, cid;//, cnum;
|
|
||||||
uint16_t sid;
|
|
||||||
int i, j, k, tdlen, dlen, dtag, tslen;
|
|
||||||
channel_t *ch;
|
channel_t *ch;
|
||||||
i = 7 + ((((int)buf[5] & 0xf) << 8) | buf[6]);
|
int sid, cid;//, cnum;
|
||||||
tslen = (((int)buf[i] & 0xf) << 8) | buf[i+1];
|
int save = 0;
|
||||||
i += 2;
|
int i = 2;
|
||||||
while (tslen > 0) {
|
while (i < len) {
|
||||||
tsid = ((int)buf[i] << 8) | buf[i+1];
|
sid = ((int)buf[i] << 8) | buf[i+1];
|
||||||
//nid = ((int)buf[i+2] << 8) | buf[i+3];
|
cid = ((int)buf[i+3] << 8) | buf[i+4];
|
||||||
tdlen = (((int)buf[i+4] & 0xf) << 8) | buf[i+5];
|
//cnum = ((int)buf[i+5] << 8) | buf[i+6];
|
||||||
j = i + 6;
|
|
||||||
i += (tdlen + 6);
|
|
||||||
tslen -= (tdlen + 6);
|
|
||||||
while (tdlen > 0) {
|
|
||||||
dtag = buf[j];
|
|
||||||
dlen = buf[j+1];
|
|
||||||
k = j + 2;
|
|
||||||
j += (dlen + 2);
|
|
||||||
tdlen -= (dlen + 2);
|
|
||||||
if (dtag == 0xb1) {
|
|
||||||
k += 2;
|
|
||||||
dlen -= 2;
|
|
||||||
while (dlen > 0) {
|
|
||||||
sid = ((int)buf[k] << 8) | buf[k+1];
|
|
||||||
cid = ((int)buf[k+3] << 8) | buf[k+4];
|
|
||||||
//cnum = ((int)buf[k+5] << 8) | buf[k+6];
|
|
||||||
|
|
||||||
/* Find the channel */
|
/* Find the channel */
|
||||||
ch = _opentv_find_channel(tsid, sid);
|
if ((ch = _opentv_find_channel(tsid, sid))) {
|
||||||
if (ch) {
|
|
||||||
int save = 0;
|
|
||||||
ec = _opentv_find_epggrab_channel(mod, cid, 1, &save);
|
ec = _opentv_find_epggrab_channel(mod, cid, 1, &save);
|
||||||
if (save) {
|
if (save) {
|
||||||
// Note: could use set_sid() but not nec.
|
|
||||||
ec->channel = ch;
|
ec->channel = ch;
|
||||||
//TODO: must be configurable
|
//TODO: must be configurable
|
||||||
//epggrab_channel_set_number(ec, cnum);
|
//epggrab_channel_set_number(ec, cnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
k += 9;
|
i += 9;
|
||||||
dlen -= 9;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _opentv_parse_ts_desc
|
||||||
|
( opentv_module_t *mod, uint8_t *buf, int len, uint16_t tsid )
|
||||||
|
{
|
||||||
|
int dtag = buf[0];
|
||||||
|
int dlen = buf[1];
|
||||||
|
if (dlen+2 > len) return -1;
|
||||||
|
if (dtag == 0xb1)
|
||||||
|
_opentv_parse_sky_channels(mod, buf+2, dlen, tsid);
|
||||||
|
return dlen + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _opentv_bat_section
|
||||||
|
( opentv_module_t *mod, uint8_t *buf, int len )
|
||||||
|
{
|
||||||
|
int i, r;
|
||||||
|
int bdlen, tllen, tdlen;
|
||||||
|
uint16_t bid, tsid;
|
||||||
|
uint8_t sec;
|
||||||
|
|
||||||
|
/* Skip (not yet applicable) */
|
||||||
|
if (!(buf[2] & 0x1)) return 0;
|
||||||
|
bid = buf[0] << 8 | buf[1];
|
||||||
|
//ver = (buf[2] >> 1) & 0x1f;
|
||||||
|
sec = buf[3];
|
||||||
|
//lst = buf[4];
|
||||||
|
|
||||||
|
/* Check for finish */
|
||||||
|
i = 0x80000000 | (bid << 8) | sec;
|
||||||
|
if (!mod->begbat) {
|
||||||
|
mod->begbat = i;
|
||||||
|
} else if (mod->begbat == i) {
|
||||||
|
mod->endbat = 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Skip (ignore bouquet info for now) */
|
||||||
|
bdlen = ((int)buf[5] & 0xf << 8) | buf[6];
|
||||||
|
buf += (7 + bdlen);
|
||||||
|
len -= (7 + bdlen);
|
||||||
|
if (bdlen > len) return -1;
|
||||||
|
|
||||||
|
/* TS descriptors */
|
||||||
|
tllen = ((int)buf[0] << 8) | buf[1];
|
||||||
|
buf += 2;
|
||||||
|
len -= 2;
|
||||||
|
if (tllen > len) return -1;
|
||||||
|
while (len > 0) {
|
||||||
|
tsid = ((int)buf[0] << 8) | buf[1];
|
||||||
|
//nid = ((int)buf[2] << 8) | buf[3];
|
||||||
|
tdlen = ((int)buf[4] & 0xf) << 8 | buf[5];
|
||||||
|
buf += 6;
|
||||||
|
len -= 6;
|
||||||
|
if (tdlen > len) return -1;
|
||||||
|
i = 0;
|
||||||
|
while (i < tdlen) {
|
||||||
|
r = _opentv_parse_ts_desc(mod, buf+i, tdlen-i, tsid);
|
||||||
|
if (r < 0) return -1;
|
||||||
|
i += r;
|
||||||
}
|
}
|
||||||
|
buf += tdlen;
|
||||||
|
len -= tdlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,18 +624,10 @@ static opentv_module_t *_opentv_table_callback
|
||||||
if (epggrab_ota_is_complete(ota)) return NULL;
|
if (epggrab_ota_is_complete(ota)) return NULL;
|
||||||
|
|
||||||
/* Begin */
|
/* Begin */
|
||||||
if (epggrab_ota_begin(ota)) {
|
epggrab_ota_begin(ota);
|
||||||
LIST_FOREACH(sta, &mod->status, link)
|
|
||||||
sta->status = OPENTV_STA_INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Insert */
|
/* Insert/Find */
|
||||||
LIST_FOREACH(sta, &mod->status, link)
|
sta = _opentv_module_get_status(mod, tdt->tdt_pid);
|
||||||
if (sta->pid == tdt->tdt_pid) break;
|
|
||||||
if (!sta) {
|
|
||||||
sta = calloc(1, sizeof(opentv_status_t));
|
|
||||||
LIST_INSERT_HEAD(&mod->status, sta, link);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set init */
|
/* Set init */
|
||||||
if (!sta->status) {
|
if (!sta->status) {
|
||||||
|
@ -551,7 +636,8 @@ static opentv_module_t *_opentv_table_callback
|
||||||
return mod;
|
return mod;
|
||||||
|
|
||||||
/* Complete */
|
/* Complete */
|
||||||
} else if (sta->status == 1 && !memcmp(sta->start, buf, 20)) {
|
} else if (sta->status == OPENTV_STA_STARTED &&
|
||||||
|
!memcmp(sta->start, buf, 20)) {
|
||||||
sta->status = OPENTV_STA_COMPLETE;
|
sta->status = OPENTV_STA_COMPLETE;
|
||||||
|
|
||||||
/* Check rest */
|
/* Check rest */
|
||||||
|
@ -586,8 +672,8 @@ static int _opentv_summary_callback
|
||||||
static int _opentv_channel_callback
|
static int _opentv_channel_callback
|
||||||
( th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, uint8_t tid, void *p )
|
( th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, uint8_t tid, void *p )
|
||||||
{
|
{
|
||||||
opentv_module_t *mod = _opentv_table_callback(tdmi, buf, len, tid, p);
|
opentv_module_t *mod = (opentv_module_t*)p;
|
||||||
if (mod)
|
if (!mod->endbat)
|
||||||
return _opentv_bat_section(mod, buf, len);
|
return _opentv_bat_section(mod, buf, len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -596,31 +682,31 @@ static int _opentv_channel_callback
|
||||||
* Module Setup
|
* Module Setup
|
||||||
* ***********************************************************************/
|
* ***********************************************************************/
|
||||||
|
|
||||||
static epggrab_channel_tree_t _opentv_channels;
|
|
||||||
|
|
||||||
static void _opentv_tune ( epggrab_module_t *m, th_dvb_mux_instance_t *tdmi )
|
static void _opentv_tune ( epggrab_module_t *m, th_dvb_mux_instance_t *tdmi )
|
||||||
{
|
{
|
||||||
int *t;
|
int *t;
|
||||||
struct dmx_sct_filter_params *fp;
|
struct dmx_sct_filter_params *fp;
|
||||||
opentv_module_t *mod = (opentv_module_t*)m;
|
opentv_module_t *mod = (opentv_module_t*)m;
|
||||||
|
opentv_event_t *ev;
|
||||||
|
opentv_status_t *sta;
|
||||||
|
|
||||||
/* Install tables */
|
/* Install tables */
|
||||||
if (m->enabled && (mod->prov->tsid == tdmi->tdmi_transport_stream_id)) {
|
if (m->enabled && (mod->tsid == tdmi->tdmi_transport_stream_id)) {
|
||||||
tvhlog(LOG_INFO, "opentv", "install provider %s tables", mod->prov->id);
|
tvhlog(LOG_INFO, "opentv", "install provider %s tables", mod->id);
|
||||||
|
|
||||||
/* Channels */
|
/* Channels */
|
||||||
t = mod->prov->channel;
|
t = mod->channel;
|
||||||
while (*t) {
|
while (*t) {
|
||||||
fp = dvb_fparams_alloc();
|
fp = dvb_fparams_alloc();
|
||||||
fp->filter.filter[0] = 0x4a;
|
fp->filter.filter[0] = 0x4a;
|
||||||
fp->filter.mask[0] = 0xff;
|
fp->filter.mask[0] = 0xff;
|
||||||
// TODO: what about 0x46 (service description)
|
// TODO: what about 0x46 (service description)
|
||||||
tdt_add(tdmi, fp, _opentv_channel_callback, mod,
|
tdt_add(tdmi, fp, _opentv_channel_callback, mod,
|
||||||
m->id, TDT_CRC | TDT_TDT, *t++, NULL);
|
m->id, TDT_CRC, *t++, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Titles */
|
/* Titles */
|
||||||
t = mod->prov->title;
|
t = mod->title;
|
||||||
while (*t) {
|
while (*t) {
|
||||||
fp = dvb_fparams_alloc();
|
fp = dvb_fparams_alloc();
|
||||||
fp->filter.filter[0] = 0xa0;
|
fp->filter.filter[0] = 0xa0;
|
||||||
|
@ -630,7 +716,7 @@ static void _opentv_tune ( epggrab_module_t *m, th_dvb_mux_instance_t *tdmi )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Summaries */
|
/* Summaries */
|
||||||
t = mod->prov->summary;
|
t = mod->summary;
|
||||||
while (*t) {
|
while (*t) {
|
||||||
fp = dvb_fparams_alloc();
|
fp = dvb_fparams_alloc();
|
||||||
fp->filter.filter[0] = 0xa8;
|
fp->filter.filter[0] = 0xa8;
|
||||||
|
@ -638,6 +724,19 @@ static void _opentv_tune ( epggrab_module_t *m, th_dvb_mux_instance_t *tdmi )
|
||||||
tdt_add(tdmi, fp, _opentv_summary_callback, mod,
|
tdt_add(tdmi, fp, _opentv_summary_callback, mod,
|
||||||
m->id, TDT_CRC | TDT_TDT, *t++, NULL);
|
m->id, TDT_CRC | TDT_TDT, *t++, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clear status (new search) */
|
||||||
|
// TODO: not sure about this!
|
||||||
|
mod->begbat = mod->endbat = 0;
|
||||||
|
LIST_FOREACH(sta, &mod->status, link)
|
||||||
|
sta->status = OPENTV_STA_INIT;
|
||||||
|
while((ev = RB_FIRST(&_opentv_events))) {
|
||||||
|
RB_REMOVE(&_opentv_events, ev, ev_link);
|
||||||
|
if (ev->title) free(ev->title);
|
||||||
|
if (ev->desc) free(ev->desc);
|
||||||
|
if (ev->summary) free(ev->summary);
|
||||||
|
free(ev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,7 +753,7 @@ static int _opentv_enable ( epggrab_module_t *m, uint8_t e )
|
||||||
/* Find muxes and enable/disable */
|
/* Find muxes and enable/disable */
|
||||||
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) {
|
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) {
|
||||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||||
if (tdmi->tdmi_transport_stream_id != mod->prov->tsid) continue;
|
if (tdmi->tdmi_transport_stream_id != mod->tsid) continue;
|
||||||
if (e) {
|
if (e) {
|
||||||
epggrab_ota_register(m, tdmi, OPENTV_SCAN_MAX, OPENTV_SCAN_PER);
|
epggrab_ota_register(m, tdmi, OPENTV_SCAN_MAX, OPENTV_SCAN_PER);
|
||||||
} else {
|
} else {
|
||||||
|
@ -668,59 +767,22 @@ static int _opentv_enable ( epggrab_module_t *m, uint8_t e )
|
||||||
|
|
||||||
void opentv_init ( epggrab_module_list_t *list )
|
void opentv_init ( epggrab_module_list_t *list )
|
||||||
{
|
{
|
||||||
int r;
|
htsmsg_t *m;
|
||||||
htsmsg_t *m, *e;
|
const char *dr = tvheadend_dataroot();
|
||||||
htsmsg_field_t *f;
|
|
||||||
opentv_prov_t *p;
|
|
||||||
opentv_module_t *mod;
|
|
||||||
char buf[100];
|
|
||||||
|
|
||||||
/* Load the dictionaries */
|
/* Load dictionaries */
|
||||||
if ((m = hts_settings_load("epggrab/opentv/dict"))) {
|
if ((m = hts_settings_load("epggrab/opentv/dict")))
|
||||||
HTSMSG_FOREACH(f, m) {
|
_opentv_dict_load(m);
|
||||||
if ((e = htsmsg_get_list(m, f->hmf_name))) {
|
if ((m = hts_settings_load("%s/data/epggrab/opentv/dict", dr)))
|
||||||
if ((r = _opentv_dict_load(f->hmf_name, e))) {
|
_opentv_dict_load(m);
|
||||||
if (r > 0)
|
|
||||||
tvhlog(LOG_INFO, "opentv", "dictionary %s loaded", f->hmf_name);
|
|
||||||
else
|
|
||||||
tvhlog(LOG_WARNING, "opentv", "dictionary %s failed", f->hmf_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
htsmsg_destroy(m);
|
|
||||||
}
|
|
||||||
tvhlog(LOG_INFO, "opentv", "dictonaries loaded");
|
tvhlog(LOG_INFO, "opentv", "dictonaries loaded");
|
||||||
|
|
||||||
/* Load providers */
|
/* Load providers */
|
||||||
if ((m = hts_settings_load("epggrab/opentv/prov"))) {
|
if ((m = hts_settings_load("epggrab/opentv/prov")))
|
||||||
HTSMSG_FOREACH(f, m) {
|
_opentv_prov_load(m, list);
|
||||||
if ((e = htsmsg_get_map_by_field(f))) {
|
if ((m = hts_settings_load("%s/data/epggrab/opentv/prov", dr)))
|
||||||
if ((r = _opentv_prov_load(f->hmf_name, e))) {
|
_opentv_prov_load(m, list);
|
||||||
if (r > 0)
|
|
||||||
tvhlog(LOG_INFO, "opentv", "provider %s loaded", f->hmf_name);
|
|
||||||
else
|
|
||||||
tvhlog(LOG_WARNING, "opentv", "provider %s failed", f->hmf_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
htsmsg_destroy(m);
|
|
||||||
}
|
|
||||||
tvhlog(LOG_INFO, "opentv", "providers loaded");
|
tvhlog(LOG_INFO, "opentv", "providers loaded");
|
||||||
|
|
||||||
/* Create modules */
|
|
||||||
RB_FOREACH(p, &_opentv_provs, h_link) {
|
|
||||||
mod = calloc(1, sizeof(opentv_module_t));
|
|
||||||
sprintf(buf, "opentv-%s", p->id);
|
|
||||||
mod->id = strdup(buf);
|
|
||||||
sprintf(buf, "OpenTV: %s", p->name);
|
|
||||||
mod->name = strdup(buf);
|
|
||||||
mod->enable = _opentv_enable;
|
|
||||||
mod->tune = _opentv_tune;
|
|
||||||
mod->channels = &_opentv_channels;
|
|
||||||
mod->prov = p;
|
|
||||||
*((uint8_t*)&mod->flags) = EPGGRAB_MODULE_OTA;
|
|
||||||
LIST_INSERT_HEAD(list, ((epggrab_module_t*)mod), link);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void opentv_load ( void )
|
void opentv_load ( void )
|
||||||
|
|
Loading…
Add table
Reference in a new issue