diff -rupN original/src/iptv_input.c new/src/iptv_input.c
--- original/src/iptv_input.c	2013-07-11 21:17:34.000000000 +0200
+++ new/src/iptv_input.c	2013-10-04 08:00:04.000000000 +0200
@@ -40,6 +40,7 @@
 #include "tsdemux.h"
 #include "psi.h"
 #include "settings.h"
+#include "tcp.h"
 
 static int iptv_thread_running;
 static int iptv_epollfd;
@@ -48,6 +49,57 @@ static pthread_mutex_t iptv_recvmutex;
 struct service_list iptv_all_services; /* All IPTV services */
 static struct service_list iptv_active_services; /* Currently enabled */
 
+
+/*
+ * URL processing - TODO: move to a library
+ */
+typedef struct
+url
+{
+  char       buf[2048];
+  const char *scheme;
+  const char *host;
+  uint16_t   port;
+  const char *path;  
+} url_t;
+
+static int
+url_parse ( url_t *up, const char *urlstr )
+{
+  char *t1, *t2;
+  strcpy(up->buf, urlstr);
+
+  /* Scheme */
+  up->scheme = t1 = up->buf;
+  if (!(t2 = strstr(t1, "://"))) {
+    return 1;
+  }
+  *t2 = 0;
+
+  /* Host */
+  up->host = t1 = t2 + 3;
+  up->path = NULL;
+  if ((t2 = strstr(t1, "/"))) {
+    *t2 = 0;
+    up->path = t2 + 1;
+  }
+
+  /* Port */
+  up->port = 0;
+  if (!(t2 = strstr(up->host, ":"))) {
+    if (!strcmp(up->scheme, "https"))
+      up->port = 443;
+    else if (!strcmp(up->scheme, "http"))
+      up->port = 80;
+  } else {
+    *t2 = 0;
+    up->port = atoi(t2+1);
+  }
+
+  return 0;
+}
+
+
 /**
  * PAT parser. We only parse a single program. CRC has already been verified
  */
@@ -124,16 +176,15 @@ iptv_ts_input(service_t *t, const uint8_
 static void *
 iptv_thread(void *aux)
 {
-  int nfds, fd, r, j, hlen;
-  uint8_t tsb[65536], *buf;
+  int nfds, fd, type, tlen = sizeof(int), r, j, hlen, err = 0;
+  uint8_t *tsb, *buf, real_buf[65536];
   struct epoll_event ev;
   service_t *t;
 
   while(1) {
     nfds = epoll_wait(iptv_epollfd, &ev, 1, -1);
     if(nfds == -1) {
-      tvhlog(LOG_ERR, "IPTV", "epoll() error -- %s, sleeping 1 second",
-	     strerror(errno));
+      tvhlog(LOG_ERR, "IPTV", "epoll() error -- %s, sleeping 1 second", strerror(errno));
       sleep(1);
       continue;
     }
@@ -142,51 +193,76 @@ iptv_thread(void *aux)
       continue;
 
     fd = ev.data.fd;
-    r = read(fd, tsb, sizeof(tsb));
+    tsb = real_buf + 188;
+    r = read(fd, tsb, sizeof(real_buf) - 188);
 
-    if(r > 1 && tsb[0] == 0x47 && (r % 188) == 0) {
+    getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, (socklen_t *)&tlen);
+
+    if(type == SOCK_STREAM || (r > 1 && tsb[0] == 0x47 && (r % 188) == 0)) {
       /* Looks like raw TS in UDP */
       buf = tsb;
     } else {
       /* Check for valid RTP packets */
       if(r < 12)
-	continue;
+        continue;
 
       if((tsb[0] & 0xc0) != 0x80)
-	continue;
+        continue;
 
       if((tsb[1] & 0x7f) != 33)
-	continue;
-      
+        continue;
+
       hlen = (tsb[0] & 0xf) * 4 + 12;
 
       if(tsb[0] & 0x10) {
-	// Extension (X bit) == true
+        // Extension (X bit) == true
 
-	if(r < hlen + 4)
-	  continue; // Packet size < hlen + extension header
+        if(r < hlen + 4)
+          continue; // Packet size < hlen + extension header
 
-	// Skip over extension header (last 2 bytes of header is length)
-	hlen += ((tsb[hlen + 2] << 8) | tsb[hlen + 3]) * 4;
-	// Add the extension header itself (EHL does not inc header)
-	hlen += 4;
+        // Skip over extension header (last 2 bytes of header is length)
+        hlen += ((tsb[hlen + 2] << 8) | tsb[hlen + 3]) * 4;
+        // Add the extension header itself (EHL does not inc header)
+        hlen += 4;
       }
 
       if(r < hlen || (r - hlen) % 188 != 0)
-	continue;
+        continue;
 
       buf = tsb + hlen;
       r -= hlen;
     }
 
     pthread_mutex_lock(&iptv_recvmutex);
-    
+
     LIST_FOREACH(t, &iptv_active_services, s_active_link) {
       if(t->s_iptv_fd != fd)
-	continue;
-      
-      for(j = 0; j < r; j += 188)
-	iptv_ts_input(t, buf + j);
+        continue;
+
+      if(t->s_iptv_url != NULL) {
+        buf = tsb - t->s_iptv_tsb_len;
+        r += t->s_iptv_tsb_len;
+        memcpy(buf, t->s_iptv_tsb, t->s_iptv_tsb_len);
+
+        // Attempt to re-sync a TS stream (3 valid sync's in a row)
+        if(buf[0] != 0x47) {
+          err = 1;
+          while (err && (r > 376)) {
+            buf++; r--;
+            err = (buf[0] != 0x47) || (buf[188] != 0x47) || (buf[376] != 0x47);
+          }
+        }
+
+        for(j = 0; j <= r - 188; j += 188) {
+          iptv_ts_input(t, buf + j);
+        }
+        t->s_iptv_tsb_len = r % 188;
+        memcpy(t->s_iptv_tsb, buf+((r/188)*188), t->s_iptv_tsb_len);
+      }
+      else{
+        for(j = 0; j < r; j += 188)
+          iptv_ts_input(t, buf + j);
+      }
     }
     pthread_mutex_unlock(&iptv_recvmutex);
   }
@@ -201,8 +277,10 @@ static int
 iptv_service_start(service_t *t, unsigned int weight, int force_start)
 {
   pthread_t tid;
-  int fd;
+  int fd, c, i;
   char straddr[INET6_ADDRSTRLEN];
+  char buf[1024];
+  url_t url;
   struct ip_mreqn m;
   struct ipv6_mreq m6;
   struct sockaddr_in sin;
@@ -218,101 +296,121 @@ iptv_service_start(service_t *t, unsigne
     pthread_create(&tid, NULL, iptv_thread, NULL);
   }
 
-  /* Now, open the real socket for UDP */
-  if(t->s_iptv_group.s_addr!=0) {
-    fd = tvh_socket(AF_INET, SOCK_DGRAM, 0);
-  
-  }
-  else {
-    fd = tvh_socket(AF_INET6, SOCK_DGRAM, 0);
-  }
-  if(fd == -1) {
-    tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot open socket", t->s_identifier);
-    return -1;
-  }
-
-  /* First, resolve interface name */
-  memset(&ifr, 0, sizeof(ifr));
-  snprintf(ifr.ifr_name, IFNAMSIZ, "%s", t->s_iptv_iface);
-  ifr.ifr_name[IFNAMSIZ - 1] = 0;
-  if(ioctl(fd, SIOCGIFINDEX, &ifr)) {
-    tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot find interface %s", 
-	   t->s_identifier, t->s_iptv_iface);
-    close(fd);
-    return -1;
-  }
+  if(t->s_iptv_url != NULL){
+    if(url_parse(&url, t->s_iptv_url))
+      return -1;
 
-  /* Bind to IPv4 multicast group */
-  if(t->s_iptv_group.s_addr!=0) {
-    memset(&sin, 0, sizeof(sin));
-    sin.sin_family = AF_INET;
-    sin.sin_port = htons(t->s_iptv_port);
-    sin.sin_addr.s_addr = t->s_iptv_group.s_addr;
-    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &m, sizeof(struct ip_mreqn));
-    if(bind(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
-      tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot bind %s:%d -- %s",
-           t->s_identifier, inet_ntoa(sin.sin_addr), t->s_iptv_port,
-           strerror(errno));
-      close(fd);
+    /* MAKE CONNECTION */
+    // TODO: move connection to thread
+    // TODO: this is really only for testing and to allow use of TVH webserver as input
+    tvhlog(LOG_DEBUG, "IPTV", "connecting to HTTP %s:%d", url.host, url.port);
+    fd = tcp_connect(url.host, url.port, buf, sizeof(buf), 10);
+    if (fd < 0) {
+      tvhlog(LOG_ERR, "IPTV", "tcp_connect() failed %s", buf);
       return -1;
+    }  
+
+    /* Send request (VERY basic) */
+    c = snprintf(buf, sizeof(buf), "GET /%s HTTP/1.1\r\n", url.path);
+    tvh_write(fd, buf, c);
+    c = snprintf(buf, sizeof(buf), "Hostname: %s\r\n", url.host);
+    tvh_write(fd, buf, c);
+    tvh_write(fd, "\r\n", 2);
+
+    /* Read back header */
+    // TODO: do this properly
+    i = 0;
+    while (1) {
+      if (!(c = read(fd, buf+i, 1)))
+        continue;
+      i++;
+      if (i == 4 && !strncmp(buf, "\r\n\r\n", 4))
+        break;
+      memmove(buf, buf+1, 3); i = 3;
+    }
+  }
+  else{
+    /* Now, open the real socket for UDP */
+    if(t->s_iptv_group.s_addr!=0) {
+      fd = tvh_socket(AF_INET, SOCK_DGRAM, 0);
     }
-    /* Join IPv4 group */
-    memset(&m, 0, sizeof(m));
-    m.imr_multiaddr.s_addr = t->s_iptv_group.s_addr;
-    m.imr_address.s_addr = 0;
-    m.imr_ifindex = ifr.ifr_ifindex;
-
-      if(setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &m,
-                sizeof(struct ip_mreqn)) == -1) {
-      tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s",
-           t->s_identifier, inet_ntoa(m.imr_multiaddr), strerror(errno));
-      close(fd);
-      return -1;
+    else {
+      fd = tvh_socket(AF_INET6, SOCK_DGRAM, 0);
     }
-  } else {
-    /* Bind to IPv6 multicast group */
-    memset(&sin6, 0, sizeof(sin6));
-    sin6.sin6_family = AF_INET6;
-    sin6.sin6_port = htons(t->s_iptv_port);
-    sin6.sin6_addr = t->s_iptv_group6;
-    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &m6, sizeof(struct ipv6_mreq));
-    if(bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) == -1) {
-      inet_ntop(AF_INET6, &sin6.sin6_addr, straddr, sizeof(straddr));
-      tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot bind %s:%d -- %s",
-           t->s_identifier, straddr, t->s_iptv_port,
-           strerror(errno));
-      close(fd);
+    if(fd == -1) {
+      tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot open socket", t->s_identifier);
       return -1;
     }
-    /* Join IPv6 group */
-    memset(&m6, 0, sizeof(m6));
-    m6.ipv6mr_multiaddr = t->s_iptv_group6;
-    m6.ipv6mr_interface = ifr.ifr_ifindex;
-
-    if(setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &m6,
-                sizeof(struct ipv6_mreq)) == -1) {
-      inet_ntop(AF_INET6, m6.ipv6mr_multiaddr.s6_addr,
-		straddr, sizeof(straddr));
-      tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s",
-           t->s_identifier, straddr, strerror(errno));
+
+    /* First, resolve interface name */
+    memset(&ifr, 0, sizeof(ifr));
+    snprintf(ifr.ifr_name, IFNAMSIZ, "%s", t->s_iptv_iface);
+    ifr.ifr_name[IFNAMSIZ - 1] = 0;
+    if(ioctl(fd, SIOCGIFINDEX, &ifr)) {
+      tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot find interface %s", t->s_identifier, t->s_iptv_iface);
       close(fd);
       return -1;
     }
-  }
 
+    /* Bind to IPv4 multicast group */
+    if(t->s_iptv_group.s_addr!=0) {
+      memset(&sin, 0, sizeof(sin));
+      sin.sin_family = AF_INET;
+      sin.sin_port = htons(t->s_iptv_port);
+      sin.sin_addr.s_addr = t->s_iptv_group.s_addr;
+      setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &m, sizeof(struct ip_mreqn));
+      if(bind(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+        tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot bind %s:%d -- %s", t->s_identifier, inet_ntoa(sin.sin_addr), t->s_iptv_port, strerror(errno));
+        close(fd);
+        return -1;
+      }
+      /* Join IPv4 group */
+      memset(&m, 0, sizeof(m));
+      m.imr_multiaddr.s_addr = t->s_iptv_group.s_addr;
+      m.imr_address.s_addr = 0;
+      m.imr_ifindex = ifr.ifr_ifindex;
+
+      if(setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, sizeof(struct ip_mreqn)) == -1) {
+        tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s", t->s_identifier, inet_ntoa(m.imr_multiaddr), strerror(errno));
+        close(fd);
+        return -1;
+      }
+    } else {
+      /* Bind to IPv6 multicast group */
+      memset(&sin6, 0, sizeof(sin6));
+      sin6.sin6_family = AF_INET6;
+      sin6.sin6_port = htons(t->s_iptv_port);
+      sin6.sin6_addr = t->s_iptv_group6;
+      setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &m6, sizeof(struct ipv6_mreq));
+      if(bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) == -1) {
+        inet_ntop(AF_INET6, &sin6.sin6_addr, straddr, sizeof(straddr));
+        tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot bind %s:%d -- %s", t->s_identifier, straddr, t->s_iptv_port, strerror(errno));
+        close(fd);
+        return -1;
+      }
+      /* Join IPv6 group */
+      memset(&m6, 0, sizeof(m6));
+      m6.ipv6mr_multiaddr = t->s_iptv_group6;
+      m6.ipv6mr_interface = ifr.ifr_ifindex;
+
+      if(setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &m6, sizeof(struct ipv6_mreq)) == -1) {
+        inet_ntop(AF_INET6, m6.ipv6mr_multiaddr.s6_addr, straddr, sizeof(straddr));
+        tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot join %s -- %s", t->s_identifier, straddr, strerror(errno));
+        close(fd);
+        return -1;
+      }
+    }
 
-  int resize = 262142;
-  if(setsockopt(fd,SOL_SOCKET,SO_RCVBUF, &resize, sizeof(resize)) == -1)
-    tvhlog(LOG_WARNING, "IPTV",
-	   "Can not icrease UDP receive buffer size to %d -- %s",
-	   resize, strerror(errno));
+    int resize = 262142;
+    if(setsockopt(fd,SOL_SOCKET,SO_RCVBUF, &resize, sizeof(resize)) == -1)
+      tvhlog(LOG_WARNING, "IPTV", "Can not icrease UDP receive buffer size to %d -- %s", resize, strerror(errno));
+  }
 
   memset(&ev, 0, sizeof(ev));
   ev.events = EPOLLIN;
   ev.data.fd = fd;
   if(epoll_ctl(iptv_epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
-    tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot add to epoll set -- %s", 
-	   t->s_identifier, strerror(errno));
+    tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot add to epoll set -- %s", t->s_identifier, strerror(errno));
     close(fd);
     return -1;
   }
@@ -350,49 +448,41 @@ iptv_service_stop(service_t *t)
 
   assert(t->s_iptv_fd >= 0);
 
-  /* First, resolve interface name */
-  memset(&ifr, 0, sizeof(ifr));
-  snprintf(ifr.ifr_name, IFNAMSIZ, "%s", t->s_iptv_iface);
-  ifr.ifr_name[IFNAMSIZ - 1] = 0;
-  if(ioctl(t->s_iptv_fd, SIOCGIFINDEX, &ifr)) {
-    tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot find interface %s",
-	   t->s_identifier, t->s_iptv_iface);
-  }
-
-  if(t->s_iptv_group.s_addr != 0) {
-
-    struct ip_mreqn m;
-    memset(&m, 0, sizeof(m));
-    /* Leave multicast group */
-    m.imr_multiaddr.s_addr = t->s_iptv_group.s_addr;
-    m.imr_address.s_addr = 0;
-    m.imr_ifindex = ifr.ifr_ifindex;
-    
-    if(setsockopt(t->s_iptv_fd, SOL_IP, IP_DROP_MEMBERSHIP, &m,
-		  sizeof(struct ip_mreqn)) == -1) {
-      tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot leave %s -- %s",
-	     t->s_identifier, inet_ntoa(m.imr_multiaddr), strerror(errno));
-    }
-  } else {
-    char straddr[INET6_ADDRSTRLEN];
-
-    struct ipv6_mreq m6;
-    memset(&m6, 0, sizeof(m6));
+  if(t->s_iptv_url == NULL) {
+    /* First, resolve interface name */
+    memset(&ifr, 0, sizeof(ifr));
+    snprintf(ifr.ifr_name, IFNAMSIZ, "%s", t->s_iptv_iface);
+    ifr.ifr_name[IFNAMSIZ - 1] = 0;
+    if(ioctl(t->s_iptv_fd, SIOCGIFINDEX, &ifr)) {
+      tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot find interface %s", t->s_identifier, t->s_iptv_iface);
+    }
+
+    if(t->s_iptv_group.s_addr != 0) {
+      struct ip_mreqn m;
+      memset(&m, 0, sizeof(m));
+      /* Leave multicast group */
+      m.imr_multiaddr.s_addr = t->s_iptv_group.s_addr;
+      m.imr_address.s_addr = 0;
+      m.imr_ifindex = ifr.ifr_ifindex;
 
-    m6.ipv6mr_multiaddr = t->s_iptv_group6;
-    m6.ipv6mr_interface = ifr.ifr_ifindex;
-
-    if(setsockopt(t->s_iptv_fd, SOL_IPV6, IPV6_DROP_MEMBERSHIP, &m6,
-		  sizeof(struct ipv6_mreq)) == -1) {
-      inet_ntop(AF_INET6, m6.ipv6mr_multiaddr.s6_addr,
-		straddr, sizeof(straddr));
+      if(setsockopt(t->s_iptv_fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, sizeof(struct ip_mreqn)) == -1) {
+        tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot leave %s -- %s", t->s_identifier, inet_ntoa(m.imr_multiaddr), strerror(errno));
+      }
+    } else {
+      char straddr[INET6_ADDRSTRLEN];
 
-      tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot leave %s -- %s",
-	     t->s_identifier, straddr, strerror(errno));
-    }
+      struct ipv6_mreq m6;
+      memset(&m6, 0, sizeof(m6));
 
+      m6.ipv6mr_multiaddr = t->s_iptv_group6;
+      m6.ipv6mr_interface = ifr.ifr_ifindex;
 
+      if(setsockopt(t->s_iptv_fd, SOL_IPV6, IPV6_DROP_MEMBERSHIP, &m6, sizeof(struct ipv6_mreq)) == -1) {
+        inet_ntop(AF_INET6, m6.ipv6mr_multiaddr.s6_addr, straddr, sizeof(straddr));
 
+        tvhlog(LOG_ERR, "IPTV", "\"%s\" cannot leave %s -- %s", t->s_identifier, straddr, strerror(errno));
+      }
+    }
   }
   close(t->s_iptv_fd); // Automatically removes fd from epoll set
 
@@ -423,9 +513,14 @@ iptv_service_save(service_t *t)
   if(t->s_iptv_iface)
     htsmsg_add_str(m, "interface", t->s_iptv_iface);
 
-  if(t->s_iptv_group.s_addr!= 0) {
-    inet_ntop(AF_INET, &t->s_iptv_group, abuf, sizeof(abuf));
-    htsmsg_add_str(m, "group", abuf);
+  if(t->s_iptv_url != 0){
+      htsmsg_add_str(m, "url", t->s_iptv_url);
+  }
+  else{
+    if(t->s_iptv_group.s_addr!= 0) {
+      inet_ntop(AF_INET, &t->s_iptv_group, abuf, sizeof(abuf));
+      htsmsg_add_str(m, "group", abuf);
+    }
   }
   if(IN6_IS_ADDR_MULTICAST(t->s_iptv_group6.s6_addr) ) {
     inet_ntop(AF_INET6, &t->s_iptv_group6, abuf6, sizeof(abuf6));
@@ -435,13 +530,13 @@ iptv_service_save(service_t *t)
     htsmsg_add_str(m, "channelname", t->s_ch->ch_name);
     htsmsg_add_u32(m, "mapped", 1);
   }
-  
+
   pthread_mutex_lock(&t->s_stream_mutex);
+  service_make_nicename(t);
   psi_save_service_settings(m, t);
   pthread_mutex_unlock(&t->s_stream_mutex);
-  
-  hts_settings_save(m, "iptvservices/%s",
-		    t->s_identifier);
+
+  hts_settings_save(m, "iptvservices/%s", t->s_identifier);
 
   htsmsg_destroy(m);
 }
@@ -453,9 +548,7 @@ iptv_service_save(service_t *t)
 static int
 iptv_service_quality(service_t *t)
 {
-  if(t->s_iptv_iface == NULL || 
-     (t->s_iptv_group.s_addr == 0 && t->s_iptv_group6.s6_addr == 0) ||
-     t->s_iptv_port == 0)
+  if(t->s_iptv_url == NULL && (t->s_iptv_iface == NULL || (t->s_iptv_group.s_addr == 0 && t->s_iptv_group6.s6_addr == 0) || t->s_iptv_port == 0))
     return 0;
 
   return 100;
@@ -481,12 +574,17 @@ iptv_service_setsourceinfo(service_t *t,
 
   si->si_type = S_MPEG_TS;
   si->si_adapter = t->s_iptv_iface ? strdup(t->s_iptv_iface) : NULL;
-  if(t->s_iptv_group.s_addr != 0) {
-    si->si_mux = strdup(inet_ntoa(t->s_iptv_group));
+  if(t->s_iptv_url != 0){
+    si->si_mux = strdup(t->s_iptv_url);
   }
-  else {
-    inet_ntop(AF_INET6, &t->s_iptv_group6, straddr, sizeof(straddr));
-    si->si_mux = strdup(straddr);
+  else{
+    if(t->s_iptv_group.s_addr != 0) {
+      si->si_mux = strdup(inet_ntoa(t->s_iptv_group));
+    }
+    else {
+      inet_ntop(AF_INET6, &t->s_iptv_group6, straddr, sizeof(straddr));
+      si->si_mux = strdup(straddr);
+    }
   }
 }
 
@@ -528,7 +626,7 @@ iptv_service_find(const char *id, int cr
 
     LIST_FOREACH(t, &iptv_all_services, s_group_link)
       if(!strcmp(t->s_identifier, id))
-	return t;
+        return t;
   }
 
   if(create == 0)
@@ -588,25 +686,30 @@ iptv_service_load(void)
     else
       old = 1;
   }
-  
+
   HTSMSG_FOREACH(f, l) {
     if((c = htsmsg_get_map_by_field(f)) == NULL)
       continue;
 
     if(htsmsg_get_u32(c, "pmt", &pmt))
       continue;
-    
+
     t = iptv_service_find(f->hmf_name, 1);
     t->s_pmt_pid = pmt;
 
     tvh_str_update(&t->s_iptv_iface, htsmsg_get_str(c, "interface"));
 
-    if((s = htsmsg_get_str(c, "group")) != NULL){
-      if (!inet_pton(AF_INET, s, &t->s_iptv_group.s_addr)) {
-         inet_pton(AF_INET6, s, &t->s_iptv_group6.s6_addr);
+    if((s = htsmsg_get_str(c, "url")) != NULL){
+      tvh_str_update(&t->s_iptv_url, htsmsg_get_str(c, "url"));
+    }
+    else{
+      if((s = htsmsg_get_str(c, "group")) != NULL){
+        if (!inet_pton(AF_INET, s, &t->s_iptv_group.s_addr)) {
+          inet_pton(AF_INET6, s, &t->s_iptv_group6.s6_addr);
+        }
       }
     }
-    
+
     if(!htsmsg_get_u32(c, "port", &u32))
       t->s_iptv_port = u32;
 
@@ -622,11 +725,11 @@ iptv_service_load(void)
     service_make_nicename(t);
     psi_load_service_settings(c, t);
     pthread_mutex_unlock(&t->s_stream_mutex);
-    
+
     s = htsmsg_get_str(c, "channelname");
     if(htsmsg_get_u32(c, "mapped", &u32))
       u32 = 0;
-    
+
     if(s && u32)
       service_map_channel(t, channel_find_by_name(s, 1, 0), 0);
 
diff -rupN original/src/service.h new/src/service.h
--- original/src/service.h	2013-07-11 21:17:34.000000000 +0200
+++ new/src/service.h	2013-10-04 08:00:04.000000000 +0200
@@ -377,10 +377,13 @@ typedef struct service {
    * IPTV members
    */
   char *s_iptv_iface;
+  char *s_iptv_url;
   struct in_addr s_iptv_group;
   struct in6_addr s_iptv_group6;
   uint16_t s_iptv_port;
   int s_iptv_fd;
+  uint8_t s_iptv_tsb[188];
+  int s_iptv_tsb_len;
 
   /**
    * For per-transport PAT/PMT parsers, allocated on demand
diff -rupN original/src/webui/extjs.c new/src/webui/extjs.c
--- original/src/webui/extjs.c	2013-07-11 21:17:34.000000000 +0200
+++ new/src/webui/extjs.c	2013-10-04 08:00:04.000000000 +0200
@@ -1744,9 +1744,16 @@ service_update_iptv(htsmsg_t *in)
       save = 1;
     }
 
+    t->s_iptv_url = NULL;
+
     if((s = htsmsg_get_str(c, "group")) != NULL) {
-      if(!inet_pton(AF_INET, s, &t->s_iptv_group.s_addr)){
-      	inet_pton(AF_INET6, s, &t->s_iptv_group6.s6_addr);
+      if(!strncmp(s, "http", 4)){
+        tvh_str_update(&t->s_iptv_url, s);
+      }
+      else{
+        if(!inet_pton(AF_INET, s, &t->s_iptv_group.s_addr)){
+          inet_pton(AF_INET6, s, &t->s_iptv_group6.s6_addr);
+        }
       }
       save = 1;
     }
@@ -1772,13 +1779,18 @@ build_record_iptv(service_t *t)
   htsmsg_add_str(r, "channelname", t->s_ch ? t->s_ch->ch_name : "");
   htsmsg_add_str(r, "interface", t->s_iptv_iface ?: "");
 
-  if(t->s_iptv_group.s_addr != 0){
-    inet_ntop(AF_INET, &t->s_iptv_group, abuf, sizeof(abuf));
-    htsmsg_add_str(r, "group", t->s_iptv_group.s_addr ? abuf : "");
+  if(t->s_iptv_url != 0){
+    htsmsg_add_str(r, "group", t->s_iptv_url ?: "");
   }
-  else {
-    inet_ntop(AF_INET6, &t->s_iptv_group6, abuf6, sizeof(abuf6));
-    htsmsg_add_str(r, "group", t->s_iptv_group6.s6_addr ? abuf6 : "");
+  else{
+    if(t->s_iptv_group.s_addr != 0){
+      inet_ntop(AF_INET, &t->s_iptv_group, abuf, sizeof(abuf));
+      htsmsg_add_str(r, "group", t->s_iptv_group.s_addr ? abuf : "");
+    }
+    else {
+      inet_ntop(AF_INET6, &t->s_iptv_group6, abuf6, sizeof(abuf6));
+      htsmsg_add_str(r, "group", t->s_iptv_group6.s6_addr ? abuf6 : "");
+    }
   }
 
   htsmsg_add_u32(r, "port", t->s_iptv_port);
diff -rupN original/src/webui/static/app/iptv.js new/src/webui/static/app/iptv.js
--- original/src/webui/static/app/iptv.js	2013-07-11 21:17:34.000000000 +0200
+++ new/src/webui/static/app/iptv.js	2013-10-04 08:00:04.000000000 +0200
@@ -48,7 +48,7 @@ tvheadend.iptv = function(adapterId) {
 		{
 			header : "Channel name",
 			dataIndex : 'channelname',
-			width : 150,
+			width : 100,
 			renderer : function(value, metadata, record, row, col, store) {
 				return value ? value
 					: '<span class="tvh-grid-unset">Unmapped</span>';
@@ -67,7 +67,7 @@ tvheadend.iptv = function(adapterId) {
 		{
 			header : "Interface",
 			dataIndex : 'interface',
-			width : 100,
+			width : 50,
 			renderer : function(value, metadata, record, row, col, store) {
 				return value ? value : '<span class="tvh-grid-unset">Unset</span>';
 			},
@@ -76,9 +76,9 @@ tvheadend.iptv = function(adapterId) {
 			})
 		},
 		{
-			header : "Group",
+			header : "Address / Group",
 			dataIndex : 'group',
-			width : 100,
+			width : 150,
 			renderer : function(value, metadata, record, row, col, store) {
 				return value ? value : '<span class="tvh-grid-unset">Unset</span>';
 			},
@@ -89,7 +89,7 @@ tvheadend.iptv = function(adapterId) {
 		{
 			header : "UDP Port",
 			dataIndex : 'port',
-			width : 60,
+			width : 50,
 			editor : new fm.NumberField({
 				minValue : 1,
 				maxValue : 65535
