Started to clean up opentv module, added some configuration (though currently its mostly ALL enabled).
This commit is contained in:
parent
2b86b25c89
commit
851f786a50
2 changed files with 287 additions and 14 deletions
|
@ -19,6 +19,7 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/dvb/dmx.h>
|
||||
#include "tvheadend.h"
|
||||
#include "dvb/dvb.h"
|
||||
#include "channels.h"
|
||||
|
@ -27,27 +28,256 @@
|
|||
#include "epggrab/opentv.h"
|
||||
#include "subscriptions.h"
|
||||
#include "service.h"
|
||||
#include "htsmsg.h"
|
||||
#include "settings.h"
|
||||
|
||||
/* ************************************************************************
|
||||
* Configuration
|
||||
*
|
||||
* TODO: I think much of this may be moved to a generic lib, as some of
|
||||
* the other OTA EPGs will have similar config reqs
|
||||
* ***********************************************************************/
|
||||
|
||||
typedef struct opentv_dict
|
||||
{
|
||||
char *key;
|
||||
huffman_node_t *codes;
|
||||
RB_ENTRY(opentv_dict) h_link;
|
||||
} opentv_dict_t;
|
||||
|
||||
typedef struct opentv_prov
|
||||
{
|
||||
char *key;
|
||||
RB_ENTRY(opentv_prov) h_link;
|
||||
int enabled;
|
||||
|
||||
int tsid;
|
||||
int sid;
|
||||
int *channel;
|
||||
int *title;
|
||||
int *summary;
|
||||
opentv_dict_t *dict;
|
||||
} opentv_prov_t;
|
||||
|
||||
RB_HEAD(opentv_dict_tree, opentv_dict);
|
||||
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 )
|
||||
{
|
||||
return strcmp(((opentv_dict_t*)a)->key, ((opentv_dict_t*)b)->key);
|
||||
}
|
||||
|
||||
static int _prov_cmp ( void *a, void *b )
|
||||
{
|
||||
return strcmp(((opentv_prov_t*)a)->key, ((opentv_prov_t*)b)->key);
|
||||
}
|
||||
|
||||
static int* _pid_list_to_array ( htsmsg_t *m )
|
||||
{
|
||||
int i = 1;
|
||||
int *ret;
|
||||
htsmsg_field_t *f;
|
||||
HTSMSG_FOREACH(f, m)
|
||||
if (f->hmf_s64) i++;
|
||||
ret = calloc(i, sizeof(int));
|
||||
i = 0;
|
||||
HTSMSG_FOREACH(f, m)
|
||||
if (f->hmf_s64)
|
||||
ret[i++] = (int)f->hmf_s64;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static opentv_dict_t *_opentv_dict_find ( const char *key )
|
||||
{
|
||||
opentv_dict_t skel;
|
||||
skel.key = (char*)key;
|
||||
return RB_FIND(&_opentv_dicts, &skel, h_link, _dict_cmp);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static opentv_prov_t *_opentv_prov_find ( const char *key )
|
||||
{
|
||||
opentv_prov_t skel;
|
||||
skel.key = (char*)key;
|
||||
return RB_FIND(&_opentv_provs, &skel, h_link, _prov_cmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _opentv_dict_load ( const char *key, htsmsg_t *m )
|
||||
{
|
||||
opentv_dict_t *dict = calloc(1, sizeof(opentv_dict_t));
|
||||
dict->key = (char*)key;
|
||||
if (RB_INSERT_SORTED(&_opentv_dicts, dict, h_link, _dict_cmp)) {
|
||||
tvhlog(LOG_WARNING, "opentv", "ignore duplicate dictionary %s", key);
|
||||
free(dict);
|
||||
return 0;
|
||||
} else {
|
||||
dict->codes = huffman_tree_build(m);
|
||||
if (!dict->codes) {
|
||||
RB_REMOVE(&_opentv_dicts, dict, h_link);
|
||||
free(dict);
|
||||
return -1;
|
||||
} else {
|
||||
dict->key = strdup(key);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int _opentv_prov_load ( const char *key, htsmsg_t *m )
|
||||
{
|
||||
htsmsg_t *cl, *tl, *sl;
|
||||
uint32_t tsid, sid;
|
||||
const char *str;
|
||||
opentv_dict_t *dict;
|
||||
opentv_prov_t *prov;
|
||||
|
||||
/* Check config */
|
||||
if (!(str = htsmsg_get_str(m, "dict"))) return -1;
|
||||
if (!(dict = _opentv_dict_find(str))) return -1;
|
||||
if (!(cl = htsmsg_get_list(m, "channel"))) return -1;
|
||||
if (!(tl = htsmsg_get_list(m, "title"))) return -1;
|
||||
if (!(sl = htsmsg_get_list(m, "summary"))) return -1;
|
||||
if (htsmsg_get_u32(m, "tsid", &tsid)) return -1;
|
||||
if (htsmsg_get_u32(m, "sid", &sid)) return -1;
|
||||
|
||||
prov = calloc(1, sizeof(opentv_prov_t));
|
||||
prov->key = (char*)key;
|
||||
if (RB_INSERT_SORTED(&_opentv_provs, prov, h_link, _prov_cmp)) {
|
||||
tvhlog(LOG_WARNING, "opentv", "ignore duplicate provider %s", key);
|
||||
free(prov);
|
||||
return 0;
|
||||
} else {
|
||||
prov->key = strdup(key);
|
||||
prov->dict = dict;
|
||||
prov->tsid = tsid;
|
||||
prov->sid = sid;
|
||||
prov->channel = _pid_list_to_array(cl);
|
||||
prov->title = _pid_list_to_array(tl);
|
||||
prov->summary = _pid_list_to_array(sl);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void _opentv_prov_add_tables
|
||||
( opentv_prov_t *prov, th_dvb_mux_instance_t *tdmi )
|
||||
{
|
||||
tvhlog(LOG_INFO, "opentv", "install provider %s", prov->key);
|
||||
/* Channels */
|
||||
/* Titles */
|
||||
/* Summaries */
|
||||
#if 0
|
||||
struct dmx_sct_filter_params *fp;
|
||||
fp = dvb_fparams_alloc();
|
||||
fp->filter.filter[0] = 0xa8;
|
||||
fp->filter.mask[0] = 0xfc;
|
||||
tdt_add(tdmi, fp, _opentv_callback, NULL, "opentv", TDT_CRC, 0x40, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
* Parser
|
||||
* ***********************************************************************/
|
||||
|
||||
#if 0
|
||||
static void _parse_short_desc ( uint8_t *buf, int len, uint16_t eid )
|
||||
{
|
||||
#if 0
|
||||
char *str = huffman_decode(_opentv_dict, (char*)buf, len, 0x20);
|
||||
printf("EID: %5d, SUMMARY: %s\n", eid, str);
|
||||
free(str);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int _parse_record ( uint8_t *buf, int len, uint16_t eid )
|
||||
{
|
||||
uint8_t rtag = buf[0];
|
||||
uint8_t rlen = buf[1];
|
||||
if (rlen+2 > len) return rlen+2;
|
||||
switch (rtag) {
|
||||
case 0xb5:
|
||||
//_parse_title(buf+2, rlen);
|
||||
break;
|
||||
case 0xb9:
|
||||
_parse_short_desc(buf+2, rlen, eid);
|
||||
break;
|
||||
case 0xbb:
|
||||
//_parse_long_desc(buf+2, rlen);
|
||||
break;
|
||||
case 0xc1:
|
||||
//_parse_series_link(buf+2, rlen);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return rlen + 2;
|
||||
}
|
||||
|
||||
static int _parse_summary ( uint8_t *buf, int len )
|
||||
{
|
||||
uint16_t eid = ((uint16_t)buf[0] << 8) | buf[1];
|
||||
int slen = ((int)buf[2] & 0xf << 8) | buf[3];
|
||||
int i = 4;
|
||||
if (slen+4 > len) return slen+4;
|
||||
while (i < slen+4) {
|
||||
i += _parse_record(buf+i, len-i, eid);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int _opentv_callback
|
||||
( th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, uint8_t tid, void *p )
|
||||
{
|
||||
// TODO: currently this will only get summary tables!
|
||||
int i = 0;
|
||||
//uint16_t cid, mjd;
|
||||
if (len < 20) return 0;
|
||||
//cid = ((uint16_t)buf[0] << 8) | buf[1];
|
||||
//mjd = ((uint16_t)buf[2] << 8) | buf[3];
|
||||
i = 10;
|
||||
while (i < len) {
|
||||
i += _parse_summary(buf+i, len-i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ************************************************************************
|
||||
* Module Setup
|
||||
* ***********************************************************************/
|
||||
|
||||
static epggrab_module_t _opentv_mod;
|
||||
static huffman_node_t *_opentv_dict;
|
||||
|
||||
static void _opentv_tune ( epggrab_module_t *m, th_dvb_mux_instance_t *tdmi )
|
||||
{
|
||||
opentv_prov_t *prov;
|
||||
if (!m->enabled) return;
|
||||
|
||||
/* Check if this in our list of enabled providers */
|
||||
RB_FOREACH(prov, &_opentv_provs, h_link) {
|
||||
if (prov->enabled && prov->tsid == tdmi->tdmi_transport_stream_id)
|
||||
_opentv_prov_add_tables(prov, tdmi);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void* _opentv_thread ( void *p )
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
th_dvb_adapter_t *tda;
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
service_t *svc = NULL;
|
||||
|
||||
pthread_mutex_lock(&global_lock);
|
||||
|
||||
printf("find service\n");
|
||||
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) {
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||
if ((svc = dvb_transport_find(tdmi, 4152, 0, NULL))) break;
|
||||
if ((svc = dvb_transport_find(tdmi, 4152, 0, NULL))) {
|
||||
_opentv_tdmi = tdmi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,19 +289,21 @@ static void* _opentv_thread ( void *p )
|
|||
pthread_mutex_unlock(&global_lock);
|
||||
|
||||
while (1) {
|
||||
// check status?
|
||||
sleep(10);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _opentv_enable ( epggrab_module_t *m, uint8_t e )
|
||||
{
|
||||
pthread_t tid;
|
||||
pthread_attr_t tattr;
|
||||
pthread_attr_init(&tattr);
|
||||
pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&tid, &tattr, _opentv_thread, NULL);
|
||||
return 0;
|
||||
int save = 0;
|
||||
if (m->enabled != e) {
|
||||
m->enabled = e;
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
void opentv_init ( epggrab_module_list_t *list )
|
||||
|
@ -79,14 +311,53 @@ void opentv_init ( epggrab_module_list_t *list )
|
|||
_opentv_mod.id = strdup("opentv");
|
||||
_opentv_mod.name = strdup("OpenTV EPG");
|
||||
_opentv_mod.enable = _opentv_enable;
|
||||
_opentv_mod.tune = _opentv_tune;
|
||||
*((uint8_t*)&_opentv_mod.flags) = EPGGRAB_MODULE_EXTERNAL; // TODO: hack
|
||||
LIST_INSERT_HEAD(list, &_opentv_mod, link);
|
||||
// Note: this is mostly ignored anyway as EIT is treated as a special case!
|
||||
}
|
||||
|
||||
void opentv_load ( void )
|
||||
{
|
||||
_opentv_dict = huffman_tree_load("epggrab/opentv/dict/skyuk");
|
||||
assert(_opentv_dict);
|
||||
tvhlog(LOG_INFO, "opentv", "huffman tree loaded");
|
||||
int r;
|
||||
htsmsg_t *m, *e;
|
||||
htsmsg_field_t *f;
|
||||
opentv_prov_t *p;
|
||||
|
||||
/* Load the dictionaries */
|
||||
if ((m = hts_settings_load("epggrab/opentv/dict"))) {
|
||||
HTSMSG_FOREACH(f, m) {
|
||||
if ((e = htsmsg_get_list(m, f->hmf_name))) {
|
||||
if ((r = _opentv_dict_load(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);
|
||||
}
|
||||
tvhlog(LOG_INFO, "opentv", "dictonaries loaded");
|
||||
|
||||
/* Load providers */
|
||||
if ((m = hts_settings_load("epggrab/opentv/prov"))) {
|
||||
HTSMSG_FOREACH(f, m) {
|
||||
if ((e = htsmsg_get_map_by_field(f))) {
|
||||
if ((r = _opentv_prov_load(f->hmf_name, e))) {
|
||||
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");
|
||||
|
||||
/* TODO: do this properly */
|
||||
RB_FOREACH(p, &_opentv_provs, h_link) {
|
||||
p->enabled = 1;
|
||||
tvhlog(LOG_INFO, "opentv", "enabled %s", p->key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
#ifndef __TVH_EPGGRAB_OPENTV_H__
|
||||
#define __TVH_EPGGRAB_OPENTV_H__
|
||||
|
||||
#include "dvb/dvb.h"
|
||||
#include "epggrab.h"
|
||||
|
||||
void opentv_tune ( th_dvb_mux_instance_t *tdmi );
|
||||
void opentv_init ( epggrab_module_list_t *list );
|
||||
void opentv_load ( void );
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue