]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
bouquet: use hard channel tag link to allow tag renaming
authorJaroslav Kysela <perex@perex.cz>
Sun, 2 Nov 2014 18:04:30 +0000 (19:04 +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

index 202b7c578c22e50c0f8e6bb8c39bf4079b9fe224..daa7384df39fab36d8b9000d453e68a6d22d0add 100644 (file)
@@ -98,6 +98,8 @@ bouquet_destroy(bouquet_t *bq)
 
   idnode_set_free(bq->bq_active_services);
   idnode_set_free(bq->bq_services);
+  assert(bq->bq_services_waiting == NULL);
+  free((char *)bq->bq_chtag_waiting);
   free(bq->bq_name);
   free(bq->bq_src);
   free(bq);
@@ -118,6 +120,21 @@ bouquet_destroy_by_service(service_t *t)
       idnode_set_remove(bq->bq_services, &t->s_id);
 }
 
+/**
+ *
+ */
+void
+bouquet_destroy_by_channel_tag(channel_tag_t *ct)
+{
+  bouquet_t *bq;
+
+  lock_assert(&global_lock);
+
+  RB_FOREACH(bq, &bouquets, bq_link)
+    if (bq->bq_chtag_ptr == ct)
+      bq->bq_chtag_ptr = NULL;
+}
+
 /*
  *
  */
@@ -146,10 +163,24 @@ bouquet_find_by_source(const char *name, const char *src, int create)
 static channel_tag_t *
 bouquet_tag(bouquet_t *bq, int create)
 {
+  channel_tag_t *ct;
   char buf[128];
-  /* TODO: cache the channel_tag_t * pointer */
+
+  assert(!bq->bq_in_load);
+  if (bq->bq_chtag_waiting) {
+    bq->bq_chtag_ptr = channel_tag_find_by_uuid(bq->bq_chtag_waiting);
+    free((char *)bq->bq_chtag_waiting);
+    bq->bq_chtag_waiting = NULL;
+  }
+  if (bq->bq_chtag_ptr)
+    return bq->bq_chtag_ptr;
   snprintf(buf, sizeof(buf), "*** %s", bq->bq_name ?: "???");
-  return channel_tag_find_by_name(buf, create);
+  ct = channel_tag_find_by_name(buf, create);
+  if (ct) {
+    bq->bq_chtag_ptr = ct;
+    bouquet_save(bq, 0);
+  }
+  return ct;
 }
 
 /*
@@ -386,6 +417,8 @@ bouquet_class_mapnolcn_notify ( void *obj )
   service_t *t;
   size_t z;
 
+  if (bq->bq_in_load)
+    return;
   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];
@@ -404,6 +437,8 @@ bouquet_class_mapnoname_notify ( void *obj )
   service_t *t;
   size_t z;
 
+  if (bq->bq_in_load)
+    return;
   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];
@@ -424,6 +459,8 @@ bouquet_class_chtag_notify ( void *obj )
   channel_tag_t *ct;
   size_t z;
 
+  if (bq->bq_in_load)
+    return;
   if (!bq->bq_chtag && bq->bq_enabled && bq->bq_maptoch) {
     ct = bouquet_tag(bq, 0);
     if (!ct)
@@ -444,9 +481,46 @@ bouquet_class_chtag_notify ( void *obj )
 static void
 bouquet_class_lcn_offset_notify ( void *obj )
 {
+  if (((bouquet_t *)obj)->bq_in_load)
+    return;
   bouquet_notify_channels((bouquet_t *)obj);
 }
 
+static const void *
+bouquet_class_chtag_ref_get ( void *obj )
+{
+  static const char *buf;
+  bouquet_t *bq = obj;
+
+  if (bq->bq_chtag_ptr)
+    buf = idnode_uuid_as_str(&bq->bq_chtag_ptr->ct_id);
+  else
+    buf = "";
+  return &buf;
+}
+
+static char *
+bouquet_class_chtag_ref_rend ( void *obj )
+{
+  bouquet_t *bq = obj;
+  if (bq->bq_chtag_ptr)
+    return strdup(bq->bq_chtag_ptr->ct_name ?: "");
+  else
+    return strdup("");
+}
+
+static int
+bouquet_class_chtag_ref_set ( void *obj, const void *p )
+{
+  bouquet_t *bq = obj;
+
+  free((char *)bq->bq_chtag_waiting);
+  bq->bq_chtag_waiting = NULL;
+  if (bq->bq_in_load)
+    bq->bq_chtag_waiting = strdup((const char *)p);
+  return 0;
+}
+
 static const void *
 bouquet_class_services_get ( void *obj )
 {
@@ -537,6 +611,15 @@ const idclass_t bouquet_class = {
       .off      = offsetof(bouquet_t, bq_chtag),
       .notify   = bouquet_class_chtag_notify,
     },
+    {
+      .type     = PT_STR,
+      .id       = "chtag_ref",
+      .name     = "Channel Tag Reference",
+      .get      = bouquet_class_chtag_ref_get,
+      .set      = bouquet_class_chtag_ref_set,
+      .rend     = bouquet_class_chtag_ref_rend,
+      .opts     = PO_RDONLY | PO_HIDDEN,
+    },
     {
       .type     = PT_STR,
       .id       = "name",
index 77a4dac892e144fe94ea470dcc1b94fbdde5cadd..fe34571f4989171589ffac055305231611d7ee51 100644 (file)
@@ -22,6 +22,7 @@
 #include "idnode.h"
 #include "htsmsg.h"
 #include "service.h"
+#include "channels.h"
 
 typedef struct bouquet {
   idnode_t bq_id;
@@ -37,6 +38,8 @@ typedef struct bouquet {
   int           bq_mapnolcn;
   int           bq_mapnoname;
   int           bq_chtag;
+  channel_tag_t*bq_chtag_ptr;
+  const char   *bq_chtag_waiting;
   char         *bq_name;
   char         *bq_src;
   char         *bq_comment;
@@ -63,6 +66,7 @@ bouquet_t * bouquet_create(const char *uuid, htsmsg_t *conf,
                            const char *name, const char *src);
 
 void bouquet_destroy_by_service(service_t *t);
+void bouquet_destroy_by_channel_tag(channel_tag_t *ct);
 
 static inline bouquet_t *
 bouquet_find_by_uuid(const char *uuid)
index 141497e64b27737463cb803e0ca39f91d8c96f5f..227bdfbaf27b9b7d949984922f970d8df5868743 100644 (file)
@@ -926,7 +926,12 @@ channel_tag_unmap(channel_t *ch, channel_tag_t *ct)
       LIST_REMOVE(ctm, ctm_channel_link);
       LIST_REMOVE(ctm, ctm_tag_link);
       free(ctm);
-      channel_tag_save(ct);
+      channel_save(ch);
+      idnode_notify_simple(&ch->ch_id);
+      if (ct->ct_enabled && !ct->ct_internal) {
+        htsp_tag_update(ct);
+        htsp_channel_update(ch);
+      }
       return;
     }
   }
@@ -990,6 +995,7 @@ channel_tag_destroy(channel_tag_t *ct, int delconf)
   TAILQ_REMOVE(&channel_tags, ct, ct_link);
   idnode_unlink(&ct->ct_id);
 
+  bouquet_destroy_by_channel_tag(ct);
   autorec_destroy_by_channel_tag(ct, delconf);
   access_destroy_by_channel_tag(ct, delconf);