]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
playlist - implement SAT>IP m3u playlist, fixes #3003
authorJaroslav Kysela <perex@perex.cz>
Tue, 22 Sep 2015 07:28:28 +0000 (09:28 +0200)
committerJaroslav Kysela <perex@perex.cz>
Tue, 22 Sep 2015 07:28:49 +0000 (09:28 +0200)
src/input/mpegts/mpegts_service.c
src/satip/server.c
src/service.h
src/webui/webui.c

index d2d255c1178f974bc0ff7f352883df2115011254..93d7c5bd85d0bf34d99dad5376dd394a071114cf 100644 (file)
@@ -580,6 +580,14 @@ mpegts_service_delete ( service_t *t, int delconf )
   //       is done in service_destroy
 }
 
+static int
+mpegts_service_satip_source ( service_t *t )
+{
+  mpegts_service_t *ms = (mpegts_service_t*)t;
+  mpegts_network_t *mn = ms->s_dvb_mux ? ms->s_dvb_mux->mm_network : NULL;
+  return mn ? mn->mn_satip_source : -1;
+}
+
 /* **************************************************************************
  * Creation/Location
  * *************************************************************************/
@@ -630,6 +638,7 @@ mpegts_service_create0
   s->s_provider_name  = mpegts_service_provider_name;
   s->s_channel_icon   = mpegts_service_channel_icon;
   s->s_mapped         = mpegts_service_mapped;
+  s->s_satip_source   = mpegts_service_satip_source;
 
   pthread_mutex_lock(&s->s_stream_mutex);
   service_make_nicename((service_t*)s);
@@ -854,6 +863,7 @@ mpegts_service_create_raw ( mpegts_mux_t *mm )
   s->s_update_pids    = mpegts_service_raw_update_pids;
   s->s_link           = mpegts_service_link;
   s->s_unlink         = mpegts_service_unlink;
+  s->s_satip_source   = mpegts_service_satip_source;
 
   pthread_mutex_lock(&s->s_stream_mutex);
   free(s->s_nicename);
index 5e0e9b2f76a7457399405f0e1f8a7119f5db3af6..0e45bcd9a2546fbd12798eeb38218d85ea45ba6b 100644 (file)
@@ -103,6 +103,7 @@ satip_server_http_xml(http_connection_t *hc)
 </iconList>\n\
 <presentationURL>http://%s:%d</presentationURL>\n\
 <satip:X_SATIPCAP xmlns:satip=\"urn:ses-com:satip\">%s</satip:X_SATIPCAP>\n\
+<satip:X_SATIPM3U xmlns:satip=\"urn:ses-com:satip\">/playlist/satip/channels</satip:X_SATIPM3U>\n\
 </device>\n\
 </root>\n"
 
index 1c1187e3b5be49c4b53d6272bc38baa0d2704ef0..d4a61031e64327c542be95e903d6a22c91a7f0be 100644 (file)
@@ -312,6 +312,8 @@ typedef struct service {
 
   void (*s_delete)(struct service *t, int delconf);
 
+  int (*s_satip_source)(struct service *t);
+
   /**
    * Channel info
    */
index 4aff3021027da12daf8677614ec45e79f790fd28..a18204c82988d47158422bd4008d4a4532c94d52 100644 (file)
@@ -65,7 +65,8 @@
 
 enum {
   PLAYLIST_M3U,
-  PLAYLIST_E2
+  PLAYLIST_E2,
+  PLAYLIST_SATIP_M3U\
 };
 
 static int webui_xspf;
@@ -500,6 +501,35 @@ http_e2_playlist_add(htsbuf_queue_t *hq, const char *hostpath,
   htsbuf_qprintf(hq, "#DESCRIPTION %s\n", svcname);
 }
 
+/*
+ *
+ */
+static void
+http_satip_m3u_playlist_add(htsbuf_queue_t *hq, const char *hostpath,
+                            channel_t *ch)
+{
+  char buf[64];
+  const char *name;
+  idnode_list_mapping_t *ilm;
+  service_t *s = NULL;
+  int src;
+
+  LIST_FOREACH(ilm, &ch->ch_services, ilm_in2_link) {
+    /* cannot handle channels with more services for SAT>IP */
+    if (s)
+      return;
+    s = (service_t *)ilm->ilm_in1;
+  }
+  src = (s && s->s_satip_source) ? s->s_satip_source(s) : -1;
+  if (src < 1)
+    return;
+  name = channel_get_name(ch);
+  snprintf(buf, sizeof(buf), "/stream/channelid/%d", channel_get_id(ch));
+  htsbuf_qprintf(hq, "#EXTINF:-1,%s\n", name);
+  htsbuf_qprintf(hq, "%s%s", hostpath, buf);
+  htsbuf_qprintf(hq, "?profile=pass\n");
+}
+
 /**
  * Output a playlist containing a single channel
  */
@@ -533,6 +563,10 @@ http_channel_playlist(http_connection_t *hc, int pltype, channel_t *channel)
     htsbuf_qprintf(hq, "#NAME %s\n", name);
     http_e2_playlist_add(hq, hostpath, buf, profile, name);
 
+  } else if (pltype == PLAYLIST_SATIP_M3U) {
+
+    http_satip_m3u_playlist_add(hq, hostpath, channel);
+
   }
 
   free(hostpath);
@@ -598,6 +632,8 @@ http_tag_playlist(http_connection_t *hc, int pltype, channel_tag_t *tag)
     } else if (pltype == PLAYLIST_E2) {
       htsbuf_qprintf(hq, "#NAME %s\n", name);
       http_e2_playlist_add(hq, hostpath, buf, profile, name);
+    } else if (pltype == PLAYLIST_SATIP_M3U) {
+      http_satip_m3u_playlist_add(hq, hostpath, ch);
     }
   }
 
@@ -650,7 +686,7 @@ http_tag_list_playlist(http_connection_t *hc, int pltype)
 
   qsort(ctlist, count, sizeof(channel_tag_t *), http_channel_tag_playlist_cmp);
 
-  if (pltype == PLAYLIST_E2) {
+  if (pltype == PLAYLIST_E2 || pltype == PLAYLIST_SATIP_M3U) {
     CHANNEL_FOREACH(ch)
       if (ch->ch_enabled)
         chcount++;
@@ -687,6 +723,13 @@ http_tag_list_playlist(http_connection_t *hc, int pltype)
             break;
           }
       }
+    } else if (pltype == PLAYLIST_SATIP_M3U) {
+      for (chidx = 0; chidx < chcount; chidx++) {
+        ch = chlist[chidx];
+        LIST_FOREACH(ilm, &ct->ct_ctms, ilm_in1_link)
+          if (ch == (channel_t *)ilm->ilm_in2)
+            http_satip_m3u_playlist_add(hq, hostpath, ch);
+      }
     }
   }
 
@@ -746,10 +789,12 @@ http_channel_list_playlist(http_connection_t *hc, int pltype)
     name = channel_get_name(ch);
     snprintf(buf, sizeof(buf), "/stream/channelid/%d", channel_get_id(ch));
 
-    if (pltype != PLAYLIST_E2) {
+    if (pltype == PLAYLIST_M3U) {
       http_m3u_playlist_add(hq, hostpath, buf, profile, name, hc->hc_access);
-    } else {
+    } else if (pltype == PLAYLIST_E2) {
       http_e2_playlist_add(hq, hostpath, buf, profile, name);
+    } else if (pltype == PLAYLIST_SATIP_M3U) {
+      http_satip_m3u_playlist_add(hq, hostpath, ch);
     }
   }
 
@@ -882,15 +927,27 @@ page_http_playlist(http_connection_t *hc, const char *remain, void *opaque)
     remain = NULL;
   }
 
+  if (remain && !strcmp(remain, "satip")) {
+    pltype = PLAYLIST_SATIP_M3U;
+    remain = NULL;
+  }
+
   if (remain && !strncmp(remain, "e2/", 3)) {
     pltype = PLAYLIST_E2;
     remain += 3;
   }
 
+  if (remain && !strncmp(remain, "satip/", 6)) {
+    pltype = PLAYLIST_SATIP_M3U;
+    remain += 6;
+  }
+
   if(!remain || *remain == '\0') {
     http_redirect(hc, pltype == PLAYLIST_E2 ? "/playlist/e2/channels" :
-                                              "/playlist/channels",
-                                              &hc->hc_req_args, 0);
+                      (pltype == PLAYLIST_SATIP_M3U ?
+                        "/playlist/satip/channels" :
+                        "/playlist/channels"),
+                      &hc->hc_req_args, 0);
     return HTTP_STATUS_FOUND;
   }
 
@@ -912,7 +969,7 @@ page_http_playlist(http_connection_t *hc, const char *remain, void *opaque)
   else if(nc == 2 && !strcmp(components[0], "channelname"))
     ch = channel_find_by_name(components[1]);
   else if(nc == 2 && !strcmp(components[0], "channel"))
-    ch = channel_find(components[1]);
+   ch = channel_find(components[1]);
   else if(nc == 2 && !strcmp(components[0], "dvrid"))
     de = dvr_entry_find_by_id(atoi(components[1]));
   else if(nc == 2 && !strcmp(components[0], "tagid"))
@@ -924,9 +981,12 @@ page_http_playlist(http_connection_t *hc, const char *remain, void *opaque)
     r = http_channel_playlist(hc, pltype, ch);
   else if(tag)
     r = http_tag_playlist(hc, pltype, tag);
-  else if(de)
-    r = http_dvr_playlist(hc, pltype, de);
-  else {
+  else if(de) {
+    if (pltype == PLAYLIST_SATIP_M3U)
+      r = HTTP_STATUS_BAD_REQUEST;
+    else
+      r = http_dvr_playlist(hc, pltype, de);
+  } else {
     cmd = s = tvh_strdupa(components[0]);
     while (*s && *s != '.') s++;
     if (*s == '.') {
@@ -939,9 +999,8 @@ page_http_playlist(http_connection_t *hc, const char *remain, void *opaque)
       r = http_tag_list_playlist(hc, pltype);
     else if(!strcmp(cmd, "channels"))
       r = http_channel_list_playlist(hc, pltype);
-    else if(!strcmp(cmd, "channels.m3u"))
-      r = http_channel_list_playlist(hc, pltype);
-    else if(!strcmp(cmd, "recordings"))
+    else if(pltype != PLAYLIST_SATIP_M3U &&
+            !strcmp(cmd, "recordings"))
       r = http_dvr_list_playlist(hc, pltype);
     else {
       r = HTTP_STATUS_BAD_REQUEST;