]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
IPTV: Add $m $n $w formatters (mux name, service name, start subscription weight...
authorJaroslav Kysela <perex@perex.cz>
Tue, 6 Oct 2015 08:52:13 +0000 (10:52 +0200)
committerJaroslav Kysela <perex@perex.cz>
Tue, 6 Oct 2015 08:52:18 +0000 (10:52 +0200)
src/input/mpegts.h
src/input/mpegts/iptv/iptv.c
src/input/mpegts/iptv/iptv_mux.c
src/input/mpegts/iptv/iptv_pipe.c
src/input/mpegts/iptv/iptv_private.h
src/input/mpegts/iptv/iptv_rtsp.c
src/input/mpegts/mpegts_service.c
src/service.c
src/service.h
src/tvheadend.h
src/utils.c

index d4ad64b34d4928b68fd9317d51f01d65a5bb20a6..25ab51bfa312274ceb602e799cfab2b41fdfa901 100644 (file)
@@ -604,6 +604,7 @@ struct mpegts_mux_instance
   mpegts_mux_t   *mmi_mux;
   mpegts_input_t *mmi_input;
 
+  int             mmi_start_weight;
   int             mmi_tune_failed;
 };
 
index 0225cecd4c71120001086e5f4caac8d99ba74a27..63865235c6a08693735fb8b4e7f3271247f59f9b 100644 (file)
@@ -21,6 +21,7 @@
 #include "tvhpoll.h"
 #include "tcp.h"
 #include "settings.h"
+#include "htsstr.h"
 
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -198,13 +199,57 @@ iptv_input_warm_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
   return 0;
 }
 
+static const char *
+iptv_sub_url_encode(iptv_mux_t *im, const char *s, char *tmp, size_t tmplen)
+{
+  char *p;
+  if (im->mm_iptv_url && !strncmp(im->mm_iptv_url, "pipe://", 7))
+    return s;
+  p = url_encode(s);
+  strncpy(tmp, p, tmplen-1);
+  tmp[tmplen-1] = '\0';
+  free(p);
+  return tmp;
+}
+
+static const char *
+iptv_sub_mux_name(const char *id, const void *aux, char *tmp, size_t tmplen)
+{
+  const mpegts_mux_instance_t *mmi = aux;
+  iptv_mux_t *im = (iptv_mux_t*)mmi->mmi_mux;
+  return iptv_sub_url_encode(im, im->mm_iptv_muxname, tmp, tmplen);
+}
+
+static const char *
+iptv_sub_service_name(const char *id, const void *aux, char *tmp, size_t tmplen)
+{
+  const mpegts_mux_instance_t *mmi = aux;
+  iptv_mux_t *im = (iptv_mux_t*)mmi->mmi_mux;
+  return iptv_sub_url_encode(im, im->mm_iptv_svcname, tmp, tmplen);
+}
+
+static const char *
+iptv_sub_weight(const char *id, const void *aux, char *tmp, size_t tmplen)
+{
+  const mpegts_mux_instance_t *mmi = aux;
+  snprintf(tmp, tmplen, "%d", mmi->mmi_start_weight);
+  return tmp;
+}
+
+static htsstr_substitute_t iptv_input_subst[] = {
+  { .id = "m",  .getval = iptv_sub_mux_name },
+  { .id = "n",  .getval = iptv_sub_service_name },
+  { .id = "w",  .getval = iptv_sub_weight },
+  { .id = NULL, .getval = NULL }
+};
+
 static int
 iptv_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
 {
   int ret = SM_CODE_TUNING_FAILED;
   iptv_mux_t *im = (iptv_mux_t*)mmi->mmi_mux;
   iptv_handler_t *ih;
-  char buf[256];
+  char buf[256], rawbuf[512], *raw = im->mm_iptv_url, *s;
   const char *scheme;
   url_t url;
 
@@ -212,18 +257,24 @@ iptv_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
   if (im->mm_active)
     return 0;
 
+  /* Substitute things */
+  if (im->mm_iptv_substitute && raw) {
+    htsstr_substitute(raw, rawbuf, sizeof(rawbuf), '$', iptv_input_subst, mmi, buf, sizeof(buf));
+    raw = rawbuf;
+  }
+
   /* Parse URL */
   mpegts_mux_nice_name((mpegts_mux_t*)im, buf, sizeof(buf));
   memset(&url, 0, sizeof(url));
 
-  if (im->mm_iptv_url && !strncmp(im->mm_iptv_url, "pipe://", 7)) {
+  if (raw && !strncmp(raw, "pipe://", 7)) {
 
     scheme = "pipe";
 
   } else {
 
-    if (urlparse(im->mm_iptv_url ?: "", &url)) {
-      tvherror("iptv", "%s - invalid URL [%s]", buf, im->mm_iptv_url);
+    if (urlparse(raw ?: "", &url)) {
+      tvherror("iptv", "%s - invalid URL [%s]", buf, raw);
       return ret;
     }
     scheme = url.scheme;
@@ -239,9 +290,11 @@ iptv_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
 
   /* Start */
   pthread_mutex_lock(&iptv_lock);
+  s = im->mm_iptv_url_raw;
+  im->mm_iptv_url_raw = strdup(raw);
   im->mm_active = mmi; // Note: must set here else mux_started call
                        // will not realise we're ready to accept pid open calls
-  ret            = ih->start(im, im->mm_iptv_url, &url);
+  ret = ih->start(im, raw, &url);
   if (!ret)
     im->im_handler = ih;
   else
@@ -249,6 +302,7 @@ iptv_input_start_mux ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
   pthread_mutex_unlock(&iptv_lock);
 
   urlreset(&url);
+  free(s);
   return ret;
 }
 
index a62dbe7dc77d91b60f82dcf1a9ef49b78a47ff2e..7d4cc921060ad28d8d5250d9dea225270a7e306b 100644 (file)
@@ -129,6 +129,12 @@ const idclass_t iptv_mux_class =
       .set      = iptv_mux_url_set,
       .opts     = PO_MULTILINE
     },
+    {
+      .type     = PT_BOOL,
+      .id       = "iptv_substitute",
+      .name     = N_("Substitute formatters"),
+      .off      = offsetof(iptv_mux_t, mm_iptv_substitute),
+    },
     {
       .type     = PT_STR,
       .id       = "iptv_interface",
@@ -202,7 +208,7 @@ iptv_mux_config_save ( mpegts_mux_t *mm )
 static void
 iptv_mux_delete ( mpegts_mux_t *mm, int delconf )
 {
-  char *url, *url_sane, *muxname;
+  char *url, *url_sane, *url_raw, *muxname;
   iptv_mux_t *im = (iptv_mux_t*)mm;
   char ubuf[UUID_HEX_SIZE];
 
@@ -213,6 +219,7 @@ iptv_mux_delete ( mpegts_mux_t *mm, int delconf )
 
   url = im->mm_iptv_url; // Workaround for silly printing error
   url_sane = im->mm_iptv_url_sane;
+  url_raw = im->mm_iptv_url_raw;
   muxname = im->mm_iptv_muxname;
   free(im->mm_iptv_interface);
   free(im->mm_iptv_svcname);
@@ -220,6 +227,7 @@ iptv_mux_delete ( mpegts_mux_t *mm, int delconf )
   mpegts_mux_delete(mm, delconf);
   free(url);
   free(url_sane);
+  free(url_raw);
   free(muxname);
 }
 
index 409dfa4d5661dc06a9495d5ced5086476cede533..77eb6e55aff68b934c064d4bc1d4afc715d1adbe 100644 (file)
@@ -132,8 +132,8 @@ iptv_pipe_read ( iptv_mux_t *im )
         pthread_mutex_lock(&global_lock);
         pthread_mutex_lock(&iptv_lock);
         if (im->mm_active) {
-          if (iptv_pipe_start(im, im->mm_iptv_url, NULL)) {
-            tvherror("iptv", "unable to respawn %s", im->mm_iptv_url);
+          if (iptv_pipe_start(im, im->mm_iptv_url_raw, NULL)) {
+            tvherror("iptv", "unable to respawn %s", im->mm_iptv_url_raw);
           } else {
             iptv_input_fd_started(im);
             im->mm_iptv_respawn_last = dispatch_clock;
index 809a755fa9fa10659442597435eef0bc1c33f770..289601a588947a4e7fff7f4aaa3ea0bac58d2a67 100644 (file)
@@ -94,8 +94,10 @@ struct iptv_mux
   udp_connection_t     *mm_iptv_connection2;
   char                 *mm_iptv_url;
   char                 *mm_iptv_url_sane;
+  char                 *mm_iptv_url_raw;
   char                 *mm_iptv_interface;
 
+  int                   mm_iptv_substitute;
   int                   mm_iptv_atsc;
 
   char                 *mm_iptv_muxname;
index de5415e8461c1abb8f7fc931f1c865424b76bba0..2c6002b39dfef19c16d6c6d3f209d4dffa285c89 100644 (file)
@@ -79,7 +79,7 @@ iptv_rtsp_header ( http_client_t *hc )
   }
 
   if (hc->hc_code != HTTP_STATUS_OK) {
-    tvherror("iptv", "invalid error code %d for '%s'", hc->hc_code, im->mm_iptv_url);
+    tvherror("iptv", "invalid error code %d for '%s'", hc->hc_code, im->mm_iptv_url_raw);
     return 0;
   }
 
@@ -126,7 +126,7 @@ iptv_rtsp_data
     return 0;
 
   if (len > 0)
-    tvherror("iptv", "unknown data %zd received for '%s'", len, im->mm_iptv_url);
+    tvherror("iptv", "unknown data %zd received for '%s'", len, im->mm_iptv_url_raw);
 
   return 0;
 }
index 93d7c5bd85d0bf34d99dad5376dd394a071114cf..c97a1702f4c716dad9ab5bbbaf8dc38623698970 100644 (file)
@@ -300,7 +300,7 @@ mpegts_service_enlist(service_t *t, tvh_input_t *ti,
  * Start service
  */
 static int
-mpegts_service_start(service_t *t, int instance, int flags)
+mpegts_service_start(service_t *t, int instance, int weight, int flags)
 {
   int r;
   mpegts_service_t      *s = (mpegts_service_t*)t;
@@ -321,6 +321,7 @@ mpegts_service_start(service_t *t, int instance, int flags)
     return SM_CODE_UNDEFINED_ERROR;
 
   /* Start Mux */
+  mmi->mmi_start_weight = weight;
   r = mpegts_mux_instance_start(&mmi, t);
 
   /* Start */
index 2a3ea0bdcf5f09033cee12e8ad8dc4171ba75de4..48a09360ff1a9742fa04c2f1539885a4e1b3cb3e 100644 (file)
@@ -594,7 +594,8 @@ ignore:
  *
  */
 int
-service_start(service_t *t, int instance, int flags, int timeout, int postpone)
+service_start(service_t *t, int instance, int weight, int flags,
+              int timeout, int postpone)
 {
   elementary_stream_t *st;
   int r, stimeout = 10;
@@ -614,7 +615,7 @@ service_start(service_t *t, int instance, int flags, int timeout, int postpone)
   descrambler_caid_changed(t);
   pthread_mutex_unlock(&t->s_stream_mutex);
 
-  if((r = t->s_start_feed(t, instance, flags)))
+  if((r = t->s_start_feed(t, instance, weight, flags)))
     return r;
 
   descrambler_service_start(t);
@@ -749,7 +750,7 @@ service_find_instance
 
   /* Start */
   tvhtrace("service", "will start new instance %d", si->si_instance);
-  if (service_start(si->si_s, si->si_instance, flags, timeout, postpone)) {
+  if (service_start(si->si_s, si->si_instance, weight, flags, timeout, postpone)) {
     tvhtrace("service", "tuning failed");
     si->si_error = SM_CODE_TUNING_FAILED;
     if (*error < SM_CODE_TUNING_FAILED)
index 8a94ee09ff164e852b66e4dc9f4d319dcd1dbbd9..97dda55fe54674916ab642d221ee14d98c35b879 100644 (file)
@@ -296,7 +296,7 @@ typedef struct service {
   void (*s_enlist)(struct service *s, struct tvh_input *ti,
                    service_instance_list_t *sil, int flags);
 
-  int (*s_start_feed)(struct service *s, int instance, int flags);
+  int (*s_start_feed)(struct service *s, int instance, int weight, int flags);
 
   void (*s_refresh_feed)(struct service *t);
 
@@ -479,7 +479,8 @@ typedef struct service {
 void service_init(void);
 void service_done(void);
 
-int service_start(service_t *t, int instance, int flags, int timeout, int postpone);
+int service_start(service_t *t, int instance, int weight, int flags,
+                  int timeout, int postpone);
 void service_stop(service_t *t);
 
 void service_build_filter(service_t *t);
index fa7db598a37cdbf123392c3e9da15ca4bca1afba..27402c9e1a069158a445fbdd10b58524ae3e22b8 100644 (file)
@@ -727,7 +727,7 @@ char *regexp_escape ( const char *str );
 
 /* URL decoding */
 char to_hex(char code);
-char *url_encode(char *str);
+char *url_encode(const char *str);
 
 int mpegts_word_count(const uint8_t *tsb, int len, uint32_t mask);
 
index 0390670aa7749483d2b7ca66797dac240c87693f..23ea46d6a11c13c0be6f07f793a5ae4b92fa1b48 100644 (file)
@@ -593,16 +593,17 @@ char to_hex(char code) {
 /* Returns a url-encoded version of str
    IMPORTANT: be sure to free() the returned string after use
    http://www.geekhideout.com/urlcode.shtml */
-char *url_encode(char *str) {
-  char *pstr = str, *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
-  while (*pstr) {
-    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
-      *pbuf++ = *pstr;
-    /*else if (*pstr == ' ') 
+char *url_encode(const char *str)
+{
+  char *buf = malloc(strlen(str) * 3 + 1), *pbuf = buf;
+  while (*str) {
+    if (isalnum(*str) || *str == '-' || *str == '_' || *str == '.' || *str == '~')
+      *pbuf++ = *str;
+    /*else if (*str == ' ')
       *pbuf++ = '+';*/
     else 
-      *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
-    pstr++;
+      *pbuf++ = '%', *pbuf++ = to_hex(*str >> 4), *pbuf++ = to_hex(*str & 15);
+    str++;
   }
   *pbuf = '\0';
   return buf;