diff --git a/src/cron.c b/src/cron.c
index 6d7a9887..802cb540 100644
--- a/src/cron.c
+++ b/src/cron.c
@@ -113,7 +113,7 @@ int cron_set_string ( cron_t *cron, const char *str )
{
int save = 0;
cron_t tmp;
- if (!cron->str || !strcmp(cron->str, str)) {
+ if (!cron->str || strcmp(cron->str, str)) {
tmp.str = (char*)str;
if (_cron_parse(&tmp, str)) {
if (cron->str) free(cron->str);
diff --git a/src/epggrab.c b/src/epggrab.c
index 9cb3e609..8576f48c 100644
--- a/src/epggrab.c
+++ b/src/epggrab.c
@@ -20,7 +20,7 @@ pthread_cond_t epggrab_cond;
/* Config */
uint32_t epggrab_advanced;
-uint32_t epggrab_eit;
+uint32_t epggrab_eitenabled;
uint32_t epggrab_interval;
epggrab_module_t* epggrab_module;
epggrab_sched_list_t epggrab_schedule;
@@ -136,10 +136,32 @@ epggrab_module_t* epggrab_module_find_by_id ( const char *id )
htsmsg_t *epggrab_module_list ( void )
{
- htsmsg_t *a = htsmsg_create_list();
+ 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);
+ else printf("no name: %s\n", m->id);
+ if(m->path) htsmsg_add_str(e, "path", m->path);
+ htsmsg_add_u32(e, "flags", m->flags);
+ htsmsg_add_msg(a, NULL, e);
+ }
return a;
}
+void epggrab_module_enable_socket ( epggrab_module_t *mod, uint8_t e )
+{
+ // TODO: implement this?
+}
+
+htsmsg_t *epggrab_module_grab
+ ( epggrab_module_t *mod, const char *cmd, const char *opts )
+{
+ // TODO: implement this
+ return NULL;
+}
+
/* **************************************************************************
* Configuration
* *************************************************************************/
@@ -162,57 +184,56 @@ static int _update_str ( char **dst, const char *src )
return save;
}
-static int _epggrab_schedule_deserialize ( htsmsg_t *m )
+static int _epggrab_schedule_deserialize ( htsmsg_t *a )
{
int save = 0;
- htsmsg_t *a, *e;
+ htsmsg_t *e;
htsmsg_field_t *f;
epggrab_sched_t *es;
epggrab_module_t *mod;
const char *str;
- es = LIST_FIRST(&epggrab_schedule);
- if ( (a = htsmsg_get_list(m, "schedule")) ) {
- HTSMSG_FOREACH(f, a) {
- if ((e = htsmsg_get_map_by_field(f))) {
- if (es) {
- es = LIST_NEXT(es, link);
- } else {
- es = calloc(1, sizeof(epggrab_sched_t));
- save = 1;
- LIST_INSERT_HEAD(&epggrab_schedule, es, link);
- }
+ es = TAILQ_FIRST(&epggrab_schedule);
+ HTSMSG_FOREACH(f, a) {
+ if ((e = htsmsg_get_map_by_field(f))) {
+ if (!es) {
+ es = calloc(1, sizeof(epggrab_sched_t));
+ save = 1;
+ TAILQ_INSERT_TAIL(&epggrab_schedule, es, link);
+ }
- mod = NULL;
- if ((str = htsmsg_get_str(e, "module")))
- mod = epggrab_module_find_by_id(str);
- if (es->mod != mod) {
- es->mod = mod;
- save = 1;
- }
+ mod = NULL;
+ if ((str = htsmsg_get_str(e, "module")))
+ mod = epggrab_module_find_by_id(str);
+ if (es->mod != mod) {
+ es->mod = mod;
+ save = 1;
+ }
- save |= _update_str(&es->cmd, htsmsg_get_str(e, "command"));
- save |= _update_str(&es->opts, htsmsg_get_str(e, "options"));
- str = htsmsg_get_str(e, "cron");
- if (es->cron) {
- if (!str) {
- free(es->cron);
- es->cron = NULL;
- save = 1;
- } else {
- save |= cron_set_string(es->cron, str);
- }
- } else if (str) {
- es->cron = cron_create(str);
+ save |= _update_str(&es->cmd, htsmsg_get_str(e, "command"));
+ save |= _update_str(&es->opts, htsmsg_get_str(e, "options"));
+ str = htsmsg_get_str(e, "cron");
+ if (es->cron) {
+ if (!str) {
+ free(es->cron);
+ es->cron = NULL;
save = 1;
+ } else {
+ save |= cron_set_string(es->cron, str);
}
+ } else if (str) {
+ es->cron = cron_create(str);
+ save = 1;
}
}
+
+ /* Next */
+ if (es) es = TAILQ_NEXT(es, link);
}
if (es)
- while ( LIST_NEXT(es, link) ) {
- LIST_REMOVE(es, link);
+ while ( (es = TAILQ_NEXT(es, link)) ) {
+ TAILQ_REMOVE(&epggrab_schedule, es, link);
save = 1;
}
@@ -224,7 +245,7 @@ static htsmsg_t *_epggrab_schedule_serialize ( void )
epggrab_sched_t *es;
htsmsg_t *e, *a;
a = htsmsg_create_list();
- LIST_FOREACH(es, &epggrab_schedule, link) {
+ TAILQ_FOREACH(es, &epggrab_schedule, link) {
e = htsmsg_create_map();
if ( es->mod ) htsmsg_add_str(e, "module", es->mod->id);
if ( es->cmd ) htsmsg_add_str(e, "command", es->cmd);
@@ -246,7 +267,7 @@ static void _epggrab_load ( void )
/* Load settings */
htsmsg_get_u32(m, "advanced", &epggrab_advanced);
- htsmsg_get_u32(m, "eit", &epggrab_eit);
+ htsmsg_get_u32(m, "eit", &epggrab_eitenabled);
htsmsg_get_u32(m, "interval", &epggrab_interval);
if ( (str = htsmsg_get_str(m, "module")) )
epggrab_module = epggrab_module_find_by_id(str);
@@ -271,6 +292,7 @@ void epggrab_save ( void )
if ( epggrab_module )
htsmsg_add_str(m, "module", epggrab_module->id);
htsmsg_add_msg(m, "schedule", _epggrab_schedule_serialize());
+ htsmsg_print(m);
hts_settings_save(m, "epggrab/config");
htsmsg_destroy(m);
}
@@ -288,9 +310,9 @@ int epggrab_set_advanced ( uint32_t advanced )
int epggrab_set_eitenabled ( uint32_t eitenabled )
{
int save = 0;
- if ( epggrab_eit != eitenabled ) {
+ if ( epggrab_eitenabled != eitenabled ) {
save = 1;
- eitenabled = eitenabled;
+ epggrab_eitenabled = eitenabled;
}
return save;
}
@@ -340,6 +362,7 @@ htsmsg_t *epggrab_get_schedule ( void )
static void _epggrab_module_run
( epggrab_module_t *mod, const char *icmd, const char *iopts )
{
+#if 0
int save = 0;
time_t tm1, tm2;
htsmsg_t *data;
@@ -399,6 +422,7 @@ static void _epggrab_module_run
if (cmd) free(cmd);
if (opts) free(cmd);
pthread_mutex_lock(&epggrab_mutex);
+#endif
}
/*
@@ -426,7 +450,7 @@ static time_t _epggrab_thread_advanced ( void )
/* Determine which to run */
time(&ret);
- LIST_FOREACH(s, &epggrab_schedule, link) {
+ TAILQ_FOREACH(s, &epggrab_schedule, link) {
if ( cron_is_time(s->cron) ) {
_epggrab_module_run(s->mod, s->cmd, s->opts);
break; // TODO: can only run once else config may have changed
@@ -480,10 +504,11 @@ static void* _epggrab_thread ( void* p )
void epggrab_init ( void )
{
/* Defaults */
- epggrab_advanced = 0;
- epggrab_eit = 1; // on air grab enabled
- epggrab_interval = 12 * 3600; // hours
- epggrab_module = NULL; // disabled
+ epggrab_advanced = 0;
+ epggrab_eitenabled = 1; // on air grab enabled
+ epggrab_interval = 12 * 3600; // hours
+ epggrab_module = NULL; // disabled
+ TAILQ_INIT(&epggrab_schedule);
/* Initialise modules */
eit_init(&epggrab_modules);
diff --git a/src/epggrab.h b/src/epggrab.h
index 50b9887b..6b704427 100644
--- a/src/epggrab.h
+++ b/src/epggrab.h
@@ -57,10 +57,11 @@ typedef struct epggrab_module epggrab_module_t;
/*
* Grabber flags
*/
-#define EPGGRAB_MODULE_SYNC 0x1
-#define EPGGRAB_MODULE_ASYNC 0x2
-#define EPGGRAB_MODULE_SIMPLE 0x4
-#define EPGGRAB_MODULE_ADVANCED 0x8
+#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
/*
* Grabber base class
@@ -96,7 +97,7 @@ struct epggrab_module
/*
* Default module functions
*/
-void epggrab_module_enable ( epggrab_module_t *m, uint8_t e );
+void epggrab_module_enable_socket ( epggrab_module_t *m, uint8_t e );
htsmsg_t *epggrab_module_grab ( epggrab_module_t *m, const char *cmd, const char *opts );
void epggrab_module_channels_load ( epggrab_module_t *m );
void epggrab_module_channels_save ( epggrab_module_t *m, const char *path );
@@ -129,7 +130,7 @@ htsmsg_t* epggrab_module_list ( void );
*/
typedef struct epggrab_sched
{
- LIST_ENTRY(epggrab_sched) link;
+ TAILQ_ENTRY(epggrab_sched) link;
cron_t *cron; ///< Cron definition
epggrab_module_t *mod; ///< Module
char *cmd; ///< Command
@@ -139,7 +140,7 @@ typedef struct epggrab_sched
/*
* Schedule list
*/
-LIST_HEAD(epggrab_sched_list, epggrab_sched);
+TAILQ_HEAD(epggrab_sched_list, epggrab_sched);
typedef struct epggrab_sched_list epggrab_sched_list_t;
/*
diff --git a/src/epggrab/pyepg.c b/src/epggrab/pyepg.c
index 088d3a56..29cd5b08 100644
--- a/src/epggrab/pyepg.c
+++ b/src/epggrab/pyepg.c
@@ -122,7 +122,7 @@ static int _pyepg_parse_brand ( htsmsg_t *data, epggrab_stats_t *stats )
}
/* Set icon */
-#if TODO
+#if TODO_ICON_SUPPORT
if ((str = htsmsg_xml_get_cdata_str(tags, "icon"))) {
save |= epg_brand_set_icon(brand, str);
}
@@ -166,7 +166,7 @@ static int _pyepg_parse_season ( htsmsg_t *data, epggrab_stats_t *stats )
}
/* Set title */
-#if TODO
+#if TODO_EXTRA_METADATA
if ((str = htsmsg_xml_get_cdata_str(tags, "title"))) {
save |= epg_season_set_title(season, str);
}
@@ -252,7 +252,7 @@ static int _pyepg_parse_episode ( htsmsg_t *data, epggrab_stats_t *stats )
/* Genre */
// TODO: can actually have multiple!
-#if TODO
+#if TODO_GENRE_SUPPORT
if ((str = htsmsg_xml_get_cdata_str(tags, "genre"))) {
// TODO: conversion?
save |= epg_episode_set_genre(episode, str);
@@ -396,13 +396,15 @@ static int _pyepg_parse
void pyepg_init ( epggrab_module_list_t *list )
{
- _pyepg_module.id = strdup("pyepg_sync");
- _pyepg_module.path = strdup("/usr/bin/pyepg");
+ _pyepg_module.id = strdup("pyepg");
+ _pyepg_module.path = strdup("/usr/bin/pyepg");
+ _pyepg_module.name = strdup("PyEPG");
*((uint8_t*)&_pyepg_module.flags) = EPGGRAB_MODULE_SYNC
| EPGGRAB_MODULE_ASYNC
| EPGGRAB_MODULE_ADVANCED
- | EPGGRAB_MODULE_SIMPLE;
- _pyepg_module.enable = epggrab_module_enable;
+ | EPGGRAB_MODULE_SIMPLE
+ | EPGGRAB_MODULE_EXTERNAL;
+ _pyepg_module.enable = epggrab_module_enable_socket;
_pyepg_module.grab = epggrab_module_grab;
_pyepg_module.parse = _pyepg_parse;
_pyepg_module.channels = &_pyepg_channels;
diff --git a/src/epggrab/xmltv.c b/src/epggrab/xmltv.c
index dee9f9fc..9be657fd 100644
--- a/src/epggrab/xmltv.c
+++ b/src/epggrab/xmltv.c
@@ -420,6 +420,8 @@ static void _xmltv_load_grabbers ( epggrab_module_list_t *list )
mod->id = mod->path = strdup(&outbuf[p]);
mod->name = malloc(200);
sprintf((char*)mod->name, "XMLTV: %s", &outbuf[n]);
+ *((uint8_t*)&mod->flags) = EPGGRAB_MODULE_SYNC
+ | EPGGRAB_MODULE_SIMPLE;
mod->parse = _xmltv_parse;
mod->ch_add = epggrab_module_channel_add;
mod->ch_rem = epggrab_module_channel_rem;
@@ -446,8 +448,9 @@ void xmltv_init ( epggrab_module_list_t *list )
mod->name = strdup("XMLTV: Advanced");
*((uint8_t*)&mod->flags) = EPGGRAB_MODULE_ASYNC
| EPGGRAB_MODULE_SYNC
- | EPGGRAB_MODULE_ADVANCED;
- mod->enable = epggrab_module_enable;
+ | EPGGRAB_MODULE_ADVANCED
+ | EPGGRAB_MODULE_EXTERNAL;
+ mod->enable = epggrab_module_enable_socket;
mod->grab = epggrab_module_grab;
mod->parse = _xmltv_parse;
mod->channels = &_xmltv_channels;
diff --git a/src/webui/extjs.c b/src/webui/extjs.c
index 7e6c5145..fdf8ccb8 100644
--- a/src/webui/extjs.c
+++ b/src/webui/extjs.c
@@ -42,6 +42,7 @@
#include "epggrab.h"
#include "epg.h"
#include "iptv_input.h"
+#include "epggrab/xmltv.h"
static void
extjs_load(htsbuf_queue_t *hq, const char *script)
@@ -322,11 +323,6 @@ extjs_channels_update(htsmsg_t *in)
if((s = htsmsg_get_str(c, "name")) != NULL)
channel_rename(ch, s);
-#if TODO_XMLTV_REMOVE_THIS
- if((s = htsmsg_get_str(c, "xmltvsrc")) != NULL)
- channel_set_xmltv_source(ch, xmltv_channel_find_by_displayname(s));
-#endif
-
if((s = htsmsg_get_str(c, "ch_icon")) != NULL)
channel_set_icon(ch, s);
@@ -376,11 +372,6 @@ extjs_channels(http_connection_t *hc, const char *remain, void *opaque)
htsmsg_add_str(c, "name", ch->ch_name);
htsmsg_add_u32(c, "chid", ch->ch_id);
-#if TODO_XMLTV_REMOVE_THIS
- if(ch->ch_xc != NULL)
- htsmsg_add_str(c, "xmltvsrc", ch->ch_xc->xc_displayname);
-#endif
-
if(ch->ch_icon != NULL)
htsmsg_add_str(c, "ch_icon", ch->ch_icon);
@@ -476,16 +467,16 @@ json_single_record(htsmsg_t *rec, const char *root)
static int
extjs_epggrab(http_connection_t *hc, const char *remain, void *opaque)
{
-#if TODO_EPGGRAB_CONFIG
htsbuf_queue_t *hq = &hc->hc_reply;
const char *op = http_arg_get(&hc->hc_req_args, "op");
- xmltv_channel_t *xc;
- htsmsg_t *out, *array, *e, *r;
- const char *s;
+ htsmsg_t *out, *array, *r;
+ const char *str;
if(op == NULL)
return 400;
+ printf("extjs_epggrab: %s\n", op);
+
pthread_mutex_lock(&global_lock);
if(http_access_verify(hc, ACCESS_ADMIN)) {
@@ -495,67 +486,64 @@ extjs_epggrab(http_connection_t *hc, const char *remain, void *opaque)
pthread_mutex_unlock(&global_lock);
- if(!strcmp(op, "listChannels")) {
+ /* Basic settings (not the advanced schedule) */
+ if(!strcmp(op, "loadSettings")) {
+ pthread_mutex_lock(&epggrab_mutex);
+ r = htsmsg_create_map();
+ htsmsg_add_u32(r, "eitenabled", epggrab_eitenabled);
+ htsmsg_add_u32(r, "advanced", epggrab_advanced);
+ if (epggrab_module)
+ htsmsg_add_str(r, "module", epggrab_module->id);
+ htsmsg_add_u32(r, "interval", epggrab_interval);
+ pthread_mutex_unlock(&epggrab_mutex);
+
+ out = json_single_record(r, "epggrabSettings");
+
+ /* List of modules */
+ } else if (!strcmp(op, "moduleList")) {
out = htsmsg_create_map();
- array = htsmsg_create_list();
-
- e = htsmsg_create_map();
- htsmsg_add_str(e, "xcTitle", "None");
- htsmsg_add_msg(array, NULL, e);
-
- pthread_mutex_lock(&global_lock);
- LIST_FOREACH(xc, &xmltv_displaylist, xc_displayname_link) {
- e = htsmsg_create_map();
- htsmsg_add_str(e, "xcTitle", xc->xc_displayname);
- htsmsg_add_msg(array, NULL, e);
- }
- pthread_mutex_unlock(&global_lock);
-
+ pthread_mutex_lock(&epggrab_mutex);
+ array = epggrab_module_list();
+ pthread_mutex_unlock(&epggrab_mutex);
htsmsg_add_msg(out, "entries", array);
- } else if(!strcmp(op, "loadSettings")) {
-
- pthread_mutex_lock(&xmltv_mutex);
- r = htsmsg_create_map();
-
- if((s = xmltv_get_current_grabber()) != NULL)
- htsmsg_add_str(r, "grabber", s);
-
- htsmsg_add_u32(r, "grabinterval", xmltv_grab_interval);
- htsmsg_add_u32(r, "grabenable", xmltv_grab_enabled);
- pthread_mutex_unlock(&xmltv_mutex);
-
- out = json_single_record(r, "xmltvSettings");
-
- } else if(!strcmp(op, "saveSettings")) {
-
- pthread_mutex_lock(&xmltv_mutex);
-
- s = http_arg_get(&hc->hc_req_args, "grabber");
- xmltv_set_current_grabber(s);
-
- s = http_arg_get(&hc->hc_req_args, "grabinterval");
- xmltv_set_grab_interval(atoi(s));
-
- s = http_arg_get(&hc->hc_req_args, "grabenable");
- xmltv_set_grab_enable(!!s);
-
- pthread_mutex_unlock(&xmltv_mutex);
+ /* Advanced schedule */
+ } else if (!strcmp(op, "loadSchedule")) {
+ out = htsmsg_create_map();
+ pthread_mutex_lock(&epggrab_mutex);
+ array = epggrab_get_schedule();
+ pthread_mutex_unlock(&epggrab_mutex);
+ htsmsg_add_msg(out, "entries", array);
+ /* Save settings */
+ } else if (!strcmp(op, "saveSettings") ) {
+ int save = 0;
+ pthread_mutex_lock(&epggrab_mutex);
+ if ( http_arg_get(&hc->hc_req_args, "advanced") )
+ save |= epggrab_set_advanced(1);
+ else
+ save |= epggrab_set_advanced(0);
+ if ( http_arg_get(&hc->hc_req_args, "eitenabled") )
+ save |= epggrab_set_eitenabled(1);
+ else
+ save |= epggrab_set_eitenabled(0);
+ if ( (str = http_arg_get(&hc->hc_req_args, "interval")) )
+ save |= epggrab_set_interval(atoi(str));
+ 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, "schedule")) ) {
+ if ( (array = htsmsg_json_deserialize(str)) ) {
+ htsmsg_print(array);
+ save |= epggrab_set_schedule(array);
+ htsmsg_destroy(array);
+ }
+ }
+ if (save) epggrab_save();
+ pthread_mutex_unlock(&epggrab_mutex);
out = htsmsg_create_map();
htsmsg_add_u32(out, "success", 1);
- } else if(!strcmp(op, "listGrabbers")) {
-
- out = htsmsg_create_map();
-
- pthread_mutex_lock(&xmltv_mutex);
- array = xmltv_list_grabbers();
- pthread_mutex_unlock(&xmltv_mutex);
- if(array != NULL)
- htsmsg_add_msg(out, "entries", array);
-
} else {
return HTTP_STATUS_BAD_REQUEST;
}
@@ -564,7 +552,6 @@ extjs_epggrab(http_connection_t *hc, const char *remain, void *opaque)
htsmsg_destroy(out);
http_output_content(hc, "text/x-json; charset=UTF-8");
-#endif
return 0;
}
diff --git a/src/webui/static/app/epggrab.js b/src/webui/static/app/epggrab.js
index b4baa0fc..6f122800 100644
--- a/src/webui/static/app/epggrab.js
+++ b/src/webui/static/app/epggrab.js
@@ -1,194 +1,422 @@
-tvheadend.grabberStore = new Ext.data.JsonStore({
- root:'entries',
- fields: ['identifier','name','version','apiconfig'],
- url:'xmltv',
- baseParams: {
- op: 'listGrabbers'
- }
-});
-
tvheadend.epggrab = function() {
+ /* ****************************************************************
+ * Data
+ * ***************************************************************/
+
+ /*
+ * Module lists (I'm sure there is a better way!)
+ */
+ var EPGGRAB_MODULE_SIMPLE = 0x04;
+ var EPGGRAB_MODULE_ADVANCED = 0x08;
+ var EPGGRAB_MODULE_EXTERNAL = 0x10;
+
+ var moduleStore = new Ext.data.JsonStore({
+ root : 'entries',
+ url : 'epggrab',
+ baseParams : { op : 'moduleList' },
+ autoLoad : true,
+ fields : [ 'id', 'name', 'path', 'flags' ]
+ });
+ var simpleModuleStore = new Ext.data.Store({
+ recordType: moduleStore.recordType
+ });
+ var advancedModuleStore = new Ext.data.Store({
+ recordType: moduleStore.recordType
+ });
+ var externalModuleStore = new Ext.data.Store({
+ recordType: moduleStore.recordType
+ });
+ moduleStore.on('load', function() {
+ moduleStore.filterBy(function(r) {
+ return r.get('flags') & EPGGRAB_MODULE_SIMPLE;
+ });
+ moduleStore.each(function(r) {
+ simpleModuleStore.add(r.copy());
+ });
+ moduleStore.filterBy(function(r) {
+ return r.get('flags') & (EPGGRAB_MODULE_ADVANCED | EPGGRAB_MODULE_SIMPLE);
+ });
+ moduleStore.each(function(r) {
+ advancedModuleStore.add(r.copy());
+ });
+ moduleStore.filterBy(function(r) {
+ return r.get('flags') & EPGGRAB_MODULE_EXTERNAL;
+ });
+ moduleStore.each(function(r) {
+ externalModuleStore.add(r.copy());
+ });
+ });
+
+ /*
+ * Schedule
+ */
+
+ var scheduleRow = Ext.data.Record.create(
+ [
+ { name : 'module' },
+ { name : 'command' },
+ { name : 'options' },
+ { name : 'cron' }
+ ]
+ );
+
+ var scheduleStore = new Ext.data.JsonStore({
+ root : 'entries',
+ url : 'epggrab',
+ baseParams : { op : 'loadSchedule' },
+ autoLoad : true,
+ fields : [ 'module', 'command', 'options', 'cron' ]
+ });
+
+ /*
+ * Basic Config
+ */
+
var confreader = new Ext.data.JsonReader(
{ root: 'epggrabSettings' },
- [ 'module', 'eitenable', 'advanced' ]
+ [ 'module', 'eitenabled', 'advanced', 'interval' ]
);
- var grabberSelect = new Ext.form.ComboBox({
- loadingText: 'Loading, please wait...',
- fieldLabel: 'XML-TV Source',
- name: 'grabber',
- width: 350,
- displayField:'name',
- valueField:'identifier',
- store: tvheadend.grabberStore,
- forceSelection: true,
- editable: false,
- triggerAction: 'all',
- mode: 'remote',
- emptyText: 'Select grabber'
- });
- grabberSelect.setVisible(false);
+ /* ****************************************************************
+ * Simple Config
+ * ***************************************************************/
- var advancedCheck = new Ext.form.Checkbox({
- fieldLabel : 'Advanced Config',
- name : 'advanced',
- });
-
- var moduleSelect = new Ext.form.ComboBox({
- fieldLabel : 'Grab Module',
- name : 'module',
- width : 150,
+ /*
+ * Module selector
+ */
+ var simpleModule = new Ext.form.ComboBox({
+ fieldLabel : 'Module',
+ hiddenName : 'module',
+ width : 300,
+ valueField : 'id',
+ displayField : 'name',
+ forceSelection : true,
+ editable : false,
+ mode : 'local',
+ triggerAction : 'all',
+ store : simpleModuleStore
+ });
+
+ /*
+ * Interval selector
+ */
+ var intervalUnits = [
+ [ 86400, 'Days' ],
+ [ 3600, 'Hours' ],
+ [ 60, 'Minutes' ],
+ [ 1, 'Seconds' ]
+ ];
+ var intervalValue = new Ext.form.NumberField({
+ width : 300,
+ allowNegative : false,
+ allowDecimals : false,
+ minValue : 1,
+ maxValue : 7,
+ value : 1,
+ fieldLabel : 'Grab interval',
+ name : 'intervalValue',
+ listeners : {
+ 'valid' : function (e) {
+ v = e.getValue() * intervalUnit.getValue();
+ interval.setValue(v);
+ }
+ }
+ })
+ var intervalUnit = new Ext.form.ComboBox({
+ name : 'intervalUnit',
+ width : 300,
valueField : 'key',
displayField : 'value',
+ value : 86400,
forceSelection : true,
editable : false,
triggerAction : 'all',
mode : 'local',
store : new Ext.data.SimpleStore({
- fields : [ 'key', 'value' ],
- data : [
- [ 'xmltv', 'XMLTV' ],
- [ 'pyepg', 'PyEPG' ],
- ]
- })
+ fields : [ 'key', 'value' ],
+ data : intervalUnits
+ }),
+ listeners : {
+ 'change' : function (e, n, o) {
+ intervalValue.maxValue = (7 * 86400) / n;
+ intervalValue.validate();
+ }
+ }
+ });
+ var interval = new Ext.form.Hidden({
+ name : 'interval',
+ value : 86400,
+ listeners : {
+ 'enable' : function (e) {
+ v = e.getValue();
+ for ( i = 0; i < intervalUnits.length; i++ ) {
+ u = intervalUnits[i][0];
+ if ( (v % u) == 0 ) {
+ intervalUnit.setValue(u);
+ intervalValue.maxValue = (7 * 86400) / u;
+ intervalValue.setValue(v / u);
+ intervalValue.validate();
+ break;
+ }
+ }
+ }
+ }
});
- var confpanel = new Ext.FormPanel(
- {
- title : 'EPG Grabber',
- iconCls : 'xml',
- border : false,
- bodyStyle : 'padding:15px',
- labelAlign : 'right',
- labelWidth : 200,
- waitMsgTarget : true,
- reader : confreader,
- layout : 'form',
- defaultType : 'textfield',
- items : [
- moduleSelect,
- new Ext.form.Checkbox({
- fieldLabel : 'Enable EIT',
- name : 'eitenable'
- }),
- advancedCheck,
- grabberSelect
- ],
- tbar: [
- {
- tooltip: 'Save changes made to configuration below',
- iconCls:'save',
- text: "Save configuration",
- handler: saveChanges
- },
- '->',
- {
- text: 'Help',
- handler: function() {
- new tvheadend.help('XMLTV configuration', 'config_xmltv.html');
- }
- }
- ]
- }
- );
+ var simplePanel = new Ext.form.FieldSet({
+ title : 'Simple Config',
+ height : 120,
+ width : 900,
+ items : [
+ simpleModule,
+ intervalValue,
+ intervalUnit
+ ]
+ });
- /*
- * Event handlers
+ /* ****************************************************************
+ * Advanced Config
+ * ***************************************************************/
+
+ /*
+ * Schedule
*/
- advancedCheck.on('enable', function(e) {
- Ext.MessageBox.alert('Test', 'testing');
- });
-
- moduleSelect.on('select', function(c,r,i) {
- alert('select module');
- });
-
- confpanel.on('render', function() {
- confpanel.getForm().load({
- url:'xmltv',
- params:{'op':'loadSettings'},
- success:function(form, action) {
- confpanel.enable();
- }
- });
- });
-
-
- grabberSelect.on('select', function(c,r,i) {
-
- Ext.MessageBox.alert('XMLTV',
- 'Make sure that the grabber is properly ' +
- 'configured before saving configuration.
'+
- '
' +
- 'To configure manually execute the ' +
- 'following command in a shell on the ' +
- 'server:
' +
- '$ ' + r.data.identifier +
- ' --configure
' +
- '
' +
- 'Note: It is important to configure the ' +
- 'grabber using the same userid as tvheadend '+
- 'since most grabbers save their '+
- 'configuration in the users home directory.'+
- '
' +
- '
' +
- 'Grabber version: ' + r.data.version
- );
-
-/*
- if(r.data.apiconfig) {
-
- Ext.MessageBox.confirm('XMLTV',
- 'Configure grabber? ' +
- 'If you know that the grabber is already '+
- 'set up or if you want to configure it '+
- 'manually you may skip this step',
- function(button) {
- Ext.MessageBox.alert('XMLTV',
- 'oops, embedded '+
- 'config not '+
- 'implemeted yet');
- }
- );
-
- } else {
- Ext.MessageBox.alert('XMLTV',
- 'This grabber does not support being ' +
- 'configured from external application ' +
- '(such as Tvheadend).
' +
- 'Make sure that the grabber is properly ' +
- 'configured before saving configuration.
'+
- '
' +
- 'To configure manually execute the ' +
- 'following command in a shell on the ' +
- 'server:
' +
- '$ ' + r.data.identifier +
- ' --configure
' +
- '
' +
- 'Note: It is important to configure the ' +
- 'grabber using the same userid as tvheadend '+
- 'since most grabbers save their '+
- 'configuration in the users home directory.'+
- '
' +
- '
' +
- 'Grabber version: ' + r.data.version
- );
- }
-*/
- });
-
- function saveChanges() {
- confpanel.getForm().submit({
- url:'xmltv',
- params:{'op':'saveSettings'},
- waitMsg:'Saving Data...',
- failure: function(form, action) {
- Ext.Msg.alert('Save failed', action.result.errormsg);
- }
- });
+ var scheduleColumnModel = new Ext.grid.ColumnModel([
+ {
+ header : 'Module',
+ dataIndex : 'module',
+ width : 300,
+ sortable : false,
+ renderer : function (v)
+ {
+ if ( v != "" ) {
+ i = advancedModuleStore.find('id', v);
+ v = advancedModuleStore.getAt(i).get('name');
+ }
+ return v;
+ },
+ editor : new Ext.form.ComboBox({
+ valueField : 'id',
+ displayField : 'name',
+ editable : false,
+ mode : 'local',
+ triggerAction : 'all',
+ store : advancedModuleStore
+ }),
+ },
+ {
+ header : 'Cron',
+ dataIndex : 'cron',
+ width : 150,
+ sortable : false,
+ editor : new Ext.form.TextField()
+ },
+ {
+ header : 'Command',
+ dataIndex : 'command',
+ width : 200,
+ sortable : false,
+ editor : new Ext.form.TextField()
+ },
+ {
+ dataIndex : 'options',
+ header : 'Options',
+ width : 200,
+ sortable : false,
+ editor : new Ext.form.TextField()
}
+ ]);
+ scheduleColumnModel.isCellEditable = function (ci, ri)
+ {
+ if (ci == 0) return true;
+ m = scheduleStore.getAt(ri).get('module');
+ if (m == "") return false;
+ m = advancedModuleStore.find('id', m);
+ m = advancedModuleStore.getAt(m);
+ if (!(m.get('flags') & EPGGRAB_MODULE_ADVANCED)) {
+ return (ci == 1);
+ }
+ return true;
+ };
- return confpanel;
+ scheduleSelectModel = new Ext.grid.RowSelectionModel({
+ singleSelect : false,
+ });
+ scheduleSelectModel.on('selectionchange', function(s) {
+ delButton.setDisabled(s.getCount() == 0);
+ });
+
+ var addButton = new Ext.Button({
+ text : 'Add',
+ iconCls : 'add',
+ handler : function () {
+ scheduleStore.add(new scheduleRow({
+ module : '',
+ cron : '',
+ command : '',
+ options : ''}
+ ));
+ }
+ });
+
+ var delButton = new Ext.Button({
+ text : 'Delete',
+ iconCls : 'remove',
+ disabled : true,
+ handler : function () {
+ var s = schedulePanel.getSelectionModel().each(function(r){
+ scheduleStore.remove(r);
+ });
+ }
+ });
+
+ var schedulePanel = new Ext.grid.EditorGridPanel({
+ store : scheduleStore,
+ cm : scheduleColumnModel,
+ sm : scheduleSelectModel,
+ width : 850,
+ height : 150,
+ frame : true,
+ viewConfig : {
+ forceFit : true,
+ markDirty : false
+ },
+ iconCls : 'icon-grid',
+ tbar : [
+ addButton,
+ delButton
+ ],
+ listeners : {
+ 'afteredit' : function (r) {
+ if ( r.field == 'module' ) {
+ d = scheduleStore.getAt(r.row);
+ c = '';
+ if ( r.value != "" ) {
+ i = advancedModuleStore.find('id', r.value);
+ m = advancedModuleStore.getAt(i);
+ c = m.get('path');
+ }
+ d.set('command', c)
+ }
+ },
+ 'select' : function(r) {
+ delButton.setDisabled(false);
+ }
+ }
+ });
+
+ var advancedPanel = new Ext.form.FieldSet({
+ title : 'Advanced Config',
+ height : 200,
+ width : 900,
+ items : [
+ // TODO: external editors
+ schedulePanel
+ ]
+ });
+
+ /* ****************************************************************
+ * Form
+ * ***************************************************************/
+
+ var advancedCheck = new Ext.form.Checkbox({
+ fieldLabel : 'Advanced Config',
+ name : 'advanced',
+ listeners : {
+ 'check' : function (e, v) {
+ simplePanel.setVisible(!v);
+ advancedPanel.setVisible(v);
+ }
+ }
+ });
+
+ var eitCheck = new Ext.form.Checkbox({
+ fieldLabel : 'EIT Enabled',
+ name : 'eitenabled'
+ });
+
+ var saveButton = new Ext.Button({
+ text : "Save configuration",
+ tooltip : 'Save changes made to configuration below',
+ iconCls :'save',
+ handler : saveChanges,
+ });
+
+ var helpButton = new Ext.Button({
+ text : 'Help',
+ handler : function() {
+ alert('TODO: help info');
+ }
+ });
+
+ var confpanel = new Ext.FormPanel({
+ title : 'EPG Grabber',
+ iconCls : 'xml',
+ border : false,
+ bodyStyle : 'padding:15px',
+ labelAlign : 'left',
+ labelWidth : 150,
+ waitMsgTarget : true,
+ reader : confreader,
+ layout : 'form',
+ defaultType : 'textfield',
+ items : [
+ interval,
+ advancedCheck,
+ eitCheck,
+ simplePanel,
+ advancedPanel
+ ],
+ tbar: [
+ saveButton,
+ '->',
+ helpButton
+ ]
+ });
+
+ // TODO: HACK: bug in extjs seems to cause sub-components of the form not to render!
+ confpanel.on('afterlayout', function()
+ {
+ simplePanel.syncSize();
+ advancedPanel.syncSize();
+ simplePanel.setVisible(!advancedCheck.getValue());
+ advancedPanel.setVisible(advancedCheck.getValue());
+ });
+
+ /* ****************************************************************
+ * Load/Save
+ * ***************************************************************/
+
+ confpanel.on('render', function() {
+ confpanel.getForm().load({
+ url : 'epggrab',
+ params : { op : 'loadSettings' },
+ success : function ( form, action ) {
+ confpanel.enable();
+ }
+ });
+ });
+
+ function saveChanges() {
+ data = [];
+ scheduleStore.each(function(r) {
+ data.push(r.data);
+ });
+ json = Ext.util.JSON.encode(data);
+ confpanel.getForm().submit({
+ url : 'epggrab',
+ params : { op : 'saveSettings', schedule : json },
+ waitMsg : 'Saving Data...',
+ success : function(form, action) {
+ scheduleStore.commitChanges();
+ },
+ failure : function (form, action) {
+ Ext.Msg.alert('Save failed', action.result.errormsg);
+ }
+ });
+ }
+
+ return confpanel;
}