Some more tidying up and adding back in missing code.
This commit is contained in:
parent
58e4068a43
commit
d59979f4de
11 changed files with 429 additions and 366 deletions
|
@ -135,10 +135,10 @@ typedef struct th_dvb_mux_instance {
|
|||
|
||||
struct service_list tdmi_transports; /* via s_mux_link */
|
||||
|
||||
|
||||
TAILQ_ENTRY(th_dvb_mux_instance) tdmi_scan_link;
|
||||
struct th_dvb_mux_instance_queue *tdmi_scan_queue;
|
||||
|
||||
TAILQ_HEAD(, epggrab_ota_mux) tdmi_epg_grab;
|
||||
|
||||
} th_dvb_mux_instance_t;
|
||||
|
||||
|
|
|
@ -34,53 +34,9 @@ uint32_t epggrab_channel_renumber;
|
|||
uint32_t epggrab_channel_reicon;
|
||||
|
||||
/* **************************************************************************
|
||||
* Helpers
|
||||
* Internal Grab Thread
|
||||
* *************************************************************************/
|
||||
|
||||
void epggrab_resched ( void )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Run the parse
|
||||
*/
|
||||
void epggrab_module_parse
|
||||
( void *m, htsmsg_t *data )
|
||||
{
|
||||
time_t tm1, tm2;
|
||||
int save = 0;
|
||||
epggrab_stats_t stats;
|
||||
epggrab_module_int_t *mod = m;
|
||||
|
||||
/* Parse */
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
pthread_mutex_lock(&global_lock);
|
||||
time(&tm1);
|
||||
save |= mod->parse(mod, data, &stats);
|
||||
time(&tm2);
|
||||
if (save) epg_updated();
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
htsmsg_destroy(data);
|
||||
|
||||
/* Debug stats */
|
||||
tvhlog(LOG_INFO, mod->id, "parse took %d seconds", tm2 - tm1);
|
||||
tvhlog(LOG_INFO, mod->id, " channels tot=%5d new=%5d mod=%5d",
|
||||
stats.channels.total, stats.channels.created,
|
||||
stats.channels.modified);
|
||||
tvhlog(LOG_INFO, mod->id, " brands tot=%5d new=%5d mod=%5d",
|
||||
stats.brands.total, stats.brands.created,
|
||||
stats.brands.modified);
|
||||
tvhlog(LOG_INFO, mod->id, " seasons tot=%5d new=%5d mod=%5d",
|
||||
stats.seasons.total, stats.seasons.created,
|
||||
stats.seasons.modified);
|
||||
tvhlog(LOG_INFO, mod->id, " episodes tot=%5d new=%5d mod=%5d",
|
||||
stats.episodes.total, stats.episodes.created,
|
||||
stats.episodes.modified);
|
||||
tvhlog(LOG_INFO, mod->id, " broadcasts tot=%5d new=%5d mod=%5d",
|
||||
stats.broadcasts.total, stats.broadcasts.created,
|
||||
stats.broadcasts.modified);
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab from module
|
||||
*/
|
||||
|
@ -103,10 +59,6 @@ static void _epggrab_module_grab ( epggrab_module_int_t *mod )
|
|||
}
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Internal Grab Thread
|
||||
* *************************************************************************/
|
||||
|
||||
/*
|
||||
* Thread (for internal grabbing)
|
||||
*/
|
||||
|
@ -340,43 +292,17 @@ int epggrab_enable_module_by_id ( const char *id, uint8_t e )
|
|||
return epggrab_enable_module(epggrab_module_find_by_id(id), e);
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Module Access
|
||||
* *************************************************************************/
|
||||
|
||||
epggrab_module_t* epggrab_module_find_by_id ( const char *id )
|
||||
{
|
||||
epggrab_module_t *m;
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
if ( !strcmp(m->id, id) ) return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
htsmsg_t *epggrab_module_list ( void )
|
||||
{
|
||||
epggrab_module_t *m;
|
||||
htsmsg_t *e, *a = htsmsg_create_list();
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "id", m->id);
|
||||
htsmsg_add_u32(e, "type", m->type);
|
||||
htsmsg_add_u32(e, "enabled", m->enabled);
|
||||
if(m->name)
|
||||
htsmsg_add_str(e, "name", m->name);
|
||||
if(m->type == EPGGRAB_EXT) {
|
||||
epggrab_module_ext_t *ext = (epggrab_module_ext_t*)m;
|
||||
htsmsg_add_str(e, "path", ext->path);
|
||||
}
|
||||
htsmsg_add_msg(a, NULL, e);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Initialisation
|
||||
* *************************************************************************/
|
||||
|
||||
/*
|
||||
* TODO: implement this
|
||||
*/
|
||||
void epggrab_resched ( void )
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise
|
||||
*/
|
||||
|
|
|
@ -125,9 +125,16 @@ struct epggrab_module
|
|||
const char *id; ///< Module identifier
|
||||
const char *name; ///< Module name (for display)
|
||||
uint8_t enabled; ///< Whether the module is enabled
|
||||
epggrab_channel_tree_t *channels; ///< Channel list
|
||||
|
||||
/* Enable/Disable */
|
||||
int (*enable) ( void *m, uint8_t e );
|
||||
|
||||
/* Channel listings */
|
||||
void (*ch_add) ( void *m, struct channel *ch );
|
||||
void (*ch_rem) ( void *m, struct channel *ch );
|
||||
void (*ch_mod) ( void *m, struct channel *ch );
|
||||
void (*ch_save) ( void *m, epggrab_channel_t *ch );
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -138,17 +145,11 @@ struct epggrab_module_int
|
|||
epggrab_module_t ; ///< Parent object
|
||||
|
||||
const char *path; ///< Path for the command
|
||||
epggrab_channel_tree_t *channels; ///< Channel list
|
||||
|
||||
/* Handle data */
|
||||
char* (*grab) ( void *mod );
|
||||
htsmsg_t* (*trans) ( void *mod, char *data );
|
||||
int (*parse) ( void *mod, htsmsg_t *data, epggrab_stats_t *stat );
|
||||
|
||||
/* Channel listings */
|
||||
void (*ch_add) ( void *m, struct channel *ch );
|
||||
void (*ch_rem) ( void *m, struct channel *ch );
|
||||
void (*ch_mod) ( void *m, struct channel *ch );
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -166,15 +167,16 @@ struct epggrab_module_ext
|
|||
*/
|
||||
struct epggrab_ota_mux
|
||||
{
|
||||
LIST_ENTRY(epggrab_ota_mux) glob_link; ///< Grabber link
|
||||
TAILQ_ENTRY(epggrab_ota_mux) reg_link; ///< List of reg'd
|
||||
TAILQ_ENTRY(epggrab_ota_mux) glob_link; ///< Grabber link
|
||||
TAILQ_ENTRY(epggrab_ota_mux) tdmi_link; ///< Link to mux
|
||||
TAILQ_ENTRY(epggrab_ota_mux) grab_link; ///< Link to grabber
|
||||
struct th_dvb_mux_instance *tdmi; ///< Mux instance
|
||||
epggrab_module_ota_t *grab; ///< Grab instance
|
||||
|
||||
int timeout; ///< Time out if this long
|
||||
int interval; ///< Re-grab this often
|
||||
|
||||
int is_reg; ///< Registered with mux
|
||||
int is_reg; ///< Permanently registered
|
||||
|
||||
void *status; ///< Status information
|
||||
enum {
|
||||
|
@ -194,7 +196,9 @@ struct epggrab_ota_mux
|
|||
*/
|
||||
struct epggrab_module_ota
|
||||
{
|
||||
epggrab_module_t ; ///< Parent object
|
||||
epggrab_module_t ; ///< Parent object
|
||||
|
||||
TAILQ_HEAD(, epggrab_ota_mux) muxes; ///< List of related muxes
|
||||
|
||||
/* Transponder tuning */
|
||||
void (*start) ( epggrab_module_ota_t *m, struct th_dvb_mux_instance *tdmi );
|
||||
|
|
|
@ -28,14 +28,12 @@
|
|||
#include "epggrab.h"
|
||||
#include "epggrab/private.h"
|
||||
|
||||
#if 0
|
||||
static int _ch_id_cmp ( void *a, void *b )
|
||||
{
|
||||
return strcmp(((epggrab_channel_t*)a)->id,
|
||||
((epggrab_channel_t*)b)->id);
|
||||
}
|
||||
#endif
|
||||
/* **************************************************************************
|
||||
* EPG Grab Channel functions
|
||||
* *************************************************************************/
|
||||
|
||||
/* Link epggrab channel to real channel */
|
||||
// returns 1 if link made
|
||||
int epggrab_channel_link ( epggrab_channel_t *ec, channel_t *ch )
|
||||
{
|
||||
service_t *sv;
|
||||
|
@ -87,6 +85,7 @@ int epggrab_channel_link ( epggrab_channel_t *ec, channel_t *ch )
|
|||
return match;
|
||||
}
|
||||
|
||||
/* Set name */
|
||||
int epggrab_channel_set_name ( epggrab_channel_t *ec, const char *name )
|
||||
{
|
||||
int save = 0;
|
||||
|
@ -94,41 +93,66 @@ int epggrab_channel_set_name ( epggrab_channel_t *ec, const char *name )
|
|||
if (!ec->name || strcmp(ec->name, name)) {
|
||||
if (ec->name) free(ec->name);
|
||||
ec->name = strdup(name);
|
||||
if (ec->channel) channel_rename(ec->channel, name);
|
||||
if (ec->channel && epggrab_channel_rename)
|
||||
channel_rename(ec->channel, name);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
/* Set icon */
|
||||
int epggrab_channel_set_icon ( epggrab_channel_t *ec, const char *icon )
|
||||
{
|
||||
int save = 0;
|
||||
if (!ec->icon || strcmp(ec->icon, icon) ) {
|
||||
if (!ec | !icon) return 0;
|
||||
if (ec->icon) free(ec->icon);
|
||||
ec->icon = strdup(icon);
|
||||
if (ec->channel) channel_set_icon(ec->channel, icon);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
/* Set channel number */
|
||||
int epggrab_channel_set_number ( epggrab_channel_t *ec, int number )
|
||||
{
|
||||
int save = 0;
|
||||
if (!ec || (number <= 0)) return 0;
|
||||
if (ec->number != number) {
|
||||
ec->number = number;
|
||||
if (ec->channel) channel_set_number(ec->channel, number);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
/* Set service IDs */
|
||||
int epggrab_channel_set_sid
|
||||
( epggrab_channel_t *ec, const uint16_t *sid )
|
||||
{
|
||||
#if 0
|
||||
int save = 0, i = 0, num = 0;
|
||||
int save = 0, i;
|
||||
if ( !ec || !sid ) return 0;
|
||||
if (!ec->sid) save = 1;
|
||||
else {
|
||||
|
||||
for (i = 0; i < num; i++ ) {
|
||||
if (sid[i] != ec->sid[i]) {
|
||||
save = 1;
|
||||
break;
|
||||
}
|
||||
i = 0;
|
||||
while ( ec->sid[i] && sid[i] ) {
|
||||
if ( ec->sid[i] != sid[i] ) break;
|
||||
i++;
|
||||
}
|
||||
if (ec->sid[i] || sid[i]) save = 1;
|
||||
}
|
||||
if (save) {
|
||||
i = 0;
|
||||
while (ec->sid[i++]);
|
||||
if (ec->sid) free(ec->sid);
|
||||
ec->sid = calloc(num, sizeof(uint16_t));
|
||||
for (i = 0; i < num; i++ ) {
|
||||
ec->sid[i] = sid[i];
|
||||
}
|
||||
ec->sid_cnt = num;
|
||||
ec->sid = calloc(i, sizeof(uint16_t));
|
||||
memcpy(ec->sid, sid, i * sizeof(uint16_t));
|
||||
}
|
||||
return save;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set names */
|
||||
int epggrab_channel_set_sname ( epggrab_channel_t *ec, const char **sname )
|
||||
{
|
||||
int save = 0, i = 0;
|
||||
|
@ -136,13 +160,10 @@ int epggrab_channel_set_sname ( epggrab_channel_t *ec, const char **sname )
|
|||
if (!ec->sname) save = 1;
|
||||
else {
|
||||
while ( ec->sname[i] && sname[i] ) {
|
||||
if (strcmp(ec->sname[i], sname[i])) {
|
||||
save = 1;
|
||||
break;
|
||||
}
|
||||
if (strcmp(ec->sname[i], sname[i])) break;
|
||||
i++;
|
||||
}
|
||||
if (!save && (ec->sname[i] || sname[i])) save = 1;
|
||||
if (ec->sname[i] || sname[i]) save = 1;
|
||||
}
|
||||
if (save) {
|
||||
if (ec->sname) {
|
||||
|
@ -163,57 +184,60 @@ int epggrab_channel_set_sname ( epggrab_channel_t *ec, const char **sname )
|
|||
return save;
|
||||
}
|
||||
|
||||
int epggrab_channel_set_icon ( epggrab_channel_t *ec, const char *icon )
|
||||
{
|
||||
int save = 0;
|
||||
if (!ec->icon || strcmp(ec->icon, icon) ) {
|
||||
if (!ec | !icon) return 0;
|
||||
if (ec->icon) free(ec->icon);
|
||||
ec->icon = strdup(icon);
|
||||
if (ec->channel) channel_set_icon(ec->channel, icon);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
int epggrab_channel_set_number ( epggrab_channel_t *ec, int number )
|
||||
{
|
||||
int save = 0;
|
||||
if (!ec || (number <= 0)) return 0;
|
||||
if (ec->number != number) {
|
||||
ec->number = number;
|
||||
if (ec->channel) channel_set_number(ec->channel, number);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
|
||||
/* Channel settings updated */
|
||||
void epggrab_channel_updated ( epggrab_channel_t *ec )
|
||||
{
|
||||
//epggrab_channel_link(ec);
|
||||
epggrab_module_ch_save(ec->mod, ec);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void epggrab_channel_link ( epggrab_channel_t *ec )
|
||||
{
|
||||
channel_t *ch;
|
||||
|
||||
if (!ec) return;
|
||||
|
||||
/* Link */
|
||||
if (!ec->channel) {
|
||||
RB_FOREACH(ch, &channel_name_tree, ch_name_link) {
|
||||
if (_ch_link(ec, ch)) break;
|
||||
/* Find a link */
|
||||
if (!ec->channel)
|
||||
RB_FOREACH(ch, &channel_name_tree, ch_name_link)
|
||||
if (epggrab_channel_link(ec, ch)) break;
|
||||
|
||||
/* Save */
|
||||
if (ec->mod->ch_save) ec->mod->ch_save(ec->mod, ec);
|
||||
}
|
||||
|
||||
/* ID comparison */
|
||||
static int _ch_id_cmp ( void *a, void *b )
|
||||
{
|
||||
return strcmp(((epggrab_channel_t*)a)->id,
|
||||
((epggrab_channel_t*)b)->id);
|
||||
}
|
||||
|
||||
/* Find/Create channel in the list */
|
||||
epggrab_channel_t *epggrab_channel_find
|
||||
( epggrab_channel_tree_t *tree, const char *id, int create, int *save )
|
||||
{
|
||||
epggrab_channel_t *ec;
|
||||
static epggrab_channel_t *skel = NULL;
|
||||
if (!skel) skel = calloc(1, sizeof(epggrab_channel_t));
|
||||
skel->id = (char*)id;
|
||||
|
||||
/* Find */
|
||||
if (!create) {
|
||||
ec = RB_FIND(tree, skel, link, _ch_id_cmp);
|
||||
|
||||
/* Find/Create */
|
||||
} else {
|
||||
ec = RB_INSERT_SORTED(tree, skel, link, _ch_id_cmp);
|
||||
if (!ec) {
|
||||
ec = skel;
|
||||
skel = NULL;
|
||||
ec->id = strdup(id);
|
||||
*save = 1;
|
||||
}
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* **************************************************************************
|
||||
* Global routines
|
||||
* *************************************************************************/
|
||||
|
||||
htsmsg_t *epggrab_channel_list ( void )
|
||||
{
|
||||
#if 0
|
||||
char name[100];
|
||||
epggrab_module_t *mod;
|
||||
epggrab_channel_t *ec;
|
||||
|
@ -232,44 +256,28 @@ htsmsg_t *epggrab_channel_list ( void )
|
|||
}
|
||||
}
|
||||
return m;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void epggrab_channel_add ( channel_t *ch )
|
||||
{
|
||||
#if 0
|
||||
epggrab_module_t *m;
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
if (m->ch_add) m->ch_add(m, ch);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void epggrab_channel_rem ( channel_t *ch )
|
||||
{
|
||||
#if 0
|
||||
epggrab_module_t *m;
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
if (m->ch_rem) m->ch_rem(m, ch);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void epggrab_channel_mod ( channel_t *ch )
|
||||
{
|
||||
#if 0
|
||||
epggrab_module_t *m;
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
if (m->ch_mod) m->ch_mod(m, ch);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
epggrab_channel_t *epggrab_channel_find
|
||||
( epggrab_channel_tree_t *tree, const char *id, int create, int *save )
|
||||
{
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,18 +35,59 @@
|
|||
#include "epggrab.h"
|
||||
#include "epggrab/private.h"
|
||||
|
||||
/* **************************************************************************
|
||||
* Module Access
|
||||
* *************************************************************************/
|
||||
|
||||
epggrab_module_t* epggrab_module_find_by_id ( const char *id )
|
||||
{
|
||||
epggrab_module_t *m;
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
if ( !strcmp(m->id, id) ) return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
htsmsg_t *epggrab_module_list ( void )
|
||||
{
|
||||
epggrab_module_t *m;
|
||||
htsmsg_t *e, *a = htsmsg_create_list();
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "id", m->id);
|
||||
htsmsg_add_u32(e, "type", m->type);
|
||||
htsmsg_add_u32(e, "enabled", m->enabled);
|
||||
if(m->name)
|
||||
htsmsg_add_str(e, "name", m->name);
|
||||
if(m->type == EPGGRAB_EXT) {
|
||||
epggrab_module_ext_t *ext = (epggrab_module_ext_t*)m;
|
||||
htsmsg_add_str(e, "path", ext->path);
|
||||
}
|
||||
htsmsg_add_msg(a, NULL, e);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Generic module routines
|
||||
* *************************************************************************/
|
||||
|
||||
epggrab_module_t *epggrab_module_create
|
||||
( epggrab_module_t *skel, const char *id, const char *name )
|
||||
( epggrab_module_t *skel, const char *id, const char *name,
|
||||
epggrab_channel_tree_t *channels )
|
||||
{
|
||||
assert(skel);
|
||||
|
||||
/* Setup */
|
||||
skel->id = strdup(id);
|
||||
skel->name = strdup(name);
|
||||
skel->id = strdup(id);
|
||||
skel->name = strdup(name);
|
||||
skel->channels = channels;
|
||||
if (channels) {
|
||||
skel->ch_save = epggrab_module_ch_save;
|
||||
skel->ch_add = epggrab_module_ch_add;
|
||||
skel->ch_mod = epggrab_module_ch_mod;
|
||||
skel->ch_rem = epggrab_module_ch_rem;
|
||||
}
|
||||
|
||||
/* Insert */
|
||||
assert(!epggrab_module_find_by_id(id));
|
||||
|
@ -55,8 +96,48 @@ epggrab_module_t *epggrab_module_create
|
|||
return skel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run the parse
|
||||
*/
|
||||
void epggrab_module_parse
|
||||
( void *m, htsmsg_t *data )
|
||||
{
|
||||
time_t tm1, tm2;
|
||||
int save = 0;
|
||||
epggrab_stats_t stats;
|
||||
epggrab_module_int_t *mod = m;
|
||||
|
||||
/* Parse */
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
pthread_mutex_lock(&global_lock);
|
||||
time(&tm1);
|
||||
save |= mod->parse(mod, data, &stats);
|
||||
time(&tm2);
|
||||
if (save) epg_updated();
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
htsmsg_destroy(data);
|
||||
|
||||
/* Debug stats */
|
||||
tvhlog(LOG_INFO, mod->id, "parse took %d seconds", tm2 - tm1);
|
||||
tvhlog(LOG_INFO, mod->id, " channels tot=%5d new=%5d mod=%5d",
|
||||
stats.channels.total, stats.channels.created,
|
||||
stats.channels.modified);
|
||||
tvhlog(LOG_INFO, mod->id, " brands tot=%5d new=%5d mod=%5d",
|
||||
stats.brands.total, stats.brands.created,
|
||||
stats.brands.modified);
|
||||
tvhlog(LOG_INFO, mod->id, " seasons tot=%5d new=%5d mod=%5d",
|
||||
stats.seasons.total, stats.seasons.created,
|
||||
stats.seasons.modified);
|
||||
tvhlog(LOG_INFO, mod->id, " episodes tot=%5d new=%5d mod=%5d",
|
||||
stats.episodes.total, stats.episodes.created,
|
||||
stats.episodes.modified);
|
||||
tvhlog(LOG_INFO, mod->id, " broadcasts tot=%5d new=%5d mod=%5d",
|
||||
stats.broadcasts.total, stats.broadcasts.created,
|
||||
stats.broadcasts.modified);
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Channel related routines
|
||||
* Module channel routines
|
||||
* *************************************************************************/
|
||||
|
||||
void epggrab_module_ch_save ( void *_m, epggrab_channel_t *ch )
|
||||
|
@ -102,7 +183,7 @@ void epggrab_module_ch_add ( void *m, channel_t *ch )
|
|||
epggrab_module_int_t *mod = m;
|
||||
RB_FOREACH(egc, mod->channels, link) {
|
||||
if (epggrab_channel_link(egc, ch)) {
|
||||
epggrab_module_ch_save(mod, egc);
|
||||
if (mod->ch_save) mod->ch_save(mod, egc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +196,7 @@ void epggrab_module_ch_rem ( void *m, channel_t *ch )
|
|||
RB_FOREACH(egc, mod->channels, link) {
|
||||
if (egc->channel == ch) {
|
||||
egc->channel = NULL;
|
||||
epggrab_module_ch_save(mod, egc);
|
||||
if (mod->ch_save) mod->ch_save(mod, egc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -126,10 +207,7 @@ void epggrab_module_ch_mod ( void *mod, channel_t *ch )
|
|||
return epggrab_module_ch_add(mod, ch);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
static void epggrab_module_ch_load
|
||||
static void _epggrab_module_channel_load
|
||||
( epggrab_module_t *mod, htsmsg_t *m, const char *id )
|
||||
{
|
||||
int save = 0, i;
|
||||
|
@ -138,7 +216,7 @@ static void epggrab_module_ch_load
|
|||
htsmsg_t *a;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
epggrab_channel_t *ch = epggrab_module_channel_find(mod, id, 1, &save);
|
||||
epggrab_channel_t *ch = epggrab_channel_find(mod->channels, id, 1, &save);
|
||||
|
||||
if ((str = htsmsg_get_str(m, "name")))
|
||||
ch->name = strdup(str);
|
||||
|
@ -147,22 +225,23 @@ static void epggrab_module_ch_load
|
|||
if ((a = htsmsg_get_list(m, "sid"))) {
|
||||
i = 0;
|
||||
HTSMSG_FOREACH(f, a) i++;
|
||||
ch->sid_cnt = i;
|
||||
ch->sid = calloc(i, sizeof(uint16_t));
|
||||
i = 0;
|
||||
HTSMSG_FOREACH(f, a) {
|
||||
ch->sid[i] = (uint16_t)f->hmf_s64;
|
||||
i++;
|
||||
if (i) {
|
||||
ch->sid = calloc(i+1, sizeof(uint16_t));
|
||||
i = 0;
|
||||
HTSMSG_FOREACH(f, a) {
|
||||
ch->sid[i++] = (uint16_t)f->hmf_s64;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((a = htsmsg_get_list(m, "sname"))) {
|
||||
i = 0;
|
||||
HTSMSG_FOREACH(f, a) i++;
|
||||
ch->sname = calloc(i+1, sizeof(char*));
|
||||
i = 0;
|
||||
HTSMSG_FOREACH(f, a) {
|
||||
ch->sname[i] = strdup(f->hmf_str);
|
||||
i++;
|
||||
if (i) {
|
||||
ch->sname = calloc(i+1, sizeof(char*));
|
||||
i = 0;
|
||||
HTSMSG_FOREACH(f, a) {
|
||||
ch->sname[i++] = strdup(f->hmf_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!htsmsg_get_u32(m, "number", &u32))
|
||||
|
@ -176,47 +255,16 @@ void epggrab_module_channels_load ( epggrab_module_t *mod )
|
|||
{
|
||||
htsmsg_t *m, *e;
|
||||
htsmsg_field_t *f;
|
||||
|
||||
if (!mod || !mod->channels) return;
|
||||
if ((m = hts_settings_load("epggrab/%s/channels", mod->id))) {
|
||||
HTSMSG_FOREACH(f, m) {
|
||||
if ((e = htsmsg_get_map_by_field(f)))
|
||||
epggrab_module_channel_load(mod, e, f->hmf_name);
|
||||
_epggrab_module_channel_load(mod, e, f->hmf_name);
|
||||
}
|
||||
htsmsg_destroy(m);
|
||||
}
|
||||
}
|
||||
|
||||
epggrab_channel_t *epggrab_module_ch_find
|
||||
( epggrab_module_t *mod, const char *id, int create, int *save )
|
||||
{
|
||||
epggrab_channel_t *ec;
|
||||
static epggrab_channel_t *skel = NULL;
|
||||
|
||||
if (!mod || !mod->channels ) return NULL;
|
||||
|
||||
if ( !skel ) skel = calloc(1, sizeof(epggrab_channel_t));
|
||||
skel->id = (char*)id;
|
||||
skel->mod = mod;
|
||||
|
||||
/* Find */
|
||||
if (!create) {
|
||||
ec = RB_FIND(mod->channels, skel, link, _ch_id_cmp);
|
||||
|
||||
/* Create (if required) */
|
||||
} else {
|
||||
ec = RB_INSERT_SORTED(mod->channels, skel, link, _ch_id_cmp);
|
||||
if ( ec == NULL ) {
|
||||
skel->id = strdup(skel->id);
|
||||
ec = skel;
|
||||
skel = NULL;
|
||||
*save = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* **************************************************************************
|
||||
* Internal module routines
|
||||
* *************************************************************************/
|
||||
|
@ -233,7 +281,7 @@ epggrab_module_int_t *epggrab_module_int_create
|
|||
if (!skel) skel = calloc(1, sizeof(epggrab_module_int_t));
|
||||
|
||||
/* Pass through */
|
||||
epggrab_module_create((epggrab_module_t*)skel, id, name);
|
||||
epggrab_module_create((epggrab_module_t*)skel, id, name, channels);
|
||||
|
||||
/* Int data */
|
||||
skel->type = EPGGRAB_INT;
|
||||
|
@ -242,11 +290,6 @@ epggrab_module_int_t *epggrab_module_int_create
|
|||
skel->grab = grab ?: epggrab_module_grab_spawn;
|
||||
skel->trans = trans ?: epggrab_module_trans_xml;
|
||||
skel->parse = parse;
|
||||
if (channels) {
|
||||
skel->ch_add = epggrab_module_ch_add;
|
||||
skel->ch_rem = epggrab_module_ch_rem;
|
||||
skel->ch_mod = epggrab_module_ch_mod;
|
||||
}
|
||||
|
||||
return skel;
|
||||
}
|
||||
|
@ -438,7 +481,7 @@ epggrab_module_ota_t *epggrab_module_ota_create
|
|||
if (!skel) skel = calloc(1, sizeof(epggrab_module_ota_t));
|
||||
|
||||
/* Pass through */
|
||||
epggrab_module_create((epggrab_module_t*)skel, id, name);
|
||||
epggrab_module_create((epggrab_module_t*)skel, id, name, channels);
|
||||
|
||||
/* Setup */
|
||||
skel->type = EPGGRAB_OTA;
|
||||
|
|
|
@ -36,6 +36,26 @@ typedef struct eit_status
|
|||
int sec;
|
||||
} eit_status_t;
|
||||
|
||||
/* ************************************************************************
|
||||
* Diagnostics
|
||||
* ***********************************************************************/
|
||||
|
||||
// Dump a descriptor tag for debug (looking for new tags etc...)
|
||||
static void _eit_dtag_dump ( uint8_t dtag, uint8_t dlen, uint8_t *buf )
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
char tmp[100];
|
||||
tvhlog(LOG_DEBUG, "eit", "dtag 0x%02X len %d\n", dtag, dlen);
|
||||
while (i < dlen)
|
||||
while (dlen--) {
|
||||
j += sprintf(tmp+j, "%02X ", buf[i]);
|
||||
i++;
|
||||
if ((i % 8) == 0 || !dlen) {
|
||||
tvhlog(LOG_DEBUG, "eit", " %s", tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
* Processing
|
||||
* ***********************************************************************/
|
||||
|
@ -182,9 +202,12 @@ static int _eit_callback
|
|||
if (!svc || !svc->s_enabled || !(ch = svc->s_ch)) return 0;
|
||||
|
||||
/* Ignore (disabled) */
|
||||
// TODO: should this be altered?
|
||||
if (!svc->s_dvb_eit_enable) return 0;
|
||||
|
||||
/* Register as interesting */
|
||||
// TODO: do we want to register for now/next?
|
||||
// TODO: want should the intervals be?
|
||||
if (tableid < 0x50)
|
||||
epggrab_ota_register(ota, 20, 0);
|
||||
else
|
||||
|
@ -320,6 +343,7 @@ static int _eit_callback
|
|||
|
||||
/* Ignore */
|
||||
default:
|
||||
_eit_dtag_dump(dtag, dlen, ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,47 +56,60 @@ typedef struct opentv_event
|
|||
uint8_t type; ///< 0x1=title, 0x2=summary
|
||||
} opentv_event_t;
|
||||
|
||||
typedef struct opentv_pid_status
|
||||
/* PID status (for event PIDs) */
|
||||
typedef struct opentv_pid
|
||||
{
|
||||
LIST_ENTRY(opentv_pid_status) link;
|
||||
int pid;
|
||||
LIST_ENTRY(opentv_pid) link;
|
||||
int pid;
|
||||
enum {
|
||||
OPENTV_PID_INIT,
|
||||
OPENTV_PID_STARTED,
|
||||
OPENTV_PID_COMPLETE
|
||||
} state;
|
||||
uint8_t start[20];
|
||||
} opentv_pid_status_t;
|
||||
} state;
|
||||
uint8_t start[20];
|
||||
} opentv_pid_t;
|
||||
|
||||
/* Scan status */
|
||||
typedef struct opentv_status
|
||||
{
|
||||
int begbat;
|
||||
int endbat;
|
||||
LIST_HEAD(, opentv_pid_status) pids;
|
||||
RB_HEAD(, opentv_event) events;
|
||||
int begbat;
|
||||
int endbat;
|
||||
LIST_HEAD(, opentv_pid) pids;
|
||||
RB_HEAD(, opentv_event) events;
|
||||
} opentv_status_t;
|
||||
|
||||
static opentv_pid_status_t *_opentv_get_pid_status
|
||||
/* Get a pid entry */
|
||||
static opentv_pid_t *_opentv_status_get_pid
|
||||
( opentv_status_t *sta, int pid )
|
||||
{
|
||||
opentv_pid_status_t *p;
|
||||
opentv_pid_t *p;
|
||||
LIST_FOREACH(p, &sta->pids, link) {
|
||||
if (p->pid == pid) break;
|
||||
}
|
||||
if (!p) {
|
||||
p = calloc(1, sizeof(opentv_pid_status_t));
|
||||
p = calloc(1, sizeof(opentv_pid_t));
|
||||
p->pid = pid;
|
||||
LIST_INSERT_HEAD(&sta->pids, p, link);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
* Data structures
|
||||
* ***********************************************************************/
|
||||
/* Clear events */
|
||||
static void _opentv_status_remove_events ( opentv_status_t *sta )
|
||||
{
|
||||
opentv_event_t *ev;
|
||||
while ((ev = RB_FIRST(&sta->events))) {
|
||||
RB_REMOVE(&sta->events, ev, ev_link);
|
||||
if (ev->title) free(ev->title);
|
||||
if (ev->summary) free(ev->summary);
|
||||
if (ev->desc) free(ev->desc);
|
||||
free(ev);
|
||||
}
|
||||
}
|
||||
|
||||
#define OPENTV_SCAN_MAX 600 // 10min max scan period
|
||||
#define OPENTV_SCAN_PER 3600 // 1hour interval
|
||||
/* ************************************************************************
|
||||
* Module structure
|
||||
* ***********************************************************************/
|
||||
|
||||
/* Huffman dictionary */
|
||||
typedef struct opentv_dict
|
||||
|
@ -138,26 +151,6 @@ static opentv_dict_t *_opentv_dict_find ( const char *id )
|
|||
return RB_FIND(&_opentv_dicts, &skel, h_link, _dict_cmp);
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
* Module functions
|
||||
* ***********************************************************************/
|
||||
|
||||
#if 0
|
||||
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));
|
||||
sta->pid = pid;
|
||||
LIST_INSERT_HEAD(&mod->status, sta, link);
|
||||
}
|
||||
return sta;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ************************************************************************
|
||||
* EPG Object wrappers
|
||||
* ***********************************************************************/
|
||||
|
@ -165,9 +158,9 @@ static opentv_status_t *_opentv_module_get_status
|
|||
static epggrab_channel_t *_opentv_find_epggrab_channel
|
||||
( opentv_module_t *mod, int cid, int create, int *save )
|
||||
{
|
||||
// char chid[32];
|
||||
// sprintf(chid, "%s-%d", mod->id, cid);
|
||||
return NULL;//return epggrab_module_channel_find((epggrab_module_t*)mod, chid, create, save);
|
||||
char chid[32];
|
||||
sprintf(chid, "%s-%d", mod->id, cid);
|
||||
return epggrab_channel_find(&_opentv_channels, chid, create, save);
|
||||
}
|
||||
|
||||
static epg_season_t *_opentv_find_season
|
||||
|
@ -518,26 +511,22 @@ static epggrab_ota_mux_t *_opentv_table_callback
|
|||
th_dvb_table_t *tdt = (th_dvb_table_t*)p;
|
||||
epggrab_ota_mux_t *ota = tdt->tdt_opaque;
|
||||
opentv_status_t *sta = ota->status;
|
||||
opentv_pid_status_t *pid;
|
||||
opentv_pid_t *pid;
|
||||
|
||||
/* Ignore (not enough data) */
|
||||
if (len < 20) return NULL;
|
||||
|
||||
/* Ignore (don't have BAT) */
|
||||
if (!sta->endbat) return NULL;
|
||||
|
||||
/* Finished / Blocked */
|
||||
if (epggrab_ota_is_complete(ota)) return NULL;
|
||||
|
||||
/* Begin (reset state) */
|
||||
if (epggrab_ota_begin(ota)) {
|
||||
opentv_event_t *ev;
|
||||
|
||||
/* Remove outstanding event data */
|
||||
while ((ev = RB_FIRST(&sta->events))) {
|
||||
RB_REMOVE(&sta->events, ev, ev_link);
|
||||
if (ev->title) free(ev->title);
|
||||
if (ev->desc) free(ev->desc);
|
||||
if (ev->summary) free(ev->summary);
|
||||
free(ev);
|
||||
}
|
||||
_opentv_status_remove_events(sta);
|
||||
|
||||
/* Reset status */
|
||||
LIST_FOREACH(pid, &sta->pids, link)
|
||||
|
@ -545,7 +534,7 @@ static epggrab_ota_mux_t *_opentv_table_callback
|
|||
}
|
||||
|
||||
/* Insert/Find */
|
||||
pid = _opentv_get_pid_status(sta, tdt->tdt_pid);
|
||||
pid = _opentv_status_get_pid(sta, tdt->tdt_pid);
|
||||
|
||||
/* Begin PID */
|
||||
if (pid->state == OPENTV_PID_INIT) {
|
||||
|
@ -614,7 +603,21 @@ static int _opentv_channel_callback
|
|||
|
||||
static void _opentv_ota_destroy ( epggrab_ota_mux_t *ota )
|
||||
{
|
||||
// TODO
|
||||
opentv_status_t *sta = ota->status;
|
||||
opentv_pid_t *pid;
|
||||
|
||||
/* Empty the events */
|
||||
_opentv_status_remove_events(sta);
|
||||
|
||||
/* Empty pids */
|
||||
while ((pid = LIST_FIRST(&sta->pids))) {
|
||||
LIST_REMOVE(pid, link);
|
||||
free(pid);
|
||||
}
|
||||
|
||||
/* Free the rest */
|
||||
free(sta);
|
||||
free(ota);
|
||||
}
|
||||
|
||||
static void _opentv_start
|
||||
|
@ -639,8 +642,8 @@ static void _opentv_start
|
|||
sta = ota->status;
|
||||
sta->begbat = sta->endbat = 0;
|
||||
|
||||
/* Register interest (we're always interested in this mux) */
|
||||
epggrab_ota_register(ota, OPENTV_SCAN_MAX, OPENTV_SCAN_PER);
|
||||
/* Register (just in case we missed it on enable somehow) */
|
||||
epggrab_ota_register(ota, 600, 3600); // 10min scan every hour
|
||||
|
||||
/* Install tables */
|
||||
tvhlog(LOG_INFO, "opentv", "install provider %s tables", mod->id);
|
||||
|
@ -652,7 +655,7 @@ static void _opentv_start
|
|||
fp->filter.filter[0] = 0x4a;
|
||||
fp->filter.mask[0] = 0xff;
|
||||
// TODO: what about 0x46 (service description)
|
||||
tdt_add(tdmi, fp, _opentv_channel_callback, mod,
|
||||
tdt_add(tdmi, fp, _opentv_channel_callback, ota,
|
||||
m->id, TDT_CRC, *t++, NULL);
|
||||
}
|
||||
|
||||
|
@ -662,7 +665,8 @@ static void _opentv_start
|
|||
fp = dvb_fparams_alloc();
|
||||
fp->filter.filter[0] = 0xa0;
|
||||
fp->filter.mask[0] = 0xfc;
|
||||
tdt_add(tdmi, fp, _opentv_title_callback, mod,
|
||||
_opentv_status_get_pid(sta, *t);
|
||||
tdt_add(tdmi, fp, _opentv_title_callback, ota,
|
||||
m->id, TDT_CRC | TDT_TDT, *t++, NULL);
|
||||
}
|
||||
|
||||
|
@ -672,33 +676,28 @@ static void _opentv_start
|
|||
fp = dvb_fparams_alloc();
|
||||
fp->filter.filter[0] = 0xa8;
|
||||
fp->filter.mask[0] = 0xfc;
|
||||
tdt_add(tdmi, fp, _opentv_summary_callback, mod,
|
||||
_opentv_status_get_pid(sta, *t);
|
||||
tdt_add(tdmi, fp, _opentv_summary_callback, ota,
|
||||
m->id, TDT_CRC | TDT_TDT, *t++, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int _opentv_enable ( void *m, uint8_t e )
|
||||
{
|
||||
//th_dvb_adapter_t *tda;
|
||||
//th_dvb_mux_instance_t *tdmi;
|
||||
opentv_module_t *mod = (opentv_module_t*)m;
|
||||
|
||||
if (mod->enabled == e) return 0;
|
||||
mod->enabled = e;
|
||||
|
||||
/* TODO
|
||||
* Find muxes and enable/disable *
|
||||
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) {
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||
if (tdmi->tdmi_transport_stream_id != mod->tsid) continue;
|
||||
if (e) {
|
||||
epggrab_ota_register(m, tdmi, OPENTV_SCAN_MAX, OPENTV_SCAN_PER);
|
||||
} else {
|
||||
epggrab_ota_unregister_one(m, tdmi);
|
||||
}
|
||||
}
|
||||
/* Register interest */
|
||||
if (e) {
|
||||
epggrab_ota_create_and_register_by_id((epggrab_module_ota_t*)mod,
|
||||
mod->nid, mod->tsid,
|
||||
600, 3600);
|
||||
/* Remove all links */
|
||||
} else {
|
||||
epggrab_ota_destroy_by_module((epggrab_module_ota_t*)mod);
|
||||
}
|
||||
*/
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -793,7 +792,7 @@ static int _opentv_prov_load_one ( const char *id, htsmsg_t *m )
|
|||
epggrab_module_ota_create(calloc(1, sizeof(opentv_module_t)),
|
||||
ibuf, nbuf,
|
||||
_opentv_start, _opentv_enable,
|
||||
&_opentv_channels);
|
||||
NULL);
|
||||
|
||||
/* Add provider details */
|
||||
mod->dict = dict;
|
||||
|
|
|
@ -435,17 +435,16 @@ static int _pyepg_parse
|
|||
void pyepg_init ( void )
|
||||
{
|
||||
/* Internal module */
|
||||
epggrab_module_int_create(NULL, "pyepg", "PyEPG", "/usr/bin/pyepg",
|
||||
NULL, _pyepg_parse, NULL,
|
||||
&_pyepg_channels);
|
||||
epggrab_module_int_create(NULL, "/usr/bin/pyepg", "PyEPG", "/usr/bin/pyepg",
|
||||
NULL, _pyepg_parse, NULL, NULL);
|
||||
|
||||
/* External module */
|
||||
epggrab_module_ext_create(NULL, "pyepg.ext", "PyEPG", "pyepg",
|
||||
epggrab_module_ext_create(NULL, "pyepg", "PyEPG", "pyepg",
|
||||
_pyepg_parse, NULL,
|
||||
&_pyepg_channels);
|
||||
}
|
||||
|
||||
void pyepg_load ( void )
|
||||
{
|
||||
// TODO epggrab_module_channels_load(_pyepg_module);
|
||||
epggrab_module_channels_load(epggrab_module_find_by_id("pyepg"));
|
||||
}
|
||||
|
|
|
@ -44,10 +44,9 @@ static epggrab_channel_tree_t _xmltv_channels;
|
|||
static epggrab_channel_t *_xmltv_channel_find
|
||||
( const char *id, int create, int *save )
|
||||
{
|
||||
return NULL;//return epggrab_module_channel_find(_xmltv_module, id, create, save);
|
||||
return epggrab_channel_find(&_xmltv_channels, id, create, save);
|
||||
}
|
||||
|
||||
|
||||
/* **************************************************************************
|
||||
* Parsing
|
||||
* *************************************************************************/
|
||||
|
@ -481,8 +480,7 @@ static void _xmltv_load_grabbers ( void )
|
|||
outbuf[i] = '\0';
|
||||
sprintf(name, "XMLTV: %s", &outbuf[n]);
|
||||
epggrab_module_int_create(NULL, &outbuf[p], name, &outbuf[p],
|
||||
NULL, _xmltv_parse, NULL,
|
||||
&_xmltv_channels);
|
||||
NULL, _xmltv_parse, NULL, NULL);
|
||||
p = n = i + 1;
|
||||
} else if ( outbuf[i] == '|' ) {
|
||||
outbuf[i] = '\0';
|
||||
|
@ -506,5 +504,5 @@ void xmltv_init ( void )
|
|||
|
||||
void xmltv_load ( void )
|
||||
{
|
||||
//epggrab_module_channels_load(_xmltv_module);
|
||||
epggrab_module_channels_load(epggrab_module_find_by_id("xmltv"));
|
||||
}
|
||||
|
|
|
@ -17,17 +17,8 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* TODO: this current implementation is a bit naff, possibly not as
|
||||
* efficient as it could be (due to use of the a single list). But generally
|
||||
* the length of the list will be short and it shouldn't significantly
|
||||
* impact the overall performance
|
||||
*
|
||||
* TODO: currently all muxes are treated independently, this might result
|
||||
* in the same mux being scanned on multiple adapters, which is
|
||||
* a bit pointless.
|
||||
*
|
||||
* I think that at least _mux_next() and _ota_complete() need
|
||||
* updating to handle this
|
||||
* TODO: currently I don't try to block multiple scans of the same
|
||||
* tdmi on different adapters
|
||||
*/
|
||||
|
||||
#include "tvheadend.h"
|
||||
|
@ -37,8 +28,7 @@
|
|||
#include "epggrab.h"
|
||||
#include "epggrab/private.h"
|
||||
|
||||
LIST_HEAD(,epggrab_ota_mux) ota_mux_all;
|
||||
TAILQ_HEAD(, epggrab_ota_mux) ota_mux_reg;
|
||||
TAILQ_HEAD(, epggrab_ota_mux) ota_mux_all;
|
||||
|
||||
/* **************************************************************************
|
||||
* Global functions (called from DVB code)
|
||||
|
@ -47,21 +37,21 @@ TAILQ_HEAD(, epggrab_ota_mux) ota_mux_reg;
|
|||
void epggrab_mux_start ( th_dvb_mux_instance_t *tdmi )
|
||||
{
|
||||
epggrab_module_t *m;
|
||||
epggrab_module_ota_t *mod;
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
if (m->type == EPGGRAB_OTA) {
|
||||
mod = (epggrab_module_ota_t*)m;
|
||||
mod->start(mod, tdmi);
|
||||
((epggrab_module_ota_t*)m)->start((epggrab_module_ota_t*)m, tdmi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void epggrab_mux_stop ( th_dvb_mux_instance_t *tdmi, int timeout )
|
||||
{
|
||||
// Note: the slightly akward list iteration here is because
|
||||
// _ota_cancel/delete can remove the object and free() it
|
||||
epggrab_ota_mux_t *a, *b;
|
||||
a = LIST_FIRST(&ota_mux_all);
|
||||
a = TAILQ_FIRST(&tdmi->tdmi_epg_grab);
|
||||
while (a) {
|
||||
b = LIST_NEXT(a, glob_link);
|
||||
b = TAILQ_NEXT(a, tdmi_link);
|
||||
if (a->tdmi == tdmi) {
|
||||
if (timeout)
|
||||
epggrab_ota_timeout(a);
|
||||
|
@ -74,21 +64,15 @@ void epggrab_mux_stop ( th_dvb_mux_instance_t *tdmi, int timeout )
|
|||
|
||||
void epggrab_mux_delete ( th_dvb_mux_instance_t *tdmi )
|
||||
{
|
||||
epggrab_ota_mux_t *a, *b;
|
||||
a = LIST_FIRST(&ota_mux_all);
|
||||
while (a) {
|
||||
b = LIST_NEXT(a, glob_link);
|
||||
if (a->tdmi == tdmi)
|
||||
epggrab_ota_destroy(a);
|
||||
a = b;
|
||||
}
|
||||
epggrab_ota_destroy_by_tdmi(tdmi);
|
||||
}
|
||||
|
||||
int epggrab_mux_period ( th_dvb_mux_instance_t *tdmi )
|
||||
{
|
||||
int period = 0;
|
||||
epggrab_ota_mux_t *ota;
|
||||
TAILQ_FOREACH(ota, &ota_mux_reg, reg_link) {
|
||||
TAILQ_FOREACH(ota, &tdmi->tdmi_epg_grab, tdmi_link) {
|
||||
if (!ota->is_reg) break;
|
||||
if (ota->timeout > period)
|
||||
period = ota->timeout;
|
||||
}
|
||||
|
@ -98,11 +82,11 @@ int epggrab_mux_period ( th_dvb_mux_instance_t *tdmi )
|
|||
th_dvb_mux_instance_t *epggrab_mux_next ( th_dvb_adapter_t *tda )
|
||||
{
|
||||
epggrab_ota_mux_t *ota;
|
||||
TAILQ_FOREACH(ota, &ota_mux_reg, reg_link) {
|
||||
TAILQ_FOREACH(ota, &ota_mux_all, glob_link) {
|
||||
if (!ota->is_reg) break;
|
||||
if (ota->tdmi->tdmi_adapter == tda) break;
|
||||
}
|
||||
if (!ota) return NULL;
|
||||
return ota->tdmi;
|
||||
return ota ? ota->tdmi : NULL;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
|
@ -116,10 +100,17 @@ th_dvb_mux_instance_t *epggrab_mux_next ( th_dvb_adapter_t *tda )
|
|||
*/
|
||||
static int _ota_time_cmp ( void *_a, void *_b )
|
||||
{
|
||||
int r;
|
||||
time_t now, wa, wb;
|
||||
time(&now);
|
||||
epggrab_ota_mux_t *a = _a;
|
||||
epggrab_ota_mux_t *b = _b;
|
||||
|
||||
/* Unreg'd always at the end */
|
||||
r = a->is_reg - b->is_reg;
|
||||
if (r) return r;
|
||||
|
||||
/* Check when */
|
||||
wa = a->completed + a->interval;
|
||||
wb = b->completed + b->interval;
|
||||
if (wa < now && wb < now)
|
||||
|
@ -136,7 +127,7 @@ epggrab_ota_mux_t *epggrab_ota_create
|
|||
{
|
||||
/* Search for existing */
|
||||
epggrab_ota_mux_t *ota;
|
||||
LIST_FOREACH(ota, &ota_mux_all, glob_link) {
|
||||
TAILQ_FOREACH(ota, &ota_mux_all, glob_link) {
|
||||
if (ota->grab == mod && ota->tdmi == tdmi) break;
|
||||
}
|
||||
|
||||
|
@ -145,7 +136,9 @@ epggrab_ota_mux_t *epggrab_ota_create
|
|||
ota = calloc(1, sizeof(epggrab_ota_mux_t));
|
||||
ota->grab = mod;
|
||||
ota->tdmi = tdmi;
|
||||
LIST_INSERT_HEAD(&ota_mux_all, ota, glob_link);
|
||||
TAILQ_INSERT_TAIL(&ota_mux_all, ota, glob_link);
|
||||
TAILQ_INSERT_TAIL(&tdmi->tdmi_epg_grab, ota, tdmi_link);
|
||||
TAILQ_INSERT_TAIL(&mod->muxes, ota, grab_link);
|
||||
|
||||
} else {
|
||||
time_t now;
|
||||
|
@ -158,13 +151,33 @@ epggrab_ota_mux_t *epggrab_ota_create
|
|||
return ota;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create and register using mux ID
|
||||
*/
|
||||
void epggrab_ota_create_and_register_by_id
|
||||
( epggrab_module_ota_t *mod, int nid, int tsid, int period, int interval )
|
||||
{
|
||||
th_dvb_adapter_t *tda;
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
epggrab_ota_mux_t *ota;
|
||||
TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) {
|
||||
//TODO: if (tda->nitoid != nid) continue;
|
||||
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
|
||||
if (tdmi->tdmi_transport_stream_id != tsid) continue;
|
||||
ota = epggrab_ota_create(mod, tdmi);
|
||||
epggrab_ota_register(ota, period, interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destrory link (either because it was temporary OR mux deleted)
|
||||
*/
|
||||
void epggrab_ota_destroy ( epggrab_ota_mux_t *ota )
|
||||
{
|
||||
LIST_REMOVE(ota, glob_link);
|
||||
if (ota->is_reg) TAILQ_REMOVE(&ota_mux_reg, ota, reg_link);
|
||||
TAILQ_REMOVE(&ota_mux_all, ota, glob_link);
|
||||
TAILQ_REMOVE(&ota->tdmi->tdmi_epg_grab, ota, tdmi_link);
|
||||
TAILQ_REMOVE(&ota->grab->muxes, ota, grab_link);
|
||||
if (ota->destroy) ota->destroy(ota);
|
||||
else {
|
||||
if (ota->status) free(ota->status);
|
||||
|
@ -172,18 +185,46 @@ void epggrab_ota_destroy ( epggrab_ota_mux_t *ota )
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy by tdmi
|
||||
*/
|
||||
void epggrab_ota_destroy_by_tdmi ( th_dvb_mux_instance_t *tdmi )
|
||||
{
|
||||
epggrab_ota_mux_t *ota;
|
||||
while ((ota = TAILQ_FIRST(&tdmi->tdmi_epg_grab)))
|
||||
epggrab_ota_destroy(ota);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy by module
|
||||
*/
|
||||
void epggrab_ota_destroy_by_module ( epggrab_module_ota_t *mod )
|
||||
{
|
||||
epggrab_ota_mux_t *ota;
|
||||
while ((ota = TAILQ_FIRST(&mod->muxes)))
|
||||
epggrab_ota_destroy(ota);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register interest (called when useful data exists on the MUX
|
||||
* thus inserting it into the EPG scanning queue
|
||||
*/
|
||||
void epggrab_ota_register ( epggrab_ota_mux_t *ota, int timeout, int interval )
|
||||
{
|
||||
// TODO: handle changes to the interval/timeout?
|
||||
if (!ota->is_reg) {
|
||||
ota->timeout = timeout;
|
||||
int up = 0;
|
||||
ota->is_reg = 1;
|
||||
if (timeout > ota->timeout) {
|
||||
up = 1;
|
||||
ota->timeout = timeout;
|
||||
}
|
||||
if (interval > ota->interval) {
|
||||
up = 1;
|
||||
ota->interval = interval;
|
||||
ota->is_reg = 1;
|
||||
TAILQ_INSERT_SORTED(&ota_mux_reg, ota, reg_link, _ota_time_cmp);
|
||||
}
|
||||
|
||||
if (up) {
|
||||
TAILQ_REMOVE(&ota_mux_all, ota, glob_link);
|
||||
TAILQ_INSERT_SORTED(&ota_mux_all, ota, glob_link, _ota_time_cmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,8 +240,8 @@ static void _epggrab_ota_finished ( epggrab_ota_mux_t *ota )
|
|||
|
||||
/* Reinsert into reg queue */
|
||||
else {
|
||||
TAILQ_REMOVE(&ota_mux_reg, ota, reg_link);
|
||||
TAILQ_INSERT_SORTED(&ota_mux_reg, ota, reg_link, _ota_time_cmp);
|
||||
TAILQ_REMOVE(&ota_mux_all, ota, glob_link);
|
||||
TAILQ_INSERT_SORTED(&ota_mux_all, ota, glob_link, _ota_time_cmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,12 +257,23 @@ int epggrab_ota_begin ( epggrab_ota_mux_t *ota )
|
|||
|
||||
void epggrab_ota_complete ( epggrab_ota_mux_t *ota )
|
||||
{
|
||||
th_dvb_mux_instance_t *tdmi = ota->tdmi;
|
||||
|
||||
if (ota->state != EPGGRAB_OTA_MUX_COMPLETE) {
|
||||
ota->state = EPGGRAB_OTA_MUX_COMPLETE;
|
||||
time(&ota->completed);
|
||||
_epggrab_ota_finished(ota);
|
||||
|
||||
// TODO: need to inform tdmi
|
||||
/* Check others */
|
||||
TAILQ_FOREACH(ota, &tdmi->tdmi_epg_grab, tdmi_link) {
|
||||
if (ota->is_reg && ota->state != EPGGRAB_OTA_MUX_RUNNING) break;
|
||||
}
|
||||
|
||||
/* All complete (bring timer forward) */
|
||||
if (!ota) {
|
||||
gtimer_arm(&tdmi->tdmi_adapter->tda_mux_scanner_timer,
|
||||
dvb_adapter_mux_scanner, tdmi->tdmi_adapter, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
epggrab_module_t *epggrab_module_create
|
||||
( epggrab_module_t *skel,
|
||||
const char *id, const char *name );
|
||||
const char *id, const char *name, epggrab_channel_tree_t *channels );
|
||||
|
||||
char *epggrab_module_grab_spawn ( void *m );
|
||||
htsmsg_t *epggrab_module_trans_xml ( void *m, char *data );
|
||||
|
@ -39,6 +39,8 @@ int epggrab_module_enable_socket ( void *m, uint8_t e );
|
|||
|
||||
void epggrab_module_parse ( void *m, htsmsg_t *data );
|
||||
|
||||
void epggrab_module_channels_load ( epggrab_module_t *m );
|
||||
|
||||
/* **************************************************************************
|
||||
* Channel processing
|
||||
* *************************************************************************/
|
||||
|
@ -94,9 +96,17 @@ epggrab_module_ota_t *epggrab_module_ota_create
|
|||
* blocked (i.e. has completed within interval period)
|
||||
*/
|
||||
epggrab_ota_mux_t *epggrab_ota_create
|
||||
( struct epggrab_module_ota *mod, struct th_dvb_mux_instance *tdmi );
|
||||
( epggrab_module_ota_t *mod, struct th_dvb_mux_instance *tdmi );
|
||||
void epggrab_ota_create_and_register_by_id
|
||||
( epggrab_module_ota_t *mod, int nid, int tsid,
|
||||
int period, int interval );
|
||||
|
||||
void epggrab_ota_destroy ( epggrab_ota_mux_t *ota );
|
||||
/*
|
||||
* Delete
|
||||
*/
|
||||
void epggrab_ota_destroy ( epggrab_ota_mux_t *ota );
|
||||
void epggrab_ota_destroy_by_module ( epggrab_module_ota_t *mod );
|
||||
void epggrab_ota_destroy_by_tdmi ( struct th_dvb_mux_instance *tdmi );
|
||||
|
||||
/*
|
||||
* Register interest
|
||||
|
|
Loading…
Add table
Reference in a new issue