]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
[PR-174] - Icon caching support to reduce overhead on upstream providers.
authorandyb2000 <andy@broadcast-tech.co.uk>
Sun, 7 Oct 2012 11:32:51 +0000 (12:32 +0100)
committerAdam Sutton <dev@adamsutton.me.uk>
Tue, 1 Jan 2013 09:30:28 +0000 (09:30 +0000)
15 files changed:
Makefile
docs/html/config_misc.html
src/config2.c
src/config2.h
src/htsp_server.c
src/http.c
src/iconserve.c [new file with mode: 0644]
src/iconserve.h [new file with mode: 0644]
src/main.c
src/webui/extjs.c
src/webui/simpleui.c
src/webui/statedump.c
src/webui/static/app/config.js
src/webui/webui.c
src/webui/webui.h

index 3d8fab24f89c82e286b1f5c2bae9db4e068cf820..c63cbe5873e9198f86cfdb27c329a5c67a169414 100644 (file)
--- 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
 #
index 00e00b07dba4e54d20a9a7c52a4b0d9e8c9ebbef..5f11cf7b1abf69bbf0d30d10d58d9e7726cc423d 100644 (file)
   dvb-apps stores these in /usr/share/dvb/. Leave blank to use TVH's internal
   file set.
 
+  <dt>Cache channel icons:
+  <dd>
+  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
+
+  <dt>TVH Server IP Address:
+  <dd>
+  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)
+
  </dl>  
 </div>
index 5bcbd0d1a02a00334fb913fe0f310147564708b3..b90db4fed1586ee51e47cc881f819df2be0a2f34 100644 (file)
@@ -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;
+};
index cd68e30621de19e679970fe49ed61f49708c6e60..6e90be6fae15a817f27aa3ecfbbd272269a7a7e5 100644 (file)
@@ -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));
index ebbb07a22d8fe1005acbd402312f069fe9393476..ba10139a8a69816b0e49611990a512c6795c07e5 100644 (file)
@@ -42,6 +42,8 @@
 #include "htsmsg_binary.h"
 #include "epg.h"
 #include "plumbing/tsfix.h"
+#include "iconserve.h"
+#include "config2.h"
 
 #include <sys/statvfs.h>
 #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;
index dee8e1f8e21ff3b0778478e1ff41e2d7dbb2a97f..e87ec54323a5efcf5494a24b6cc48bf098f4ab77 100644 (file)
@@ -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 (file)
index 0000000..85f0fe0
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#define CURL_STATICLIB
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <curl/curl.h>
+#include <curl/easy.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <time.h>
+
+#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 (file)
index 0000000..ff8a0f9
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 */
index 73afb0757b18fc3537ee40a450d3062f735512cd..1bb3b50941cd3e47985a4c5be47b1e30e00b2985 100644 (file)
@@ -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
index bf254d037641b719e8653f7f2cc92d954ede24f7..6999eacf1e555ae0a029249304a519693d255179 100644 (file)
@@ -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);
index 0950fd72622abeb2d2b76744818a944eaace2e97..faabaf8d9bb425f674d689c2fa31c3e81e1a0eb3 100644 (file)
@@ -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);
 }
-
-
index 603fd15843fba6659e46df047aa6cb19334102ba..294251432168d80ff4234b656192c6ddeedae05f 100644 (file)
@@ -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 ?: "<none set>");
+                  logo_query(ch->ch_id, ch->ch_icon) ?: "<none set>");
   }
 }
 
index 2c9b6a8672c5155c9d095b38ae983599a5749bc6..a862e0bbf5f14a3180a53e0b4e2cdff1b6087973 100644 (file)
@@ -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 ]
        });
 
index 0f3560c5b3c417b7abd0924279fc54a3f8c031ab..6376c812456f96e40d8e9684c97937dec1d1419d 100644 (file)
@@ -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");
index cbbec569d0a004ae7c928929881eae86ce715247..0d50b554aef8f4a45eb0d23338561efedb4d0aea 100644 (file)
@@ -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_ */