]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
bouquets: add noname, no channel, channel tag options
authorJaroslav Kysela <perex@perex.cz>
Sat, 1 Nov 2014 15:58:29 +0000 (16:58 +0100)
committerJaroslav Kysela <perex@perex.cz>
Sat, 8 Nov 2014 20:05:38 +0000 (21:05 +0100)
src/bouquet.c
src/bouquet.h
src/channels.c
src/channels.h
src/service_mapper.c
src/service_mapper.h
src/webui/static/app/cteditor.js

index adb779ac40a760d524a436aebf4a7732a6376a2b..d3fd56fdcc95f2a60e71daa3fbf3b8cb650549b2 100644 (file)
@@ -140,19 +140,56 @@ bouquet_find_by_source(const char *name, const char *src, int create)
   return NULL;
 }
 
+/*
+ *
+ */
+static channel_tag_t *
+bouquet_tag(bouquet_t *bq, int create)
+{
+  char buf[128];
+  /* TODO: cache the channel_tag_t * pointer */
+  snprintf(buf, sizeof(buf), "*** %s", bq->bq_name ?: "???");
+  return channel_tag_find_by_name(buf, create);
+}
+
+/*
+ *
+ */
+static int
+noname(const char *s)
+{
+  if (!s)
+    return 1;
+  while (*s) {
+    if (*s > ' ')
+      return 0;
+    s++;
+  }
+  return 1;
+}
+
 /*
  *
  */
 static void
 bouquet_map_channel(bouquet_t *bq, service_t *t)
 {
+  channel_t *ch = NULL;
   channel_service_mapping_t *csm;
 
+  if (!bq->bq_mapnolcn && service_get_channel_number(t) <= 0)
+    return;
+  if (!bq->bq_mapnoname && noname(service_get_channel_name(t)))
+    return;
   LIST_FOREACH(csm, &t->s_channels, csm_svc_link)
     if (csm->csm_chn->ch_bouquet == bq)
       break;
   if (!csm)
-    service_mapper_process(t, bq);
+    ch = service_mapper_process(t, bq);
+  else
+    ch = csm->csm_chn;
+  if (ch && bq->bq_chtag)
+    channel_tag_map(ch, bouquet_tag(bq, 1));
 }
 
 /*
@@ -324,6 +361,68 @@ bouquet_class_maptoch_notify ( void *obj )
   bouquet_map_to_channels((bouquet_t *)obj);
 }
 
+static void
+bouquet_class_mapnolcn_notify ( void *obj )
+{
+  bouquet_t *bq = obj;
+  service_t *t;
+  size_t z;
+
+  if (!bq->bq_mapnolcn && bq->bq_enabled && bq->bq_maptoch) {
+    for (z = 0; z < bq->bq_services->is_count; z++) {
+      t = (service_t *)bq->bq_services->is_array[z];
+      if (service_get_channel_number(t) <= 0)
+        bouquet_unmap_channel(bq, t);
+    }
+  } else {
+    bouquet_map_to_channels((bouquet_t *)obj);
+  }
+}
+
+static void
+bouquet_class_mapnoname_notify ( void *obj )
+{
+  bouquet_t *bq = obj;
+  service_t *t;
+  size_t z;
+
+  if (!bq->bq_mapnoname && bq->bq_enabled && bq->bq_maptoch) {
+    for (z = 0; z < bq->bq_services->is_count; z++) {
+      t = (service_t *)bq->bq_services->is_array[z];
+      if (noname(service_get_channel_name(t)))
+        bouquet_unmap_channel(bq, t);
+    }
+  } else {
+    bouquet_map_to_channels((bouquet_t *)obj);
+  }
+}
+
+static void
+bouquet_class_chtag_notify ( void *obj )
+{
+  bouquet_t *bq = obj;
+  service_t *t;
+  channel_service_mapping_t *csm;
+  channel_tag_t *ct;
+  size_t z;
+
+  if (!bq->bq_chtag && bq->bq_enabled && bq->bq_maptoch) {
+    ct = bouquet_tag(bq, 0);
+    if (!ct)
+      return;
+    for (z = 0; z < bq->bq_services->is_count; z++) {
+      t = (service_t *)bq->bq_services->is_array[z];
+      LIST_FOREACH(csm, &t->s_channels, csm_svc_link)
+        if (csm->csm_chn->ch_bouquet == bq)
+          break;
+      if (csm)
+        channel_tag_unmap(csm->csm_chn, ct);
+    }
+  } else {
+    bouquet_map_to_channels((bouquet_t *)obj);
+  }
+}
+
 static const void *
 bouquet_class_services_get ( void *obj )
 {
@@ -393,6 +492,27 @@ const idclass_t bouquet_class = {
       .off      = offsetof(bouquet_t, bq_maptoch),
       .notify   = bouquet_class_maptoch_notify,
     },
+    {
+      .type     = PT_BOOL,
+      .id       = "mapnolcn",
+      .name     = "Map Zero Numbers",
+      .off      = offsetof(bouquet_t, bq_mapnolcn),
+      .notify   = bouquet_class_mapnolcn_notify,
+    },
+    {
+      .type     = PT_BOOL,
+      .id       = "mapnoname",
+      .name     = "Map No Name",
+      .off      = offsetof(bouquet_t, bq_mapnoname),
+      .notify   = bouquet_class_mapnoname_notify,
+    },
+    {
+      .type     = PT_BOOL,
+      .id       = "chtag",
+      .name     = "Create Tag",
+      .off      = offsetof(bouquet_t, bq_chtag),
+      .notify   = bouquet_class_chtag_notify,
+    },
     {
       .type     = PT_STR,
       .id       = "name",
index fa577e60ececccbcacaedbb254f7c9029d083bae..986541652d691ed01c6ca8c40d148faf75bb1805 100644 (file)
@@ -34,6 +34,9 @@ typedef struct bouquet {
   int           bq_shield;
   int           bq_enabled;
   int           bq_maptoch;
+  int           bq_mapnolcn;
+  int           bq_mapnoname;
+  int           bq_chtag;
   char         *bq_name;
   char         *bq_src;
   char         *bq_comment;
index 8d9a7be2c50bf1a458772527cbbab3e10c95eab9..141497e64b27737463cb803e0ca39f91d8c96f5f 100644 (file)
@@ -912,6 +912,25 @@ channel_tag_mapping_destroy(channel_tag_mapping_t *ctm, int flags)
   }
 }
 
+/**
+ *
+ */
+void
+channel_tag_unmap(channel_t *ch, channel_tag_t *ct)
+{
+  channel_tag_mapping_t *ctm, *n;
+
+  for (ctm = LIST_FIRST(&ch->ch_ctms); ctm != NULL; ctm = n) {
+    n = LIST_NEXT(ctm, ctm_channel_link);
+    if (ctm->ctm_channel == ch) {
+      LIST_REMOVE(ctm, ctm_channel_link);
+      LIST_REMOVE(ctm, ctm_tag_link);
+      free(ctm);
+      channel_tag_save(ct);
+      return;
+    }
+  }
+}
 
 /**
  *
index a1fd54e32cbc55901e67a916f357e90b91cd72c9..cc38bcd143037166f765c1176718aaecb615b64a 100644 (file)
@@ -179,6 +179,7 @@ const char * channel_tag_get_icon(channel_tag_t *ct);
 int channel_access(channel_t *ch, struct access *a, const char *username);
 
 int channel_tag_map(channel_t *ch, channel_tag_t *ct);
+void channel_tag_unmap(channel_t *ch, channel_tag_t *ct);
 
 void channel_save(channel_t *ch);
 
index 4f8f46a9a9cea2cf7a47564218f401ef9ce02b43..ddfe8360f2ca38632b7d867a7428de529f73b261 100644 (file)
@@ -264,7 +264,7 @@ service_mapper_clean ( service_t *s, channel_t *c, void *origin )
 /*
  * Process a service 
  */
-void
+channel_t *
 service_mapper_process ( service_t *s, bouquet_t *bq )
 {
   channel_t *chn = NULL;
@@ -327,6 +327,7 @@ service_mapper_process ( service_t *s, bouquet_t *bq )
   /* Remove */
 exit:
   service_mapper_remove(s);
+  return chn;
 }
 
 /**
index c7e94ffa1eccae9ae11a8d509be2f6b26e443b90..f10118fe97ec94f97ead69813ae9b8e56848a203 100644 (file)
@@ -75,7 +75,7 @@ void service_mapper_unlink ( struct service *s, struct channel *c, void *origin
 int service_mapper_clean ( struct service *s, struct channel *ch, void *origin );
 
 // Process one service
-void service_mapper_process ( struct service *s, struct bouquet *bq );
+struct channel *service_mapper_process ( struct service *s, struct bouquet *bq );
 
 // Resets the stat counters
 void service_mapper_reset_stats ( void );
index bbba03923b519a710b40c50b5e5bb7b24e55cb1f..2755c2dc7198a0d8ff19778ff797e301507c30a4 100644 (file)
@@ -32,7 +32,7 @@ tvheadend.cteditor = function(panel, index)
  */
 tvheadend.bouquet = function(panel, index)
 {
-    var list = 'enabled,name,maptoch,source,services_count,comment,lcn_off';
+    var list = 'enabled,name,maptoch,mapnolcn,lcn_off,mapnoname,chtag,source,services_count,comment';
 
     tvheadend.idnode_grid(panel, {
         url: 'api/bouquet',
@@ -40,6 +40,18 @@ tvheadend.bouquet = function(panel, index)
         titleP: 'Bouquets',
         iconCls: 'bouquets',
         tabIndex: index,
+        columns: {
+            enabled:        { width: 50 },
+            name:           { width: 200 },
+            maptoch:        { width: 100 },
+            mapnolcn:       { width: 100 },
+            lcn_off:        { width: 100 },
+            mapnoname:      { width: 100 },
+            chtag:          { width: 100 },
+            source:         { width: 200 },
+            services_count: { width: 100 },
+            comment:        { width: 200 },
+        },
         list: list,
         del: true,
         edit: { params: { list: list } },