]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
channel number: add minor number handling for ATSC
authorJaroslav Kysela <perex@perex.cz>
Thu, 11 Sep 2014 13:27:01 +0000 (15:27 +0200)
committerJaroslav Kysela <perex@perex.cz>
Thu, 11 Sep 2014 13:27:01 +0000 (15:27 +0200)
12 files changed:
src/channels.c
src/channels.h
src/htsp_server.c
src/input/mpegts.h
src/input/mpegts/dvb_psi.c
src/input/mpegts/mpegts_service.c
src/prop.c
src/prop.h
src/service.c
src/service.h
src/webui/statedump.c
src/webui/static/app/idnode.js

index a8921116d072c85d608d7c4b43f36de294070134..4c5eb837f042dfbed4a8b3b476605720cc1c74d9 100644 (file)
@@ -208,7 +208,7 @@ channel_class_get_name ( void *p )
 static const void *
 channel_class_get_number ( void *p )
 {
-  static int i;
+  static int64_t i;
   i = channel_get_number(p);
   return &i;
 }
@@ -296,7 +296,8 @@ const idclass_t channel_class = {
       .get      = channel_class_get_name,
     },
     {
-      .type     = PT_INT,
+      .type     = PT_S64,
+      .intsplit = CHANNEL_SPLIT,
       .id       = "number",
       .name     = "Number",
       .off      = offsetof(channel_t, ch_number),
@@ -507,7 +508,7 @@ channel_get_name ( channel_t *ch )
   return blank;
 }
 
-int
+int64_t
 channel_get_number ( channel_t *ch )
 {
   int n;
index fe0fc9cc5105cc3bcc6780cfcab570ea7bd0a558..d75cc9ef504e81c1e011d4bca621f1762aa6b594 100644 (file)
@@ -177,7 +177,12 @@ void channel_save(channel_t *ch);
 const char *channel_get_name ( channel_t *ch );
 int channel_set_name ( channel_t *ch, const char *s );
 
-int channel_get_number ( channel_t *ch );
+#define CHANNEL_SPLIT 1000000
+
+static inline uint32_t channel_get_major ( int64_t chnum ) { return chnum / CHANNEL_SPLIT; }
+static inline uint32_t channel_get_minor ( int64_t chnum ) { return chnum % CHANNEL_SPLIT; }
+
+int64_t channel_get_number ( channel_t *ch );
 
 const char *channel_get_icon ( channel_t *ch );
 int channel_set_icon ( channel_t *ch, const char *icon );
index ff46aac04b7750365e22c5e03d980ceb9564a8c9..05f958d8eeaa06c8028c7e31f13d0c3fe21a0c42 100644 (file)
@@ -550,13 +550,16 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp)
   channel_tag_t *ct;
   service_t *t;
   epg_broadcast_t *now, *next = NULL;
+  int64_t chnum = channel_get_number(ch);
 
   htsmsg_t *out = htsmsg_create_map();
   htsmsg_t *tags = htsmsg_create_list();
   htsmsg_t *services = htsmsg_create_list();
 
   htsmsg_add_u32(out, "channelId", channel_get_id(ch));
-  htsmsg_add_u32(out, "channelNumber", channel_get_number(ch));
+  htsmsg_add_u32(out, "channelNumber", channel_get_major(chnum));
+  if (channel_get_minor(chnum))
+    htsmsg_add_u32(out, "channelNumberMinor", channel_get_minor(chnum));
 
   htsmsg_add_str(out, "channelName", channel_get_name(ch));
   if(ch->ch_icon != NULL) {
index 20e78058723147f8b611f27b30593eb6b55f07d6..285d3683597f54a8c0ea21305a47b3c0d6ea093b 100644 (file)
@@ -425,6 +425,7 @@ struct mpegts_service
 
   uint16_t s_dvb_service_id;
   uint16_t s_dvb_channel_num;
+  uint16_t s_dvb_channel_minor;
   char    *s_dvb_svcname;
   char    *s_dvb_provider;
   char    *s_dvb_cridauth;
@@ -438,7 +439,7 @@ struct mpegts_service
    */
 
   int      s_dvb_eit_enable;
-  uint16_t s_dvb_opentv_chnum;
+  uint64_t s_dvb_opentv_chnum;
 
   /*
    * Link to carrying multiplex and active adapter
index 0a420c648bb21635d9df47d95a2cbd99c59e6a17..67d35c9231bcafc456cc3af1046fe23d27aa43f6 100644 (file)
@@ -1070,11 +1070,9 @@ atsc_vct_callback
       tvh_str_set(&s->s_dvb_svcname, chname);
       save = 1;
     }
-    if (s->s_dvb_channel_num != maj) {
-      // TODO: ATSC channel numbering is plain weird!
-      //       could shift the major (*100 or something) and append
-      //       minor, but that'll probably confuse people, as will this!
+    if (s->s_dvb_channel_num != maj || s->s_dvb_channel_minor != min) {
       s->s_dvb_channel_num = maj;
+      s->s_dvb_channel_minor = min;
       save = 1;
     }
 
index 9b2310f2fac19d3d862787050629b21fa664ba94..e095925789538fcda57682ba8da03b0e630bd4ec 100644 (file)
@@ -20,6 +20,7 @@
 #include <assert.h>
 
 #include "service.h"
+#include "channels.h"
 #include "input.h"
 #include "settings.h"
 #include "dvb_charset.h"
@@ -101,6 +102,13 @@ const idclass_t mpegts_service_class =
       .opts     = PO_RDONLY,
       .off      = offsetof(mpegts_service_t, s_dvb_channel_num),
     },
+    {
+      .type     = PT_U16,
+      .id       = "lcn_minor",
+      .name     = "Local Channel Minor",
+      .opts     = PO_RDONLY,
+      .off      = offsetof(mpegts_service_t, s_dvb_channel_minor),
+    },
     {
       .type     = PT_U16,
       .id       = "lcn2",
@@ -364,12 +372,13 @@ mpegts_service_grace_period(service_t *t)
 /*
  * Channel number
  */
-static int
+static int64_t
 mpegts_service_channel_number ( service_t *s )
 {
-  int r = ((mpegts_service_t*)s)->s_dvb_channel_num;
+  int r = ((mpegts_service_t*)s)->s_dvb_channel_num * CHANNEL_SPLIT +
+          ((mpegts_service_t*)s)->s_dvb_channel_minor;
   if (r <= 0)
-    r = ((mpegts_service_t*)s)->s_dvb_opentv_chnum;
+    r = ((mpegts_service_t*)s)->s_dvb_opentv_chnum * CHANNEL_SPLIT;
   return r;
 }
 
index bb748c30bc71431a4df950666ef3baa9d02816f0..a2962ce38c51952814b457ea09c1306eed9c266c 100644 (file)
@@ -133,16 +133,33 @@ prop_write_values
         break;
       }
       case PT_U32: {
-        if (htsmsg_field_get_u32(f, &u32))
-          continue;
+        if (p->intsplit) {
+          char *s;
+          if (!(new = htsmsg_field_get_str(f)))
+            continue;
+          u32 = atol(new) * p->intsplit;
+          if ((s = strchr(new, '.')) != NULL)
+            u32 += (atol(s + 1) % p->intsplit);
+        } else {
+          if (htsmsg_field_get_u32(f, &u32))
+            continue;
+        }
         PROP_UPDATE(u32, uint32_t);
         break;
       }
       case PT_S64: {
-        if (htsmsg_field_get_s64(f, &s64))
-          continue;
-        i = s64;
-        PROP_UPDATE(i, int64_t);
+        if (p->intsplit) {
+          char *s;
+          if (!(new = htsmsg_field_get_str(f)))
+            continue;
+          s64 = atol(new) * p->intsplit;
+          if ((s = strchr(new, '.')) != NULL)
+            s64 += (atol(s + 1) % p->intsplit);
+        } else {
+          if (htsmsg_field_get_s64(f, &s64))
+            continue;
+        }
+        PROP_UPDATE(s64, int64_t);
         break;
       }
       case PT_DBL: {
@@ -230,7 +247,7 @@ prop_read_value
   const char *s;
   const void *val = obj + p->off;
   uint32_t u32;
-  char buf[16];
+  char buf[24];
 
   /* Ignore */
   u32 = p->get_opts ? p->get_opts(obj) : p->opts;
@@ -262,10 +279,28 @@ prop_read_value
       htsmsg_add_u32(m, name, *(uint16_t *)val);
       break;
     case PT_U32:
-      htsmsg_add_u32(m, name, *(uint32_t *)val);
+      if (p->intsplit) {
+        uint32_t maj = *(int64_t *)val / p->intsplit;
+        uint32_t min = *(int64_t *)val % p->intsplit;
+        if (min) {
+          snprintf(buf, sizeof(buf), "%u.%u", (unsigned int)maj, (unsigned int)min);
+          htsmsg_add_str(m, name, buf);
+        } else
+          htsmsg_add_s64(m, name, maj);
+      } else
+        htsmsg_add_u32(m, name, *(uint32_t *)val);
       break;
     case PT_S64:
-      htsmsg_add_s64(m, name, *(int64_t *)val);
+      if (p->intsplit) {
+        int64_t maj = *(int64_t *)val / p->intsplit;
+        int64_t min = *(int64_t *)val % p->intsplit;
+        if (min) {
+          snprintf(buf, sizeof(buf), "%lu.%lu", (unsigned long)maj, (unsigned long)min);
+          htsmsg_add_str(m, name, buf);
+        } else
+          htsmsg_add_s64(m, name, maj);
+      } else
+        htsmsg_add_s64(m, name, *(int64_t *)val);
       break;
     case PT_STR:
       if ((s = *(const char **)val))
@@ -421,6 +456,10 @@ prop_serialize_value
   if (pl->group)
     htsmsg_add_u32(m, "group", pl->group);
 
+  /* Split integer value */
+  if (pl->intsplit)
+    htsmsg_add_u32(m, "intsplit", pl->intsplit);
+
   /* Data */
   if (obj)
     prop_read_value(obj, pl, m, "value", optmask);
index babcb54f192a7ae28899266d682953f66d2257d2..42ee871d26c8b772ced3d1d9fbd9909641dce882 100644 (file)
@@ -62,10 +62,11 @@ typedef struct property {
   const char  *id;        ///< Property Key
   const char *name;       ///< Textual description
   prop_type_t type;       ///< Type
-  int         islist;     ///< Is a list
+  uint8_t     islist;     ///< Is a list
+  uint8_t     group;      ///< Visual group ID (like ExtJS FieldSet)
   size_t      off;        ///< Offset into object
   uint32_t    opts;       ///< Options
-  uint32_t    group;      ///< Visual group ID (like ExtJS FieldSet)
+  uint32_t    intsplit;   ///< integer/remainder boundary
 
   /* String based processing */
   const void *(*get)  (void *ptr);
index 51ebd92871cdee08616b7c01044c04c77eb5a5a3..973c8199053c6cd1ea83342f38fcd4e42dbce1e4 100644 (file)
@@ -803,7 +803,7 @@ service_destroy(service_t *t, int delconf)
   service_unref(t);
 }
 
-static int
+static int64_t
 service_channel_number ( service_t *s )
 {
   return 0;
@@ -1567,7 +1567,7 @@ service_get_full_channel_name ( service_t *s )
 /*
  * Get number for service
  */
-int
+int64_t
 service_get_channel_number ( service_t *s )
 {
   if (s->s_channel_number) return s->s_channel_number(s);
index d1419803fd37944c3c2b3676acc44d17a4bbbe5d..6707daa9f0030ac51aee0b44a66b72993f0f2adb 100644 (file)
@@ -292,7 +292,7 @@ typedef struct service {
   /**
    * Channel info
    */
-  int         (*s_channel_number) (struct service *);
+  int64_t     (*s_channel_number) (struct service *);
   const char *(*s_channel_name)   (struct service *);
   const char *(*s_provider_name)  (struct service *);
 
@@ -554,6 +554,6 @@ void sort_elementary_streams(service_t *t);
 
 const char *service_get_channel_name (service_t *s);
 const char *service_get_full_channel_name (service_t *s);
-int         service_get_channel_number (service_t *s);
+int64_t     service_get_channel_number (service_t *s);
 
 #endif // SERVICE_H__
index 79dfc0fdc0ff7a39455a49a8471831fbfc7c3534..db74cd55889c533132b5d6c53800a84bcd969892 100644 (file)
@@ -54,18 +54,27 @@ dumpchannels(htsbuf_queue_t *hq)
 {
   channel_t *ch;
   outputtitle(hq, 0, "Channels");
+  int64_t chnum;
+  char chbuf[32];
 
   CHANNEL_FOREACH(ch) {
     
     htsbuf_qprintf(hq, "%s (%d)\n", channel_get_name(ch), channel_get_id(ch));
+    chnum = channel_get_number(ch);
+    if (channel_get_minor(chnum))
+      snprintf(chbuf, sizeof(chbuf), "%u.%u",
+               channel_get_major(chnum),
+               channel_get_minor(chnum));
+    else
+      snprintf(chbuf, sizeof(chbuf), "%u", channel_get_major(chnum));
     htsbuf_qprintf(hq,
                   "  refcount = %d\n"
                   "  zombie = %d\n"
-                  "  number = %d\n"
+                  "  number = %s\n"
                   "  icon = %s\n\n",
                   ch->ch_refcount,
                   ch->ch_zombie,
-                  channel_get_number(ch),
+                  chbuf,
                   ch->ch_icon ?: "<none set>");
   }
 }
index 175d7581f1886c46477af4e387c12f34530e7f52..18eabf5f8a361a2bb9e2592794affcf9053c2028 100644 (file)
@@ -122,6 +122,7 @@ tvheadend.IdNodeField = function(conf)
     this.hidden = conf.hidden || conf.advanced;
     this.password = conf.password;
     this.duration = conf.duration;
+    this.intsplit = conf.intsplit;
     this.group = conf.group;
     this.enum = conf.enum;
     this.store = null;
@@ -490,6 +491,17 @@ tvheadend.idnode_editor_field = function(f, create)
         case 'u16':
         case 's64':
         case 'dbl':
+            if (f.intsplit) {
+                /* this should be improved */
+                return new Ext.form.TextField({
+                    fieldLabel: f.caption,
+                    name: f.id,
+                    value: value,
+                    disabled: d,
+                    width: 300,
+                    maskRe: /[0-9\.]/,
+                });
+            }
             return new Ext.form.NumberField({
                 fieldLabel: f.caption,
                 name: f.id,