Merge branch 'epg-autoscan' into epg-eitscan
This commit is contained in:
commit
9e7391bf41
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\
|
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 \
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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
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