Finalize support for configuring xmltv grabbers

This commit is contained in:
Andreas Öman 2008-04-19 13:30:06 +00:00
parent cc204b709d
commit cc7d2c1d51
5 changed files with 312 additions and 17 deletions

View file

@ -54,6 +54,16 @@ img { border: 0; }
* Misc classes
*/
.iconbackdrop {
background: #fff;
height: 64px;
width: 64px;
float: left;
margin: 2px;
text-align: center;
margin-right: 4px;
}
.infoprefix {
float: left;
width: 50px;

View file

@ -120,6 +120,78 @@ ajax_config_xmltv_tab(http_connection_t *hc, http_reply_t *hr)
return 0;
}
/**
* Generate displaylisting
*/
static void
xmltv_grabber_chlist(tcp_queue_t *tq, xmltv_grabber_t *xg)
{
xmltv_channel_t *xc;
th_channel_group_t *tcg;
th_channel_t *ch;
tcp_qprintf(tq,
"<div style=\"overflow: auto; height: 450px\">");
TAILQ_FOREACH(xc, &xg->xg_channels, xc_link) {
tcp_qprintf(tq,
"<div style=\"overflow: auto; width: 100%%\">");
tcp_qprintf(tq, "<div class=\"iconbackdrop\">");
if(xc->xc_icon_url != NULL) {
tcp_qprintf(tq,
"<img style=\"border: 0px;\" src=\"%s\" height=62px\">",
xc->xc_icon_url);
} else {
tcp_qprintf(tq,
"<div style=\"margin-top: 20px; text-align: center\">"
"No icon</div>");
}
tcp_qprintf(tq, "</div>"); /* iconbackdrop */
tcp_qprintf(tq,
"<div class=\"infoprefixwide\">Name:</div>"
"<div>%s (%s)</div>", xc->xc_displayname, xc->xc_name);
tcp_qprintf(tq,
"<div class=\"infoprefixwide\">Best match:</div>"
"<div>%s</div>", xc->xc_bestmatch ?: "(no channel)");
tcp_qprintf(tq,
"<div class=\"infoprefixwidefat\">Mapped to:</div>"
"<select class=\"textinput\" "
"onChange=\"new Ajax.Request('/ajax/xmltvgrabberchmap/%s', "
"{parameters: { xmltvch: '%s', channel: this.value }})\">",
xg->xg_identifier, xc->xc_name);
tcp_qprintf(tq, "<option value=\"auto\">Automatic mapper</option>",
!xc->xc_disabled && xc->xc_channel == NULL ? " selected" : "");
tcp_qprintf(tq, "<option value=\"none\"%s>No channel</option>",
xc->xc_disabled ? " selected" : "");
TAILQ_FOREACH(tcg, &all_channel_groups, tcg_global_link) {
if(tcg->tcg_hidden)
continue;
TAILQ_FOREACH(ch, &tcg->tcg_channels, ch_group_link) {
if(LIST_FIRST(&ch->ch_transports) == NULL)
continue;
tcp_qprintf(tq, "<option value=\"%d\"%s>%s</option>",
ch->ch_tag,
!strcmp(ch->ch_name, xc->xc_channel ?: "")
? " selected " : "", ch->ch_name);
}
}
tcp_qprintf(tq, "</select>");
tcp_qprintf(tq, "</div><hr>\r\n");
}
tcp_qprintf(tq, "</div>");
}
/**
* Display detailes about a grabber
@ -154,10 +226,12 @@ ajax_xmltvgrabber(http_connection_t *hc, http_reply_t *hr,
case XMLTV_GRABBER_GRABBING:
case XMLTV_GRABBER_UNCONFIGURED:
case XMLTV_GRABBER_DYSFUNCTIONAL:
case XMLTV_GRABBER_IDLE:
tcp_qprintf(tq, "<p>%s</p>", xmltv_grabber_status_long(xg, xg->xg_status));
break;
case XMLTV_GRABBER_IDLE:
xmltv_grabber_chlist(tq, xg);
break;
}
@ -185,7 +259,7 @@ ajax_xmltvgrabbermode(http_connection_t *hc, http_reply_t *hr,
xmltv_grabber_enable(xg);
tcp_qprintf(tq,"$('details_%s').innerHTML='Ok, please wait...';",
tcp_qprintf(tq,"$('details_%s').innerHTML='Please wait...';",
xg->xg_identifier);
http_output(hc, hr, "text/javascript; charset=UTF8", NULL, 0);
@ -194,13 +268,88 @@ ajax_xmltvgrabbermode(http_connection_t *hc, http_reply_t *hr,
/**
* Enable / Disable a grabber
*/
static int
ajax_xmltvgrabberlist(http_connection_t *hc, http_reply_t *hr,
const char *remain, void *opaque)
{
xmltv_grabber_t *xg;
tcp_queue_t *tq = &hr->hr_tq;
if(remain == NULL || (xg = xmltv_grabber_find(remain)) == NULL)
return HTTP_STATUS_NOT_FOUND;
xmltv_grabber_chlist(tq, xg);
http_output_html(hc, hr);
return 0;
}
/**
* Change mapping of a channel for a grabber
*/
static int
ajax_xmltvgrabberchmap(http_connection_t *hc, http_reply_t *hr,
const char *remain, void *opaque)
{
xmltv_grabber_t *xg;
xmltv_channel_t *xc;
const char *xmltvname;
const char *chname;
th_channel_t *ch;
// tcp_queue_t *tq = &hr->hr_tq;
if(remain == NULL || (xg = xmltv_grabber_find(remain)) == NULL)
return HTTP_STATUS_NOT_FOUND;
if((xmltvname = http_arg_get(&hc->hc_req_args, "xmltvch")) == NULL)
return HTTP_STATUS_BAD_REQUEST;
if((chname = http_arg_get(&hc->hc_req_args, "channel")) == NULL)
return HTTP_STATUS_BAD_REQUEST;
TAILQ_FOREACH(xc, &xg->xg_channels, xc_link)
if(!strcmp(xc->xc_name, xmltvname))
break;
if(xc == NULL)
return HTTP_STATUS_BAD_REQUEST;
pthread_mutex_lock(&xg->xg_mutex);
free(xc->xc_channel);
xc->xc_channel = NULL;
xc->xc_disabled = 0;
if(!strcmp(chname, "none")) {
xc->xc_disabled = 1;
} else if(!strcmp(chname, "auto")) {
} else if((ch = channel_by_tag(atoi(chname))) != NULL) {
xc->xc_disabled = 0;
xc->xc_channel = strdup(ch->ch_name);
}
pthread_mutex_unlock(&xg->xg_mutex);
xmltv_config_save();
http_output(hc, hr, "text/javascript; charset=UTF8", NULL, 0);
return 0;
}
/**
*
*/
void
ajax_config_xmltv_init(void)
{
http_path_add("/ajax/xmltvgrabber" , NULL, ajax_xmltvgrabber);
http_path_add("/ajax/xmltvgrabbermode" , NULL, ajax_xmltvgrabbermode);
http_path_add("/ajax/xmltvgrabber" , NULL, ajax_xmltvgrabber);
http_path_add("/ajax/xmltvgrabbermode" , NULL, ajax_xmltvgrabbermode);
http_path_add("/ajax/xmltvgrabberlist" , NULL, ajax_xmltvgrabberlist);
http_path_add("/ajax/xmltvgrabberchmap" , NULL, ajax_xmltvgrabberchmap);
}

View file

@ -36,8 +36,8 @@
#define MAILBOX_EMPTY_REPLY_TIMEOUT 10
//#define mbdebug(fmt...) printf(fmt);
#define mbdebug(fmt...)
#define mbdebug(fmt...) printf(fmt);
//#define mbdebug(fmt...)
static LIST_HEAD(, ajaxui_mailbox) mailboxes;
@ -453,13 +453,23 @@ ajax_mailbox_tda_change(th_dvb_adapter_t *tda)
void
ajax_mailbox_xmltv_grabber_status_change(xmltv_grabber_t *xg, int status)
{
char buf[500];
ajax_mailbox_update_div("xmltvgrabbers",
"status", xg->xg_identifier,
xmltv_grabber_status(xg));
ajax_mailbox_update_div(xg->xg_identifier,
"details", xg->xg_identifier,
xmltv_grabber_status_long(xg, status));
if(status == XMLTV_GRABBER_IDLE) {
snprintf(buf, sizeof(buf), "/ajax/xmltvgrabberlist/%s", xg->xg_identifier);
ajax_mailbox_reload_div("xmltvgrabbers",
"details", xg->xg_identifier,
buf);
} else {
ajax_mailbox_update_div(xg->xg_identifier,
"details", xg->xg_identifier,
xmltv_grabber_status_long(xg, status));
}
}

View file

@ -45,6 +45,7 @@ struct xmltv_grabber_list xmltv_grabbers;
struct xmltv_grabber_queue xmltv_grabber_workq;
static pthread_mutex_t xmltv_work_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t xmltv_work_cond = PTHREAD_COND_INITIALIZER;
static void xmltv_config_load(void);
static xmltv_channel_t *
@ -52,14 +53,14 @@ xc_find(xmltv_grabber_t *xg, const char *name)
{
xmltv_channel_t *xc;
LIST_FOREACH(xc, &xg->xg_channels, xc_link)
TAILQ_FOREACH(xc, &xg->xg_channels, xc_link)
if(!strcmp(xc->xc_name, name))
return xc;
xc = calloc(1, sizeof(xmltv_channel_t));
xc->xc_name = strdup(name);
TAILQ_INIT(&xc->xc_events);
LIST_INSERT_HEAD(&xg->xg_channels, xc, xc_link);
TAILQ_INSERT_TAIL(&xg->xg_channels, xc, xc_link);
return xc;
}
@ -213,7 +214,7 @@ xmltv_flush_events(xmltv_grabber_t *xg)
xmltv_channel_t *xc;
event_t *e;
LIST_FOREACH(xc, &xg->xg_channels, xc_link) {
TAILQ_FOREACH(xc, &xg->xg_channels, xc_link) {
while((e = TAILQ_FIRST(&xc->xc_events)) != NULL) {
TAILQ_REMOVE(&xc->xc_events, e, e_link);
epg_event_free(e);
@ -321,6 +322,7 @@ xmltv_transfer(void)
}
#endif
/*
* Execute grabber and parse result,
*
@ -443,6 +445,9 @@ xmltv_find_grabbers(const char *prog)
continue;
xg = calloc(1, sizeof(xmltv_grabber_t));
pthread_mutex_init(&xg->xg_mutex, NULL);
TAILQ_INIT(&xg->xg_channels);
xg->xg_path = a;
xg->xg_title = b;
@ -451,6 +456,7 @@ xmltv_find_grabbers(const char *prog)
LIST_INSERT_SORTED(&xmltv_grabbers, xg, xg_link, grabbercmp);
}
xmltv_config_load();
return 0;
}
@ -559,13 +565,14 @@ xmltv_grabber_enable(xmltv_grabber_t *xg)
{
pthread_mutex_lock(&xmltv_work_lock);
if(xg->xg_status == XMLTV_GRABBER_DISABLED) {
if(xg->xg_status != XMLTV_GRABBER_ENQUEUED) {
xg->xg_status = XMLTV_GRABBER_ENQUEUED;
TAILQ_INSERT_TAIL(&xmltv_grabber_workq, xg, xg_work_link);
pthread_cond_signal(&xmltv_work_cond);
}
pthread_mutex_unlock(&xmltv_work_lock);
xmltv_config_save();
}
/**
@ -647,3 +654,112 @@ xmltv_grabber_status_long(xmltv_grabber_t *xg, int status)
return "Unknown status";
}
}
/*
* Write grabber configuration
*/
void
xmltv_config_save(void)
{
char buf[PATH_MAX];
xmltv_grabber_t *xg;
xmltv_channel_t *xc;
FILE *fp;
snprintf(buf, sizeof(buf), "%s/xmltv-settings.cfg", settings_dir);
if((fp = settings_open_for_write(buf)) == NULL)
return;
LIST_FOREACH(xg, &xmltv_grabbers, xg_link) {
if(xg->xg_status == XMLTV_GRABBER_DISABLED)
continue;
fprintf(fp, "grabber {\n");
fprintf(fp, "\ttitle = %s\n", xg->xg_title);
TAILQ_FOREACH(xc, &xg->xg_channels, xc_link) {
fprintf(fp, "\tchannel {\n");
fprintf(fp, "\t\tdisplayname = %s\n", xc->xc_displayname);
fprintf(fp, "\t\ticon = %s\n", xc->xc_icon_url);
fprintf(fp, "\t\tname = %s\n", xc->xc_name);
if(xc->xc_disabled)
fprintf(fp, "\t\tmapping = disabled\n");
else
fprintf(fp, "\t\tmapping = %s\n", xc->xc_channel ?: "auto");
fprintf(fp, "\t}\n");
}
fprintf(fp, "}\n");
}
fclose(fp);
}
/**
*
*/
static void
xmltv_config_load(void)
{
struct config_head cl;
config_entry_t *ce, *ce2;
char buf[PATH_MAX];
const char *title, *name, *s;
xmltv_channel_t *xc;
xmltv_grabber_t *xg;
TAILQ_INIT(&cl);
snprintf(buf, sizeof(buf), "%s/xmltv-settings.cfg", settings_dir);
config_read_file0(buf, &cl);
pthread_mutex_lock(&xmltv_work_lock);
TAILQ_FOREACH(ce, &cl, ce_link) {
if(ce->ce_type != CFG_SUB || strcasecmp("grabber", ce->ce_key))
continue;
if((title = config_get_str_sub(&ce->ce_sub, "title", NULL)) == NULL)
continue;
LIST_FOREACH(xg, &xmltv_grabbers, xg_link)
if(!strcmp(title, xg->xg_title))
break;
if(xg == NULL)
continue;
xg->xg_status = XMLTV_GRABBER_ENQUEUED;
TAILQ_INSERT_TAIL(&xmltv_grabber_workq, xg, xg_work_link);
TAILQ_FOREACH(ce2, &ce->ce_sub, ce_link) {
if(ce2->ce_type != CFG_SUB || strcasecmp("channel", ce2->ce_key))
continue;
if((name = config_get_str_sub(&ce2->ce_sub, "name", NULL)) == NULL)
continue;
xc = xc_find(xg, name);
if((s = config_get_str_sub(&ce2->ce_sub, "displayname", NULL)) != NULL)
xc->xc_displayname = strdup(s);
if((s = config_get_str_sub(&ce2->ce_sub, "icon", NULL)) != NULL)
xc->xc_icon_url = strdup(s);
if((s = config_get_str_sub(&ce2->ce_sub, "mapping", NULL)) != NULL) {
xc->xc_channel = NULL;
if(!strcmp(s, "disabled")) {
xc->xc_disabled = 1;
} else if(!strcmp(s, "auto")) {
} else {
xc->xc_channel = strdup(s);
}
}
}
}
pthread_mutex_unlock(&xmltv_work_lock);
config_free0(&cl);
}

View file

@ -23,7 +23,7 @@
LIST_HEAD(xmltv_grabber_list, xmltv_grabber);
TAILQ_HEAD(xmltv_grabber_queue, xmltv_grabber);
LIST_HEAD(xmltv_channel_list, xmltv_channel);
TAILQ_HEAD(xmltv_channel_queue, xmltv_channel);
typedef struct xmltv_grabber {
LIST_ENTRY(xmltv_grabber) xg_link;
@ -44,7 +44,9 @@ typedef struct xmltv_grabber {
time_t xg_nextgrab;
struct xmltv_channel_list xg_channels;
struct xmltv_channel_queue xg_channels;
pthread_mutex_t xg_mutex;
} xmltv_grabber_t;
@ -54,10 +56,16 @@ typedef struct xmltv_grabber {
* A channel in the XML-TV world
*/
typedef struct xmltv_channel {
LIST_ENTRY(xmltv_channel) xc_link;
TAILQ_ENTRY(xmltv_channel) xc_link;
char *xc_name;
char *xc_displayname;
char *xc_bestmatch; /* Best matching channel */
char *xc_channel;
int xc_disabled;
char *xc_icon_url;
struct event_queue xc_events;
@ -82,4 +90,6 @@ xmltv_grabber_t *xmltv_grabber_find(const char *id);
const char *xmltv_grabber_status_long(xmltv_grabber_t *xg, int status);
void xmltv_config_save(void);
#endif /* __XMLTV_H__ */