epggrab: ota - add multi-line cron scheduler
- the initial EPG scan can be turned off in webui - the OTA mux timeout is configurable through webui
This commit is contained in:
parent
24adf59330
commit
26705e9310
5 changed files with 214 additions and 16 deletions
|
@ -158,10 +158,10 @@ static void _epggrab_load ( void )
|
|||
gtimer_arm(&epggrab_save_timer, epg_save_callback, NULL,
|
||||
epggrab_epgdb_periodicsave);
|
||||
if ((str = htsmsg_get_str(m, "cron")) == NULL) {
|
||||
str = buf;
|
||||
if (!htsmsg_get_u32(m, old ? "grab-interval" : "interval",
|
||||
&interval)) {
|
||||
if (old) interval *= 3600;
|
||||
str = buf;
|
||||
if (interval <= 600)
|
||||
strcpy(buf, "*/10 * * * *");
|
||||
else if (interval <= 900)
|
||||
|
@ -209,6 +209,10 @@ static void _epggrab_load ( void )
|
|||
}
|
||||
}
|
||||
}
|
||||
htsmsg_get_u32(m, "ota_timeout", &epggrab_ota_timeout);
|
||||
htsmsg_get_u32(m, "ota_initial", &epggrab_ota_initial);
|
||||
if ((str = htsmsg_get_str(m, "ota_cron")) != NULL)
|
||||
epggrab_ota_set_cron(str, 0);
|
||||
htsmsg_destroy(m);
|
||||
|
||||
/* Finish up migration */
|
||||
|
@ -247,7 +251,7 @@ static void _epggrab_load ( void )
|
|||
/* Defaults */
|
||||
} else {
|
||||
free(epggrab_cron);
|
||||
epggrab_cron = strdup("4 */12 * * *"); // each 12 hours (noon)
|
||||
epggrab_cron = strdup("# Default config (00:04 and 12:04 everyday)\n4 */12 * * *");
|
||||
epggrab_module = NULL; // disabled
|
||||
LIST_FOREACH(mod, &epggrab_modules, link) // enable all OTA by default
|
||||
if (mod->type == EPGGRAB_OTA)
|
||||
|
@ -278,6 +282,9 @@ void epggrab_save ( void )
|
|||
htsmsg_add_u32(m, "channel_renumber", epggrab_channel_renumber);
|
||||
htsmsg_add_u32(m, "epgdb_periodicsave", epggrab_epgdb_periodicsave);
|
||||
htsmsg_add_str(m, "cron", epggrab_cron);
|
||||
htsmsg_add_str(m, "ota_cron", epggrab_ota_cron);
|
||||
htsmsg_add_u32(m, "ota_timeout", epggrab_ota_timeout);
|
||||
htsmsg_add_u32(m, "ota_initial", epggrab_ota_initial);
|
||||
if ( epggrab_module )
|
||||
htsmsg_add_str(m, "module", epggrab_module->id);
|
||||
a = NULL;
|
||||
|
@ -437,6 +444,9 @@ void epggrab_init ( void )
|
|||
/* Load config */
|
||||
_epggrab_load();
|
||||
|
||||
/* Post-init for OTA subsystem */
|
||||
epggrab_ota_post();
|
||||
|
||||
/* Start internal grab thread */
|
||||
epggrab_running = 1;
|
||||
tvhthread_create(&epggrab_tid, NULL, _epggrab_internal_thread, NULL, 0);
|
||||
|
|
|
@ -255,6 +255,9 @@ extern uint32_t epggrab_channel_rename;
|
|||
extern uint32_t epggrab_channel_renumber;
|
||||
extern uint32_t epggrab_channel_reicon;
|
||||
extern uint32_t epggrab_epgdb_periodicsave;
|
||||
extern char *epggrab_ota_cron;
|
||||
extern uint32_t epggrab_ota_timeout;
|
||||
extern uint32_t epggrab_ota_initial;
|
||||
|
||||
/*
|
||||
* Set configuration
|
||||
|
@ -268,6 +271,9 @@ int epggrab_set_channel_reicon ( uint32_t e );
|
|||
int epggrab_set_periodicsave ( uint32_t e );
|
||||
int epggrab_enable_module ( epggrab_module_t *mod, uint8_t e );
|
||||
int epggrab_enable_module_by_id ( const char *id, uint8_t e );
|
||||
int epggrab_ota_set_cron ( const char *cron, int lock );
|
||||
int epggrab_ota_set_timeout ( uint32_t e );
|
||||
int epggrab_ota_set_initial ( uint32_t e );
|
||||
|
||||
/*
|
||||
* Load/Save
|
||||
|
@ -276,6 +282,7 @@ void epggrab_init ( void );
|
|||
void epggrab_done ( void );
|
||||
void epggrab_save ( void );
|
||||
void epggrab_ota_init ( void );
|
||||
void epggrab_ota_post ( void );
|
||||
void epggrab_ota_shutdown ( void );
|
||||
|
||||
/* **************************************************************************
|
||||
|
|
|
@ -24,14 +24,15 @@
|
|||
#include "epggrab/private.h"
|
||||
#include "input.h"
|
||||
#include "subscriptions.h"
|
||||
#include "cron.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define EPGGRAB_OTA_MIN_INTERVAL 300
|
||||
#define EPGGRAB_OTA_MIN_TIMEOUT 30
|
||||
#define EPGGRAB_OTA_MAX_TIMEOUT 7200
|
||||
|
||||
#define EPGGRAB_OTA_DONE_COMPLETE 0
|
||||
#define EPGGRAB_OTA_DONE_TIMEOUT 1
|
||||
|
@ -39,12 +40,21 @@
|
|||
|
||||
typedef TAILQ_HEAD(epggrab_ota_head,epggrab_ota_mux) epggrab_ota_head_t;
|
||||
|
||||
uint32_t epggrab_ota_initial;
|
||||
char *epggrab_ota_cron;
|
||||
cron_multi_t *epggrab_ota_cron_multi;
|
||||
uint32_t epggrab_ota_timeout;
|
||||
|
||||
RB_HEAD(,epggrab_ota_mux) epggrab_ota_all;
|
||||
epggrab_ota_head_t epggrab_ota_pending;
|
||||
epggrab_ota_head_t epggrab_ota_active;
|
||||
|
||||
gtimer_t epggrab_ota_kick_timer;
|
||||
gtimer_t epggrab_ota_pending_timer;
|
||||
gtimer_t epggrab_ota_start_timer;
|
||||
|
||||
int epggrab_ota_pending_flag;
|
||||
|
||||
pthread_mutex_t epggrab_ota_mutex;
|
||||
|
||||
SKEL_DECLARE(epggrab_ota_mux_skel, epggrab_ota_mux_t);
|
||||
SKEL_DECLARE(epggrab_svc_link_skel, epggrab_ota_svc_link_t);
|
||||
|
@ -73,12 +83,14 @@ om_svcl_cmp ( epggrab_ota_svc_link_t *a, epggrab_ota_svc_link_t *b )
|
|||
}
|
||||
|
||||
static int
|
||||
epggrab_ota_timeout ( void )
|
||||
epggrab_ota_timeout_get ( void )
|
||||
{
|
||||
int timeout = 600;
|
||||
int timeout = epggrab_ota_timeout;
|
||||
|
||||
if (timeout < EPGGRAB_OTA_MIN_TIMEOUT)
|
||||
timeout = EPGGRAB_OTA_MIN_TIMEOUT;
|
||||
if (timeout > EPGGRAB_OTA_MAX_TIMEOUT)
|
||||
timeout = EPGGRAB_OTA_MAX_TIMEOUT;
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
@ -86,6 +98,19 @@ epggrab_ota_timeout ( void )
|
|||
static void
|
||||
epggrab_ota_kick ( int delay )
|
||||
{
|
||||
epggrab_ota_mux_t *om;
|
||||
|
||||
if (TAILQ_EMPTY(&epggrab_ota_pending) &&
|
||||
TAILQ_EMPTY(&epggrab_ota_active)) {
|
||||
/* next round is pending? queue all ota muxes */
|
||||
if (epggrab_ota_pending_flag) {
|
||||
epggrab_ota_pending_flag = 0;
|
||||
RB_FOREACH(om, &epggrab_ota_all, om_global_link)
|
||||
TAILQ_INSERT_TAIL(&epggrab_ota_pending, om, om_q_link);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
gtimer_arm(&epggrab_ota_kick_timer, epggrab_ota_kick_cb, NULL, delay);
|
||||
}
|
||||
|
||||
|
@ -121,7 +146,7 @@ epggrab_ota_start ( epggrab_ota_mux_t *om, int grace )
|
|||
|
||||
TAILQ_INSERT_TAIL(&epggrab_ota_active, om, om_q_link);
|
||||
gtimer_arm(&om->om_timer, epggrab_ota_timeout_cb, om,
|
||||
epggrab_ota_timeout() + grace);
|
||||
epggrab_ota_timeout_get() + grace);
|
||||
LIST_FOREACH(map, &om->om_modules, om_link) {
|
||||
map->om_first = 1;
|
||||
map->om_complete = 0;
|
||||
|
@ -361,6 +386,55 @@ done:
|
|||
goto next_one;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start times management
|
||||
*/
|
||||
|
||||
static void
|
||||
epggrab_ota_start_cb ( void *p )
|
||||
{
|
||||
time_t next;
|
||||
|
||||
tvhtrace("epggrab", "ota start callback");
|
||||
|
||||
epggrab_ota_pending_flag = 1;
|
||||
|
||||
/* Finish previous job? */
|
||||
if (TAILQ_EMPTY(&epggrab_ota_pending) &&
|
||||
TAILQ_EMPTY(&epggrab_ota_active)) {
|
||||
tvhtrace("epggrab", "ota - idle - kicked");
|
||||
epggrab_ota_kick(1);
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&epggrab_ota_mutex);
|
||||
if (!cron_multi_next(epggrab_ota_cron_multi, dispatch_clock, &next)) {
|
||||
tvhtrace("epggrab", "next ota start event in %li seconds", next - time(NULL));
|
||||
gtimer_arm_abs(&epggrab_ota_start_timer, epggrab_ota_start_cb, NULL, next);
|
||||
}
|
||||
pthread_mutex_unlock(&epggrab_ota_mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
epggrab_ota_arm ( time_t last )
|
||||
{
|
||||
time_t next;
|
||||
|
||||
pthread_mutex_lock(&epggrab_ota_mutex);
|
||||
|
||||
if (!cron_multi_next(epggrab_ota_cron_multi, time(NULL), &next)) {
|
||||
/* do not trigger the next EPG scan for 1/2 hour */
|
||||
if (last != (time_t)-1 && last + 1800 > next)
|
||||
next = last + 1800;
|
||||
tvhtrace("epggrab", "next ota start event in %li seconds", next - time(NULL));
|
||||
gtimer_arm_abs(&epggrab_ota_start_timer, epggrab_ota_start_cb, NULL, next);
|
||||
}
|
||||
pthread_mutex_unlock(&epggrab_ota_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Service management
|
||||
*/
|
||||
|
||||
void
|
||||
epggrab_ota_service_add ( epggrab_ota_map_t *map, epggrab_ota_mux_t *ota,
|
||||
const char *uuid, int save )
|
||||
|
@ -447,7 +521,6 @@ epggrab_ota_load_one
|
|||
free(ota);
|
||||
return;
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&epggrab_ota_pending, ota, om_q_link);
|
||||
|
||||
if (!(l = htsmsg_get_list(c, "modules"))) return;
|
||||
HTSMSG_FOREACH(f, l) {
|
||||
|
@ -475,6 +548,18 @@ epggrab_ota_init ( void )
|
|||
char path[1024];
|
||||
struct stat st;
|
||||
|
||||
epggrab_ota_initial = 1;
|
||||
epggrab_ota_timeout = 600;
|
||||
epggrab_ota_cron = strdup("# Default config (02:04 and 14:04 everyday)\n4 2 * * *\n4 14 * * *");;
|
||||
epggrab_ota_cron_multi = NULL;
|
||||
epggrab_ota_pending_flag = 0;
|
||||
|
||||
RB_INIT(&epggrab_ota_all);
|
||||
TAILQ_INIT(&epggrab_ota_pending);
|
||||
TAILQ_INIT(&epggrab_ota_active);
|
||||
|
||||
pthread_mutex_init(&epggrab_ota_mutex, NULL);
|
||||
|
||||
/* Add listener */
|
||||
static mpegts_listener_t ml = {
|
||||
.ml_mux_start = epggrab_mux_start,
|
||||
|
@ -482,9 +567,6 @@ epggrab_ota_init ( void )
|
|||
};
|
||||
mpegts_add_listener(&ml);
|
||||
|
||||
TAILQ_INIT(&epggrab_ota_pending);
|
||||
TAILQ_INIT(&epggrab_ota_active);
|
||||
|
||||
/* Delete old config */
|
||||
hts_settings_buildpath(path, sizeof(path), "epggrab/otamux");
|
||||
if (!lstat(path, &st))
|
||||
|
@ -499,10 +581,22 @@ epggrab_ota_init ( void )
|
|||
}
|
||||
htsmsg_destroy(c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
epggrab_ota_post ( void )
|
||||
{
|
||||
time_t t = (time_t)-1;
|
||||
|
||||
/* Init timer (call after full init - wait for network tuners) */
|
||||
if (TAILQ_FIRST(&epggrab_ota_pending))
|
||||
if (epggrab_ota_initial) {
|
||||
epggrab_ota_pending_flag = 1;
|
||||
epggrab_ota_kick(15);
|
||||
t = time(NULL);
|
||||
}
|
||||
|
||||
/* arm the first scheduled time */
|
||||
epggrab_ota_arm(t);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -535,6 +629,59 @@ epggrab_ota_shutdown ( void )
|
|||
pthread_mutex_unlock(&global_lock);
|
||||
SKEL_FREE(epggrab_ota_mux_skel);
|
||||
SKEL_FREE(epggrab_svc_link_skel);
|
||||
free(epggrab_ota_cron);
|
||||
epggrab_ota_cron = NULL;
|
||||
free(epggrab_ota_cron_multi);
|
||||
epggrab_ota_cron_multi = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Global configuration handlers
|
||||
*/
|
||||
|
||||
int
|
||||
epggrab_ota_set_cron ( const char *cron, int lock )
|
||||
{
|
||||
int save = 0;
|
||||
if ( epggrab_ota_cron == NULL || strcmp(epggrab_ota_cron, cron) ) {
|
||||
save = 1;
|
||||
pthread_mutex_lock(&epggrab_ota_mutex);
|
||||
free(epggrab_ota_cron);
|
||||
epggrab_ota_cron = strdup(cron);
|
||||
free(epggrab_ota_cron_multi);
|
||||
epggrab_ota_cron_multi = cron_multi_set(cron);
|
||||
pthread_mutex_unlock(&epggrab_ota_mutex);
|
||||
if (lock) {
|
||||
pthread_mutex_lock(&global_lock);
|
||||
epggrab_ota_arm((time_t)-1);
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
} else {
|
||||
epggrab_ota_arm((time_t)-1);
|
||||
}
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
int
|
||||
epggrab_ota_set_timeout( uint32_t e )
|
||||
{
|
||||
int save = 0;
|
||||
if (epggrab_ota_timeout != e) {
|
||||
epggrab_ota_timeout = e;
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
int
|
||||
epggrab_ota_set_initial( uint32_t e )
|
||||
{
|
||||
int save = 0;
|
||||
if (epggrab_ota_initial != e) {
|
||||
epggrab_ota_initial = e;
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
|
|
@ -432,11 +432,14 @@ extjs_epggrab(http_connection_t *hc, const char *remain, void *opaque)
|
|||
r = htsmsg_create_map();
|
||||
if (epggrab_module)
|
||||
htsmsg_add_str(r, "module", epggrab_module->id);
|
||||
htsmsg_add_str(r, "cron", epggrab_cron);
|
||||
htsmsg_add_str(r, "cron", epggrab_cron ? epggrab_cron : "");
|
||||
htsmsg_add_u32(r, "channel_rename", epggrab_channel_rename);
|
||||
htsmsg_add_u32(r, "channel_renumber", epggrab_channel_renumber);
|
||||
htsmsg_add_u32(r, "channel_reicon", epggrab_channel_reicon);
|
||||
htsmsg_add_u32(r, "epgdb_periodicsave", epggrab_epgdb_periodicsave / 3600);
|
||||
htsmsg_add_str(r, "ota_cron", epggrab_ota_cron ? epggrab_ota_cron : "");
|
||||
htsmsg_add_u32(r, "ota_timeout", epggrab_ota_timeout);
|
||||
htsmsg_add_u32(r, "ota_initial", epggrab_ota_initial);
|
||||
pthread_mutex_unlock(&epggrab_mutex);
|
||||
|
||||
out = json_single_record(r, "epggrabSettings");
|
||||
|
@ -463,6 +466,14 @@ extjs_epggrab(http_connection_t *hc, const char *remain, void *opaque)
|
|||
save |= epggrab_set_periodicsave(atoi(str) * 3600);
|
||||
if ( (str = http_arg_get(&hc->hc_req_args, "cron")) )
|
||||
save |= epggrab_set_cron(str);
|
||||
if ( (str = http_arg_get(&hc->hc_req_args, "ota_cron")) )
|
||||
save |= epggrab_ota_set_cron(str, 1);
|
||||
if ( (str = http_arg_get(&hc->hc_req_args, "ota_timeout")) )
|
||||
save |= epggrab_ota_set_timeout(atoi(str));
|
||||
str = http_arg_get(&hc->hc_req_args, "ota_initial");
|
||||
save |= epggrab_ota_set_initial(str ? 1 : 0);
|
||||
if ( (str = http_arg_get(&hc->hc_req_args, "epgdb_periodicsave")) )
|
||||
save |= epggrab_set_periodicsave(atoi(str) * 3600);
|
||||
if ( (str = http_arg_get(&hc->hc_req_args, "module")) )
|
||||
save |= epggrab_set_module_by_id(str);
|
||||
if ( (str = http_arg_get(&hc->hc_req_args, "external")) ) {
|
||||
|
|
|
@ -83,7 +83,8 @@ tvheadend.epggrab = function() {
|
|||
var confreader = new Ext.data.JsonReader({
|
||||
root: 'epggrabSettings'
|
||||
}, ['module', 'cron', 'channel_rename', 'channel_renumber',
|
||||
'channel_reicon', 'epgdb_periodicsave']);
|
||||
'channel_reicon', 'epgdb_periodicsave',
|
||||
'ota_cron', 'ota_timeout', 'ota_initial']);
|
||||
|
||||
/* ****************************************************************
|
||||
* Basic Fields
|
||||
|
@ -255,13 +256,35 @@ tvheadend.epggrab = function() {
|
|||
iconCls: 'icon-grid'
|
||||
});
|
||||
|
||||
var otaInitial = new Ext.form.Checkbox({
|
||||
name: 'ota_initial',
|
||||
fieldLabel: 'Force initial EPG scan at startup'
|
||||
});
|
||||
|
||||
var otaCron = new Ext.form.TextArea({
|
||||
fieldLabel: 'Over-the-air Cron multi-line',
|
||||
name: 'ota_cron',
|
||||
width: 300,
|
||||
});
|
||||
|
||||
var otaTimeout = new Ext.form.NumberField({
|
||||
width: 30,
|
||||
allowNegative: false,
|
||||
allowDecimals: false,
|
||||
minValue: 30,
|
||||
maxValue: 7200,
|
||||
value: 600,
|
||||
fieldLabel: 'EPG scan timeout in seconds (30-7200)',
|
||||
name: 'ota_timeout'
|
||||
});
|
||||
|
||||
var otaPanel = new Ext.form.FieldSet({
|
||||
title: 'Over-the-air Grabbers',
|
||||
width: 700,
|
||||
autoHeight: true,
|
||||
collapsible: true,
|
||||
collapsed: true,
|
||||
items: [otaGrid]
|
||||
items: [otaInitial, otaCron, otaTimeout, otaGrid]
|
||||
});
|
||||
|
||||
/* ****************************************************************
|
||||
|
|
Loading…
Add table
Reference in a new issue