diff --git a/Makefile b/Makefile
index 3d8fab24..c63cbe58 100644
--- a/Makefile
+++ b/Makefile
@@ -32,7 +32,7 @@ CFLAGS += -Wmissing-prototypes -fms-extensions
CFLAGS += -g -funsigned-char -O2
CFLAGS += -D_FILE_OFFSET_BITS=64
CFLAGS += -I${BUILDDIR} -I${CURDIR}/src -I${CURDIR}
-LDFLAGS += -lrt -ldl -lpthread -lm
+LDFLAGS += -lrt -ldl -lpthread -lm -lcurl
#
# Other config
@@ -140,6 +140,8 @@ SRCS += src/muxer.c \
src/muxer_pass.c \
src/muxer_tvh.c \
+SRCS += src/iconserve.c \
+
#
# Optional code
#
diff --git a/docs/html/config_misc.html b/docs/html/config_misc.html
index 00e00b07..5f11cf7b 100644
--- a/docs/html/config_misc.html
+++ b/docs/html/config_misc.html
@@ -20,5 +20,19 @@
dvb-apps stores these in /usr/share/dvb/. Leave blank to use TVH's internal
file set.
+
Cache channel icons:
+
+ Enable the caching of channel icons. This will cause TVH to download channel
+ icons locally, and then when requested via HTSP clients the URL for the icon
+ (or logo) will be retrieved from the TVH web server rather than fetched each
+ time by the HTSP client.
+ This REQUIRES the TVH server IP address field to also be populated
+
+ TVH Server IP Address:
+
+ Enter the IP address of the TVH server used for HTSP clients. This permits the
+ above cache channel icons to work (TVH Clients are directed to the IP address
+ entered here to retrieve channel icons from)
+
diff --git a/src/config2.c b/src/config2.c
index 5bcbd0d1..b90db4fe 100644
--- a/src/config2.c
+++ b/src/config2.c
@@ -74,3 +74,50 @@ int config_set_muxconfpath ( const char *path )
}
return 0;
}
+
+const char *config_get_iconserve ( void )
+{
+ return htsmsg_get_str(config, "iconserve");
+}
+
+int config_set_iconserve ( const char *setting )
+{
+ const char *c = config_get_iconserve();
+ if (!c || strcmp(c, setting)) {
+ if (c) htsmsg_delete_field(config, "iconserve");
+ htsmsg_add_str(config, "iconserve", setting);
+ return 1;
+ }
+ return 0;
+}
+const char *config_get_iconserve_periodicdownload ( void )
+{
+ return htsmsg_get_str(config, "iconserve_periodicdownload");
+}
+
+int config_set_iconserve_periodicdownload ( const char *setting )
+{
+ const char *c = config_get_iconserve_periodicdownload();
+ if (!c || strcmp(c, setting)) {
+ if (c) htsmsg_delete_field(config, "iconserve_periodicdownload");
+ htsmsg_add_str(config, "iconserve_periodicdownload", setting);
+ return 1;
+ }
+ return 0;
+}
+
+const char *config_get_serverip ( void )
+{
+ return htsmsg_get_str(config, "serverip");
+};
+
+int config_set_serverip ( const char *setting )
+{
+ const char *c = config_get_serverip();
+ if (!c || strcmp(c, setting)) {
+ if (c) htsmsg_delete_field(config, "serverip");
+ htsmsg_add_str(config, "serverip", setting);
+ return 1;
+ }
+ return 0;
+};
diff --git a/src/config2.h b/src/config2.h
index cd68e306..6e90be6f 100644
--- a/src/config2.h
+++ b/src/config2.h
@@ -32,6 +32,18 @@ const char *config_get_muxconfpath ( void );
int config_set_muxconfpath ( const char *str )
__attribute__((warn_unused_result));
+const char *config_get_iconserve ( void );
+int config_set_iconserve ( const char *str )
+ __attribute__((warn_unused_result));
+
+const char *config_get_iconserve_periodicdownload ( void );
+int config_set_iconserve_periodicdownload ( const char *str )
+ __attribute__((warn_unused_result));
+
+const char *config_get_serverip ( void );
+int config_set_serverip ( const char *str )
+ __attribute__((warn_unused_result));
+
const char *config_get_language ( void );
int config_set_language ( const char *str )
__attribute__((warn_unused_result));
diff --git a/src/htsp_server.c b/src/htsp_server.c
index ebbb07a2..ba10139a 100644
--- a/src/htsp_server.c
+++ b/src/htsp_server.c
@@ -42,6 +42,8 @@
#include "htsmsg_binary.h"
#include "epg.h"
#include "plumbing/tsfix.h"
+#include "iconserve.h"
+#include "config2.h"
#include
#include "settings.h"
@@ -447,8 +449,10 @@ htsp_build_channel(channel_t *ch, const char *method)
htsmsg_add_u32(out, "channelNumber", ch->ch_number);
htsmsg_add_str(out, "channelName", ch->ch_name);
- if(ch->ch_icon != NULL)
- htsmsg_add_str(out, "channelIcon", ch->ch_icon);
+
+ if(ch->ch_icon != NULL) {
+ htsmsg_add_str(out, "channelIcon", logo_query(ch->ch_id, ch->ch_icon));
+ };
now = ch->ch_epg_now;
next = ch->ch_epg_next;
diff --git a/src/http.c b/src/http.c
index dee8e1f8..e87ec543 100644
--- a/src/http.c
+++ b/src/http.c
@@ -173,18 +173,18 @@ http_send_header(http_connection_t *hc, int rc, const char *content,
tm = gmtime_r(&t, &tm0);
htsbuf_qprintf(&hdrs,
- "Last-Modified: %s, %02d %s %d %02d:%02d:%02d GMT\r\n",
- cachedays[tm->tm_wday], tm->tm_year + 1900,
- cachemonths[tm->tm_mon], tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
+ "Last-Modified: %s, %d %s %02d %02d:%02d:%02d GMT\r\n",
+ cachedays[tm->tm_wday], tm->tm_mday,
+ cachemonths[tm->tm_mon], tm->tm_year + 1900,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
t += maxage;
tm = gmtime_r(&t, &tm0);
htsbuf_qprintf(&hdrs,
- "Expires: %s, %02d %s %d %02d:%02d:%02d GMT\r\n",
- cachedays[tm->tm_wday], tm->tm_year + 1900,
- cachemonths[tm->tm_mon], tm->tm_mday,
+ "Expires: %s, %d %s %02d %02d:%02d:%02d GMT\r\n",
+ cachedays[tm->tm_wday], tm->tm_mday,
+ cachemonths[tm->tm_mon], tm->tm_year + 1900,
tm->tm_hour, tm->tm_min, tm->tm_sec);
htsbuf_qprintf(&hdrs, "Cache-Control: max-age=%d\r\n", maxage);
diff --git a/src/iconserve.c b/src/iconserve.c
new file mode 100644
index 00000000..85f0fe04
--- /dev/null
+++ b/src/iconserve.c
@@ -0,0 +1,358 @@
+/*
+ * Icon file server operations
+ * Copyright (C) 2012 Andy Brown
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#define CURL_STATICLIB
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "settings.h"
+#include "tvheadend.h"
+#include "channels.h"
+#include "http.h"
+#include "webui/webui.h"
+#include "filebundle.h"
+#include "iconserve.h"
+#include "config2.h"
+#include "queue.h"
+#include "spawn.h"
+
+/* Queue, Cond to signal data and Mutex to protect it */
+static TAILQ_HEAD(,iconserve_grab_queue) iconserve_queue;
+static pthread_mutex_t iconserve_mutex;
+static pthread_cond_t iconserve_cond;
+
+/**
+ * https://github.com/andyb2000 Function to provide local icon files
+ */
+int
+page_logo(http_connection_t *hc, const char *remain, void *opaque)
+{
+ const char *homedir = hts_settings_get_root();
+ channel_t *ch = NULL;
+ char *inpath, *inpath2;
+ const char *outpath = "none";
+ char homepath[254];
+ char iconpath[100];
+ pthread_mutex_lock(&global_lock);
+ fb_file *fp;
+ ssize_t size;
+ char buf[4096];
+ char *mimetest_outbuf;
+
+ if(remain == NULL) {
+ pthread_mutex_unlock(&global_lock);
+ return 404;
+ };
+
+ if(strstr(remain, "..")) {
+ pthread_mutex_unlock(&global_lock);
+ return HTTP_STATUS_BAD_REQUEST;
+ };
+
+ ch = channel_find_by_identifier(atoi(remain));
+ if (ch == NULL || ch->ch_icon == NULL) {
+ pthread_mutex_unlock(&global_lock);
+ return 404;
+ };
+
+ snprintf(homepath, sizeof(homepath), "%s/icons", homedir);
+ inpath = NULL;
+ inpath2 = NULL;
+ outpath = NULL;
+ /* split icon to last component */
+ inpath = strdup(ch->ch_icon);
+ inpath2 = strtok(inpath, "/");
+ while (inpath2 != NULL) {
+ inpath2 = strtok(NULL, "/");
+ if (inpath2 != NULL) {
+ outpath = strdup(inpath2);
+ };
+ };
+ snprintf(iconpath, sizeof(iconpath), "%s/%s", homepath, outpath);
+ fp = fb_open(iconpath, 1, 0);
+ if (!fp) {
+ tvhlog(LOG_DEBUG, "page_logo",
+ "failed to open %s redirecting to http link for icon (%s)",
+ iconpath, ch->ch_icon);
+ http_redirect(hc, ch->ch_icon);
+ iconserve_queue_add ( ch->ch_id, ch->ch_icon );
+ } else {
+ tvhlog(LOG_DEBUG, "page_logo", "File %s opened", iconpath);
+ size = fb_size(fp);
+ mimetest_outbuf = strdup("image/jpeg");
+ http_send_header(hc, 200, mimetest_outbuf, size, NULL, NULL, 300, 0, NULL);
+ while (!fb_eof(fp)) {
+ ssize_t c = fb_read(fp, buf, sizeof(buf));
+ if (c < 0) {
+ break;
+ };
+ if (write(hc->hc_fd, buf, c) != c) {
+ break;
+ };
+ };
+ fb_close(fp);
+ };
+
+ pthread_mutex_unlock(&global_lock);
+ return 0;
+}
+
+/*
+* Logo loader functions, called from http htsp
+* Will return local cache url instead of icon stored
+*/
+const char
+*logo_query(int ch_id, const char *ch_icon)
+{
+ const char *setting = config_get_iconserve();
+ const char *serverip = config_get_serverip();
+ char outiconpath[255];
+ char *return_icon = strdup(ch_icon);
+
+ if (!setting || !*setting || (strcmp(setting, "off") == 0)) {
+ return return_icon;
+ };
+
+ if (!serverip || !*serverip) {
+ return return_icon;
+ };
+
+ snprintf(outiconpath, sizeof(outiconpath),
+ "http://%s:%d/channellogo/%d", serverip, webui_port, ch_id);
+ return_icon = strdup(outiconpath);
+return return_icon;
+};
+
+/*
+ * Icon grabber queue thread
+ */
+void *iconserve_thread ( void *aux )
+{
+ iconserve_grab_queue_t *qe;
+ pthread_mutex_lock(&iconserve_mutex);
+ char *inpath, *inpath2;
+ const char *header_parse = NULL, *header_maxage = NULL;
+ const char *outpath = "none";
+ CURL *curl;
+ FILE *curl_fp, *curl_fp_header;
+ CURLcode res;
+ fb_file *fp;
+ char iconpath[100], iconpath_header[100];
+ char homepath[254];
+ const char *homedir = hts_settings_get_root();
+ struct stat fileStat;
+ int trigger_download = 0;
+ char buf[256];
+ int file = 0;
+ time_t seconds;
+ int dif, compare_seconds, rc;
+ const char *periodicdownload = config_get_iconserve_periodicdownload();
+ struct timespec timertrigger;
+ channel_t *ch;
+
+ tvhlog(LOG_INFO, "iconserve_thread", "Thread startup");
+ curl = curl_easy_init();
+ snprintf(homepath, sizeof(homepath), "%s/icons", homedir);
+ if(stat(homepath, &fileStat) == 0 || mkdir(homepath, 0700) == 0) {
+ if (curl) {
+ while (1) {
+
+ /* Get entry from queue */
+ qe = TAILQ_FIRST(&iconserve_queue);
+ /* Check for queue data */
+ if (!qe) { /* Queue Empty */
+ periodicdownload = config_get_iconserve_periodicdownload();
+ if (!periodicdownload || !*periodicdownload ||
+ (strcmp(periodicdownload, "off") == 0)) {
+ tvhlog(LOG_DEBUG, "iconserve_thread", "Non-timer wakeup");
+ rc = pthread_cond_wait(&iconserve_cond, &iconserve_mutex);
+ } else {
+ tvhlog(LOG_DEBUG, "iconserve_thread", "Timer wakeup set");
+ timertrigger.tv_sec = time(NULL) + 86400;
+ timertrigger.tv_nsec = 0;
+ rc = pthread_cond_timedwait(&iconserve_cond,
+ &iconserve_mutex, &timertrigger);
+ };
+ if (rc == ETIMEDOUT) {
+ tvhlog(LOG_INFO, "iconserve_thread", "Thread wakeup by timer");
+ RB_FOREACH(ch, &channel_name_tree, ch_name_link) {
+ if (ch->ch_icon != NULL) {
+ iconserve_grab_queue_t *qe = calloc(1, sizeof(iconserve_grab_queue_t));
+ qe->chan_number = ch->ch_id;
+ qe->icon_url = ch->ch_icon;
+ TAILQ_INSERT_TAIL(&iconserve_queue, qe, iconserve_link);
+ };
+ };
+ };
+ continue;
+ }
+ TAILQ_REMOVE(&iconserve_queue, qe, iconserve_link);
+ pthread_mutex_unlock(&iconserve_mutex);
+
+ inpath = NULL;
+ inpath2 = NULL;
+ outpath = NULL;
+ curl_fp = NULL;
+ /* split icon to last component */
+ inpath = strdup(qe->icon_url);
+ inpath2 = strtok(inpath, "/");
+ while (inpath2 != NULL) {
+ inpath2 = strtok(NULL, "/");
+ if (inpath2 != NULL)
+ outpath = strdup(inpath2);
+ };
+ if (outpath != NULL) {
+ snprintf(iconpath, sizeof(iconpath), "%s/%s", homepath, outpath);
+ snprintf(iconpath_header, sizeof(iconpath_header), "%s/%s.head",
+ homepath, outpath);
+ fp = fb_open(iconpath, 0, 1);
+ if (!fp) {
+ /* No file exists so grab immediately */
+ tvhlog(LOG_INFO, "logo_loader", "No logo, downloading file %s", outpath);
+ trigger_download = 1;
+ } else {
+ /* File exists so compare expiry times to re-grab */
+ fb_close(fp);
+ fp = fb_open(iconpath_header, 0, 0);
+ while (!fb_eof(fp)) {
+ memset(buf, 0, sizeof(buf));
+ if (!fb_gets(fp, buf, sizeof(buf) - 1)) break;
+ if (buf[strlen(buf) - 1] == '\n') {
+ buf[strlen(buf) - 1] = '\0';
+ };
+ if(strstr(buf, "Cache-Control: ")) {
+ header_parse = strtok(buf, "=");
+ header_parse = strtok ( NULL, "=");
+ header_maxage = strdup(header_parse);
+ };
+ };
+ fb_close(fp);
+ file=open(iconpath, O_RDONLY);
+ fstat(file,&fileStat);
+ seconds = time (NULL);
+ dif = difftime (seconds,fileStat.st_mtime);
+ compare_seconds=atoi(header_maxage);
+ if (dif > compare_seconds) {
+ tvhlog(LOG_DEBUG, "logo_loader", "Logo expired, downloading %s", outpath);
+ trigger_download = 1;
+ } else {
+ tvhlog(LOG_INFO, "logo_loader", "Logo not expired %s", outpath);
+ };
+ close(file);
+ };
+ if (trigger_download == 1) {
+ curl_fp=fopen(iconpath,"wb");
+ curl_fp_header=fopen(iconpath_header,"w");
+ curl_easy_setopt(curl, CURLOPT_URL, qe->icon_url);
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl_fp);
+ curl_easy_setopt(curl, CURLOPT_WRITEHEADER, curl_fp_header);
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, "TVHeadend");
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120);
+ curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
+ res = curl_easy_perform(curl);
+ if (res == 0) {
+ tvhlog(LOG_INFO, "logo_loader", "Downloaded icon via curl (%s)",
+ qe->icon_url);
+ } else {
+ tvhlog(LOG_WARNING, "logo_loader", "Error with curl download (%s)",
+ qe->icon_url);
+ };
+ fclose(curl_fp);
+ fclose(curl_fp_header);
+ trigger_download = 0;
+ };
+ };
+ }; /* while loop */
+ curl_easy_cleanup(curl);
+ } else {
+ tvhlog(LOG_WARNING, "iconserve", "CURL cannot initialise");
+ };
+ };
+ return NULL;
+};
+
+/*
+ * Add data to the queue
+ */
+void iconserve_queue_add ( int chan_number, char *icon_url )
+{
+ /* Create entry */
+ tvhlog(LOG_DEBUG, "iconserve_queue_add", "Adding chan_number to queue: %i",
+ chan_number);
+ iconserve_grab_queue_t *qe = calloc(1, sizeof(iconserve_grab_queue_t));
+ qe->chan_number = chan_number;
+ qe->icon_url = strdup(icon_url);
+
+ pthread_mutex_lock(&iconserve_mutex);
+ TAILQ_INSERT_TAIL(&iconserve_queue, qe, iconserve_link);
+ pthread_cond_signal(&iconserve_cond);
+ pthread_mutex_unlock(&iconserve_mutex);
+}
+
+
+/**
+ * Loader for icons, check config params and pull them in one go
+ */
+void
+logo_loader(void)
+{
+ channel_t *ch;
+ const char *setting = config_get_iconserve();
+ const char *serverip = config_get_serverip();
+
+ if (!setting || !*setting || (strcmp(setting, "off") == 0)) {
+ tvhlog(LOG_DEBUG, "logo_loader", "Disabled by config, skipping");
+ return;
+ };
+
+ if (!serverip || !*serverip) {
+ tvhlog(LOG_ALERT, "logo_loader", "No server IP, skipping icon cache");
+ return;
+ };
+
+
+ pthread_t tid;
+ pthread_mutex_init(&iconserve_mutex, NULL);
+ pthread_cond_init(&iconserve_cond, NULL);
+ TAILQ_INIT(&iconserve_queue);
+ /* Start thread - presumably permanently active */
+ pthread_create(&tid, NULL, iconserve_thread, NULL); // last param is passed as aux
+ // as this is single global
+ // you can probably use global
+ // vars
+
+ tvhlog(LOG_INFO, "logo_loader", "Caching logos locally");
+ /* loop through channels and load logo files */
+ RB_FOREACH(ch, &channel_name_tree, ch_name_link) {
+ if (ch->ch_icon != NULL) {
+ iconserve_queue_add ( ch->ch_id, ch->ch_icon );
+ };
+ };
+ pthread_mutex_lock(&iconserve_mutex);
+ pthread_cond_signal(&iconserve_cond); // tell thread data is available
+ pthread_mutex_unlock(&iconserve_mutex);
+};
diff --git a/src/iconserve.h b/src/iconserve.h
new file mode 100644
index 00000000..ff8a0f92
--- /dev/null
+++ b/src/iconserve.h
@@ -0,0 +1,47 @@
+/*
+ * Icon file serve operations
+ * Copyright (C) 2012 Andy Brown
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef ICONSERVE_H
+#define ICONSERVE_H
+
+#include "http.h"
+
+/* Struct of entries for icon grabbing
+ * FIELD: chan_number
+ * FIELD: icon url
+ */
+typedef struct iconserve_grab_queue
+{
+ TAILQ_ENTRY(iconserve_grab_queue) iconserve_link;
+ int chan_number;
+ char *icon_url;
+} iconserve_grab_queue_t;
+
+
+int page_logo(http_connection_t *hc, const char *remain, void *opaque);
+size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream);
+
+void *iconserve_thread ( void *aux );
+
+const char *logo_query(int ch_id, const char *ch_icon);
+
+void iconserve_queue_add ( int chan_number, char *icon_url );
+
+void logo_loader(void);
+
+#endif /* ICONSERVE_H */
diff --git a/src/main.c b/src/main.c
index 73afb075..1bb3b509 100644
--- a/src/main.c
+++ b/src/main.c
@@ -60,6 +60,7 @@
#include "ffdecsa/FFdecsa.h"
#include "muxes.h"
#include "config2.h"
+#include "iconserve.h"
int running;
time_t dispatch_clock;
@@ -488,6 +489,8 @@ main(int argc, char **argv)
http_server_init();
webui_init();
+ logo_loader();
+
serviceprobe_init();
#if ENABLE_CWC
diff --git a/src/webui/extjs.c b/src/webui/extjs.c
index bf254d03..6999eacf 100644
--- a/src/webui/extjs.c
+++ b/src/webui/extjs.c
@@ -47,6 +47,7 @@
#include "config2.h"
#include "lang_codes.h"
#include "subscriptions.h"
+#include "iconserve.h"
/**
*
@@ -858,7 +859,7 @@ extjs_epg(http_connection_t *hc, const char *remain, void *opaque)
htsmsg_add_str(m, "channel", ch->ch_name);
htsmsg_add_u32(m, "channelid", ch->ch_id);
if(ch->ch_icon != NULL)
- htsmsg_add_str(m, "chicon", ch->ch_icon);
+ htsmsg_add_str(m, "chicon", logo_query(ch->ch_id, ch->ch_icon));
if((s = epg_episode_get_title(ee, lang)))
htsmsg_add_str(m, "title", s);
@@ -940,7 +941,7 @@ extjs_epgrelated(http_connection_t *hc, const char *remain, void *opaque)
m = htsmsg_create_map();
htsmsg_add_u32(m, "id", ebc->id);
if ( ch->ch_name ) htsmsg_add_str(m, "channel", ch->ch_name);
- if ( ch->ch_icon ) htsmsg_add_str(m, "chicon", ch->ch_icon);
+ if ( ch->ch_icon ) htsmsg_add_str(m, "chicon", logo_query(ch->ch_id, ch->ch_icon));
htsmsg_add_u32(m, "start", ebc->start);
htsmsg_add_msg(array, NULL, m);
}
@@ -1340,7 +1341,7 @@ extjs_dvrlist(http_connection_t *hc, const char *remain, void *opaque,
if(de->de_channel != NULL) {
htsmsg_add_str(m, "channel", de->de_channel->ch_name);
if(de->de_channel->ch_icon != NULL)
- htsmsg_add_str(m, "chicon", de->de_channel->ch_icon);
+ htsmsg_add_str(m, "chicon", logo_query(de->de_channel->ch_id, de->de_channel->ch_icon));
}
htsmsg_add_str(m, "config_name", de->de_config_name);
@@ -1930,7 +1931,23 @@ extjs_config(http_connection_t *hc, const char *remain, void *opaque)
save |= config_set_muxconfpath(str);
if ((str = http_arg_get(&hc->hc_req_args, "language")))
save |= config_set_language(str);
+ str = http_arg_get(&hc->hc_req_args, "iconserve");
+ if (str != NULL) {
+ save |= config_set_iconserve(str);
+ } else {
+ save |= config_set_iconserve("off");
+ };
+ str = http_arg_get(&hc->hc_req_args, "iconserve_periodicdownload");
+ if (str != NULL) {
+ save |= config_set_iconserve_periodicdownload(str);
+ } else {
+ save |= config_set_iconserve_periodicdownload("off");
+ };
+ if ((str = http_arg_get(&hc->hc_req_args, "serverip")))
+ save |= config_set_serverip(str);
if (save) config_save();
+ /* trigger the iconserve init routine */
+ logo_loader();
pthread_mutex_unlock(&global_lock);
out = htsmsg_create_map();
htsmsg_add_u32(out, "success", 1);
diff --git a/src/webui/simpleui.c b/src/webui/simpleui.c
index 0950fd72..faabaf8d 100644
--- a/src/webui/simpleui.c
+++ b/src/webui/simpleui.c
@@ -482,7 +482,5 @@ simpleui_start(void)
http_path_add("/simple.html", NULL, page_simple, ACCESS_SIMPLE);
http_path_add("/eventinfo", NULL, page_einfo, ACCESS_SIMPLE);
http_path_add("/pvrinfo", NULL, page_pvrinfo, ACCESS_SIMPLE);
- http_path_add("/status.xml", NULL, page_status, ACCESS_SIMPLE);
+ http_path_add("/status.xml", NULL, page_status, ACCESS_SIMPLE);
}
-
-
diff --git a/src/webui/statedump.c b/src/webui/statedump.c
index 603fd158..29425143 100644
--- a/src/webui/statedump.c
+++ b/src/webui/statedump.c
@@ -30,6 +30,7 @@
#include "epg.h"
#include "psi.h"
#include "channels.h"
+#include "iconserve.h"
#if ENABLE_LINUXDVB
#include "dvr/dvr.h"
#include "dvb/dvb.h"
@@ -72,7 +73,7 @@ dumpchannels(htsbuf_queue_t *hq)
ch->ch_refcount,
ch->ch_zombie,
ch->ch_number,
- ch->ch_icon ?: "");
+ logo_query(ch->ch_id, ch->ch_icon) ?: "");
}
}
diff --git a/src/webui/static/app/config.js b/src/webui/static/app/config.js
index 2c9b6a86..a862e0bb 100644
--- a/src/webui/static/app/config.js
+++ b/src/webui/static/app/config.js
@@ -37,7 +37,7 @@ tvheadend.miscconf = function() {
*/
var confreader = new Ext.data.JsonReader({
root : 'config'
- }, [ 'muxconfpath', 'language' ]);
+ }, [ 'muxconfpath', 'language', 'iconserve', 'serverip' ]);
/* ****************************************************************
* Form Fields
@@ -50,6 +50,22 @@ tvheadend.miscconf = function() {
width: 400
});
+ var iconServeConfig = new Ext.form.Checkbox({
+ name : 'iconserve',
+ fieldLabel : 'Cache channel icons'
+ });
+ var iconPeriodicDownload = new Ext.form.Checkbox({
+ name : 'iconserve_periodicdownload',
+ fieldLabel : 'Periodically check for updated icons'
+ });
+ var serveripConfig = new Ext.form.TextField({
+ fieldLabel : 'TVH Server IP address',
+ name : 'serverip',
+ allowBlank : true,
+ width: 150
+ });
+
+
var language = new Ext.ux.ItemSelector({
name: 'language',
fromStore: tvheadend.languages,
@@ -95,7 +111,7 @@ tvheadend.miscconf = function() {
layout : 'form',
defaultType : 'textfield',
autoHeight : true,
- items : [ language, dvbscanPath ],
+ items : [ language, dvbscanPath, iconServeConfig, iconPeriodicDownload, serveripConfig ],
tbar : [ saveButton, '->', helpButton ]
});
diff --git a/src/webui/webui.c b/src/webui/webui.c
index 0f3560c5..6376c812 100644
--- a/src/webui/webui.c
+++ b/src/webui/webui.c
@@ -44,6 +44,7 @@
#include "muxer.h"
#include "dvb/dvb.h"
#include "dvb/dvb_support.h"
+#include "iconserve.h"
/**
*
@@ -95,7 +96,7 @@ page_root2(http_connection_t *hc, const char *remain, void *opaque)
/**
* Static download of a file from the filesystem
*/
-static int
+int
page_static_file(http_connection_t *hc, const char *remain, void *opaque)
{
int ret = 0;
@@ -909,6 +910,8 @@ webui_init(void)
http_path_add("/stream", NULL, http_stream, ACCESS_STREAMING);
+ http_path_add("/channellogo", NULL, page_logo, ACCESS_ANONYMOUS);
+
webui_static_content("/static", "src/webui/static");
webui_static_content("/docs", "docs/html");
webui_static_content("/docresources", "docs/docresources");
diff --git a/src/webui/webui.h b/src/webui/webui.h
index cbbec569..0d50b554 100644
--- a/src/webui/webui.h
+++ b/src/webui/webui.h
@@ -20,6 +20,7 @@
#define WEBUI_H_
#include "htsmsg.h"
+#include "http.h"
void webui_init(void);
@@ -30,6 +31,8 @@ void extjs_start(void);
size_t html_escaped_len(const char *src);
const char* html_escape(char *dst, const char *src, size_t len);
+int page_static_file(http_connection_t *hc, const char *remain, void *opaque);
+
#if ENABLE_LINUXDVB
void extjs_list_dvb_adapters(htsmsg_t *array);
void extjs_start_dvb(void);
@@ -54,5 +57,4 @@ void comet_mailbox_add_message(htsmsg_t *m, int isdebug);
void comet_flush(void);
-
#endif /* WEBUI_H_ */