Significant updates to the opentv structure.

This commit is contained in:
Adam Sutton 2012-06-26 10:08:29 +01:00
parent 567c7be55f
commit 458d6515c4

View file

@ -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 )