Very experimental attempt to integrate EPG scanning into the idle scan.
This commit is contained in:
parent
ae0cde8b50
commit
4cb753cc20
10 changed files with 315 additions and 115 deletions
3
Makefile
3
Makefile
|
@ -76,8 +76,9 @@ SRCS = src/main.c \
|
|||
|
||||
SRCS += src/epggrab/pyepg.c\
|
||||
src/epggrab/xmltv.c\
|
||||
src/epggrab/ota.c \
|
||||
src/epggrab/eit.c \
|
||||
src/epggrab/opentv.c
|
||||
src/epggrab/opentv.c \
|
||||
|
||||
SRCS += src/plumbing/tsfix.c \
|
||||
src/plumbing/globalheaders.c \
|
||||
|
|
|
@ -120,6 +120,8 @@ typedef struct th_dvb_mux_instance {
|
|||
|
||||
int tdmi_enabled;
|
||||
|
||||
LIST_HEAD(, epggrab_ota_mux) tdmi_epg_grabbers;
|
||||
|
||||
time_t tdmi_got_adapter;
|
||||
time_t tdmi_lost_adapter;
|
||||
|
||||
|
@ -148,13 +150,18 @@ typedef struct th_dvb_mux_instance {
|
|||
*/
|
||||
#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 {
|
||||
|
||||
TAILQ_ENTRY(th_dvb_adapter) tda_global_link;
|
||||
|
||||
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;
|
||||
|
||||
struct th_dvb_mux_instance_queue tda_initial_scan_queue;
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "tsdemux.h"
|
||||
#include "notify.h"
|
||||
#include "service.h"
|
||||
#include "epggrab/ota.h"
|
||||
|
||||
struct th_dvb_adapter_queue dvb_adapters;
|
||||
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 *
|
||||
tda_alloc(void)
|
||||
{
|
||||
int i;
|
||||
th_dvb_adapter_t *tda = calloc(1, sizeof(th_dvb_adapter_t));
|
||||
pthread_mutex_init(&tda->tda_delivery_mutex, NULL);
|
||||
|
||||
TAILQ_INIT(&tda->tda_scan_queues[0]);
|
||||
TAILQ_INIT(&tda->tda_scan_queues[1]);
|
||||
for (i = 0; i < TDA_SCANQ_NUM; i++ )
|
||||
TAILQ_INIT(&tda->tda_scan_queues[i]);
|
||||
TAILQ_INIT(&tda->tda_initial_scan_queue);
|
||||
TAILQ_INIT(&tda->tda_satconfs);
|
||||
|
||||
|
@ -418,13 +420,21 @@ dvb_adapter_init(uint32_t adapter_mask)
|
|||
void
|
||||
dvb_adapter_mux_scanner(void *aux)
|
||||
{
|
||||
epggrab_ota_mux_t *ota;
|
||||
th_dvb_adapter_t *tda = aux;
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
int i;
|
||||
int idle_epg;
|
||||
static const char* scan_string[] = {
|
||||
"Autoscan BAD",
|
||||
"Autoscan OK",
|
||||
"Autoscan EPG"
|
||||
};
|
||||
|
||||
if(tda->tda_rootpath == NULL)
|
||||
return; // No hardware
|
||||
|
||||
// default period
|
||||
gtimer_arm(&tda->tda_mux_scanner_timer, dvb_adapter_mux_scanner, tda, 20);
|
||||
|
||||
if(LIST_FIRST(&tda->tda_muxes) == NULL)
|
||||
|
@ -439,8 +449,18 @@ dvb_adapter_mux_scanner(void *aux)
|
|||
return;
|
||||
}
|
||||
|
||||
if(!tda->tda_idlescan && TAILQ_FIRST(&tda->tda_scan_queues[0]) == NULL) {
|
||||
/* Idlescan is disabled and no muxes are bad */
|
||||
/* Mark any incomplete EPG grabbers as timed out (basically complete) */
|
||||
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)
|
||||
return; // Quality monitoring is disabled
|
||||
|
@ -452,12 +472,26 @@ dvb_adapter_mux_scanner(void *aux)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Alternate between the other two (bad and OK) */
|
||||
for(i = 0; i < 2; i++) {
|
||||
tda->tda_scan_selector = !tda->tda_scan_selector;
|
||||
/* Alternate between the three queues (BAD, OK, EPG) */
|
||||
for(i = 0; i < TDA_SCANQ_NUM; i++) {
|
||||
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]);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -228,7 +228,17 @@ dvb_fe_stop(th_dvb_mux_instance_t *tdmi)
|
|||
assert(tdmi->tdmi_scan_queue == NULL);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "dvb_support.h"
|
||||
#include "notify.h"
|
||||
#include "subscriptions.h"
|
||||
#include "epggrab/ota.h"
|
||||
|
||||
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
|
||||
dvb_mux_destroy(th_dvb_mux_instance_t *tdmi)
|
||||
{
|
||||
epggrab_ota_mux_t *ota;
|
||||
th_dvb_adapter_t *tda = tdmi->tdmi_adapter;
|
||||
service_t *t;
|
||||
|
||||
|
@ -330,6 +332,9 @@ dvb_mux_destroy(th_dvb_mux_instance_t *tdmi)
|
|||
if(tdmi->tdmi_table_initial)
|
||||
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);
|
||||
|
||||
free(tdmi->tdmi_network);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "htsmsg.h"
|
||||
#include "settings.h"
|
||||
#include "tvheadend.h"
|
||||
#include "src/queue.h"
|
||||
#include "queue.h"
|
||||
#include "epg.h"
|
||||
#include "epggrab.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 )
|
||||
{
|
||||
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) {
|
||||
if (m->tune) m->tune(m, tdmi);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#ifndef __EPGGRAB_H__
|
||||
#define __EPGGRAB_H__
|
||||
|
||||
typedef struct epggrab_module epggrab_module_t;
|
||||
|
||||
#include <pthread.h>
|
||||
#include "channels.h"
|
||||
#include "dvb/dvb.h"
|
||||
|
||||
typedef struct epggrab_module epggrab_module_t;
|
||||
#include "epggrab/ota.h"
|
||||
|
||||
/* **************************************************************************
|
||||
* Grabber Stats
|
||||
|
@ -96,13 +97,14 @@ struct epggrab_module
|
|||
{
|
||||
LIST_ENTRY(epggrab_module) link; ///< Global list link
|
||||
|
||||
const char *id; ///< Module identifier
|
||||
const char *name; ///< Module name (for display)
|
||||
const char *path; ///< Module path (for fixed config)
|
||||
const uint8_t flags; ///< Mode flag
|
||||
uint8_t enabled; ///< Whether the module is enabled
|
||||
int sock; ///< Socket descriptor
|
||||
epggrab_channel_tree_t *channels; ///< Channel list
|
||||
const char *id; ///< Module identifier
|
||||
const char *name; ///< Module name (for display)
|
||||
const char *path; ///< Module path (for fixed config)
|
||||
const uint8_t flags; ///< Mode flag
|
||||
uint8_t enabled; ///< Whether the module is enabled
|
||||
int sock; ///< Socket descriptor
|
||||
epggrab_channel_tree_t *channels; ///< Channel list
|
||||
LIST_HEAD(, epggrab_ota_mux) muxes; ///< Linked muxes
|
||||
|
||||
/* Enable/Disable */
|
||||
int (*enable) ( epggrab_module_t *m, uint8_t e );
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "channels.h"
|
||||
#include "huffman.h"
|
||||
#include "epg.h"
|
||||
#include "epggrab/ota.h"
|
||||
#include "epggrab/opentv.h"
|
||||
#include "subscriptions.h"
|
||||
#include "streaming.h"
|
||||
|
@ -42,6 +43,9 @@
|
|||
* 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 */
|
||||
typedef struct opentv_dict
|
||||
{
|
||||
|
@ -378,10 +382,23 @@ static int _opentv_parse_event_section
|
|||
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
|
||||
( 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
|
||||
|
@ -395,7 +412,7 @@ static int _opentv_channel_callback
|
|||
uint16_t sid;
|
||||
int i, j, k, tdlen, dlen, dtag, tslen;
|
||||
channel_t *ch;
|
||||
if (tid != 0x4a) return 0;
|
||||
_opentv_table_callback(mod, tdmi);
|
||||
i = 7 + ((((int)buf[5] & 0xf) << 8) | buf[6]);
|
||||
tslen = (((int)buf[i] & 0xf) << 8) | buf[i+1];
|
||||
i += 2;
|
||||
|
@ -441,82 +458,6 @@ static int _opentv_channel_callback
|
|||
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
|
||||
* ***********************************************************************/
|
||||
|
@ -528,7 +469,7 @@ static void _opentv_tune ( epggrab_module_t *m, th_dvb_mux_instance_t *tdmi )
|
|||
int *t;
|
||||
struct dmx_sct_filter_params *fp;
|
||||
opentv_module_t *mod = (opentv_module_t*)m;
|
||||
|
||||
|
||||
/* Install tables */
|
||||
if (m->enabled && (mod->prov->tsid == tdmi->tdmi_transport_stream_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 )
|
||||
{
|
||||
int save = 0;
|
||||
pthread_t t;
|
||||
pthread_attr_t ta;
|
||||
th_dvb_adapter_t *tda;
|
||||
th_dvb_mux_instance_t *tdmi;
|
||||
opentv_module_t *mod = (opentv_module_t*)m;
|
||||
pthread_mutex_lock(&mod->mutex);
|
||||
if (m->enabled != e) {
|
||||
m->enabled = e;
|
||||
if (e) {
|
||||
pthread_attr_init(&ta);
|
||||
pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&t, &ta, _opentv_thread, mod);
|
||||
} else
|
||||
pthread_cond_signal(&mod->cond);
|
||||
save = 1;
|
||||
|
||||
if (m->enabled == e) return 0;
|
||||
|
||||
m->enabled = e;
|
||||
|
||||
/* 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->prov->tsid) continue;
|
||||
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 )
|
||||
|
|
110
src/epggrab/ota.c
Normal file
110
src/epggrab/ota.c
Normal 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
74
src/epggrab/ota.h
Normal 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__ */
|
Loading…
Add table
Reference in a new issue