]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
imagecache: big cleanups
authorJaroslav Kysela <perex@perex.cz>
Wed, 12 Dec 2018 18:08:00 +0000 (19:08 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 12 Dec 2018 18:08:00 +0000 (19:08 +0100)
- let imagecache work also for fanart / recording specific images
- let imagecache work for EPG entries
- global cleanups (try to have only one function for duplicate things)
- fix the local file handling when imagecache is not enabled for external URLs
- imagecache code is part of the tvh's core code (cannot be ommited from compilation)

16 files changed:
configure
src/api/api_epg.c
src/api/api_imagecache.c
src/channels.c
src/channels.h
src/dvr/dvr.h
src/dvr/dvr_db.c
src/htsp_server.c
src/http.c
src/http.h
src/imagecache.c
src/imagecache.h
src/main.c
src/webui/static/app/config.js
src/webui/webui.c
src/webui/xmltv.c

index 201dfba574a40fc10134ba03b0dd854ee25cefc4..e5f6f593b673d8c91ecc9bba726afd64ee4decf1 100755 (executable)
--- a/configure
+++ b/configure
@@ -34,7 +34,6 @@ OPTIONS=(
   "dvbscan:yes"
   "timeshift:yes"
   "trace:yes"
-  "imagecache:auto"
   "avahi:auto"
   "zlib:auto"
   "libav:auto"
@@ -701,13 +700,6 @@ if enabled_or_auto tvhcsa; then
   fi
 fi
 
-#
-# Icon caching
-#
-if enabled_or_auto imagecache; then
-  enable imagecache
-fi
-
 #
 # DVB scan
 #
index 35a93864d7a7cd0c3ec04b6899f71b7a9eb28c5d..8a2709cb11d0a2bdfdaca0a599eb77634f2ed88f 100644 (file)
@@ -54,7 +54,7 @@ static void
 api_epg_add_channel ( htsmsg_t *m, channel_t *ch, const char *blank )
 {
   int64_t chnum;
-  char buf[32];
+  char buf[128];
   const char *s;
   htsmsg_add_str(m, "channelName", channel_get_name(ch, blank));
   htsmsg_add_uuid(m, "channelUuid", &ch->ch_id.in_uuid);
@@ -67,16 +67,20 @@ api_epg_add_channel ( htsmsg_t *m, channel_t *ch, const char *blank )
       snprintf(buf, sizeof(buf), "%u", maj);
     htsmsg_add_str(m, "channelNumber", buf);
   }
-  if ((s = channel_get_icon(ch)) != NULL)
-    htsmsg_add_str(m, "channelIcon", s);
+  s = channel_get_icon(ch);
+  if (!strempty(s)) {
+    s = imagecache_get_propstr(s, buf, sizeof(buf));
+    if (s)
+      htsmsg_add_str(m, "channelIcon", s);
+  }
 }
 
 static htsmsg_t *
 api_epg_entry ( epg_broadcast_t *eb, const char *lang, const access_t *perm, const char **blank )
 {
   const char *s, *blank2 = NULL;
-  char buf[64];
-  channel_t     *ch = eb->channel;
+  char buf[32];
+  channel_t *ch = eb->channel;
   htsmsg_t *m, *m2;
   epg_episode_num_t epnum;
   epg_genre_t *eg;
@@ -170,8 +174,12 @@ api_epg_entry ( epg_broadcast_t *eb, const char *lang, const access_t *perm, con
     htsmsg_add_str(m, "episodeOnscreen", buf);
 
   /* Image */
-  if (eb->image)
-    htsmsg_add_str(m, "image", eb->image);
+  s = eb->image;
+  if (!strempty(s)) {
+    s = imagecache_get_propstr(s, buf, sizeof(buf));
+    if (s)
+      htsmsg_add_str(m, "image", s);
+  }
 
   /* Rating */
   if (eb->star_rating)
index 3e6c585f6a64db02e590cd2da077d2b363962ad9..c0894c225a39669f87668ffd4bac97b80734f632 100644 (file)
@@ -23,8 +23,6 @@
 #include "api.h"
 #include "imagecache.h"
 
-#if ENABLE_IMAGECACHE
-
 static int
 api_imagecache_clean
   ( access_t *perm, void *opaque, const char *op, htsmsg_t *args, htsmsg_t **resp )
@@ -68,12 +66,3 @@ api_imagecache_init ( void )
 
   api_register_all(ah);
 }
-
-#else /* ENABLE_IMAGECACHE */
-
-void 
-api_imagecache_init ( void )
-{
-}
-
-#endif
index 46bdc2cfe2e8d36fffe90c7420fbbae1bb4ba5cf..cff8fe24272d72102f21db2eb5fb4b0ad4a8164a 100644 (file)
@@ -58,6 +58,18 @@ ch_id_cmp ( channel_t *a, channel_t *b )
   return channel_get_id(a) - channel_get_id(b);
 }
 
+static void
+channel_load_icon ( channel_t *ch )
+{
+  (void)imagecache_get_id(channel_get_icon(ch));
+}
+
+static void
+channel_tag_load_icon ( channel_tag_t *tag )
+{
+  (void)imagecache_get_id(channel_tag_get_icon(tag));
+}
+
 /* **************************************************************************
  * Class definition
  * *************************************************************************/
@@ -209,13 +221,15 @@ channel_class_icon_notify ( void *obj, const char *lang )
 {
   channel_t *ch = obj;
   if (!ch->ch_load)
-    (void)channel_get_icon(obj);
+    channel_load_icon(obj);
 }
 
-static const void *
+const void *
 channel_class_get_icon ( void *obj )
 {
   prop_ptr = channel_get_icon(obj);
+  if (!strempty(prop_ptr))
+    prop_ptr = imagecache_get_propstr(prop_ptr, prop_sbuf, PROP_SBUF_LEN);
   return &prop_ptr;
 }
 
@@ -1032,7 +1046,7 @@ channel_get_icon ( channel_t *ch )
              *picon  = config.picon_path,
              *icon   = ch->ch_icon,
              *chname, *icn;
-  int id, i, pick, prefer = config.prefer_picon ? 1 : 0;
+  int i, pick, prefer = config.prefer_picon ? 1 : 0;
   char c;
 
   if (tvh_str_default(icon, NULL) == NULL)
@@ -1170,14 +1184,7 @@ found:
     icon = buf2;
   }
 
-  /* Lookup imagecache ID */
-  if ((id = imagecache_get_id(icon))) {
-    snprintf(buf, sizeof(buf), "imagecache/%d", id);
-  } else {
-    strlcpy(buf, icon, sizeof(buf));
-  }
-
-  return buf;
+  return icon;
 }
 
 int channel_set_icon ( channel_t *ch, const char *icon )
@@ -1259,7 +1266,7 @@ channel_create0
   htsp_channel_add(ch);
 
   /* determine icon URL */
-  (void)channel_get_icon(ch);
+  channel_load_icon(ch);
 
   return ch;
 }
@@ -1634,16 +1641,7 @@ channel_tag_destroy(channel_tag_t *ct, int delconf)
 const char *
 channel_tag_get_icon(channel_tag_t *ct)
 {
-  static char buf[64];
-  const char *icon  = ct->ct_icon;
-  int id;
-
-  /* Lookup imagecache ID */
-  if ((id = imagecache_get_id(icon))) {
-    snprintf(buf, sizeof(buf), "imagecache/%d", id);
-    return buf;
-  }
-  return icon;
+  return ct->ct_icon;
 }
 
 /**
@@ -1720,13 +1718,15 @@ channel_tag_class_get_title
 static void
 channel_tag_class_icon_notify ( void *obj, const char *lang )
 {
-  (void)channel_tag_get_icon(obj);
+  channel_tag_load_icon(obj);
 }
 
 static const void *
 channel_tag_class_get_icon ( void *obj )
 {
   prop_ptr = channel_tag_get_icon(obj);
+  if (!strempty(prop_ptr))
+    prop_ptr = imagecache_get_propstr(prop_ptr, prop_sbuf, PROP_SBUF_LEN);
   return &prop_ptr;
 }
 
index 5d4bd79fb5e10dd9c4380935321be0d7927f4f22..aa97ec3160c5491ef6ff9435cc238b9001000417 100644 (file)
@@ -155,6 +155,8 @@ channel_t *channel_find_by_number(const char *no);
 
 htsmsg_t * channel_class_get_list(void *o, const char *lang);
 
+const void * channel_class_get_icon ( void *obj );
+
 int channel_set_tags_by_list ( channel_t *ch, htsmsg_t *tags );
 
 channel_tag_t *channel_tag_create(const char *uuid, htsmsg_t *conf);
index 73645efadaf93c57786e19d70e71fb1c10acb310..755b14cfbc2fdce7bbfc4477d68c265cf26ef4c6 100644 (file)
@@ -702,7 +702,8 @@ htsmsg_t * dvr_autorec_entry_class_time_list(void *o, const char *null);
 htsmsg_t * dvr_autorec_entry_class_weekdays_get(uint32_t weekdays);
 htsmsg_t * dvr_autorec_entry_class_weekdays_list (void *o, const char *list);
 char * dvr_autorec_entry_class_weekdays_rend(uint32_t weekdays, const char *lang);
-const char *dvr_entry_class_image_url_get(const dvr_entry_t *o);
+const char *dvr_entry_get_image(const dvr_entry_t *o);
+const char *dvr_entry_get_fanart_image(const dvr_entry_t *o);
 
 void dvr_autorec_check_event(epg_broadcast_t *e);
 
index 972f1fa2134a35204b56602747201abf59736875..06d48cb5664f31f818619e6a05ce392d63953923 100644 (file)
@@ -3855,50 +3855,61 @@ dvr_entry_class_channel_icon_url_get(void *o)
   dvr_entry_t *de = (dvr_entry_t *)o;
   channel_t *ch = de->de_channel;
   if (ch == NULL) {
-    prop_ptr = NULL;
+    prop_ptr = "";
   } else {
-    prop_ptr = channel_get_icon(ch);
+    return channel_class_get_icon(ch);
   }
+  return &prop_ptr;
+}
+
+const char *
+dvr_entry_get_image(const dvr_entry_t *de)
+{
+  if (de->de_bcast && de->de_bcast && de->de_bcast->image)
+    return de->de_bcast->image;
+  if (de->de_image)
+    return de->de_image;
+  return NULL;
+}
+
+const char *
+dvr_entry_get_fanart_image(const dvr_entry_t *de)
+{
+  return de->de_fanart_image;
+}
+
+static const void *
+dvr_entry_class_image_get0(dvr_entry_t *de, const char *image)
+{
+  prop_ptr = imagecache_get_propstr(image, prop_sbuf, PROP_SBUF_LEN);
   if (prop_ptr == NULL)
     prop_ptr = "";
   return &prop_ptr;
 }
 
 static const void *
-dvr_entry_class_image_url_get_as_property(void *o)
+dvr_entry_class_image_get(void *o)
 {
-  dvr_entry_t *de = (dvr_entry_t *)o;
-  static const char *s = "";
-  /* We prefer the image from the broadcast to the one currently
-   * persisted.  This is because a programme scheduled far in the
-   * future may have a generic image that will be updated nearer the
-   * broadcast date with a more specific image.
-   */
-  if (de->de_bcast && de->de_bcast && de->de_bcast->image) {
-    snprintf(prop_sbuf, PROP_SBUF_LEN, "%s", de->de_bcast->image);
-    return &prop_sbuf_ptr;
-  }
-
-  if (de->de_image) {
-    prop_ptr = de->de_image;
-    return &prop_ptr;
-  }
-
-  return &s;
+  return dvr_entry_class_image_get0(o, dvr_entry_get_image(o));
 }
 
-const char *
-dvr_entry_class_image_url_get(const dvr_entry_t *o)
+static void
+dvr_entry_class_image_notify(void *o, const char *lang)
 {
-    const void *image = dvr_entry_class_image_url_get_as_property((void*)o);
-    if (!image) return NULL;
-    const char *image_str = *(const char**)image;
-    if (!image_str) return NULL;
-    if (!*image_str) return NULL;
-    return image_str;
+  (void)imagecache_get_id(dvr_entry_get_image(o));
 }
 
+static const void *
+dvr_entry_class_fanart_image_get(void *o)
+{
+  return dvr_entry_class_image_get0(o, dvr_entry_get_fanart_image(o));
+}
 
+static void
+dvr_entry_class_fanart_image_notify(void *o, const char *lang)
+{
+  (void)imagecache_get_id(dvr_entry_get_fanart_image(o));
+}
 
 static const void *
 dvr_entry_class_duplicate_get(void *o)
@@ -4157,7 +4168,8 @@ const idclass_t dvr_entry_class = {
       .id       = "image", /* Name chosen to be compatible with api_epg */
       .name     = N_("Episode image"),
       .desc     = N_("Episode image."),
-      .get      = dvr_entry_class_image_url_get_as_property,
+      .get      = dvr_entry_class_image_get,
+      .notify   = dvr_entry_class_image_notify,
       .off      = offsetof(dvr_entry_t, de_image),
       .opts     = PO_HIDDEN,
     },
@@ -4166,6 +4178,8 @@ const idclass_t dvr_entry_class = {
       .id       = "fanart_image",
       .name     = N_("Fanart image"),
       .desc     = N_("Fanart image."),
+      .get      = dvr_entry_class_fanart_image_get,
+      .notify   = dvr_entry_class_fanart_image_notify,
       .off      = offsetof(dvr_entry_t, de_fanart_image),
       .opts     = PO_HIDDEN,
     },
index 49af61b17e2a7722a771d2c95199a9472338be09..5a6d794dfe0bea72f84b116d944f90d08bf64214 100644 (file)
@@ -56,14 +56,6 @@ static void *htsp_server, *htsp_server_2;
 #define HTSP_ASYNC_ON   0x01
 #define HTSP_ASYNC_EPG  0x02
 
-#define HTSP_ASYNC_AUX_CH        0x01
-#define HTSP_ASYNC_AUX_CHTAG     0x02
-#define HTSP_ASYNC_AUX_CHTAG_DEL 0x03
-#define HTSP_ASYNC_AUX_DVR       0x04
-#define HTSP_ASYNC_AUX_AUTOREC   0x05
-#define HTSP_ASYNC_AUX_TIMEREC   0x06
-#define HTSP_ASYNC_AUX_EPG       0x07
-
 #define HTSP_ASYNC_EPG_INTERVAL 30
 
 #define HTSP_PRIV_MASK (ACCESS_HTSP_STREAMING)
@@ -344,6 +336,44 @@ htsp_flush_queue(htsp_connection_t *htsp, htsp_msg_q_t *hmq, int dead)
   tvh_mutex_unlock(&htsp->htsp_out_mutex);
 }
 
+/*
+ *
+ */
+static const char *
+htsp_image(htsp_connection_t *htsp, const char *image, char *buf, size_t buflen)
+{
+  const char *ret = image;
+  const int id = imagecache_get_id(image);
+
+  /* Handle older clients */
+  if (id) {
+    if (htsp->htsp_version < 8) {
+      struct sockaddr_storage addr;
+      socklen_t addrlen;
+      char abuf[50];
+      addrlen = sizeof(addr);
+      getsockname(htsp->htsp_fd, (struct sockaddr*)&addr, &addrlen);
+      tcp_get_str_from_ip(&addr, abuf, sizeof(abuf));
+      snprintf(buf, buflen, "http://%s%s%s:%d%s/imagecache/%d",
+                      (addr.ss_family == AF_INET6)?"[":"",
+                      abuf,
+                      (addr.ss_family == AF_INET6)?"]":"",
+                      tvheadend_webui_port,
+                      tvheadend_webroot ?: "",
+                      id);
+      ret = buf;
+    } else if (htsp->htsp_version < 15) {
+      /* older clients expects '/imagecache/' */
+      snprintf(buf, buflen, "/imagecache/%d", id);
+      ret = buf;
+    } else {
+      snprintf(buf, buflen, "imagecache/%d", id);
+      ret = buf;
+    }
+  }
+  return ret;
+}
+
 /**
  *
  */
@@ -827,7 +857,7 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp)
   epg_broadcast_t *now, *next = NULL;
   int64_t chnum = channel_get_number(ch);
   const char *icon;
-  char buf[64];
+  char buf[512];
 
   htsmsg_t *out = htsmsg_create_map();
   htsmsg_t *tags = htsmsg_create_list();
@@ -839,36 +869,8 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp)
     htsmsg_add_u32(out, "channelNumberMinor", channel_get_minor(chnum));
 
   htsmsg_add_str(out, "channelName", channel_get_name(ch, channel_blank_name));
-  if ((icon = channel_get_icon(ch))) {
-
-    /* Handle older clients */
-    if ((strstr(icon, "imagecache") == icon) && htsp->htsp_version < 8) {
-      struct sockaddr_storage addr;
-      socklen_t addrlen;
-      char url[256];
-      char buf[50];
-      addrlen = sizeof(addr);
-      getsockname(htsp->htsp_fd, (struct sockaddr*)&addr, &addrlen);
-      tcp_get_str_from_ip(&addr, buf, 50);
-      snprintf(url, sizeof(url), "http://%s%s%s:%d%s/%s",
-                    (addr.ss_family == AF_INET6)?"[":"",
-                    buf,
-                    (addr.ss_family == AF_INET6)?"]":"",
-                    tvheadend_webui_port,
-                    tvheadend_webroot ?: "",
-                    icon);
-      htsmsg_add_str(out, "channelIcon", url);
-    } else {
-      if (htsp->htsp_version < 15) {
-        /* older clients expects '/imagecache/' */
-        if (strncmp(icon, "imagecache/", 11) == 0) {
-          snprintf(buf, sizeof(buf), "/%s", icon);
-          icon = buf;
-        }
-      }
-      htsmsg_add_str(out, "channelIcon", icon);
-    }
-  }
+  if ((icon = channel_get_icon(ch)))
+    htsmsg_add_str(out, "channelIcon", htsp_image(htsp, icon, buf, sizeof(buf)));
 
   now  = ch->ch_epg_now;
   next = ch->ch_epg_next;
@@ -915,8 +917,10 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp)
  *
  */
 static htsmsg_t *
-htsp_build_tag(channel_tag_t *ct, const char *method, int include_channels)
+htsp_build_tag(htsp_connection_t *htsp, channel_tag_t *ct, const char *method, int include_channels)
 {
+  char buf[512];
+  const char *icon;
   idnode_list_mapping_t *ilm;
   htsmsg_t *out = htsmsg_create_map();
   htsmsg_t *members = include_channels ? htsmsg_create_list() : NULL;
@@ -925,7 +929,9 @@ htsp_build_tag(channel_tag_t *ct, const char *method, int include_channels)
   htsmsg_add_u32(out, "tagIndex", ct->ct_index);
 
   htsmsg_add_str(out, "tagName", ct->ct_name);
-  htsmsg_add_str(out, "tagIcon", channel_tag_get_icon(ct));
+  icon = channel_tag_get_icon(ct);
+  if (!strempty(icon))
+    htsmsg_add_str(out, "tagIcon", htsp_image(htsp, icon, buf, sizeof(buf)));
   htsmsg_add_u32(out, "tagTitledIcon", ct->ct_titled_icon);
 
   if(members != NULL) {
@@ -950,6 +956,7 @@ htsp_build_dvrentry(htsp_connection_t *htsp, dvr_entry_t *de, const char *method
   const char *p, *last;
   int64_t fsize = -1, start, stop;
   uint32_t u32;
+  char buf[512];
   char ubuf[UUID_HEX_SIZE];
 
   htsmsg_add_u32(out, "id", idnode_get_short_uuid(&de->de_id));
@@ -1027,13 +1034,13 @@ htsp_build_dvrentry(htsp_connection_t *htsp, dvr_entry_t *de, const char *method
      * an image from current EPG if recording does not have
      * an associated image.
      */
-    const char *image = dvr_entry_class_image_url_get(de);
-    if(image && *image)
-      htsmsg_add_str(out, "image", image);
+    const char *image = dvr_entry_get_image(de);
+    if(!strempty(image))
+      htsmsg_add_str(out, "image", htsp_image(htsp, image, buf, sizeof(buf)));
     /* htsmsg camelcase to be compatible with other names */
     image = de->de_fanart_image;
-    if(image && *image)
-      htsmsg_add_str(out, "fanartImage", image);
+    if(!strempty(image))
+      htsmsg_add_str(out, "fanartImage", htsp_image(htsp, image, buf, sizeof(buf)));
     if (de->de_copyright_year)
       htsmsg_add_u32(out, "copyrightYear", de->de_copyright_year);
 
@@ -1228,6 +1235,7 @@ htsp_build_event
   epg_genre_t *g;
   epg_episode_num_t epnum;
   const char *str;
+  char buf[512];
 
   /* Ignore? */
   if (update && e->updated <= update) return NULL;
@@ -1296,8 +1304,8 @@ htsp_build_event
     htsmsg_add_s64(out, "firstAired", e->first_aired);
   epg_broadcast_get_epnum(e, &epnum);
   htsp_serialize_epnum(out, &epnum, NULL);
-  if (e->image)
-    htsmsg_add_str(out, "image", e->image);
+  if (!strempty(e->image))
+    htsmsg_add_str(out, "image", htsp_image(htsp, e->image, buf, sizeof(buf)));
 
   if (e->channel) {
     LIST_FOREACH(de, &e->channel->ch_dvrs, de_channel_link) {
@@ -1565,7 +1573,7 @@ htsp_method_async(htsp_connection_t *htsp, htsmsg_t *in)
   /* Send all enabled and external tags */
   TAILQ_FOREACH(ct, &channel_tags, ct_link)
     if(channel_tag_access(ct, htsp->htsp_granted_access, 0))
-      htsp_send_message(htsp, htsp_build_tag(ct, "tagAdd", 0), NULL);
+      htsp_send_message(htsp, htsp_build_tag(htsp, ct, "tagAdd", 0), NULL);
   
   /* Send all channels */
   CHANNEL_FOREACH(ch)
@@ -1575,7 +1583,7 @@ htsp_method_async(htsp_connection_t *htsp, htsmsg_t *in)
   /* Send all enabled and external tags (now with channel mappings) */
   TAILQ_FOREACH(ct, &channel_tags, ct_link)
     if(channel_tag_access(ct, htsp->htsp_granted_access, 0))
-      htsp_send_message(htsp, htsp_build_tag(ct, "tagUpdate", 1), NULL);
+      htsp_send_message(htsp, htsp_build_tag(htsp, ct, "tagUpdate", 1), NULL);
 
   /* Send all autorecs */
   TAILQ_FOREACH(dae, &autorec_entries, dae_link)
@@ -3560,21 +3568,39 @@ htsp_done(void)
  *
  */
 static void
-htsp_async_send(htsmsg_t *m, int mode, int aux_type, void *aux)
+htsp_async_send(htsmsg_t *m, int mode, void *aux)
 {
   htsp_connection_t *htsp;
 
   lock_assert(&global_lock);
   LIST_FOREACH(htsp, &htsp_async_connections, htsp_async_link)
-    if (htsp->htsp_async_mode & mode) {
-      if (aux_type == HTSP_ASYNC_AUX_CHTAG &&
-          !channel_tag_access(aux, htsp->htsp_granted_access, 0))
-        continue;
+    if (htsp->htsp_async_mode & mode)
       htsp_send_message(htsp, htsmsg_copy(m), NULL);
-    }
   htsmsg_destroy(m);
 }
 
+/**
+ *
+ */
+typedef htsmsg_t *(*http_async_send_cb_t)(htsp_connection_t *htsp, void *aux);
+
+static void
+htsp_async_send_cb(http_async_send_cb_t cb, int mode, void *aux)
+{
+  htsp_connection_t *htsp;
+  htsmsg_t *m;
+
+  lock_assert(&global_lock);
+  LIST_FOREACH(htsp, &htsp_async_connections, htsp_async_link)
+    if (htsp->htsp_async_mode & mode) {
+      m = cb(htsp, aux);
+      if (m != NULL) {
+        htsp_send_message(htsp, m, NULL);
+        htsmsg_destroy(m);
+      }
+    }
+}
+
 /**
  * Called from channel.c when a new channel is created
  */
@@ -3643,9 +3669,19 @@ htsp_channel_delete(channel_t *ch)
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_u32(m, "channelId", channel_get_id(ch));
   htsmsg_add_str(m, "method", "channelDelete");
-  htsp_async_send(m, HTSP_ASYNC_ON, HTSP_ASYNC_AUX_CH, ch);
+  htsp_async_send(m, HTSP_ASYNC_ON, ch);
 }
 
+/**
+ *
+ */
+static htsmsg_t *
+htsp_tag_update_msg(htsp_connection_t *htsp, void *tag)
+{
+  if (!channel_tag_access(tag, htsp->htsp_granted_access, 0))
+    return NULL;
+  return htsp_build_tag(htsp, tag, "tagUpdate", 1);
+}
 
 /**
  * Called from channel.c when a tag is exported
@@ -3653,21 +3689,17 @@ htsp_channel_delete(channel_t *ch)
 void
 htsp_tag_add(channel_tag_t *ct)
 {
-  htsp_async_send(htsp_build_tag(ct, "tagAdd", 1), HTSP_ASYNC_ON,
-                  HTSP_ASYNC_AUX_CHTAG, ct);
+  htsp_async_send_cb(htsp_tag_update_msg, HTSP_ASYNC_ON, ct);
 }
 
-
 /**
  * Called from channel.c when an exported tag is changed
  */
 void
 htsp_tag_update(channel_tag_t *ct)
 {
-  if (ct->ct_enabled && !ct->ct_internal) {
-    htsp_async_send(htsp_build_tag(ct, "tagUpdate", 1), HTSP_ASYNC_ON,
-                    HTSP_ASYNC_AUX_CHTAG, ct);
-  }
+  if (ct->ct_enabled && !ct->ct_internal)
+    htsp_async_send_cb(htsp_tag_update_msg, HTSP_ASYNC_ON, ct);
   else // in case the tag was ever sent to the client
     htsp_tag_delete(ct);
 }
@@ -3682,7 +3714,7 @@ htsp_tag_delete(channel_tag_t *ct)
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_u32(m, "tagId", htsp_channel_tag_get_identifier(ct));
   htsmsg_add_str(m, "method", "tagDelete");
-  htsp_async_send(m, HTSP_ASYNC_ON, HTSP_ASYNC_AUX_CHTAG_DEL, ct);
+  htsp_async_send(m, HTSP_ASYNC_ON, ct);
 }
 
 /**
@@ -3712,7 +3744,6 @@ htsp_dvr_entry_add(dvr_entry_t *de)
   _htsp_dvr_entry_update(de, "dvrEntryAdd", NULL);
 }
 
-
 /**
  * Called from dvr_db.c when a DVR entry is updated
  */
@@ -3739,7 +3770,6 @@ htsp_dvr_entry_update_stats(dvr_entry_t *de)
   }
 }
 
-
 /**
  * Called from dvr_db.c when a DVR entry is deleted
  */
@@ -3749,7 +3779,7 @@ htsp_dvr_entry_delete(dvr_entry_t *de)
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_u32(m, "id", idnode_get_short_uuid(&de->de_id));
   htsmsg_add_str(m, "method", "dvrEntryDelete");
-  htsp_async_send(m, HTSP_ASYNC_ON, HTSP_ASYNC_AUX_DVR, de);
+  htsp_async_send(m, HTSP_ASYNC_ON, de);
 }
 
 /**
@@ -3803,7 +3833,7 @@ htsp_autorec_entry_delete(dvr_autorec_entry_t *dae)
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_str(m, "id", idnode_uuid_as_str(&dae->dae_id, ubuf));
   htsmsg_add_str(m, "method", "autorecEntryDelete");
-  htsp_async_send(m, HTSP_ASYNC_ON, HTSP_ASYNC_AUX_AUTOREC, dae);
+  htsp_async_send(m, HTSP_ASYNC_ON, dae);
 }
 
 /**
@@ -3857,7 +3887,7 @@ htsp_timerec_entry_delete(dvr_timerec_entry_t *dte)
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_str(m, "id", idnode_uuid_as_str(&dte->dte_id, ubuf));
   htsmsg_add_str(m, "method", "timerecEntryDelete");
-  htsp_async_send(m, HTSP_ASYNC_ON, HTSP_ASYNC_AUX_TIMEREC, dte);
+  htsp_async_send(m, HTSP_ASYNC_ON, dte);
 }
 
 /**
@@ -3951,7 +3981,7 @@ htsp_event_delete(epg_broadcast_t *ebc)
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_str(m, "method", "eventDelete");
   htsmsg_add_u32(m, "eventId", ebc->id);
-  htsp_async_send(m, HTSP_ASYNC_EPG, HTSP_ASYNC_AUX_EPG, ebc);
+  htsp_async_send(m, HTSP_ASYNC_EPG, ebc);
 }
 
 static const char frametypearray[PKT_NTYPES] = {
index dd852047c14154b79ba5c2c54a4aaf205b76bec9..a11caf80df0b2faa06a84f0874e7e58293b0402a 100644 (file)
@@ -909,19 +909,18 @@ http_extra_send_prealloc(http_connection_t *hc, const void *data,
  *
  */
 char *
-http_get_hostpath(http_connection_t *hc)
+http_get_hostpath(http_connection_t *hc, char *buf, size_t buflen)
 {
-  char buf[256];
   const char *host, *proto;
 
   host  = http_arg_get(&hc->hc_args, "Host") ?:
           http_arg_get(&hc->hc_args, "X-Forwarded-Host");
   proto = http_arg_get(&hc->hc_args, "X-Forwarded-Proto");
 
-  snprintf(buf, sizeof(buf), "%s://%s%s",
+  snprintf(buf, buflen, "%s://%s%s",
            proto ?: "http", host ?: "localhost", tvheadend_webroot ?: "");
 
-  return strdup(buf);
+  return buf;
 }
 
 /**
index e193717e94f82c3ca5bf6cf0ecd30fb2fcb0926e..6c6bb6cd8c100585289104bfc5af61c80487e151 100644 (file)
@@ -326,7 +326,7 @@ int http_access_verify_channel(http_connection_t *hc, int mask,
 
 void http_parse_args(http_arg_list_t *list, char *args);
 
-char *http_get_hostpath(http_connection_t *hc);
+char *http_get_hostpath(http_connection_t *hc, char *buf, size_t buflen);
 
 /*
  * HTTP/RTSP Client
index 7188404cdad30d858b01c55a577172a5bb890c94..502c466abd7533ab5750aa88f005af1bdd68d951 100644 (file)
@@ -37,7 +37,8 @@ typedef struct imagecache_image
 {
   int         id;       ///< Internal ID
   const char *url;      ///< Upstream URL
-  int         failed;   ///< Last update failed
+  uint8_t     failed;   ///< Last update failed
+  uint8_t     savepend; ///< Pending save
   time_t      accessed; ///< Last time the file was accessed
   time_t      updated;  ///< Last time the file was checked
   uint8_t     sha1[20]; ///< Contents hash
@@ -58,7 +59,6 @@ static RB_HEAD(,imagecache_image)     imagecache_by_id;
 static RB_HEAD(,imagecache_image)     imagecache_by_url;
 SKEL_DECLARE(imagecache_skel, imagecache_image_t);
 
-#if ENABLE_IMAGECACHE
 struct imagecache_config imagecache_conf = {
   .idnode.in_class = &imagecache_class,
 };
@@ -128,10 +128,8 @@ const idclass_t imagecache_class = {
 static tvh_cond_t                     imagecache_cond;
 static TAILQ_HEAD(, imagecache_image) imagecache_queue;
 static mtimer_t                       imagecache_timer;
-#endif
 
-#if ENABLE_IMAGECACHE
-static int
+static inline int
 sha1_empty( const uint8_t *sha1 )
 {
   int i;
@@ -140,7 +138,6 @@ sha1_empty( const uint8_t *sha1 )
       return 0;
   return 1;
 }
-#endif
 
 static int
 url_cmp ( imagecache_image_t *a, imagecache_image_t *b )
@@ -154,7 +151,6 @@ id_cmp ( imagecache_image_t *a, imagecache_image_t *b )
   return (a->id - b->id);
 }
 
-#if ENABLE_IMAGECACHE
 static htsmsg_t *
 imagecache_image_htsmsg ( imagecache_image_t *img )
 {
@@ -175,6 +171,7 @@ imagecache_image_htsmsg ( imagecache_image_t *img )
 static void
 imagecache_image_save ( imagecache_image_t *img )
 {
+  img->savepend = 1;
   if (img->state != SAVE && img->state != QUEUED && img->state != FETCHING) {
     img->state = SAVE;
     TAILQ_INSERT_TAIL(&imagecache_queue, img, q_link);
@@ -182,7 +179,6 @@ imagecache_image_save ( imagecache_image_t *img )
   }
 }
 
-
 static void
 imagecache_new_id ( imagecache_image_t *i )
 {
@@ -199,6 +195,7 @@ static void
 imagecache_image_add ( imagecache_image_t *img )
 {
   int oldstate = img->state;
+  if (!imagecache_conf.enabled) return;
   if (strncasecmp("file://", img->url, 7)) {
     img->state = QUEUED;
     if (oldstate != SAVE && oldstate != QUEUED)
@@ -380,10 +377,12 @@ imagecache_thread ( void *p )
 
     TAILQ_REMOVE(&imagecache_queue, img, q_link);
 
+retry:
     if (img->state == SAVE) {
       /* Do save outside global mutex */
       htsmsg_t *m = imagecache_image_htsmsg(img);
       img->state = IDLE;
+      img->savepend = 0;
       tvh_mutex_unlock(&global_lock);
       hts_settings_save(m, "imagecache/meta/%d", img->id);
       htsmsg_destroy(m);
@@ -391,8 +390,14 @@ imagecache_thread ( void *p )
 
     } else if (img->state == QUEUED) {
       /* Fetch */
-      img->state = FETCHING;
-      (void)imagecache_image_fetch(img);
+      if (imagecache_conf.enabled) {
+        img->state = FETCHING;
+        (void)imagecache_image_fetch(img);
+      }
+      if (img->savepend) {
+        img->state = SAVE;
+        goto retry;
+      }
       img->state = IDLE;
 
     } else {
@@ -427,8 +432,6 @@ imagecache_timer_cb ( void *p )
   }
 }
 
-#endif /* ENABLE_IMAGECACHE */
-
 /*
  * Initialise
  */
@@ -444,8 +447,7 @@ imagecache_init ( void )
   int id;
 
   /* Init vars */
-  imagecache_id             = 0;
-#if ENABLE_IMAGECACHE
+  imagecache_id                  = 0;
   imagecache_conf.enabled        = 0;
   imagecache_conf.expire         = 7;      // 7 days
   imagecache_conf.ok_period      = 24 * 7; // weekly
@@ -453,21 +455,16 @@ imagecache_init ( void )
   imagecache_conf.ignore_sslcert = 0;
 
   idclass_register(&imagecache_class);
-#endif
 
   /* Create threads */
-#if ENABLE_IMAGECACHE
   tvh_cond_init(&imagecache_cond, 1);
   TAILQ_INIT(&imagecache_queue);
-#endif
 
   /* Load settings */
-#if ENABLE_IMAGECACHE
   if ((m = hts_settings_load("imagecache/config"))) {
     idnode_load(&imagecache_conf.idnode, m);
     htsmsg_destroy(m);
   }
-#endif
   if ((m = hts_settings_load("imagecache/meta"))) {
     HTSMSG_FOREACH(f, m) {
       if (!(e   = htsmsg_get_map_by_field(f))) continue;
@@ -491,21 +488,18 @@ imagecache_init ( void )
       }
       i = RB_INSERT_SORTED(&imagecache_by_id, img, id_link, id_cmp);
       assert(!i);
-#if ENABLE_IMAGECACHE
       if (img->accessed == 0) {
         img->accessed = gclk();
         imagecache_image_save(img);
       }
       if (!img->updated)
         imagecache_image_add(img);
-#endif
       if (imagecache_id <= id)
         imagecache_id = id + 1;
     }
     htsmsg_destroy(m);
   }
 
-#if ENABLE_IMAGECACHE
   /* Start threads */
   tvh_thread_create(&imagecache_tid, NULL, imagecache_thread, NULL, "imagecache");
 
@@ -514,7 +508,6 @@ imagecache_init ( void )
   //       the reality its not necessary and I'd prefer to avoid dumping
   //       100's of timers into the global pool
   mtimer_arm_rel(&imagecache_timer, imagecache_timer_cb, NULL, sec2mono(600));
-#endif
 }
 
 
@@ -542,22 +535,18 @@ imagecache_done ( void )
 {
   imagecache_image_t *img;
 
-#if ENABLE_IMAGECACHE
   tvh_mutex_lock(&global_lock);
   mtimer_disarm(&imagecache_timer);
   tvh_mutex_unlock(&global_lock);
   tvh_cond_signal(&imagecache_cond, 1);
   pthread_join(imagecache_tid, NULL);
-#endif
   tvh_mutex_lock(&global_lock);
   while ((img = RB_FIRST(&imagecache_by_id)) != NULL) {
-#if ENABLE_IMAGECACHE
     if (img->state == SAVE) {
       htsmsg_t *m = imagecache_image_htsmsg(img);
       hts_settings_save(m, "imagecache/meta/%d", img->id);
       htsmsg_destroy(m);
     }
-#endif
     imagecache_destroy(img, 0);
   }
   tvh_mutex_unlock(&global_lock);
@@ -565,8 +554,6 @@ imagecache_done ( void )
 }
 
 
-#if ENABLE_IMAGECACHE
-
 /*
  * Class save
  */
@@ -644,20 +631,19 @@ imagecache_trigger( void )
   }
 }
 
-#endif /* ENABLE_IMAGECACHE */
-
 /*
  * Fetch a URLs ID
+ *
+ * If imagecache is not enabled, just manage the id<->local filename
+ * mapping database.
  */
 int
 imagecache_get_id ( const char *url )
 {
   int id = 0;
   imagecache_image_t *i;
-#if ENABLE_IMAGECACHE
   int save = 0;
   time_t clk;
-#endif
 
   lock_assert(&global_lock);
 
@@ -666,10 +652,8 @@ imagecache_get_id ( const char *url )
     return 0;
 
   /* Disabled */
-#if !ENABLE_IMAGECACHE
-  if (strncasecmp(url, "file://", 7))
+  if (!imagecache_conf.enabled && strncasecmp(url, "file://", 7))
     return 0;
-#endif
 
   /* Skeleton */
   SKEL_ALLOC(imagecache_skel);
@@ -681,21 +665,15 @@ imagecache_get_id ( const char *url )
     i = imagecache_skel;
     i->url = strdup(url);
     SKEL_USED(imagecache_skel);
-#if ENABLE_IMAGECACHE
+    save = 1;
     imagecache_new_id(i);
     imagecache_image_add(i);
-    save = 1;
-#endif
   }
-#if ENABLE_IMAGECACHE
-  if (!strncasecmp(url, "file://", 7) || imagecache_conf.enabled)
-    id = i->id;
-#else
-  if (!strncasecmp(url, "file://", 7))
+
+  /* Do file:// to imagecache ID mapping even if imagecache is not enabled */
+  if (imagecache_conf.enabled || !strncasecmp(url, "file://", 7))
     id = i->id;
-#endif
 
-#if ENABLE_IMAGECACHE
   clk = gclk();
   if (clk != i->accessed) {
     i->accessed = clk;
@@ -703,10 +681,21 @@ imagecache_get_id ( const char *url )
   }
   if (save)
     imagecache_image_save(i);
-#endif
   return id;
 }
 
+/*
+ *
+ */
+const char *
+imagecache_get_propstr ( const char *image, char *buf, size_t buflen )
+{
+  int id = imagecache_get_id(image);
+  if (id == 0) return image;
+  snprintf(buf, buflen, "imagecache/%d", id);
+  return buf;
+}
+
 /*
  * Get data
  */
@@ -731,7 +720,6 @@ imagecache_filename ( int id, char *name, size_t len )
   }
 
   /* Remote file */
-#if ENABLE_IMAGECACHE
   else if (imagecache_conf.enabled) {
     int e;
     int64_t mono;
@@ -759,7 +747,6 @@ imagecache_filename ( int id, char *name, size_t len )
     if (hts_settings_buildpath(name, len, "imagecache/data/%d", i->id))
       return -1;
   }
-#endif
 
   return 0;
 }
index c0c91d298e6cc2f2477ac943c7cb246305f64937..5a2d0e19b9ae8fd94932fece0342b716782f1382 100644 (file)
@@ -36,15 +36,17 @@ extern const idclass_t imagecache_class;
 
 extern tvh_mutex_t imagecache_mutex;
 
-void     imagecache_init     ( void );
-void    imagecache_done     ( void );
+void imagecache_init     ( void );
+void imagecache_done     ( void );
 
-void     imagecache_clean    ( void );
-void     imagecache_trigger  ( void );
+void imagecache_clean    ( void );
+void imagecache_trigger  ( void );
 
 // Note: will return 0 if invalid (must serve original URL)
-int      imagecache_get_id  ( const char *url );
+int imagecache_get_id  ( const char *url );
 
-int      imagecache_filename ( int id, char *name, size_t len );
+const char *imagecache_get_propstr ( const char *image, char *buf, size_t buflen );
+
+int imagecache_filename ( int id, char *name, size_t len );
 
 #endif /* __IMAGE_CACHE_H__ */
index 83331f9e61e53bfa68a038be8b08ec076edeb2ec..87d6f12700f6648e66c08348eb44ad034a9848cb 100644 (file)
@@ -165,9 +165,6 @@ const tvh_caps_t tvheadend_capabilities[] = {
 #if ENABLE_SATIP_SERVER
   { "satip_server", NULL },
 #endif
-#if ENABLE_IMAGECACHE
-  { "imagecache", (uint32_t*)&imagecache_conf.enabled },
-#endif
 #if ENABLE_TIMESHIFT
   { "timeshift", (uint32_t *)&timeshift_conf.enabled },
 #endif
index 5cce152243fde764ec2f3a7f32b3e0219dda77b1..8300274e24d632223aaee4e1ffd760a0e98b67e1 100644 (file)
@@ -66,9 +66,6 @@ tvheadend.baseconf = function(panel, index) {
 
 tvheadend.imgcacheconf = function(panel, index) {
 
-    if (tvheadend.capabilities.indexOf('imagecache') === -1)
-        return;
-
     var cleanButton = {
         name: 'clean',
         builder: function() {
index 3e46221e7dad78cdbd9f2f3288ec13eee35ec005..2d7d135e3db1e5efb5767c5c86118c4a0eb0b1c1 100644 (file)
@@ -508,9 +508,10 @@ http_m3u_playlist_add(htsbuf_queue_t *hq, const char *hostpath,
   if (urlauth == URLAUTH_TICKET)
     ticket = access_ticket_create(url_remain, access);
   htsbuf_append_str(hq, "#EXTINF:-1");
-  if (logo) {
-    if (strncmp(logo, "imagecache/", 11) == 0) {
-      htsbuf_qprintf(hq, " logo=\"%s/%s", hostpath, logo);
+  if (!strempty(logo)) {
+    int id = imagecache_get_id(logo);
+    if (id) {
+      htsbuf_qprintf(hq, " logo=\"%s/imagecache/%d", hostpath, id);
       switch (urlauth) {
       case URLAUTH_NONE:
         break;
@@ -578,7 +579,7 @@ http_satip_m3u_playlist_add(htsbuf_queue_t *hq, const char *hostpath,
   const char *name, *logo;
   idnode_list_mapping_t *ilm;
   service_t *s = NULL;
-  int src;
+  int id, src;
 
   LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) {
     /* cannot handle channels with more services for SAT>IP */
@@ -591,16 +592,15 @@ http_satip_m3u_playlist_add(htsbuf_queue_t *hq, const char *hostpath,
     return;
   name = channel_get_name(ch, blank);
   logo = channel_get_icon(ch);
+  id = imagecache_get_id(logo);
   snprintf(buf, sizeof(buf), "/stream/channelid/%d", channel_get_id(ch));
   htsbuf_append_str(hq, "#EXTINF:-1");
-  if (logo) {
-    if (strncmp(logo, "imagecache/", 11) == 0) {
-      htsbuf_qprintf(hq, " logo=%s/%s", hostpath, logo);
-      if (urlauth == URLAUTH_CODE && !strempty(access->aa_auth))
-        htsbuf_qprintf(hq, "?auth=%s", access->aa_auth);
-    } else {
-      htsbuf_qprintf(hq, " logo=%s", logo);
-    }
+  if (id) {
+    htsbuf_qprintf(hq, " logo=%s/imagecache/%d", hostpath, id);
+    if (urlauth == URLAUTH_CODE && !strempty(access->aa_auth))
+      htsbuf_qprintf(hq, "?auth=%s", access->aa_auth);
+  } else if (!strempty(logo)) {
+    htsbuf_qprintf(hq, " logo=%s", logo);
   }
   htsbuf_qprintf(hq, ",%s\n%s%s?profile=pass", name, hostpath, buf);
   if (urlauth == URLAUTH_CODE && !strempty(access->aa_auth))
@@ -615,8 +615,8 @@ static int
 http_channel_playlist(http_connection_t *hc, int pltype, int urlauth, channel_t *channel)
 {
   htsbuf_queue_t *hq;
-  char buf[255], chnum[32];
-  char *profile, *hostpath;
+  char buf[255], hostpath[512], chnum[32];
+  char *profile;
   const char *name, *blank;
   const char *lang = hc->hc_access->aa_lang_ui;
   char ubuf[UUID_HEX_SIZE];
@@ -625,7 +625,7 @@ http_channel_playlist(http_connection_t *hc, int pltype, int urlauth, channel_t
     return http_noaccess_code(hc);
 
   profile = profile_validate_name(http_arg_get(&hc->hc_req_args, "profile"));
-  hostpath = http_get_hostpath(hc);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
 
   hq = &hc->hc_reply;
 
@@ -654,7 +654,6 @@ http_channel_playlist(http_connection_t *hc, int pltype, int urlauth, channel_t
 
   }
 
-  free(hostpath);
   free(profile);
   return 0;
 }
@@ -667,8 +666,8 @@ static int
 http_tag_playlist(http_connection_t *hc, int pltype, int urlauth, channel_tag_t *tag)
 {
   htsbuf_queue_t *hq;
-  char buf[255], chnum[32], ubuf[UUID_HEX_SIZE];
-  char *profile, *hostpath;
+  char buf[255], hostpath[512], chnum[32], ubuf[UUID_HEX_SIZE];
+  char *profile;
   const char *name, *blank, *sort, *lang;
   channel_t *ch;
   channel_t **chlist;
@@ -680,7 +679,7 @@ http_tag_playlist(http_connection_t *hc, int pltype, int urlauth, channel_tag_t
   lang = hc->hc_access->aa_lang_ui;
   hq = &hc->hc_reply;
   profile = profile_validate_name(http_arg_get(&hc->hc_req_args, "profile"));
-  hostpath = http_get_hostpath(hc);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
   sort = http_arg_get(&hc->hc_req_args, "sort");
   chlist = channel_get_sorted_list_for_tag(sort, tag, &count);
 
@@ -710,7 +709,6 @@ http_tag_playlist(http_connection_t *hc, int pltype, int urlauth, channel_tag_t
   }
 
   free(chlist);
-  free(hostpath);
   free(profile);
   return 0;
 }
@@ -723,7 +721,7 @@ static int
 http_tag_list_playlist(http_connection_t *hc, int pltype, int urlauth)
 {
   htsbuf_queue_t *hq;
-  char buf[255];
+  char buf[255], hostpath[512];
   channel_tag_t *ct;
   channel_tag_t **ctlist;
   channel_t *ch;
@@ -731,7 +729,7 @@ http_tag_list_playlist(http_connection_t *hc, int pltype, int urlauth)
   int labelidx = 0;
   int idx, count = 0;
   int chidx, chcount = 0;
-  char *profile, *hostpath;
+  char *profile;
   const char *blank, *sort, *lang;
   idnode_list_mapping_t *ilm;
 
@@ -741,7 +739,7 @@ http_tag_list_playlist(http_connection_t *hc, int pltype, int urlauth)
   lang = hc->hc_access->aa_lang_ui;
   hq = &hc->hc_reply;
   profile = profile_validate_name(http_arg_get(&hc->hc_req_args, "profile"));
-  hostpath = http_get_hostpath(hc);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
   sort = http_arg_get(&hc->hc_req_args, "sort");
   ctlist = channel_tag_get_sorted_list(sort, &count);
 
@@ -758,7 +756,8 @@ http_tag_list_playlist(http_connection_t *hc, int pltype, int urlauth)
     if (pltype == PLAYLIST_M3U) {
       snprintf(buf, sizeof(buf), "/playlist/tagid/%d", idnode_get_short_uuid(&ct->ct_id));
       http_m3u_playlist_add(hq, hostpath, buf, profile, ct->ct_name, NULL,
-                            channel_tag_get_icon(ct), NULL, urlauth, hc->hc_access);
+                            channel_tag_get_icon(ct),
+                            NULL, urlauth, hc->hc_access);
     } else if (pltype == PLAYLIST_E2) {
       htsbuf_qprintf(hq, "#SERVICE 1:64:%d:0:0:0:0:0:0:0::%s\n", labelidx++, ct->ct_name);
       htsbuf_qprintf(hq, "#DESCRIPTION %s\n", ct->ct_name);
@@ -784,7 +783,6 @@ http_tag_list_playlist(http_connection_t *hc, int pltype, int urlauth)
   free(ctlist);
   free(chlist);
 
-  free(hostpath);
   free(profile);
   return 0;
 }
@@ -797,11 +795,11 @@ static int
 http_channel_list_playlist(http_connection_t *hc, int pltype, int urlauth)
 {
   htsbuf_queue_t *hq;
-  char buf[255], chnum[32], ubuf[UUID_HEX_SIZE];
+  char buf[255], hostpath[512], chnum[32], ubuf[UUID_HEX_SIZE];
   channel_t *ch;
   channel_t **chlist;
   int idx = 0, count = 0;
-  char *profile, *hostpath;
+  char *profile;
   const char *name, *blank, *sort, *lang;
 
   if (access_verify2(hc->hc_access, ACCESS_STREAMING))
@@ -811,7 +809,7 @@ http_channel_list_playlist(http_connection_t *hc, int pltype, int urlauth)
 
   lang = hc->hc_access->aa_lang_ui;
   profile = profile_validate_name(http_arg_get(&hc->hc_req_args, "profile"));
-  hostpath = http_get_hostpath(hc);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
   sort = http_arg_get(&hc->hc_req_args, "sort");
   chlist = channel_get_sorted_list(sort, 0, &count);
   blank = tvh_gettext_lang(lang, channel_blank_name);
@@ -840,7 +838,6 @@ http_channel_list_playlist(http_connection_t *hc, int pltype, int urlauth)
   }
 
   free(chlist);
-  free(hostpath);
   free(profile);
   return 0;
 }
@@ -854,10 +851,9 @@ static int
 http_dvr_list_playlist(http_connection_t *hc, int pltype, int urlauth)
 {
   htsbuf_queue_t *hq;
-  char buf[255], ubuf[UUID_HEX_SIZE];
+  char buf[255], hostpath[512], ubuf[UUID_HEX_SIZE];
   dvr_entry_t *de;
   const char *uuid;
-  char *hostpath;
   off_t fsize;
   time_t durration;
   struct tm tm;
@@ -867,7 +863,7 @@ http_dvr_list_playlist(http_connection_t *hc, int pltype, int urlauth)
     return HTTP_STATUS_BAD_REQUEST;
 
   hq = &hc->hc_reply;
-  hostpath = http_get_hostpath(hc);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
 
   htsbuf_append_str(hq, "#EXTM3U\n");
   LIST_FOREACH(de, &dvrentries, de_global_link) {
@@ -909,7 +905,6 @@ http_dvr_list_playlist(http_connection_t *hc, int pltype, int urlauth)
     htsbuf_append_str(hq, "\n");
   }
 
-  free(hostpath);
   return 0;
 }
 
@@ -920,13 +915,12 @@ static int
 http_dvr_playlist(http_connection_t *hc, int pltype, int urlauth, dvr_entry_t *de)
 {
   htsbuf_queue_t *hq = &hc->hc_reply;
-  char buf[255], ubuf[UUID_HEX_SIZE];
+  char buf[255], hostpath[512], ubuf[UUID_HEX_SIZE];
   const char *ticket_id = NULL, *uuid;
   time_t durration = 0;
   off_t fsize = 0;
   int bandwidth = 0, ret = 0;
   struct tm tm;  
-  char *hostpath;
 
   if(pltype != PLAYLIST_M3U)
     return HTTP_STATUS_BAD_REQUEST;
@@ -937,8 +931,8 @@ http_dvr_playlist(http_connection_t *hc, int pltype, int urlauth, dvr_entry_t *d
   if(dvr_entry_verify(de, hc->hc_access, 1))
     return HTTP_STATUS_NOT_FOUND;
 
-  hostpath  = http_get_hostpath(hc);
-  durration  = dvr_entry_get_stop_time(de) - dvr_entry_get_start_time(de, 0);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
+  durration = dvr_entry_get_stop_time(de) - dvr_entry_get_start_time(de, 0);
   fsize = dvr_get_filesize(de, 0);
 
   if(fsize) {
@@ -971,7 +965,6 @@ http_dvr_playlist(http_connection_t *hc, int pltype, int urlauth, dvr_entry_t *d
     ret = HTTP_STATUS_NOT_FOUND;
   }
 
-  free(hostpath);
   return ret;
 }
 
@@ -1405,12 +1398,12 @@ static int
 page_xspf(http_connection_t *hc, const char *remain, void *opaque, int urlauth)
 {
   htsbuf_queue_t *hq = &hc->hc_reply;
-  char buf[80], *hostpath;
+  char buf[80], hostpath[512];
   const char *title, *profile, *ticket, *image, *delim = "?";
 
   if ((title = http_arg_get(&hc->hc_req_args, "title")) == NULL)
     title = "TVHeadend Stream";
-  hostpath = http_get_hostpath(hc);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
   htsbuf_qprintf(hq, "\
 <?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n\
 <playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\r\n\
@@ -1418,7 +1411,6 @@ page_xspf(http_connection_t *hc, const char *remain, void *opaque, int urlauth)
      <track>\r\n\
        <title>%s</title>\r\n\
        <location>%s/%s", title, hostpath, remain);
-  free(hostpath);
   profile = http_arg_get(&hc->hc_req_args, "profile");
   if (profile) {
     htsbuf_qprintf(hq, "?profile=%s", profile);
@@ -1466,17 +1458,16 @@ static int
 page_m3u(http_connection_t *hc, const char *remain, void *opaque, int urlauth)
 {
   htsbuf_queue_t *hq = &hc->hc_reply;
-  char buf[80], *hostpath;
+  char buf[80], hostpath[512];
   const char *title, *profile, *ticket, *delim = "?";
 
   if ((title = http_arg_get(&hc->hc_req_args, "title")) == NULL)
     title = "TVHeadend Stream";
-  hostpath = http_get_hostpath(hc);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
   htsbuf_qprintf(hq, "\
 #EXTM3U\r\n\
 #EXTINF:-1,%s\r\n\
 %s/%s", title, hostpath, remain);
-  free(hostpath);
   profile = http_arg_get(&hc->hc_req_args, "profile");
   if (profile) {
     htsbuf_qprintf(hq, "?profile=%s", profile);
index d7087c26cb3a8942b078ca10382c53bf36eb09c9..f6ca90a333ac643d1c10abe0ef62d583d80226db 100644 (file)
@@ -22,6 +22,7 @@
 #include "channels.h"
 #include "http.h"
 #include "string_list.h"
+#include "imagecache.h"
 
 /*
  *
@@ -72,12 +73,14 @@ http_xmltv_channel_add(htsbuf_queue_t *hq, const char *hostpath, channel_t *ch)
   htsbuf_append_and_escape_xml(hq, channel_get_name(ch, ""));
   htsbuf_append_str(hq, "</display-name>\n");
   if (icon) {
-    if (strncmp(icon, "imagecache/", 11) == 0)
-      htsbuf_qprintf(hq, "  <icon src=\"%s/", hostpath);
-    else
+    int id = imagecache_get_id(icon);
+    if (id) {
+      htsbuf_qprintf(hq, "  <icon src=\"%s/imagecache/%d\"/>\n", hostpath, id);
+    } else {
       htsbuf_append_str(hq, "  <icon src=\"");
-    htsbuf_append_and_escape_xml(hq, icon);
-    htsbuf_append_str(hq, "\"/>\n");
+      htsbuf_append_and_escape_xml(hq, icon);
+      htsbuf_append_str(hq, "\"/>\n");
+    }
   }
   htsbuf_append_str(hq, "</channel>\n");
 }
@@ -211,17 +214,16 @@ http_xmltv_programme_add(htsbuf_queue_t *hq, const char *hostpath, channel_t *ch
 static int
 http_xmltv_channel(http_connection_t *hc, channel_t *channel)
 {
-  char *hostpath;
+  char hostpath[512];
 
   if (http_access_verify_channel(hc, ACCESS_STREAMING, channel))
     return http_noaccess_code(hc);
 
-  hostpath = http_get_hostpath(hc);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
   http_xmltv_begin(&hc->hc_reply);
   http_xmltv_channel_add(&hc->hc_reply, hostpath, channel);
   http_xmltv_programme_add(&hc->hc_reply, hostpath, channel);
   http_xmltv_end(&hc->hc_reply);
-  free(hostpath);
   return 0;
 }
 
@@ -233,13 +235,13 @@ static int
 http_xmltv_tag(http_connection_t *hc, channel_tag_t *tag)
 {
   idnode_list_mapping_t *ilm;
-  char *hostpath;
+  char hostpath[512];
   channel_t *ch;
 
   if (access_verify2(hc->hc_access, ACCESS_STREAMING))
     return http_noaccess_code(hc);
 
-  hostpath = http_get_hostpath(hc);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
 
   http_xmltv_begin(&hc->hc_reply);
   LIST_FOREACH(ilm, &tag->ct_ctms, ilm_in1_link) {
@@ -256,7 +258,6 @@ http_xmltv_tag(http_connection_t *hc, channel_tag_t *tag)
   }
   http_xmltv_end(&hc->hc_reply);
 
-  free(hostpath);
   return 0;
 }
 
@@ -267,12 +268,12 @@ static int
 http_xmltv_channel_list(http_connection_t *hc)
 {
   channel_t *ch;
-  char *hostpath;
+  char hostpath[512];
 
   if (access_verify2(hc->hc_access, ACCESS_STREAMING))
     return http_noaccess_code(hc);
 
-  hostpath = http_get_hostpath(hc);
+  http_get_hostpath(hc, hostpath, sizeof(hostpath));
 
   http_xmltv_begin(&hc->hc_reply);
   CHANNEL_FOREACH(ch) {
@@ -287,7 +288,6 @@ http_xmltv_channel_list(http_connection_t *hc)
   }
   http_xmltv_end(&hc->hc_reply);
 
-  free(hostpath);
   return 0;
 }