Some tidying up and enabled full config save/store again.
This commit is contained in:
parent
e652b27822
commit
7d6201b90e
6 changed files with 225 additions and 195 deletions
353
src/epggrab.c
353
src/epggrab.c
|
@ -32,15 +32,76 @@ uint32_t epggrab_interval;
|
|||
epggrab_module_t* epggrab_module;
|
||||
epggrab_module_list_t epggrab_modules;
|
||||
|
||||
/* Prototypes */
|
||||
static void _epggrab_module_parse
|
||||
( epggrab_module_t *mod, htsmsg_t *data );
|
||||
|
||||
/* **************************************************************************
|
||||
* Threads
|
||||
* Helpers
|
||||
* *************************************************************************/
|
||||
|
||||
// TODO: should I put this in a thread
|
||||
/*
|
||||
* Run the parse
|
||||
*/
|
||||
static void _epggrab_module_parse
|
||||
( epggrab_module_t *mod, htsmsg_t *data )
|
||||
{
|
||||
time_t tm1, tm2;
|
||||
int save = 0;
|
||||
epggrab_stats_t stats;
|
||||
|
||||
/* Parse */
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
pthread_mutex_lock(&global_lock);
|
||||
time(&tm1);
|
||||
save |= mod->parse(mod, data, &stats);
|
||||
time(&tm2);
|
||||
if (save) epg_updated();
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
htsmsg_destroy(data);
|
||||
|
||||
/* Debug stats */
|
||||
tvhlog(LOG_DEBUG, mod->id, "parse took %d seconds", tm2 - tm1);
|
||||
tvhlog(LOG_DEBUG, mod->id, " channels tot=%5d new=%5d mod=%5d",
|
||||
stats.channels.total, stats.channels.created,
|
||||
stats.channels.modified);
|
||||
tvhlog(LOG_DEBUG, mod->id, " brands tot=%5d new=%5d mod=%5d",
|
||||
stats.brands.total, stats.brands.created,
|
||||
stats.brands.modified);
|
||||
tvhlog(LOG_DEBUG, mod->id, " seasons tot=%5d new=%5d mod=%5d",
|
||||
stats.seasons.total, stats.seasons.created,
|
||||
stats.seasons.modified);
|
||||
tvhlog(LOG_DEBUG, mod->id, " episodes tot=%5d new=%5d mod=%5d",
|
||||
stats.episodes.total, stats.episodes.created,
|
||||
stats.episodes.modified);
|
||||
tvhlog(LOG_DEBUG, mod->id, " broadcasts tot=%5d new=%5d mod=%5d",
|
||||
stats.broadcasts.total, stats.broadcasts.created,
|
||||
stats.broadcasts.modified);
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab from module
|
||||
*/
|
||||
static void _epggrab_module_grab ( epggrab_module_t *mod )
|
||||
{
|
||||
time_t tm1, tm2;
|
||||
htsmsg_t *data;
|
||||
|
||||
/* Grab */
|
||||
time(&tm1);
|
||||
data = mod->trans(mod, mod->grab(mod));
|
||||
time(&tm2);
|
||||
|
||||
/* Process */
|
||||
if ( data ) {
|
||||
tvhlog(LOG_DEBUG, mod->id, "grab took %d seconds", tm2 - tm1);
|
||||
_epggrab_module_parse(mod, data);
|
||||
} else {
|
||||
tvhlog(LOG_WARNING, mod->id, "grab returned no data");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Socket handler
|
||||
*
|
||||
* TODO: could make this threaded to allow multiple simultaneous inputs
|
||||
*/
|
||||
static void _epggrab_socket_handler ( epggrab_module_t *mod, int s )
|
||||
{
|
||||
size_t outlen;
|
||||
|
@ -65,7 +126,50 @@ static void _epggrab_socket_handler ( epggrab_module_t *mod, int s )
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: what happens if we terminate early?
|
||||
/* **************************************************************************
|
||||
* Threads
|
||||
* *************************************************************************/
|
||||
|
||||
/*
|
||||
* Thread (for internal grabbing)
|
||||
*/
|
||||
static void* _epggrab_internal_thread ( void* p )
|
||||
{
|
||||
int confver = -1; // force first run
|
||||
struct timespec ts;
|
||||
epggrab_module_t *mod;
|
||||
|
||||
/* Setup timeout */
|
||||
ts.tv_nsec = 0;
|
||||
ts.tv_sec = 0;
|
||||
|
||||
while ( 1 ) {
|
||||
|
||||
/* Check for config change */
|
||||
pthread_mutex_lock(&epggrab_mutex);
|
||||
while ( confver == epggrab_confver ) {
|
||||
int err = pthread_cond_timedwait(&epggrab_cond, &epggrab_mutex, &ts);
|
||||
if ( err == ETIMEDOUT ) break;
|
||||
}
|
||||
confver = epggrab_confver;
|
||||
mod = NULL;//epggrab_module;
|
||||
ts.tv_sec += epggrab_interval;
|
||||
pthread_mutex_unlock(&epggrab_mutex);
|
||||
|
||||
/* Run grabber */
|
||||
if (mod) _epggrab_module_grab(mod);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* External (socket) grab thread
|
||||
*
|
||||
* TODO: I could common all of this up and have a single thread
|
||||
* servicing all the available sockets, but we're unlikely to
|
||||
* have a massive number of modules enabled anyway!
|
||||
*/
|
||||
static void *_epggrab_socket_thread ( void *p )
|
||||
{
|
||||
int s;
|
||||
|
@ -82,7 +186,7 @@ static void *_epggrab_socket_thread ( void *p )
|
|||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Modules
|
||||
* Base Module functions
|
||||
* *************************************************************************/
|
||||
|
||||
static int _ch_id_cmp ( void *a, void *b )
|
||||
|
@ -93,6 +197,7 @@ static int _ch_id_cmp ( void *a, void *b )
|
|||
|
||||
static int _ch_match ( epggrab_channel_t *ec, channel_t *ch )
|
||||
{
|
||||
// TODO: this needs implementing
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -169,6 +274,7 @@ int epggrab_module_channel_mod ( epggrab_module_t *mod, channel_t *ch )
|
|||
|
||||
epggrab_channel_t *epggrab_module_channel_create ( epggrab_module_t *mod )
|
||||
{
|
||||
// TODO: implement this
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -180,41 +286,17 @@ epggrab_channel_t *epggrab_module_channel_find
|
|||
return RB_FIND(mod->channels, &skel, link, _ch_id_cmp);
|
||||
}
|
||||
|
||||
epggrab_module_t* epggrab_module_find_by_id ( const char *id )
|
||||
{
|
||||
epggrab_module_t *m;
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
if ( !strcmp(m->id, id) ) return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
htsmsg_t *epggrab_module_list ( void )
|
||||
{
|
||||
epggrab_module_t *m;
|
||||
htsmsg_t *e, *a = htsmsg_create_list();
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "id", m->id);
|
||||
if(m->name) htsmsg_add_str(e, "name", m->name);
|
||||
if(m->path) htsmsg_add_str(e, "path", m->path);
|
||||
htsmsg_add_u32(e, "flags", m->flags);
|
||||
htsmsg_add_u32(e, "enabled", m->enabled);
|
||||
htsmsg_add_msg(a, NULL, e);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// Uses a unix domain socket, but we could extend to a remote interface
|
||||
// to allow EPG data to be remotely generated (another machine in the local
|
||||
// network etc...)
|
||||
void epggrab_module_enable_socket ( epggrab_module_t *mod, uint8_t e )
|
||||
// TODO: could use TCP socket to allow remote access
|
||||
int epggrab_module_enable_socket ( epggrab_module_t *mod, uint8_t e )
|
||||
{
|
||||
pthread_t tid;
|
||||
pthread_attr_t tattr;
|
||||
struct sockaddr_un addr;
|
||||
assert(mod->path);
|
||||
assert(mod->flags & EPGGRAB_MODULE_EXTERNAL);
|
||||
|
||||
/* Ignore */
|
||||
if ( mod->enabled == e ) return 0;
|
||||
|
||||
/* Disable */
|
||||
if (!e) {
|
||||
|
@ -222,7 +304,6 @@ void epggrab_module_enable_socket ( epggrab_module_t *mod, uint8_t e )
|
|||
close(mod->sock);
|
||||
unlink(mod->path);
|
||||
mod->sock = 0;
|
||||
// TODO: I don't shutdown the thread!
|
||||
|
||||
/* Enable */
|
||||
} else {
|
||||
|
@ -234,18 +315,28 @@ void epggrab_module_enable_socket ( epggrab_module_t *mod, uint8_t e )
|
|||
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, mod->path, 100);
|
||||
// TODO: possibly asserts here not a good idea if I make the socket
|
||||
// path configurable
|
||||
assert(bind(mod->sock, (struct sockaddr*)&addr,
|
||||
sizeof(struct sockaddr_un)) == 0);
|
||||
if ( bind(mod->sock, (struct sockaddr*)&addr,
|
||||
sizeof(struct sockaddr_un)) != 0 ) {
|
||||
tvhlog(LOG_ERR, mod->id, "failed to bind socket");
|
||||
close(mod->sock);
|
||||
mod->sock = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(listen(mod->sock, 5) == 0);
|
||||
if ( listen(mod->sock, 5) != 0 ) {
|
||||
tvhlog(LOG_ERR, mod->id, "failed to listen on socket");
|
||||
close(mod->sock);
|
||||
mod->sock = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
tvhlog(LOG_DEBUG, mod->id, "starting socket thread");
|
||||
pthread_attr_init(&tattr);
|
||||
pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&tid, &tattr, _epggrab_socket_thread, mod);
|
||||
tvhlog(LOG_DEBUG, mod->id, "enabled socket");
|
||||
}
|
||||
mod->enabled = e;
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *epggrab_module_grab ( epggrab_module_t *mod )
|
||||
|
@ -295,7 +386,8 @@ const char *epggrab_module_socket_path ( epggrab_module_t *mod )
|
|||
|
||||
static void _epggrab_load ( void )
|
||||
{
|
||||
htsmsg_t *m;
|
||||
epggrab_module_t *mod;
|
||||
htsmsg_t *m, *a;
|
||||
const char *str;
|
||||
|
||||
/* No config */
|
||||
|
@ -307,13 +399,20 @@ static void _epggrab_load ( void )
|
|||
htsmsg_get_u32(m, "interval", &epggrab_interval);
|
||||
if ( (str = htsmsg_get_str(m, "module")) )
|
||||
epggrab_module = epggrab_module_find_by_id(str);
|
||||
// TODO: module states
|
||||
if ( (a = htsmsg_get_map(m, "mod_enabled")) ) {
|
||||
LIST_FOREACH(mod, &epggrab_modules, link) {
|
||||
if (htsmsg_get_u32_or_default(a, mod->id, 0)) {
|
||||
if (mod->enable) mod->enable(mod, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
htsmsg_destroy(m);
|
||||
}
|
||||
|
||||
void epggrab_save ( void )
|
||||
{
|
||||
htsmsg_t *m;
|
||||
epggrab_module_t *mod;
|
||||
htsmsg_t *m, *a;
|
||||
|
||||
/* Register */
|
||||
epggrab_confver++;
|
||||
|
@ -325,6 +424,11 @@ void epggrab_save ( void )
|
|||
htsmsg_add_u32(m, "interval", epggrab_interval);
|
||||
if ( epggrab_module )
|
||||
htsmsg_add_str(m, "module", epggrab_module->id);
|
||||
a = htsmsg_create_map();
|
||||
LIST_FOREACH(mod, &epggrab_modules, link) {
|
||||
if (mod->enabled) htsmsg_add_u32(a, mod->id, 1);
|
||||
}
|
||||
htsmsg_add_msg(m, "mod_enabled", a);
|
||||
hts_settings_save(m, "epggrab/config");
|
||||
htsmsg_destroy(m);
|
||||
}
|
||||
|
@ -353,10 +457,12 @@ int epggrab_set_interval ( uint32_t interval )
|
|||
int epggrab_set_module ( epggrab_module_t *mod )
|
||||
{
|
||||
int save = 0;
|
||||
if ( mod && epggrab_module != mod ) {
|
||||
assert(mod->grab);
|
||||
assert(mod->trans);
|
||||
assert(mod->parse);
|
||||
if ( epggrab_module != mod ) {
|
||||
if (mod) {
|
||||
assert(mod->grab);
|
||||
assert(mod->trans);
|
||||
assert(mod->parse);
|
||||
}
|
||||
epggrab_module = mod;
|
||||
save = 1;
|
||||
}
|
||||
|
@ -371,11 +477,10 @@ int epggrab_set_module_by_id ( const char *id )
|
|||
int epggrab_enable_module ( epggrab_module_t *mod, uint8_t e )
|
||||
{
|
||||
int save = 0;
|
||||
if ( e != mod->enabled ) {
|
||||
assert(mod->trans);
|
||||
assert(mod->parse);
|
||||
if (mod->enable) {
|
||||
save = mod->enable(mod, e);
|
||||
} else if ( e != mod->enabled ) {
|
||||
mod->enabled = e;
|
||||
if (mod->enable) mod->enable(mod, e);
|
||||
save = 1;
|
||||
}
|
||||
return save;
|
||||
|
@ -386,112 +491,6 @@ int epggrab_enable_module_by_id ( const char *id, uint8_t e )
|
|||
return epggrab_enable_module(epggrab_module_find_by_id(id), e);
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Module Execution
|
||||
* *************************************************************************/
|
||||
|
||||
/*
|
||||
* Run the parse
|
||||
*/
|
||||
static void _epggrab_module_parse
|
||||
( epggrab_module_t *mod, htsmsg_t *data )
|
||||
{
|
||||
time_t tm1, tm2;
|
||||
int save = 0;
|
||||
epggrab_stats_t stats;
|
||||
|
||||
/* Parse */
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
pthread_mutex_lock(&global_lock);
|
||||
time(&tm1);
|
||||
save |= mod->parse(mod, data, &stats);
|
||||
time(&tm2);
|
||||
if (save) epg_updated();
|
||||
pthread_mutex_unlock(&global_lock);
|
||||
htsmsg_destroy(data);
|
||||
|
||||
/* Debug stats */
|
||||
tvhlog(LOG_DEBUG, mod->id, "parse took %d seconds", tm2 - tm1);
|
||||
tvhlog(LOG_DEBUG, mod->id, " channels tot=%5d new=%5d mod=%5d",
|
||||
stats.channels.total, stats.channels.created,
|
||||
stats.channels.modified);
|
||||
tvhlog(LOG_DEBUG, mod->id, " brands tot=%5d new=%5d mod=%5d",
|
||||
stats.brands.total, stats.brands.created,
|
||||
stats.brands.modified);
|
||||
tvhlog(LOG_DEBUG, mod->id, " seasons tot=%5d new=%5d mod=%5d",
|
||||
stats.seasons.total, stats.seasons.created,
|
||||
stats.seasons.modified);
|
||||
tvhlog(LOG_DEBUG, mod->id, " episodes tot=%5d new=%5d mod=%5d",
|
||||
stats.episodes.total, stats.episodes.created,
|
||||
stats.episodes.modified);
|
||||
tvhlog(LOG_DEBUG, mod->id, " broadcasts tot=%5d new=%5d mod=%5d",
|
||||
stats.broadcasts.total, stats.broadcasts.created,
|
||||
stats.broadcasts.modified);
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab from module
|
||||
*/
|
||||
static void _epggrab_module_grab ( epggrab_module_t *mod )
|
||||
{
|
||||
time_t tm1, tm2;
|
||||
htsmsg_t *data;
|
||||
|
||||
/* Grab */
|
||||
time(&tm1);
|
||||
printf("mod = %s\n", mod->id);
|
||||
printf("trans = %p, grab = %p\n", mod->trans, mod->grab);
|
||||
data = mod->trans(mod, mod->grab(mod));
|
||||
time(&tm2);
|
||||
|
||||
/* Process */
|
||||
if ( data ) {
|
||||
tvhlog(LOG_DEBUG, mod->id, "grab took %d seconds", tm2 - tm1);
|
||||
_epggrab_module_parse(mod, data);
|
||||
} else {
|
||||
tvhlog(LOG_WARNING, mod->id, "grab returned no data");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Thread (for internal grabbing)
|
||||
*/
|
||||
static void* _epggrab_thread ( void* p )
|
||||
{
|
||||
int confver = 0;
|
||||
struct timespec ts;
|
||||
pthread_mutex_lock(&epggrab_mutex);
|
||||
epggrab_module_t *mod;
|
||||
|
||||
/* Load */
|
||||
_epggrab_load();
|
||||
|
||||
/* Setup timeout */
|
||||
ts.tv_nsec = 0;
|
||||
ts.tv_sec = 0;
|
||||
|
||||
while ( 1 ) {
|
||||
|
||||
/* Check for config change */
|
||||
while ( confver == epggrab_confver ) {
|
||||
int err = pthread_cond_timedwait(&epggrab_cond, &epggrab_mutex, &ts);
|
||||
if ( err == ETIMEDOUT ) break;
|
||||
}
|
||||
confver = epggrab_confver;
|
||||
mod = NULL;//epggrab_module;
|
||||
ts.tv_sec += epggrab_interval;
|
||||
|
||||
/* Run grabber (without lock) */
|
||||
if (mod) {
|
||||
pthread_mutex_unlock(&epggrab_mutex);
|
||||
_epggrab_module_grab(mod);
|
||||
pthread_mutex_lock(&epggrab_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Global Functions
|
||||
* *************************************************************************/
|
||||
|
@ -511,12 +510,15 @@ void epggrab_init ( void )
|
|||
xmltv_init(&epggrab_modules);
|
||||
pyepg_init(&epggrab_modules);
|
||||
|
||||
/* Start thread */
|
||||
/* Load config */
|
||||
_epggrab_load();
|
||||
|
||||
/* Start internal grab 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);
|
||||
pthread_create(&tid, &tattr, _epggrab_internal_thread, NULL);
|
||||
}
|
||||
|
||||
void epggrab_channel_add ( channel_t *ch )
|
||||
|
@ -548,3 +550,28 @@ void epggrab_channel_mod ( channel_t *ch )
|
|||
m->ch_save(m);
|
||||
}
|
||||
}
|
||||
|
||||
epggrab_module_t* epggrab_module_find_by_id ( const char *id )
|
||||
{
|
||||
epggrab_module_t *m;
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
if ( !strcmp(m->id, id) ) return m;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
htsmsg_t *epggrab_module_list ( void )
|
||||
{
|
||||
epggrab_module_t *m;
|
||||
htsmsg_t *e, *a = htsmsg_create_list();
|
||||
LIST_FOREACH(m, &epggrab_modules, link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_str(e, "id", m->id);
|
||||
if(m->name) htsmsg_add_str(e, "name", m->name);
|
||||
if(m->path) htsmsg_add_str(e, "path", m->path);
|
||||
htsmsg_add_u32(e, "flags", m->flags);
|
||||
htsmsg_add_u32(e, "enabled", m->enabled);
|
||||
htsmsg_add_msg(a, NULL, e);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -42,11 +42,16 @@ typedef struct epggrab_channel
|
|||
} epggrab_channel_t;
|
||||
|
||||
/*
|
||||
* Channel list
|
||||
* Channel list structure
|
||||
*/
|
||||
RB_HEAD(epggrab_channel_tree, epggrab_channel);
|
||||
typedef struct epggrab_channel_tree epggrab_channel_tree_t;
|
||||
|
||||
/*
|
||||
* Access functions
|
||||
*/
|
||||
htsmsg_t* epggrab_channel_list ( void );
|
||||
|
||||
/* **************************************************************************
|
||||
* Grabber Modules
|
||||
* *************************************************************************/
|
||||
|
@ -56,11 +61,9 @@ typedef struct epggrab_module epggrab_module_t;
|
|||
/*
|
||||
* Grabber flags
|
||||
*/
|
||||
#define EPGGRAB_MODULE_SYNC 0x01
|
||||
#define EPGGRAB_MODULE_ASYNC 0x02
|
||||
#define EPGGRAB_MODULE_SIMPLE 0x04
|
||||
#define EPGGRAB_MODULE_ADVANCED 0x08
|
||||
#define EPGGRAB_MODULE_EXTERNAL 0x10
|
||||
#define EPGGRAB_MODULE_SIMPLE 0x01
|
||||
#define EPGGRAB_MODULE_EXTERNAL 0x02
|
||||
#define EPGGRAB_MODULE_SPECIAL 0x04
|
||||
|
||||
/*
|
||||
* Grabber base class
|
||||
|
@ -72,13 +75,13 @@ struct epggrab_module
|
|||
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 flags
|
||||
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
|
||||
|
||||
/* Enable/Disable */
|
||||
void (*enable) ( epggrab_module_t *m, uint8_t e );
|
||||
int (*enable) ( epggrab_module_t *m, uint8_t e );
|
||||
|
||||
/* Grab/Translate/Parse */
|
||||
char* (*grab) ( epggrab_module_t *m );
|
||||
|
@ -96,20 +99,26 @@ struct epggrab_module
|
|||
};
|
||||
|
||||
/*
|
||||
* Default module functions (shared by pyepg and xmltv)
|
||||
* Default module functions
|
||||
*
|
||||
* Kinda like a base class (shared by current modules xmltv and pyepg)
|
||||
*/
|
||||
const char *epggrab_module_socket_path ( epggrab_module_t *m );
|
||||
void epggrab_module_enable_socket ( epggrab_module_t *m, uint8_t e );
|
||||
char *epggrab_module_grab ( epggrab_module_t *m );
|
||||
|
||||
int epggrab_module_enable_socket ( epggrab_module_t *m, uint8_t e );
|
||||
const char *epggrab_module_socket_path ( epggrab_module_t *m );
|
||||
|
||||
char *epggrab_module_grab ( epggrab_module_t *m );
|
||||
htsmsg_t *epggrab_module_trans_xml ( epggrab_module_t *m, char *d );
|
||||
|
||||
void epggrab_module_channels_load ( epggrab_module_t *m );
|
||||
void epggrab_module_channels_save ( epggrab_module_t *m, const char *path );
|
||||
int epggrab_module_channel_add ( epggrab_module_t *m, channel_t *ch );
|
||||
int epggrab_module_channel_rem ( epggrab_module_t *m, channel_t *ch );
|
||||
int epggrab_module_channel_mod ( epggrab_module_t *m, channel_t *ch );
|
||||
|
||||
epggrab_channel_t *epggrab_module_channel_create
|
||||
( epggrab_module_t *m );
|
||||
epggrab_channel_t *epggrab_module_channel_find
|
||||
epggrab_channel_t *epggrab_module_channel_find
|
||||
( epggrab_module_t *m, const char *id );
|
||||
|
||||
/*
|
||||
|
@ -124,11 +133,6 @@ typedef struct epggrab_module_list epggrab_module_list_t;
|
|||
epggrab_module_t* epggrab_module_find_by_id ( const char *id );
|
||||
htsmsg_t* epggrab_module_list ( void );
|
||||
|
||||
/*
|
||||
* Channel list
|
||||
*/
|
||||
htsmsg_t* epggrab_channel_list ( void );
|
||||
|
||||
/* **************************************************************************
|
||||
* Configuration
|
||||
* *************************************************************************/
|
||||
|
|
|
@ -92,7 +92,7 @@ void eit_init ( epggrab_module_list_t *list )
|
|||
{
|
||||
_eit_mod.id = strdup("eit");
|
||||
_eit_mod.name = strdup("EIT: On-Air Grabber");
|
||||
*((uint8_t*)&_eit_mod.flags) = EPGGRAB_MODULE_ASYNC;
|
||||
*((uint8_t*)&_eit_mod.flags) = EPGGRAB_MODULE_SPECIAL;
|
||||
LIST_INSERT_HEAD(list, &_eit_mod, link);
|
||||
// Note: this is mostly ignored anyway as EIT is treated as a special case!
|
||||
}
|
||||
|
|
|
@ -421,6 +421,8 @@ static void _xmltv_load_grabbers ( epggrab_module_list_t *list )
|
|||
mod->name = malloc(200);
|
||||
sprintf((char*)mod->name, "XMLTV: %s", &outbuf[n]);
|
||||
*((uint8_t*)&mod->flags) = EPGGRAB_MODULE_SIMPLE;
|
||||
mod->grab = epggrab_module_grab;
|
||||
mod->trans = epggrab_module_trans_xml;
|
||||
mod->parse = _xmltv_parse;
|
||||
LIST_INSERT_HEAD(list, mod, link);
|
||||
p = n = i + 1;
|
||||
|
@ -441,15 +443,16 @@ void xmltv_init ( epggrab_module_list_t *list )
|
|||
mod = calloc(1, sizeof(epggrab_module_t));
|
||||
mod->id = strdup("xmltv");
|
||||
mod->name = strdup("XMLTV");
|
||||
*((uint8_t*)&mod->flags) = EPGGRAB_MODULE_EXTERNAL;
|
||||
mod->path = epggrab_module_socket_path(mod);
|
||||
mod->enable = epggrab_module_enable_socket;
|
||||
mod->grab = epggrab_module_grab;
|
||||
mod->trans = epggrab_module_trans_xml;
|
||||
mod->parse = _xmltv_parse;
|
||||
mod->channels = &_xmltv_channels;
|
||||
mod->ch_add = epggrab_module_channel_add;
|
||||
mod->ch_rem = epggrab_module_channel_rem;
|
||||
mod->ch_mod = epggrab_module_channel_mod;
|
||||
mod->ch_save = _xmltv_save;
|
||||
*((uint8_t*)&mod->flags) = EPGGRAB_MODULE_EXTERNAL;
|
||||
LIST_INSERT_HEAD(list, mod, link);
|
||||
|
||||
/* Standard modules */
|
||||
|
|
|
@ -518,17 +518,12 @@ extjs_epggrab(http_connection_t *hc, const char *remain, void *opaque)
|
|||
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")) ) {
|
||||
printf("got external\n");
|
||||
if ( (array = htsmsg_json_deserialize(str)) ) {
|
||||
printf("got array\n");
|
||||
HTSMSG_FOREACH(f, array) {
|
||||
if ( (e = htsmsg_get_map_by_field(f)) ) {
|
||||
printf("got field\n");
|
||||
str = htsmsg_get_str(e, "id");
|
||||
printf("id = %s\n", str);
|
||||
u32 = 0;
|
||||
htsmsg_get_u32(e, "enabled", &u32);
|
||||
printf("enabled = %d\n", u32);
|
||||
if ( str ) save |= epggrab_enable_module_by_id(str, u32);
|
||||
}
|
||||
}
|
||||
|
@ -543,7 +538,6 @@ extjs_epggrab(http_connection_t *hc, const char *remain, void *opaque)
|
|||
return HTTP_STATUS_BAD_REQUEST;
|
||||
}
|
||||
|
||||
htsmsg_print(out);
|
||||
htsmsg_json_serialize(out, hq, 0);
|
||||
htsmsg_destroy(out);
|
||||
http_output_content(hc, "text/x-json; charset=UTF-8");
|
||||
|
|
|
@ -7,8 +7,8 @@ tvheadend.epggrab = function() {
|
|||
/*
|
||||
* Module lists (I'm sure there is a better way!)
|
||||
*/
|
||||
var EPGGRAB_MODULE_SIMPLE = 0x04;
|
||||
var EPGGRAB_MODULE_EXTERNAL = 0x10;
|
||||
var EPGGRAB_MODULE_SIMPLE = 0x01;
|
||||
var EPGGRAB_MODULE_EXTERNAL = 0x02;
|
||||
|
||||
var moduleStore = new Ext.data.JsonStore({
|
||||
root : 'entries',
|
||||
|
@ -27,6 +27,8 @@ tvheadend.epggrab = function() {
|
|||
moduleStore.filterBy(function(r) {
|
||||
return r.get('flags') & EPGGRAB_MODULE_SIMPLE;
|
||||
});
|
||||
r = new simpleModuleStore.recordType({ id: '', name : 'Disabled'});
|
||||
simpleModuleStore.add(r);
|
||||
moduleStore.each(function(r) {
|
||||
simpleModuleStore.add(r.copy());
|
||||
});
|
||||
|
@ -150,14 +152,14 @@ tvheadend.epggrab = function() {
|
|||
{
|
||||
header : 'Path',
|
||||
dataIndex : 'path',
|
||||
width : 200,
|
||||
width : 300,
|
||||
sortable : false,
|
||||
// TODO: editable?
|
||||
},
|
||||
{
|
||||
dataIndex : 'enabled',
|
||||
header : 'Enabled',
|
||||
width : 50,
|
||||
width : 100,
|
||||
sortable : false,
|
||||
editor : new Ext.form.Checkbox(),
|
||||
// TODO: newer versions of extjs provide proper checkbox in grid
|
||||
|
@ -175,7 +177,7 @@ tvheadend.epggrab = function() {
|
|||
var externalGrid = new Ext.grid.EditorGridPanel({
|
||||
store : externalModuleStore,
|
||||
cm : externalColumnModel,
|
||||
width : 450,
|
||||
width : 600,
|
||||
height : 150,
|
||||
frame : false,
|
||||
viewConfig : {
|
||||
|
|
Loading…
Add table
Reference in a new issue