Start initial work on new epggrab framework.

This commit is contained in:
Adam Sutton 2012-05-16 16:48:09 +01:00
parent 5084ca63fd
commit 4f8dc6e315
4 changed files with 417 additions and 0 deletions

47
src/cron.c Normal file
View file

@ -0,0 +1,47 @@
#include "cron.h"
#include <time.h>
int cron_is_time ( cron_t *cron )
{
int ret = 1;
uint64_t b = 0x1;
/* Get the current time */
time_t t = time(NULL);
struct tm now;
localtime_r(&t, &now);
/* Check */
if ( ret && !((b << now.tm_min) & cron->min) ) ret = 0;
if ( ret && !((b << now.tm_hour) & cron->hour) ) ret = 0;
if ( ret && !((b << now.tm_mday) & cron->dom) ) ret = 0;
if ( ret && !((b << now.tm_mon) & cron->mon) ) ret = 0;
if ( ret && !((b << now.tm_wday) & cron->dow) ) ret = 0;
return ret;
}
void cron_pack ( cron_t *cron, htsmsg_t *msg )
{
htsmsg_add_u32(msg, "min0", cron->min & 0xFFFFFFFF);
htsmsg_add_u32(msg, "min1", cron->min >> 32);
htsmsg_add_u32(msg, "hour", cron->hour);
htsmsg_add_u32(msg, "dom", cron->dom);
htsmsg_add_u32(msg, "mon", cron->mon);
htsmsg_add_u32(msg, "dow", cron->dow);
}
void cron_unpack ( cron_t *cron, htsmsg_t *msg )
{
uint32_t u32 = 0;
htsmsg_get_u32(msg, "min0", &u32);
cron->min = u32;
htsmsg_get_u32(msg, "min1", &u32);
cron->min += ((uint64_t)u32 << 32);
htsmsg_get_u32(msg, "hour", &cron->hour);
htsmsg_get_u32(msg, "dom", &cron->dom);
htsmsg_get_u32(msg, "mon", &u32);
cron->mon = (uint16_t)u32;
htsmsg_get_u32(msg, "dow", &u32);
cron->dow = (uint8_t)u32;
}

22
src/cron.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef __CRON_H__
#define __CRON_H__
#include <stdint.h>
#include <sys/types.h>
#include "htsmsg.h"
typedef struct cron
{
uint64_t min; ///< Minutes
uint32_t hour; ///< Hours
uint32_t dom; ///< Day of month
uint16_t mon; ///< Month
uint8_t dow; ///< Day of week
} cron_t;
void cron_set_string ( cron_t *cron, const char *str );
int cron_is_time ( cron_t *cron );
void cron_pack ( cron_t *cron, htsmsg_t *msg );
void cron_unpack ( cron_t *cron, htsmsg_t *msg );
#endif /* __CRON_H__ */

278
src/epggrab.c Normal file
View file

@ -0,0 +1,278 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "htsmsg.h"
#include "settings.h"
#include "tvheadend.h"
#include "epggrab.h"
/* Thread protection */
int epggrab_confver;
pthread_mutex_t epggrab_mutex;
pthread_cond_t epggrab_cond;
/* Config */
uint32_t epggrab_advanced;
uint32_t epggrab_eit;
uint32_t epggrab_interval;
epggrab_module_t* epggrab_module;
epggrab_sched_list_t epggrab_schedule;
/* Internal prototypes */
static void* _epggrab_thread ( void* );
static time_t _epggrab_thread_simple ( void );
static time_t _epggrab_thread_advanced ( void );
static void _epggrab_load ( void );
static void _epggrab_save ( void );
static void _epggrab_set_schedule ( int, epggrab_sched_t* );
/*
* Initialise
*/
void epggrab_init ( void )
{
/* Defaults */
epggrab_advanced = 0;
epggrab_eit = 1; // on air grab enabled
epggrab_interval = 12; // hours
epggrab_module = NULL; // disabled
// TODO: HACK : testing
#if 0
epggrab_advanced = 1;
epggrab_sched_t es;
memset(&es, 0, sizeof(epggrab_sched_t));
es.opts = strdup("-d 1");
es.mod = NULL;
es.cron.hour = 0x1001;
_epggrab_set_schedule(1, &es);
_epggrab_save();
#endif
/* Start thread */
pthread_t tid;
pthread_attr_t tattr;
pthread_attr_init(&tattr);
pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &tattr, _epggrab_thread, NULL);
}
/*
* Simple run
*/
time_t _epggrab_thread_simple ( void )
{
/* Copy config */
time_t ret = time(NULL) + epggrab_interval;
epggrab_module_t* mod = epggrab_module;
/* Unlock */
pthread_mutex_unlock(&epggrab_mutex);
/* Run the module */
if ( mod ) mod->run(NULL);
/* Re-lock */
pthread_mutex_lock(&epggrab_mutex);
return ret;
}
/*
* Advanced run
*
* TODO: might be nice to put each module run in another thread, in case
* they're scheduled at the same time?
*/
time_t _epggrab_thread_advanced ( void )
{
epggrab_sched_t *s;
/* Determine which to run */
LIST_FOREACH(s, &epggrab_schedule, es_link) {
if ( s->mod && cron_is_time(&s->cron) ) {
s->mod->run(s->opts);
}
}
// TODO: make this driven off next time
// get cron to tell us when next call will run
return time(NULL) + 30;
}
/*
* Thread
*/
void* _epggrab_thread ( void* p )
{
int confver = 0;
struct timespec ts;
pthread_mutex_lock(&epggrab_mutex);
/* Load */
_epggrab_load();
/* Setup timeout */
ts.tv_nsec = 0;
ts.tv_sec = 0;
while ( 1 ) {
/* Check for config change */
while ( confver == epggrab_confver ) {
if ( pthread_cond_timedwait(&epggrab_cond, &epggrab_mutex, &ts) == ETIMEDOUT ) break;
}
/* Run grabber */
ts.tv_sec = epggrab_advanced
? _epggrab_thread_advanced()
: _epggrab_thread_simple();
}
return NULL;
}
/* **************************************************************************
* Module access
* *************************************************************************/
epggrab_module_t* epggrab_module_find_by_name ( const char *name )
{
return NULL;
}
/* **************************************************************************
* Configuration handling
* *************************************************************************/
void _epggrab_load ( void )
{
htsmsg_t *m, *s, *e, *c;
htsmsg_field_t *f;
const char *str;
epggrab_sched_t *es;
/* No config */
if ((m = hts_settings_load("epggrab/config")) == NULL)
return;
/* Load settings */
htsmsg_get_u32(m, "advanced", &epggrab_advanced);
printf("advanced = %d\n", epggrab_advanced);
htsmsg_get_u32(m, "eit", &epggrab_eit);
printf("eit = %d\n", epggrab_eit);
if ( !epggrab_advanced ) {
htsmsg_get_u32(m, "interval", &epggrab_interval);
printf("interval = %d\n", epggrab_interval);
str = htsmsg_get_str(m, "module");
if (str) epggrab_module = epggrab_module_find_by_name(str);
printf("module = %p\n", epggrab_module);
} else {
if ((s = htsmsg_get_list(m, "schedule")) != NULL) {
HTSMSG_FOREACH(f, s) {
if ((e = htsmsg_get_map_by_field(f)) != NULL) {
es = calloc(1, sizeof(epggrab_sched_t));
str = htsmsg_get_str(e, "module");
if (str) es->mod = epggrab_module_find_by_name(str);
str = htsmsg_get_str(e, "opts");
if (str) es->opts = strdup(str);
c = htsmsg_get_map(e, "cron");
if (f) cron_unpack(&es->cron, c);
printf("scheduleN: mod %p opts %s cron 0x%04X\n",
es->mod, es->opts, es->cron.hour);
}
}
}
}
}
void _epggrab_save ( void )
{
htsmsg_t *m, *s, *e, *c;
epggrab_sched_t *es;
/* Enable EIT */
/* Register */
epggrab_confver++;
pthread_cond_signal(&epggrab_cond);
/* Save */
m = htsmsg_create_map();
htsmsg_add_u32(m, "advanced", epggrab_advanced);
htsmsg_add_u32(m, "eit", epggrab_eit);
if ( !epggrab_advanced ) {
htsmsg_add_u32(m, "interval", epggrab_interval);
if ( epggrab_module )
htsmsg_add_str(m, "module", epggrab_module->name());
} else {
s = htsmsg_create_list();
LIST_FOREACH(es, &epggrab_schedule, es_link) {
e = htsmsg_create_map();
if ( es->mod ) htsmsg_add_str(e, "module", es->mod->name());
if ( es->opts ) htsmsg_add_str(e, "opts", es->opts);
c = htsmsg_create_map();
cron_pack(&es->cron, c);
htsmsg_add_msg(e, "cron", c);
htsmsg_add_msg(s, NULL, e);
}
htsmsg_add_msg(m, "schedule", s);
}
hts_settings_save(m, "epggrab/config");
htsmsg_destroy(m);
}
void _epggrab_set_schedule ( int count, epggrab_sched_t *sched )
{
int i;
/* Remove existing */
#if 0
for ( i = 0; i < epggrab_schedcnt; i++ ) {
if ( epggrab_schedule[i].opts ) free(epggrab_schedule[i].opts);
}
free(epggrab_schedule);
#endif
/* Create new */
for ( i = 0; i < count; i++ ) {
epggrab_sched_t *es = calloc(1, sizeof(epggrab_sched_t));
es->mod = sched[i].mod;
es->cron = sched[i].cron;
if ( sched[i].opts ) es->opts = strdup(sched[i].opts);
LIST_INSERT_HEAD(&epggrab_schedule, es, es_link);
}
}
void epggrab_set_simple ( uint32_t interval, epggrab_module_t *mod )
{
/* Set config */
lock_assert(&epggrab_mutex);
epggrab_advanced = 0;
epggrab_interval = interval;
epggrab_module = mod;
/* Save */
_epggrab_save();
}
void epggrab_set_advanced ( uint32_t count, epggrab_sched_t *sched )
{
/* Set config */
lock_assert(&epggrab_mutex);
epggrab_advanced = 1;
_epggrab_set_schedule(count, sched);
/* Save */
_epggrab_save();
}
void epggrab_set_eit ( uint32_t eit )
{
/* Set config */
lock_assert(&epggrab_mutex);
epggrab_eit = eit;
/* Save */
_epggrab_save();
}

70
src/epggrab.h Normal file
View file

@ -0,0 +1,70 @@
#ifndef __EPGGRAB_H__
#define __EPGGRAB_H__
#include <pthread.h>
#include "cron.h"
/* **************************************************************************
* Type definitions
* *************************************************************************/
/*
* Grabber base class
*/
typedef struct epggrab_module
{
const char* (*name) ( void );
void (*enable) ( void );
void (*disable) ( void );
void (*run ) ( const char *opts );
} epggrab_module_t;
/*
* Schedule specification
*/
typedef struct epggrab_sched
{
LIST_ENTRY(epggrab_sched) es_link;
cron_t cron; ///< Cron definition
epggrab_module_t *mod; ///< Module
char *opts; ///< Extra (advanced) options
} epggrab_sched_t;
/*
* Schedule list
*/
LIST_HEAD(epggrab_sched_list, epggrab_sched);
typedef struct epggrab_sched_list epggrab_sched_list_t;
/* **************************************************************************
* Variables
* *************************************************************************/
/*
* Lock this if accessing configuration
*/
pthread_mutex_t epggrab_mutex;
/* **************************************************************************
* Functions
* *************************************************************************/
/*
* Setup
*/
void epggrab_init ( void );
/*
* Access the list of supported modules
*/
//epggrab_module_t** epggrab_module_list ( void );
epggrab_module_t* epggrab_module_find_by_name ( const char *name );
/*
* Set configuration
*/
void epggrab_set_simple ( uint32_t interval, epggrab_module_t* mod );
void epggrab_set_advanced ( uint32_t count, epggrab_sched_t* sched );
void epggrab_set_eit ( uint32_t eit );
#endif /* __EPGGRAB_H__ */