]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
service_mapper: fixes problems with saves when updating from services tab
authorAdam Sutton <dev@adamsutton.me.uk>
Fri, 14 Mar 2014 22:51:06 +0000 (22:51 +0000)
committerAdam Sutton <dev@adamsutton.me.uk>
Fri, 14 Mar 2014 22:51:06 +0000 (22:51 +0000)
Fixes #1999

src/channels.c
src/input/mpegts/tsfile/tsfile.c
src/service.c
src/service_mapper.c
src/service_mapper.h

index 5105a5225d65ab910b993adb31c4205b329d0648..668bb09ac1f656ebc65b6af35802602984cb75c1 100644 (file)
@@ -424,7 +424,7 @@ channel_set_services_by_list ( channel_t *ch, htsmsg_t *svcs )
   const char *str;
   service_t *svc;
   htsmsg_field_t *f;
-  channel_service_mapping_t *csm, *n;
+  channel_service_mapping_t *csm;
 
   /* Mark all for deletion */
   LIST_FOREACH(csm, &ch->ch_services, csm_chn_link)
@@ -434,19 +434,11 @@ channel_set_services_by_list ( channel_t *ch, htsmsg_t *svcs )
   HTSMSG_FOREACH(f, svcs) {
     if ((str = htsmsg_field_get_str(f)))
       if ((svc = service_find(str)))
-        save |= service_mapper_link(svc, ch);
+        save |= service_mapper_link(svc, ch, 0);
   }
 
   /* Remove */
-  for (csm = LIST_FIRST(&ch->ch_services); csm != NULL; csm = n) {
-    n = LIST_NEXT(csm, csm_chn_link);
-    if (csm->csm_mark) {
-      LIST_REMOVE(csm, csm_chn_link);
-      LIST_REMOVE(csm, csm_svc_link);
-      free(csm);
-      save = 1;
-    }
-  }
+  save |= service_mapper_clean(NULL, ch, 0);
 
   return save;
 }
@@ -567,7 +559,7 @@ channel_delete ( channel_t *ch, int delconf )
 
   /* Services */
   while((csm = LIST_FIRST(&ch->ch_services)) != NULL)
-    service_mapper_unlink(csm->csm_svc, ch);
+    service_mapper_unlink(csm->csm_svc, ch, 0);
 
   /* Subscriptions */
   while((s = LIST_FIRST(&ch->ch_subscriptions)) != NULL) {
index d05fe46975b3fe624d8cf027d29f5b01c017d164..938a0c1ba5d971482b82e247f3bc36b259cb3f1f 100644 (file)
@@ -47,7 +47,7 @@ tsfile_network_create_service
   // TODO: HACK: REMOVE ME
   if (s) {
     channel_t *c = channel_create(NULL, NULL, NULL);
-    service_mapper_link((service_t*)s, c);
+    service_mapper_link((service_t*)s, c, 0);
   }
   return s;
 }
index a3ff609c4fa67257d40ae3ac6106cc076fe4a0a6..5a250ef7d4ef56a15cc1ccf3fd452acb2bedf6f9 100644 (file)
@@ -89,7 +89,7 @@ service_class_channel_set
   const char *str;
   htsmsg_field_t *f;
   channel_t *ch;
-  channel_service_mapping_t *csm, *n;
+  channel_service_mapping_t *csm;
 
   /* Mark all for deletion */
   LIST_FOREACH(csm, &svc->s_channels, csm_svc_link)
@@ -99,19 +99,11 @@ service_class_channel_set
   HTSMSG_FOREACH(f, chns) {
     if ((str = htsmsg_field_get_str(f)))
       if ((ch = channel_find(str)))
-        save |= service_mapper_link(svc, ch);
+        save |= service_mapper_link(svc, ch, 1);
   }
 
   /* Delete unlinked */
-  for (csm = LIST_FIRST(&svc->s_channels); csm != NULL; csm = n ) {
-    n = LIST_NEXT(csm, csm_svc_link);
-    if (csm->csm_mark) {
-      save = 1;
-      LIST_REMOVE(csm, csm_chn_link);
-      LIST_REMOVE(csm, csm_svc_link);
-      free(csm);
-    }
-  }
+  service_mapper_clean(svc, NULL, 1);
     
   return save;
 }
index 3e0310e4592484a2c9bfbb5c71152fcd448be392..349eee1464ddfa7ac3a47178d5a395aed746e97c 100644 (file)
@@ -178,7 +178,7 @@ service_mapper_remove ( service_t *s )
  * Link service and channel
  */
 int
-service_mapper_link ( service_t *s, channel_t *c )
+service_mapper_link ( service_t *s, channel_t *c, int dosave )
 {
   channel_service_mapping_t *csm;
 
@@ -200,25 +200,50 @@ service_mapper_link ( service_t *s, channel_t *c )
   csm->csm_svc = s;
   LIST_INSERT_HEAD(&s->s_channels,  csm, csm_svc_link);
   LIST_INSERT_HEAD(&c->ch_services, csm, csm_chn_link);
+  if (dosave) channel_save(c);
   return 1;
 }
 
+static void
+service_mapper_unlink0 ( channel_service_mapping_t *csm, int save )
+{
+  if (save) channel_save(csm->csm_chn);
+  LIST_REMOVE(csm, csm_chn_link);
+  LIST_REMOVE(csm, csm_svc_link);
+  free(csm);
+}
+
 void
-service_mapper_unlink ( service_t *s, channel_t *c )
+service_mapper_unlink ( service_t *s, channel_t *c, int save )
 {
   channel_service_mapping_t *csm;
 
   /* Unlink */
   LIST_FOREACH(csm, &s->s_channels, csm_svc_link) {
     if (csm->csm_chn == c) {
-      LIST_REMOVE(csm, csm_chn_link);
-      LIST_REMOVE(csm, csm_svc_link);
-      free(csm);
+      service_mapper_unlink0(csm, save);
       break;
     }
   }
 }
 
+int
+service_mapper_clean ( service_t *s, channel_t *c, int dosave )
+{
+  int save = 0;
+  channel_service_mapping_t *csm, *n;
+
+  csm = s ? LIST_FIRST(&s->s_channels) : LIST_FIRST(&c->ch_services);
+  for (; csm != NULL; csm = n ) {
+    n = s ? LIST_NEXT(csm, csm_svc_link) : LIST_NEXT(csm, csm_chn_link);
+    if (csm->csm_mark) {
+      service_mapper_unlink0(csm, dosave);
+      save = 1;
+    }
+  }
+  return save;
+}
+
 /*
  * Process a service 
  */
@@ -250,7 +275,7 @@ service_mapper_process ( service_t *s )
   /* Map */
   if (chn) {
     const char *prov;
-    service_mapper_link(s, chn);
+    service_mapper_link(s, chn, 0);
 
     /* Type tags */
     if (service_is_hdtv(s)) {
index a6c5fb54e4b87b5469330b3f5c563aaab61a3beb..8e54dd6ec320878d265124fb8b9b8a364b1441a4 100644 (file)
@@ -53,9 +53,22 @@ void service_mapper_remove ( struct service *t );
 service_mapper_status_t service_mapper_status ( void );
 
 // Link service to channel
-int  service_mapper_link   ( struct service *s, struct channel *c );
+int  service_mapper_link   ( struct service *s, struct channel *c, int save );
 
 // Unlink service from channel
-void service_mapper_unlink ( struct service *s, struct channel *c );
+void service_mapper_unlink ( struct service *s, struct channel *c, int save );
+
+/**
+ * Clean linkages that are marked for deletion
+ *
+ * Note: only ever pass one of s and c
+ *
+ * @param s     The service to clean linkages for
+ * @param c     The channel to clean linkages for
+ * @parma save  Force channel saves for affected channels
+ *
+ * @return 1 if changes were made, else 0
+ */
+int service_mapper_clean ( struct service *s, struct channel *ch, int save );
 
 #endif /* __TVH_SERVICE_MAPPER_H__ */