Merge branch 'epg-autoscan' into epg-eitscan

This commit is contained in:
Adam Sutton 2012-06-21 21:24:35 +01:00
commit 9e7391bf41
10 changed files with 315 additions and 115 deletions

View file

@ -76,8 +76,9 @@ SRCS = src/main.c \
SRCS += src/epggrab/pyepg.c\ SRCS += src/epggrab/pyepg.c\
src/epggrab/xmltv.c\ src/epggrab/xmltv.c\
src/epggrab/ota.c \
src/epggrab/eit.c \ src/epggrab/eit.c \
src/epggrab/opentv.c src/epggrab/opentv.c \
SRCS += src/plumbing/tsfix.c \ SRCS += src/plumbing/tsfix.c \
src/plumbing/globalheaders.c \ src/plumbing/globalheaders.c \

View file

@ -115,6 +115,8 @@ typedef struct th_dvb_mux_instance {
int tdmi_enabled; int tdmi_enabled;
LIST_HEAD(, epggrab_ota_mux) tdmi_epg_grabbers;
time_t tdmi_got_adapter; time_t tdmi_got_adapter;
time_t tdmi_lost_adapter; time_t tdmi_lost_adapter;
@ -143,13 +145,18 @@ typedef struct th_dvb_mux_instance {
*/ */
#define TDA_MUX_HASH_WIDTH 101 #define TDA_MUX_HASH_WIDTH 101
#define TDA_SCANQ_BAD 0 ///< Bad muxes (monitor quality)
#define TDA_SCANQ_OK 1 ///< OK muxes
#define TDA_SCANQ_EPG 2 ///< EPG muxes (TBD)
#define TDA_SCANQ_NUM 3
typedef struct th_dvb_adapter { typedef struct th_dvb_adapter {
TAILQ_ENTRY(th_dvb_adapter) tda_global_link; TAILQ_ENTRY(th_dvb_adapter) tda_global_link;
struct th_dvb_mux_instance_list tda_muxes; struct th_dvb_mux_instance_list tda_muxes;
struct th_dvb_mux_instance_queue tda_scan_queues[2]; struct th_dvb_mux_instance_queue tda_scan_queues[TDA_SCANQ_NUM];
int tda_scan_selector; int tda_scan_selector;
struct th_dvb_mux_instance_queue tda_initial_scan_queue; struct th_dvb_mux_instance_queue tda_initial_scan_queue;

View file

@ -41,6 +41,7 @@
#include "tsdemux.h" #include "tsdemux.h"
#include "notify.h" #include "notify.h"
#include "service.h" #include "service.h"
#include "epggrab/ota.h"
struct th_dvb_adapter_queue dvb_adapters; struct th_dvb_adapter_queue dvb_adapters;
struct th_dvb_mux_instance_tree dvb_muxes; struct th_dvb_mux_instance_tree dvb_muxes;
@ -53,11 +54,12 @@ static void *dvb_adapter_input_dvr(void *aux);
static th_dvb_adapter_t * static th_dvb_adapter_t *
tda_alloc(void) tda_alloc(void)
{ {
int i;
th_dvb_adapter_t *tda = calloc(1, sizeof(th_dvb_adapter_t)); th_dvb_adapter_t *tda = calloc(1, sizeof(th_dvb_adapter_t));
pthread_mutex_init(&tda->tda_delivery_mutex, NULL); pthread_mutex_init(&tda->tda_delivery_mutex, NULL);
TAILQ_INIT(&tda->tda_scan_queues[0]); for (i = 0; i < TDA_SCANQ_NUM; i++ )
TAILQ_INIT(&tda->tda_scan_queues[1]); TAILQ_INIT(&tda->tda_scan_queues[i]);
TAILQ_INIT(&tda->tda_initial_scan_queue); TAILQ_INIT(&tda->tda_initial_scan_queue);
TAILQ_INIT(&tda->tda_satconfs); TAILQ_INIT(&tda->tda_satconfs);
@ -418,13 +420,21 @@ dvb_adapter_init(uint32_t adapter_mask)
void void
dvb_adapter_mux_scanner(void *aux) dvb_adapter_mux_scanner(void *aux)
{ {
epggrab_ota_mux_t *ota;
th_dvb_adapter_t *tda = aux; th_dvb_adapter_t *tda = aux;
th_dvb_mux_instance_t *tdmi; th_dvb_mux_instance_t *tdmi;
int i; int i;
int idle_epg;
static const char* scan_string[] = {
"Autoscan BAD",
"Autoscan OK",
"Autoscan EPG"
};
if(tda->tda_rootpath == NULL) if(tda->tda_rootpath == NULL)
return; // No hardware return; // No hardware
// default period
gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 20); gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 20);
if(LIST_FIRST(&tda->tda_muxes) == NULL) if(LIST_FIRST(&tda->tda_muxes) == NULL)
@ -439,8 +449,18 @@ dvb_adapter_mux_scanner(void *aux)
return; return;
} }
if(!tda->tda_idlescan && TAILQ_FIRST(&tda->tda_scan_queues[0]) == NULL) { /* Mark any incomplete EPG grabbers as timed out (basically complete) */
/* Idlescan is disabled and no muxes are bad */ if (tda->tda_mux_current)
LIST_FOREACH(ota, &tda->tda_mux_current->tdmi_epg_grabbers, tdmi_link) {
epggrab_ota_timeout(ota);
}
/* Idle or EPG scan enabled */
idle_epg = tda->tda_idlescan ||
TAILQ_FIRST(&tda->tda_scan_queues[TDA_SCANQ_EPG]);
/* Idlescan is disabled and no muxes are bad */
if(!idle_epg && TAILQ_FIRST(&tda->tda_scan_queues[TDA_SCANQ_BAD]) == NULL) {
if(!tda->tda_qmon) if(!tda->tda_qmon)
return; // Quality monitoring is disabled return; // Quality monitoring is disabled
@ -452,12 +472,26 @@ dvb_adapter_mux_scanner(void *aux)
return; return;
} }
/* Alternate between the other two (bad and OK) */ /* Alternate between the three queues (BAD, OK, EPG) */
for(i = 0; i < 2; i++) { for(i = 0; i < TDA_SCANQ_NUM; i++) {
tda->tda_scan_selector = !tda->tda_scan_selector; tda->tda_scan_selector++;
if (tda->tda_scan_selector == TDA_SCANQ_NUM)
tda->tda_scan_selector = 0;
tdmi = TAILQ_FIRST(&tda->tda_scan_queues[tda->tda_scan_selector]); tdmi = TAILQ_FIRST(&tda->tda_scan_queues[tda->tda_scan_selector]);
if(tdmi != NULL) { if(tdmi != NULL) {
dvb_fe_tune(tdmi, "Autoscan");
/* EPG - adjust dwell time */
if (tda->tda_scan_selector == TDA_SCANQ_EPG) {
epggrab_ota_mux_t *ota;
int period = 20;
LIST_FOREACH(ota, &tdmi->tdmi_epg_grabbers, tdmi_link) {
if (ota->timeout > period) period = ota->timeout;
}
gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, period);
}
dvb_fe_tune(tdmi, scan_string[tda->tda_scan_selector]);
return; return;
} }
} }

View file

@ -228,7 +228,17 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi)
assert(tdmi->tdmi_scan_queue == NULL); assert(tdmi->tdmi_scan_queue == NULL);
if(tdmi->tdmi_enabled) { if(tdmi->tdmi_enabled) {
tdmi->tdmi_scan_queue = &tda->tda_scan_queues[tdmi->tdmi_quality == 100]; int ti;
time_t now;
epggrab_ota_mux_t *ota;
time(&now);
LIST_FOREACH(ota, &tdmi->tdmi_epg_grabbers, tdmi_link) {
if ( now >= (ota->completed+ota->interval) ) break;
}
ti = ota ? TDA_SCANQ_EPG
: tdmi->tdmi_quality == 100 ? TDA_SCANQ_OK
: TDA_SCANQ_BAD;
tdmi->tdmi_scan_queue = &tda->tda_scan_queues[ti];
TAILQ_INSERT_TAIL(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link); TAILQ_INSERT_TAIL(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link);
} }

View file

@ -44,6 +44,7 @@
#include "dvb_support.h" #include "dvb_support.h"
#include "notify.h" #include "notify.h"
#include "subscriptions.h" #include "subscriptions.h"
#include "epggrab/ota.h"
struct th_dvb_mux_instance_tree dvb_muxes; struct th_dvb_mux_instance_tree dvb_muxes;
@ -297,6 +298,7 @@ dvb_mux_create(th_dvb_adapter_t *tda, const struct dvb_mux_conf *dmc,
void void
dvb_mux_destroy(th_dvb_mux_instance_t *tdmi) dvb_mux_destroy(th_dvb_mux_instance_t *tdmi)
{ {
epggrab_ota_mux_t *ota;
th_dvb_adapter_t *tda = tdmi->tdmi_adapter; th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
service_t *t; service_t *t;
@ -330,6 +332,9 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi)
if(tdmi->tdmi_table_initial) if(tdmi->tdmi_table_initial)
tda->tda_initial_num_mux--; tda->tda_initial_num_mux--;
while ((ota = LIST_FIRST(&tdmi->tdmi_epg_grabbers)))
epggrab_ota_unregister(ota);
hts_settings_remove("dvbmuxes/%s", tdmi->tdmi_identifier); hts_settings_remove("dvbmuxes/%s", tdmi->tdmi_identifier);
free(tdmi->tdmi_network); free(tdmi->tdmi_network);

View file

@ -10,7 +10,7 @@
#include "htsmsg.h" #include "htsmsg.h"
#include "settings.h" #include "settings.h"
#include "tvheadend.h" #include "tvheadend.h"
#include "src/queue.h" #include "queue.h"
#include "epg.h" #include "epg.h"
#include "epggrab.h" #include "epggrab.h"
#include "epggrab/eit.h" #include "epggrab/eit.h"
@ -834,6 +834,18 @@ void epggrab_channel_mod ( channel_t *ch )
void epggrab_tune ( th_dvb_mux_instance_t *tdmi ) void epggrab_tune ( th_dvb_mux_instance_t *tdmi )
{ {
epggrab_module_t *m; epggrab_module_t *m;
epggrab_ota_mux_t *o;
th_dvb_mux_instance_t *t;
/* Cancel all currently active ota grabs */
LIST_FOREACH(t, &tdmi->tdmi_adapter->tda_muxes, tdmi_adapter_link) {
if (t == tdmi) continue;
LIST_FOREACH(o, &t->tdmi_epg_grabbers, tdmi_link) {
epggrab_ota_cancel(o);
}
}
/* Inform all modules */
LIST_FOREACH(m, &epggrab_modules, link) { LIST_FOREACH(m, &epggrab_modules, link) {
if (m->tune) m->tune(m, tdmi); if (m->tune) m->tune(m, tdmi);
} }

View file

@ -1,11 +1,12 @@
#ifndef __EPGGRAB_H__ #ifndef __EPGGRAB_H__
#define __EPGGRAB_H__ #define __EPGGRAB_H__
typedef struct epggrab_module epggrab_module_t;
#include <pthread.h> #include <pthread.h>
#include "channels.h" #include "channels.h"
#include "dvb/dvb.h" #include "dvb/dvb.h"
#include "epggrab/ota.h"
typedef struct epggrab_module epggrab_module_t;
/* ************************************************************************** /* **************************************************************************
* Grabber Stats * Grabber Stats
@ -96,13 +97,14 @@ struct epggrab_module
{ {
LIST_ENTRY(epggrab_module) link; ///< Global list link LIST_ENTRY(epggrab_module) link; ///< Global list link
const char *id; ///< Module identifier const char *id; ///< Module identifier
const char *name; ///< Module name (for display) const char *name; ///< Module name (for display)
const char *path; ///< Module path (for fixed config) const char *path; ///< Module path (for fixed config)
const uint8_t flags; ///< Mode flag const uint8_t flags; ///< Mode flag
uint8_t enabled; ///< Whether the module is enabled uint8_t enabled; ///< Whether the module is enabled
int sock; ///< Socket descriptor int sock; ///< Socket descriptor
epggrab_channel_tree_t *channels; ///< Channel list epggrab_channel_tree_t *channels; ///< Channel list
LIST_HEAD(, epggrab_ota_mux) muxes; ///< Linked muxes
/* Enable/Disable */ /* Enable/Disable */
int (*enable) ( epggrab_module_t *m, uint8_t e ); int (*enable) ( epggrab_module_t *m, uint8_t e );

View file

@ -25,6 +25,7 @@
#include "channels.h" #include "channels.h"
#include "huffman.h" #include "huffman.h"
#include "epg.h" #include "epg.h"
#include "epggrab/ota.h"
#include "epggrab/opentv.h" #include "epggrab/opentv.h"
#include "subscriptions.h" #include "subscriptions.h"
#include "streaming.h" #include "streaming.h"
@ -42,6 +43,9 @@
* dicts/provs etc... they're only used to get things up and running * dicts/provs etc... they're only used to get things up and running
* ***********************************************************************/ * ***********************************************************************/
#define OPENTV_SCAN_MAX 600 // 10min max scan period
#define OPENTV_SCAN_PER 3600 // 1hour interval
/* Huffman dictionary */ /* Huffman dictionary */
typedef struct opentv_dict typedef struct opentv_dict
{ {
@ -378,10 +382,23 @@ static int _opentv_parse_event_section
return 0; return 0;
} }
static void _opentv_table_callback
( opentv_module_t *m, th_dvb_mux_instance_t *tdmi )
{
epggrab_ota_mux_t *ota;
ota = epggrab_ota_register((epggrab_module_t*)m, tdmi,
OPENTV_SCAN_MAX, OPENTV_SCAN_PER);
if (epggrab_ota_begin(ota)) {
// setup internal status
}
}
static int _opentv_event_callback static int _opentv_event_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 )
{ {
return _opentv_parse_event_section((opentv_module_t*)p, buf, len); opentv_module_t *mod = (opentv_module_t*)p;
_opentv_table_callback(mod, tdmi);
return _opentv_parse_event_section(mod, buf, len);
} }
// TODO: this function is currently a bit of a mess // TODO: this function is currently a bit of a mess
@ -395,7 +412,7 @@ static int _opentv_channel_callback
uint16_t sid; uint16_t sid;
int i, j, k, tdlen, dlen, dtag, tslen; int i, j, k, tdlen, dlen, dtag, tslen;
channel_t *ch; channel_t *ch;
if (tid != 0x4a) return 0; _opentv_table_callback(mod, tdmi);
i = 7 + ((((int)buf[5] & 0xf) << 8) | buf[6]); i = 7 + ((((int)buf[5] & 0xf) << 8) | buf[6]);
tslen = (((int)buf[i] & 0xf) << 8) | buf[i+1]; tslen = (((int)buf[i] & 0xf) << 8) | buf[i+1];
i += 2; i += 2;
@ -441,82 +458,6 @@ static int _opentv_channel_callback
return 0; return 0;
} }
/* ************************************************************************
* Tuning Thread
* ***********************************************************************/
static void _opentv_stream ( void *p, streaming_message_t *sm )
{
// TODO: handle start?
// TODO: handle stop?
}
// TODO: if channel not found we still wait
// TODO: make time periods configurable?
// TODO: dynamic detection of when to start/stop
static void* _opentv_thread ( void *p )
{
int err;
service_t *svc;
th_subscription_t *sub;
streaming_target_t stream;
time_t start;
struct timespec ts;
opentv_module_t *mod = (opentv_module_t*)p;
streaming_target_init(&stream, _opentv_stream, NULL, 0);
tvhlog(LOG_INFO, mod->id, "thread started\n");
do {
/* Find channel and subscribe */
tvhlog(LOG_DEBUG, mod->id, "grab begin %d %d", mod->prov->tsid, mod->prov->sid);
pthread_mutex_lock(&global_lock);
svc = _opentv_find_service(mod->prov->tsid, mod->prov->sid);
if (svc) {
sub = subscription_create_from_service(svc, mod->prov->id,
&stream, 0);
if (sub) subscription_change_weight(sub, 1);
}
else
sub = NULL;
pthread_mutex_unlock(&global_lock);
if (sub) tvhlog(LOG_DEBUG, mod->id, "subscription added");
/* Allow scanning */
if (sub) {
time(&start);
ts.tv_nsec = 0;
pthread_mutex_lock(&mod->mutex);
while ( mod->enabled ) {
ts.tv_sec = start + 300;
err = pthread_cond_timedwait(&mod->cond, &mod->mutex, &ts);
if (err == ETIMEDOUT ) break;
}
pthread_mutex_unlock(&mod->mutex);
}
tvhlog(LOG_DEBUG, mod->id, "grab complete");
/* Terminate subscription */
pthread_mutex_lock(&global_lock);
if (sub) subscription_unsubscribe(sub);
pthread_mutex_unlock(&global_lock);
/* Wait */
time(&mod->updated);
pthread_mutex_lock(&mod->mutex);
while ( mod->enabled ) {
ts.tv_sec = mod->updated + 3600;
err = pthread_cond_timedwait(&mod->cond, &mod->mutex, &ts);
if (err == ETIMEDOUT) break;
}
if (!mod->enabled) break;
pthread_mutex_unlock(&mod->mutex);
} while (1);
pthread_mutex_unlock(&mod->mutex);
return NULL;
}
/* ************************************************************************ /* ************************************************************************
* Module Setup * Module Setup
* ***********************************************************************/ * ***********************************************************************/
@ -528,7 +469,7 @@ 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;
/* Install tables */ /* Install tables */
if (m->enabled && (mod->prov->tsid == tdmi->tdmi_transport_stream_id)) { if (m->enabled && (mod->prov->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->prov->id);
@ -568,23 +509,27 @@ 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 ) static int _opentv_enable ( epggrab_module_t *m, uint8_t e )
{ {
int save = 0; th_dvb_adapter_t *tda;
pthread_t t; th_dvb_mux_instance_t *tdmi;
pthread_attr_t ta;
opentv_module_t *mod = (opentv_module_t*)m; opentv_module_t *mod = (opentv_module_t*)m;
pthread_mutex_lock(&mod->mutex);
if (m->enabled != e) { if (m->enabled == e) return 0;
m->enabled = e;
if (e) { m->enabled = e;
pthread_attr_init(&ta);
pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED); /* Find muxes and enable/disable */
pthread_create(&t, &ta, _opentv_thread, mod); TAILQ_FOREACH(tda, &dvb_adapters, tda_global_link) {
} else LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
pthread_cond_signal(&mod->cond); if (tdmi->tdmi_transport_stream_id != mod->prov->tsid) continue;
save = 1; if (e) {
epggrab_ota_register(m, tdmi, OPENTV_SCAN_MAX, OPENTV_SCAN_PER);
} else {
epggrab_ota_unregister_one(m, tdmi);
}
}
} }
pthread_mutex_unlock(&mod->mutex);
return save; return 1;
} }
void opentv_init ( epggrab_module_list_t *list ) void opentv_init ( epggrab_module_list_t *list )

110
src/epggrab/ota.c Normal file
View file

@ -0,0 +1,110 @@
/*
* Electronic Program Guide - EPG grabber OTA functions
* Copyright (C) 2012 Adam Sutton
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tvheadend.h"
#include "queue.h"
#include "epg.h"
#include "dvb/dvb.h"
#include "epggrab.h"
#include "epggrab/ota.h"
LIST_HEAD(,epggrab_ota_mux) ota_muxes;
epggrab_ota_mux_t *epggrab_ota_register
( epggrab_module_t *mod, th_dvb_mux_instance_t *tdmi,
int timeout, int interval )
{
epggrab_ota_mux_t *ota;
/* Check for existing */
LIST_FOREACH(ota, &ota_muxes, glob_link) {
if (ota->grab == mod && ota->tdmi == tdmi) return ota;
}
/* Install new */
ota = calloc(1, sizeof(epggrab_ota_mux_t));
ota->grab = mod;
ota->tdmi = tdmi;
ota->timeout = timeout;
ota->interval = interval;
LIST_INSERT_HEAD(&ota_muxes, ota, glob_link);
LIST_INSERT_HEAD(&tdmi->tdmi_epg_grabbers, ota, tdmi_link);
LIST_INSERT_HEAD(&mod->muxes, ota, grab_link);
return ota;
}
/*
* Unregister
*/
void epggrab_ota_unregister ( epggrab_ota_mux_t *ota )
{
LIST_REMOVE(ota, glob_link);
LIST_REMOVE(ota, tdmi_link);
LIST_REMOVE(ota, grab_link);
free(ota);
}
void epggrab_ota_unregister_one
( epggrab_module_t *mod, th_dvb_mux_instance_t *tdmi )
{
epggrab_ota_mux_t *ota;
LIST_FOREACH(ota, &ota_muxes, glob_link) {
if (ota->grab == mod && (!tdmi || ota->tdmi == tdmi)) {
epggrab_ota_unregister(ota);
if (tdmi) break;
}
}
}
void epggrab_ota_unregister_all
( epggrab_module_t *mod )
{
epggrab_ota_unregister_one(mod, NULL);
}
/*
* Status
*/
int epggrab_ota_begin ( epggrab_ota_mux_t *ota )
{
if (ota->status != EPGGRAB_OTA_STARTED) {
ota->status = EPGGRAB_OTA_STARTED;
time(&ota->started);
return 1;
}
return 0;
}
void epggrab_ota_complete ( epggrab_ota_mux_t *ota )
{
if (ota->status != EPGGRAB_OTA_COMPLETED)
time(&ota->completed);
ota->status = EPGGRAB_OTA_COMPLETED;
}
void epggrab_ota_cancel ( epggrab_ota_mux_t *ota )
{
ota->status = EPGGRAB_OTA_IDLE;
}
void epggrab_ota_timeout ( epggrab_ota_mux_t *ota )
{
epggrab_ota_complete(ota);
// TODO: for now just treat as completed, stops it being allowed
// to immediately re-enter the queue
}

74
src/epggrab/ota.h Normal file
View file

@ -0,0 +1,74 @@
/*
* Electronic Program Guide - EPG grabber OTA functions
* Copyright (C) 2012 Adam Sutton
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __TVH_EPGGRAB_OTA_H__
#define __TVH_EPGGRAB_OTA_H__
#include "queue.h"
#include <sys/time.h>
/*
* Mux to OTA Grabber link
*/
typedef struct epggrab_ota_mux
{
LIST_ENTRY(epggrab_ota_mux) glob_link; ///< Global list of all instances
LIST_ENTRY(epggrab_ota_mux) grab_link; ///< Grabber's list link
LIST_ENTRY(epggrab_ota_mux) tdmi_link; ///< Mux list link
struct epggrab_module *grab; ///< Grabber module
struct th_dvb_mux_instance *tdmi; ///< Mux instance
int timeout; ///< Time out if this long
int interval; ///< Re-grab this often
enum {
EPGGRAB_OTA_IDLE,
EPGGRAB_OTA_STARTED,
EPGGRAB_OTA_COMPLETED
} status; ///< Status of the scan
time_t started; ///< Time of last start
time_t completed; ///< Time of last completion
} epggrab_ota_mux_t;
/*
* Register interest (will return existing if already registered)
*/
epggrab_ota_mux_t *epggrab_ota_register
( struct epggrab_module *mod, struct th_dvb_mux_instance *tdmi,
int timeout, int interval );
/*
* Unregister
*/
void epggrab_ota_unregister
( epggrab_ota_mux_t *ota );
void epggrab_ota_unregister_one
( struct epggrab_module *mod, struct th_dvb_mux_instance *tdmi );
void epggrab_ota_unregister_all
( struct epggrab_module *mod );
/*
* Status
*/
int epggrab_ota_begin ( epggrab_ota_mux_t *ota );
void epggrab_ota_complete ( epggrab_ota_mux_t *ota );
void epggrab_ota_cancel ( epggrab_ota_mux_t *ota );
void epggrab_ota_timeout ( epggrab_ota_mux_t *ota );
#endif /* __TVH_EPGGRAB_OTA_H__ */