]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
idnode: change config save mechanism (do I/O outside global_lock)
authorJaroslav Kysela <perex@perex.cz>
Wed, 10 Feb 2016 16:08:22 +0000 (17:08 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 10 Feb 2016 16:13:56 +0000 (17:13 +0100)
66 files changed:
src/access.c
src/access.h
src/api/api_access.c
src/api/api_bouquet.c
src/api/api_channel.c
src/api/api_dvr.c
src/api/api_mpegts.c
src/api/api_wizard.c
src/bouquet.c
src/bouquet.h
src/channels.c
src/channels.h
src/config.c
src/config.h
src/descrambler/caclient.c
src/dvr/dvr.h
src/dvr/dvr_autorec.c
src/dvr/dvr_config.c
src/dvr/dvr_db.c
src/dvr/dvr_inotify.c
src/dvr/dvr_timerec.c
src/dvr/dvr_vfsmgr.c
src/epggrab.c
src/epggrab.h
src/epggrab/channel.c
src/epggrab/module.c
src/esfilter.c
src/idnode.c
src/idnode.h
src/imagecache.c
src/input/mpegts.h
src/input/mpegts/dvb_psi.c
src/input/mpegts/fastscan.c
src/input/mpegts/iptv/iptv.c
src/input/mpegts/iptv/iptv_auto.c
src/input/mpegts/iptv/iptv_mux.c
src/input/mpegts/iptv/iptv_service.c
src/input/mpegts/linuxdvb/linuxdvb_adapter.c
src/input/mpegts/linuxdvb/linuxdvb_ca.c
src/input/mpegts/linuxdvb/linuxdvb_frontend.c
src/input/mpegts/linuxdvb/linuxdvb_private.h
src/input/mpegts/linuxdvb/linuxdvb_satconf.c
src/input/mpegts/mpegts_mux.c
src/input/mpegts/mpegts_mux_dvb.c
src/input/mpegts/mpegts_mux_sched.c
src/input/mpegts/mpegts_mux_sched.h
src/input/mpegts/mpegts_network.c
src/input/mpegts/mpegts_network_dvb.c
src/input/mpegts/mpegts_network_scan.c
src/input/mpegts/mpegts_service.c
src/input/mpegts/satip/satip.c
src/input/mpegts/satip/satip_frontend.c
src/input/mpegts/satip/satip_private.h
src/input/mpegts/satip/satip_satconf.c
src/input/mpegts/tsfile/tsfile.c
src/input/mpegts/tsfile/tsfile_mux.c
src/input/mpegts/tvhdhomerun/tvhdhomerun.c
src/input/mpegts/tvhdhomerun/tvhdhomerun_frontend.c
src/input/mpegts/tvhdhomerun/tvhdhomerun_private.h
src/profile.c
src/satip/server.c
src/service.c
src/service.h
src/service_mapper.c
src/tvhlog.c
src/wizard.c

index d65b797105df59c4733b6e33928676f6cab613fa..b11886f6ad0c563206531ac45a6b3e3fc057dd65 100644 (file)
@@ -1143,19 +1143,6 @@ access_destroy_by_channel_tag(channel_tag_t *ct, int delconf)
   idnode_list_destroy(&ct->ct_accesses, delconf ? ct : NULL);
 }
 
-/**
- *
- */
-void
-access_entry_save(access_entry_t *ae)
-{
-  htsmsg_t *c = htsmsg_create_map();
-  char ubuf[UUID_HEX_SIZE];
-  idnode_save(&ae->ae_id, c);
-  hts_settings_save(c, "accesscontrol/%s", idnode_uuid_as_str(&ae->ae_id, ubuf));
-  htsmsg_destroy(c);
-}
-
 /**
  *
  */
@@ -1168,7 +1155,7 @@ access_entry_reindex(void)
   TAILQ_FOREACH(ae, &access_entries, ae_link) {
     if (ae->ae_index != i) {
       ae->ae_index = i;
-      access_entry_save(ae);
+      idnode_changed(&ae->ae_id);
     }
     i++;
   }
@@ -1178,11 +1165,16 @@ access_entry_reindex(void)
  * Class definition
  * **************************************************************************/
 
-static void
-access_entry_class_save(idnode_t *self)
+static htsmsg_t *
+access_entry_class_save(idnode_t *self, char *filename, size_t fsize)
 {
+  access_entry_t *ae = (access_entry_t *)self;
+  char ubuf[UUID_HEX_SIZE];
+  htsmsg_t *c = htsmsg_create_map();
   access_entry_update_rights((access_entry_t *)self);
-  access_entry_save((access_entry_t *)self);
+  idnode_save(&ae->ae_id, c);
+  snprintf(filename, fsize, "accesscontrol/%s", idnode_uuid_as_str(&ae->ae_id, ubuf));
+  return c;
 }
 
 static void
@@ -1778,20 +1770,15 @@ passwd_entry_destroy(passwd_entry_t *pw, int delconf)
   free(pw);
 }
 
-void
-passwd_entry_save(passwd_entry_t *pw)
+static htsmsg_t *
+passwd_entry_class_save(idnode_t *self, char *filename, size_t fsize)
 {
-  htsmsg_t *c = htsmsg_create_map();
+  passwd_entry_t *pw = (passwd_entry_t *)self;
   char ubuf[UUID_HEX_SIZE];
+  htsmsg_t *c = htsmsg_create_map();
   idnode_save(&pw->pw_id, c);
-  hts_settings_save(c, "passwd/%s", idnode_uuid_as_str(&pw->pw_id, ubuf));
-  htsmsg_destroy(c);
-}
-
-static void
-passwd_entry_class_save(idnode_t *self)
-{
-  passwd_entry_save((passwd_entry_t *)self);
+  snprintf(filename, fsize, "passwd/%s", idnode_uuid_as_str(&pw->pw_id, ubuf));
+  return c;
 }
 
 static void
@@ -1954,20 +1941,15 @@ ipblock_entry_destroy(ipblock_entry_t *ib)
   free(ib);
 }
 
-void
-ipblock_entry_save(ipblock_entry_t *ib)
+static htsmsg_t *
+ipblock_entry_class_save(idnode_t *self, char *filename, size_t fsize)
 {
+  ipblock_entry_t *ib = (ipblock_entry_t *)self;
   htsmsg_t *c = htsmsg_create_map();
   char ubuf[UUID_HEX_SIZE];
   idnode_save(&ib->ib_id, c);
-  hts_settings_save(c, "ipblock/%s", idnode_uuid_as_str(&ib->ib_id, ubuf));
-  htsmsg_destroy(c);
-}
-
-static void
-ipblock_entry_class_save(idnode_t *self)
-{
-  ipblock_entry_save((ipblock_entry_t *)self);
+  snprintf(filename, fsize, "ipblock/%s", idnode_uuid_as_str(&ib->ib_id, ubuf));
+  return c;
 }
 
 static const char *
@@ -2109,7 +2091,7 @@ access_init(int createdefault, int noacl)
     ae->ae_admin          = 1;
     access_entry_update_rights(ae);
 
-    access_entry_save(ae);
+    idnode_changed(&ae->ae_id);
 
     tvhlog(LOG_WARNING, "access",
           "Created default wide open access controle entry");
index 8b5f6a8ff65a214fa51b38141f4cb76fbd83b9fc..60462b53d5bae4fe5ddab0b7c2e4ce510e32a0b5 100644 (file)
@@ -275,12 +275,6 @@ access_entry_create(const char *uuid, htsmsg_t *conf);
 void
 access_entry_destroy(access_entry_t *ae, int delconf);
 
-/**
- *
- */
-void
-access_entry_save(access_entry_t *ae);
-
 /**
  *
  */
@@ -298,16 +292,12 @@ passwd_entry_t *
 passwd_entry_create(const char *uuid, htsmsg_t *conf);
 void
 passwd_entry_destroy(passwd_entry_t *ae, int delconf);
-void
-passwd_entry_save(passwd_entry_t *pw);
 
 /**
  *
  */
 ipblock_entry_t *
 ipblock_entry_create(const char *uuid, htsmsg_t *conf);
-void
-ipblock_entry_save(ipblock_entry_t *pw);
 
 /**
  *
index f31ef64131c9d361d5419b8ac69b724896c089a8..734d6deeb154e507a04a27d9d49da215e8d36a7e 100644 (file)
@@ -47,7 +47,7 @@ api_passwd_entry_create
 
   pthread_mutex_lock(&global_lock);
   if ((pw = passwd_entry_create(NULL, conf)) != NULL)
-    passwd_entry_save(pw);
+    idnode_changed(&pw->pw_id);
   pthread_mutex_unlock(&global_lock);
 
   return 0;
@@ -79,7 +79,7 @@ api_ipblock_entry_create
 
   pthread_mutex_lock(&global_lock);
   if ((ib = ipblock_entry_create(NULL, conf)) != NULL)
-    ipblock_entry_save(ib);
+    idnode_changed(&ib->ib_id);
   pthread_mutex_unlock(&global_lock);
 
   return 0;
@@ -155,7 +155,7 @@ api_access_entry_create
 
   pthread_mutex_lock(&global_lock);
   if ((ae = access_entry_create(NULL, conf)) != NULL)
-    access_entry_save(ae);
+    idnode_changed(&ae->ae_id);
   pthread_mutex_unlock(&global_lock);
 
   return 0;
index 4143f975a02bb86175316ca71dde6c7a3381c98b..6ed798f6892a390da19ee95887e9b8d4c654cdd1 100644 (file)
@@ -75,7 +75,7 @@ api_bouquet_create
   pthread_mutex_lock(&global_lock);
   bq = bouquet_create(NULL, conf, NULL, NULL);
   if (bq)
-    bouquet_save(bq, 0);
+    idnode_changed(&bq->bq_id);
   pthread_mutex_unlock(&global_lock);
 
   return 0;
index 79df5c5533139d0351d226a88f3cea1ae2ea840b..2de1c2aad1947ebc96c8918dbb9e2dcb489fd60f 100644 (file)
@@ -94,7 +94,7 @@ api_channel_create
   pthread_mutex_lock(&global_lock);
   ch = channel_create(NULL, conf, NULL);
   if (ch)
-    channel_save(ch);
+    idnode_changed(&ch->ch_id);
   pthread_mutex_unlock(&global_lock);
 
   return 0;
@@ -151,7 +151,7 @@ api_channel_tag_create
   pthread_mutex_lock(&global_lock);
   ct = channel_tag_create(NULL, conf);
   if (ct)
-    channel_tag_save(ct);
+    idnode_changed(&ct->ct_id);
   pthread_mutex_unlock(&global_lock);
 
   return 0;
index 911965468418c5be34c99ef65df99bf5efa0790b..3e3d9d637ac3f7ff29492d697fe7cd462fe240b7 100644 (file)
@@ -57,7 +57,7 @@ api_dvr_config_create
 
   pthread_mutex_lock(&global_lock);
   if ((cfg = dvr_config_create(NULL, NULL, conf)))
-    dvr_config_save(cfg);
+    idnode_changed(&cfg->dvr_id);
   pthread_mutex_unlock(&global_lock);
 
   return 0;
@@ -172,7 +172,7 @@ api_dvr_entry_create
       htsmsg_add_msg(conf, "subtitle", m);
     }
     if ((de = dvr_entry_create(NULL, conf, 0)))
-      dvr_entry_save(de);
+      idnode_changed(&de->de_id);
 
     res = 0;
     free(lang);
@@ -244,7 +244,7 @@ api_dvr_entry_create_by_event
                                        NULL, DVR_PRIO_NORMAL, DVR_RET_DVRCONFIG,
                                        DVR_RET_DVRCONFIG, comment);
         if (de)
-          dvr_entry_save(de);
+          idnode_changed(&de->de_id);
       }
     }
     pthread_mutex_unlock(&global_lock);
@@ -382,10 +382,8 @@ api_dvr_autorec_create
   if (cfg) {
     htsmsg_set_str(conf, "config_name", idnode_uuid_as_str(&cfg->dvr_id, ubuf));
     dae = dvr_autorec_create(NULL, conf);
-    if (dae) {
-      dvr_autorec_save(dae);
-      dvr_autorec_changed(dae, 1);
-    }
+    if (dae)
+      idnode_changed(&dae->dae_id);
   }
   pthread_mutex_unlock(&global_lock);
 
@@ -427,10 +425,8 @@ api_dvr_autorec_create_by_series
                                           perm->aa_username,
                                           perm->aa_representative,
                                           "Created from EPG query");
-        if (dae) {
-          dvr_autorec_save(dae);
-          dvr_autorec_changed(dae, 1);
-        }
+        if (dae)
+          idnode_changed(&dae->dae_id);
       }
     }
     pthread_mutex_unlock(&global_lock);
@@ -467,10 +463,8 @@ api_dvr_timerec_create
 
   pthread_mutex_lock(&global_lock);
   dte = dvr_timerec_create(NULL, conf);
-  if (dte) {
-    dvr_timerec_save(dte);
-    dvr_timerec_check(dte);
-  }
+  if (dte)
+    idnode_changed(&dte->dte_id);
   pthread_mutex_unlock(&global_lock);
 
   return 0;
index 596b74b0150c87411711473a1f69e886df3dcb8c..ea54ad0b4deff7add67c3fd211cafe34623b7efb 100644 (file)
@@ -128,7 +128,7 @@ api_mpegts_network_create
   if (mn) {
     err = 0;
     *resp = htsmsg_create_map();
-    mn->mn_config_save(mn);
+    idnode_changed(&mn->mn_id);
   } else {
     err = EINVAL;
   }
@@ -225,7 +225,7 @@ api_mpegts_network_muxcreate
   if (!(mm = mn->mn_mux_create2(mn, conf)))
     goto exit;
 
-  mm->mm_config_save(mm);
+  idnode_changed(&mm->mm_id);
   err = 0;
 
 exit:
@@ -319,7 +319,7 @@ api_mpegts_mux_sched_create
   if (mms) {
     err = 0;
     *resp = htsmsg_create_map();
-    mpegts_mux_sched_save(mms);
+    idnode_changed(&mms->mms_id);
   } else {
     err = EINVAL;
   }
index d7128e961fc6905dce73f14fbf92a8dd20e170b3..d586870fd16cae177a7e1e302eea417965c1dd0e 100644 (file)
@@ -32,7 +32,7 @@ wizard_page ( const char *page )
   if (strcmp(page, config.wizard ?: "")) {
     free(config.wizard);
     config.wizard = page[0] ? strdup(page) : NULL;
-    config_save();
+    idnode_changed(&config.idnode);
   }
   pthread_mutex_unlock(&global_lock);
   return 0;
index 26f43d7b58ca268023203ae4e171c0645cc31a1e..a628f2180bb77cc638bb615a391a38eb31d9cd75 100644 (file)
@@ -206,7 +206,7 @@ bouquet_find_by_source(const char *name, const char *src, int create)
       tvhwarn("bouquet", "bouquet name '%s' changed to '%s'", bq->bq_name ?: "", name);
       free(bq->bq_name);
       bq->bq_name = strdup(name);
-      bouquet_save(bq, 1);
+      idnode_changed(&bq->bq_id);
     }
     return bq;
   }
@@ -239,7 +239,7 @@ bouquet_tag(bouquet_t *bq, int create)
   ct = channel_tag_find_by_name(buf, create);
   if (ct) {
     bq->bq_chtag_ptr = ct;
-    bouquet_save(bq, 0);
+    idnode_changed(&bq->bq_id);
   }
   return ct;
 }
@@ -294,10 +294,8 @@ bouquet_map_channel(bouquet_t *bq, service_t *t)
   else
     ch = (channel_t *)ilm->ilm_in2;
   if (ch && bq->bq_chtag)
-    if (channel_tag_map(bouquet_tag(bq, 1), ch, ch)) {
-      idnode_notify_changed(&ch->ch_id);
-      channel_save(ch);
-    }
+    if (channel_tag_map(bouquet_tag(bq, 1), ch, ch))
+      idnode_changed(&ch->ch_id);
 }
 
 /*
@@ -462,8 +460,10 @@ bouquet_completed(bouquet_t *bq, uint32_t seen)
   bq->bq_active_services = idnode_set_create(1);
 
 save:
-  if (bq->bq_saveflag)
-    bouquet_save(bq, 1);
+  if (bq->bq_saveflag) {
+    bq->bq_saveflag = 0;
+    idnode_changed(&bq->bq_id);
+  }
 }
 
 /*
@@ -568,28 +568,10 @@ bouquet_delete(bouquet_t *bq)
   } else {
     idnode_set_free(bq->bq_services);
     bq->bq_services = idnode_set_create(1);
-    bouquet_save(bq, 1);
+    idnode_changed(&bq->bq_id);
   }
 }
 
-/**
- *
- */
-void
-bouquet_save(bouquet_t *bq, int notify)
-{
-  htsmsg_t *c = htsmsg_create_map();
-  char ubuf[UUID_HEX_SIZE];
-  idnode_save(&bq->bq_id, c);
-  hts_settings_save(c, "bouquet/%s", idnode_uuid_as_str(&bq->bq_id, ubuf));
-  if (bq->bq_shield)
-    htsmsg_add_bool(c, "shield", 1);
-  htsmsg_destroy(c);
-  bq->bq_saveflag = 0;
-  if (notify)
-    idnode_notify_changed(&bq->bq_id);
-}
-
 /**
  *
  */
@@ -607,10 +589,18 @@ bouquet_change_comment ( bouquet_t *bq, const char *comment, int replace )
  * Class definition
  * **************************************************************************/
 
-static void
-bouquet_class_save(idnode_t *self)
+static htsmsg_t *
+bouquet_class_save(idnode_t *self, char *filename, size_t fsize)
 {
-  bouquet_save((bouquet_t *)self, 0);
+  bouquet_t *bq = (bouquet_t *)self;
+  htsmsg_t *c = htsmsg_create_map();
+  char ubuf[UUID_HEX_SIZE];
+  idnode_save(&bq->bq_id, c);
+  snprintf(filename, fsize, "bouquet/%s", idnode_uuid_as_str(&bq->bq_id, ubuf));
+  if (bq->bq_shield)
+    htsmsg_add_bool(c, "shield", 1);
+  bq->bq_saveflag = 0;
+  return c;
 }
 
 static void
index 44b8a75bed2a6e3c86b414d4d7c81577e26fa482..1cf3eb9c2c76f9efac824e321c21e99bcf4712f5 100644 (file)
@@ -96,8 +96,6 @@ void bouquet_change_comment(bouquet_t *bq, const char *comment, int replace);
 
 uint64_t bouquet_get_channel_number(bouquet_t *bq, service_t *t);
 
-void bouquet_save(bouquet_t *bq, int notify);
-
 /**
  *
  */
index c3f15538b7a45fcec11fad1b48fe8c5a2887fc7e..59d649ed0c90515a0ba8530df497625c96ed7754 100644 (file)
@@ -69,9 +69,28 @@ ch_id_cmp ( channel_t *a, channel_t *b )
  * *************************************************************************/
 
 static void
-channel_class_save ( idnode_t *self )
+channel_class_changed ( idnode_t *self )
 {
-  channel_save((channel_t *)self);
+  channel_t *ch = (channel_t *)self;
+
+  /* update the EPG channel <-> channel mapping here */
+  if (ch->ch_enabled && ch->ch_epgauto)
+    epggrab_channel_add(ch);
+}
+
+static htsmsg_t *
+channel_class_save ( idnode_t *self, char *filename, size_t fsize )
+{
+  channel_t *ch = (channel_t *)self;
+  htsmsg_t *c = NULL;
+  char ubuf[UUID_HEX_SIZE];
+  /* save channel (on demand) */
+  if (ch->ch_dont_save == 0) {
+    c = htsmsg_create_map();
+    idnode_save(&ch->ch_id, c);
+    snprintf(filename, fsize, "channel/config/%s", idnode_uuid_as_str(&ch->ch_id, ubuf));
+  }
+  return c;
 }
 
 static void
@@ -342,6 +361,7 @@ const idclass_t channel_class = {
   .ic_class      = "channel",
   .ic_caption    = N_("Channel"),
   .ic_event      = "channel",
+  .ic_changed    = channel_class_changed,
   .ic_save       = channel_class_save,
   .ic_get_title  = channel_class_get_title,
   .ic_delete     = channel_class_delete,
@@ -768,8 +788,7 @@ channel_get_icon ( channel_t *ch )
       if (strncmp(icn, "picon://", 8) == 0) continue;
       if (check_file(icn)) {
         icon = ch->ch_icon = strdup(icn);
-        channel_save(ch);
-        idnode_notify_changed(&ch->ch_id);
+        idnode_changed(&ch->ch_id);
         goto found;
       }
     }
@@ -857,8 +876,7 @@ channel_get_icon ( channel_t *ch )
 
       if (i > 1 || check_file(buf)) {
         icon = ch->ch_icon = strdup(buf);
-        channel_save(ch);
-        idnode_notify_changed(&ch->ch_id);
+        idnode_changed(&ch->ch_id);
       }
     }
 
@@ -871,8 +889,7 @@ channel_get_icon ( channel_t *ch )
         snprintf(buf2, sizeof(buf2), "%s/%s", picon, icn+8);
         if (i > 1 || check_file(buf2)) {
           icon = ch->ch_icon = strdup(icn);
-          channel_save(ch);
-          idnode_notify_changed(&ch->ch_id);
+          idnode_changed(&ch->ch_id);
           break;
         }
       }
@@ -1026,7 +1043,7 @@ channel_delete ( channel_t *ch, int delconf )
     if (delconf) {
       free(ch1->ch_epg_parent);
       ch1->ch_epg_parent = NULL;
-      channel_save(ch1);
+      idnode_changed(&ch1->ch_id);
     }
   }
 
@@ -1046,26 +1063,6 @@ channel_delete ( channel_t *ch, int delconf )
   free(ch);
 }
 
-/*
- * Save
- */
-void
-channel_save ( channel_t *ch )
-{
-  htsmsg_t *c;
-  char ubuf[UUID_HEX_SIZE];
-  if (ch->ch_dont_save == 0) {
-    c = htsmsg_create_map();
-    idnode_save(&ch->ch_id, c);
-    hts_settings_save(c, "channel/config/%s", idnode_uuid_as_str(&ch->ch_id, ubuf));
-    htsmsg_destroy(c);
-  }
-  /* update the EPG channel <-> channel mapping here */
-  if (ch->ch_enabled && ch->ch_epgauto)
-    epggrab_channel_add(ch);
-}
-
-
 
 
 /**
@@ -1252,21 +1249,6 @@ channel_tag_destroy(channel_tag_t *ct, int delconf)
   free(ct);
 }
 
-/**
- *
- */
-void
-channel_tag_save(channel_tag_t *ct)
-{
-  htsmsg_t *c = htsmsg_create_map();
-  char ubuf[UUID_HEX_SIZE];
-  idnode_save(&ct->ct_id, c);
-  hts_settings_save(c, "channel/tag/%s", idnode_uuid_as_str(&ct->ct_id, ubuf));
-  htsmsg_destroy(c);
-  htsp_tag_update(ct);
-}
-
-
 /**
  *
  */
@@ -1319,10 +1301,16 @@ chtags_ok:
  * Channel Tag Class definition
  * **************************************************************************/
 
-static void
-channel_tag_class_save(idnode_t *self)
+static htsmsg_t *
+channel_tag_class_save(idnode_t *self, char *filename, size_t fsize)
 {
-  channel_tag_save((channel_tag_t *)self);
+  channel_tag_t *ct = (channel_tag_t *)self;
+  htsmsg_t *c = htsmsg_create_map();
+  char ubuf[UUID_HEX_SIZE];
+  idnode_save(&ct->ct_id, c);
+  snprintf(filename, fsize, "channel/tag/%s", idnode_uuid_as_str(&ct->ct_id, ubuf));
+  htsp_tag_update(ct);
+  return c;
 }
 
 static void
@@ -1474,7 +1462,7 @@ channel_tag_find_by_name(const char *name, int create)
   ct->ct_enabled = 1;
   tvh_str_update(&ct->ct_name, name);
 
-  channel_tag_save(ct);
+  idnode_changed(&ct->ct_id);
   return ct;
 }
 
index fe74cec8d05a43953f1b49932ab53c62f20ae738..991045fd08bc0937bacc6f5cac9161cb7de97bb0 100644 (file)
@@ -150,8 +150,6 @@ channel_tag_t *channel_tag_find_by_identifier(uint32_t id);
 static inline channel_tag_t *channel_tag_find_by_uuid(const char *uuid)
   {  return (channel_tag_t*)idnode_find(uuid, &channel_tag_class, NULL); }
 
-void channel_tag_save(channel_tag_t *ct);
-
 htsmsg_t * channel_tag_class_get_list(void *o, const char *lang);
 
 const char * channel_tag_get_icon(channel_tag_t *ct);
@@ -165,8 +163,6 @@ void channel_tag_unmap(channel_t *ch, void *origin);
 
 int channel_tag_access(channel_tag_t *ct, struct access *a, int disabled);
 
-void channel_save(channel_t *ch);
-
 const char *channel_get_name ( channel_t *ch );
 int channel_set_name ( channel_t *ch, const char *name );
 
index cb3ceddf7b143ecebd4559e39baf92f6b1742a12..8e6ff9d21578f46a088315d2f19e06a2b1d5cb93 100644 (file)
@@ -1568,7 +1568,7 @@ config_migrate ( int backup )
 update:
   config.version = v;
   tvh_str_set(&config.full_version, tvheadend_version);
-  config_save();
+  idnode_changed(&config.idnode);
   return 1;
 }
 
@@ -1722,7 +1722,7 @@ config_init ( int backup )
     config.version = ARRAY_SIZE(config_migrate_table);
     tvh_str_set(&config.full_version, tvheadend_version);
     tvh_str_set(&config.server_name, "Tvheadend");
-    config_save();
+    idnode_changed(&config.idnode);
   
   /* Perform migrations */
   } else {
@@ -1748,24 +1748,20 @@ void config_done ( void )
   file_unlock(config_lock, config_lock_fd);
 }
 
-void config_save ( void )
+/* **************************************************************************
+ * Config Class
+ * *************************************************************************/
+
+static htsmsg_t *
+config_class_save(idnode_t *self, char *filename, size_t fsize)
 {
   htsmsg_t *c = htsmsg_create_map();
   idnode_save(&config.idnode, c);
 #if ENABLE_SATIP_SERVER
   idnode_save(&satip_server_conf.idnode, c);
 #endif
-  hts_settings_save(c, "config");
-  htsmsg_destroy(c);
-}
-
-/* **************************************************************************
- * Config Class
- * *************************************************************************/
-
-static void config_class_save(idnode_t *self)
-{
-  config_save();
+  snprintf(filename, fsize, "config");
+  return c;
 }
 
 static int
index 306777c0db8bed5b381f675e9c3fc20e5ec05819..1df2d7bd9ee1224d832216cb65e2b0c0b1c52002 100644 (file)
@@ -62,7 +62,6 @@ extern config_t config;
 void        config_boot    ( const char *path, gid_t gid, uid_t uid );
 void        config_init    ( int backup );
 void        config_done    ( void );
-void        config_save    ( void );
 
 const char *config_get_server_name ( void );
 const char *config_get_language    ( void );
index ad73b2a992f7e18250be4740e9042a7febc4e6fa..83e2ed11b552574015bc0709de19abc81bc4758b 100644 (file)
@@ -37,8 +37,6 @@ const idclass_t *caclient_classes[] = {
 struct caclient_entry_queue caclients;
 static pthread_mutex_t caclients_mutex;
 
-static void caclient_class_save ( idnode_t *in );
-
 static const idclass_t *
 caclient_class_find(const char *name)
 {
@@ -68,7 +66,7 @@ caclient_reindex(void)
   TAILQ_FOREACH(cac, &caclients, cac_link)
     if (cac->cac_save) {
       cac->cac_save = 0;
-      caclient_class_save((idnode_t *)cac);
+      idnode_changed((idnode_t *)cac);
     }
 }
 
@@ -129,7 +127,7 @@ caclient_create
   }
   pthread_mutex_unlock(&caclients_mutex);
   if (save)
-    caclient_class_save((idnode_t *)cac);
+    idnode_changed((idnode_t *)cac);
   cac->cac_conf_changed(cac);
   return cac;
 }
@@ -155,15 +153,20 @@ caclient_delete(caclient_t *cac, int delconf)
 }
 
 static void
-caclient_class_save ( idnode_t *in )
+caclient_class_changed ( idnode_t *in )
 {
-  char ubuf[UUID_HEX_SIZE];
   caclient_t *cac = (caclient_t *)in;
+  cac->cac_conf_changed(cac);
+}
+
+static htsmsg_t *
+caclient_class_save ( idnode_t *in, char *filename, size_t fsize )
+{
+  char ubuf[UUID_HEX_SIZE];
   htsmsg_t *c = htsmsg_create_map();
   idnode_save(in, c);
-  hts_settings_save(c, "caclient/%s", idnode_uuid_as_str(in, ubuf));
-  htsmsg_destroy(c);
-  cac->cac_conf_changed(cac);
+  snprintf(filename, fsize, "caclient/%s", idnode_uuid_as_str(in, ubuf));
+  return c;
 }
 
 static const char *
@@ -237,6 +240,7 @@ const idclass_t caclient_class =
 {
   .ic_class      = "caclient",
   .ic_caption    = N_("Conditional access client"),
+  .ic_changed    = caclient_class_changed,
   .ic_save       = caclient_class_save,
   .ic_event      = "caclient",
   .ic_get_title  = caclient_class_get_title,
index 4d66b6889ce2521ebef998700d86b9023b8c9954..7be02c34df371b6215867bf6be0cff392fd461db 100644 (file)
@@ -440,8 +440,6 @@ static inline dvr_config_t *dvr_config_find_by_uuid(const char *uuid)
 
 void dvr_config_delete(const char *name);
 
-void dvr_config_save(dvr_config_t *cfg);
-
 void dvr_config_destroy_by_profile(profile_t *pro, int delconf);
 
 static inline uint32_t dvr_retention_cleanup(uint32_t val)
@@ -487,8 +485,6 @@ void dvr_entry_init(void);
 
 void dvr_entry_done(void);
 
-void dvr_entry_save(dvr_entry_t *de);
-
 void dvr_entry_destroy_by_config(dvr_config_t *cfg, int delconf);
 
 int dvr_entry_set_state(dvr_entry_t *de, dvr_entry_sched_state_t state,
@@ -635,8 +631,6 @@ dvr_autorec_add_series_link(const char *dvr_config_name,
                             const char *owner, const char *creator,
                             const char *comment);
 
-void dvr_autorec_save(dvr_autorec_entry_t *dae);
-
 void dvr_autorec_changed(dvr_autorec_entry_t *dae, int purge);
 
 static inline dvr_autorec_entry_t *
@@ -709,8 +703,6 @@ dvr_timerec_find_by_uuid(const char *uuid)
   { return (dvr_timerec_entry_t*)idnode_find(uuid, &dvr_timerec_entry_class, NULL); }
 
 
-void dvr_timerec_save(dvr_timerec_entry_t *dae);
-
 void dvr_timerec_check(dvr_timerec_entry_t *dae);
 
 void timerec_destroy_by_config(dvr_config_t *cfg, int delconf);
index 54fcc94ac32dd146e3854577f5dc8750c31d8dff..bb08edf281bd1b9fa75e75fd38d145595e5a7f72 100644 (file)
@@ -87,7 +87,7 @@ dvr_autorec_purge_spawns(dvr_autorec_entry_t *dae, int del, int disabled)
       }
       dvr_entry_cancel(de, 0);
     } else
-      dvr_entry_save(de);
+      idnode_changed(&de->de_id);
   }
   if (bcast)
     bcast[i] = NULL;
@@ -310,10 +310,8 @@ dvr_autorec_create_htsp(htsmsg_t *conf)
   dae = dvr_autorec_create(NULL, conf);
   htsmsg_destroy(conf);
 
-  if (dae) {
-    dvr_autorec_save(dae);
-    dvr_autorec_changed(dae, 1);
-  }
+  if (dae)
+    idnode_changed(&dae->dae_id);
 
   return dae;
 }
@@ -322,8 +320,7 @@ void
 dvr_autorec_update_htsp(dvr_autorec_entry_t *dae, htsmsg_t *conf)
 {
   idnode_update(&dae->dae_id, conf);
-  dvr_autorec_save(dae);
-  dvr_autorec_changed(dae, 1);
+  idnode_changed(&dae->dae_id);
   tvhlog(LOG_INFO, "autorec", "\"%s\" on \"%s\": Updated", dae->dae_title ? dae->dae_title : "",
       (dae->dae_channel && dae->dae_channel->ch_name) ? dae->dae_channel->ch_name : "any channel");
 }
@@ -407,36 +404,31 @@ autorec_entry_destroy(dvr_autorec_entry_t *dae, int delconf)
   free(dae);
 }
 
-/**
- *
- */
-void
-dvr_autorec_save(dvr_autorec_entry_t *dae)
-{
-  htsmsg_t *m = htsmsg_create_map();
-  char ubuf[UUID_HEX_SIZE]; 
-
-  lock_assert(&global_lock);
-
-  idnode_save(&dae->dae_id, m);
-  hts_settings_save(m, "dvr/autorec/%s", idnode_uuid_as_str(&dae->dae_id, ubuf));
-  htsmsg_destroy(m);
-}
-
 /* **************************************************************************
  * DVR Autorec Entry Class definition
  * **************************************************************************/
 
 static void
-dvr_autorec_entry_class_save(idnode_t *self)
+dvr_autorec_entry_class_changed(idnode_t *self)
 {
   dvr_autorec_entry_t *dae = (dvr_autorec_entry_t *)self;
-  dvr_autorec_save(dae);
+
   dvr_autorec_changed(dae, 1);
   dvr_autorec_completed(dae, 0);
   htsp_autorec_entry_update(dae);
 }
 
+static htsmsg_t *
+dvr_autorec_entry_class_save(idnode_t *self, char *filename, size_t fsize)
+{
+  dvr_autorec_entry_t *dae = (dvr_autorec_entry_t *)self;
+  htsmsg_t *m = htsmsg_create_map();
+  char ubuf[UUID_HEX_SIZE];
+  idnode_save(&dae->dae_id, m);
+  snprintf(filename, fsize, "dvr/autorec/%s", idnode_uuid_as_str(&dae->dae_id, ubuf));
+  return m;
+}
+
 static void
 dvr_autorec_entry_class_delete(idnode_t *self)
 {
@@ -981,6 +973,7 @@ const idclass_t dvr_autorec_entry_class = {
   .ic_class      = "dvrautorec",
   .ic_caption    = N_("DVR Auto-record entry"),
   .ic_event      = "dvrautorec",
+  .ic_changed    = dvr_autorec_entry_class_changed,
   .ic_save       = dvr_autorec_entry_class_save,
   .ic_get_title  = dvr_autorec_entry_class_get_title,
   .ic_delete     = dvr_autorec_entry_class_delete,
@@ -1409,7 +1402,7 @@ autorec_destroy_by_channel_tag(channel_tag_t *ct, int delconf)
     dae->dae_channel_tag = NULL;
     idnode_notify_changed(&dae->dae_id);
     if (delconf)
-      dvr_autorec_save(dae);
+      idnode_changed(&dae->dae_id);
   }
 }
 
@@ -1443,7 +1436,7 @@ autorec_destroy_by_config(dvr_config_t *kcfg, int delconf)
       LIST_INSERT_HEAD(&cfg->dvr_autorec_entries, dae, dae_config_link);
     dae->dae_config = cfg;
     if (delconf)
-      dvr_autorec_save(dae);
+      idnode_changed(&dae->dae_id);
   }
 }
 
index fcc62ac4fd276eb0e9539de42126bb00f6e078a4..eff44d30c7a61b6a57d42fd051e51f4c8febe87e 100644 (file)
@@ -74,7 +74,7 @@ dvr_config_find_by_name_default(const char *name)
   if (dvrdefaultconfig == NULL) {
     cfg = dvr_config_create("", NULL, NULL);
     assert(cfg);
-    dvr_config_save(cfg);
+    idnode_changed(&cfg->dvr_id);
     dvrdefaultconfig = cfg;
   }
 
@@ -508,38 +508,12 @@ dvr_config_delete(const char *name)
     tvhwarn("dvr", "Attempt to delete default config ignored");
 }
 
-/*
- *
- */
-void
-dvr_config_save(dvr_config_t *cfg)
-{
-  htsmsg_t *m = htsmsg_create_map();
-  char ubuf[UUID_HEX_SIZE];
-
-  lock_assert(&global_lock);
-
-  dvr_config_storage_check(cfg);
-  if (cfg->dvr_cleanup_threshold_free < 50)
-    cfg->dvr_cleanup_threshold_free = 50; // as checking is only periodically, lower is not save
-  if (cfg->dvr_removal_days != DVR_RET_FOREVER &&
-      cfg->dvr_removal_days > cfg->dvr_retention_days)
-    cfg->dvr_retention_days = DVR_RET_ONREMOVE;
-  if (cfg->dvr_removal_days > DVR_RET_FOREVER)
-    cfg->dvr_removal_days = DVR_RET_FOREVER;
-  if (cfg->dvr_retention_days > DVR_RET_FOREVER)
-    cfg->dvr_retention_days = DVR_RET_FOREVER;
-  idnode_save(&cfg->dvr_id, m);
-  hts_settings_save(m, "dvr/config/%s", idnode_uuid_as_str(&cfg->dvr_id, ubuf));
-  htsmsg_destroy(m);
-}
-
 /* **************************************************************************
  * DVR Config Class definition
  * **************************************************************************/
 
 static void
-dvr_config_class_save(idnode_t *self)
+dvr_config_class_changed(idnode_t *self)
 {
   dvr_config_t *cfg = (dvr_config_t *)self;
   if (dvr_config_is_default(cfg))
@@ -551,7 +525,27 @@ dvr_config_class_save(idnode_t *self)
   } else {
     dvr_update_pathname_from_booleans(cfg);
   }
-  dvr_config_save(cfg);
+  dvr_config_storage_check(cfg);
+  if (cfg->dvr_cleanup_threshold_free < 50)
+    cfg->dvr_cleanup_threshold_free = 50; // as checking is only periodically, lower is not save
+  if (cfg->dvr_removal_days != DVR_RET_FOREVER &&
+      cfg->dvr_removal_days > cfg->dvr_retention_days)
+    cfg->dvr_retention_days = DVR_RET_ONREMOVE;
+  if (cfg->dvr_removal_days > DVR_RET_FOREVER)
+    cfg->dvr_removal_days = DVR_RET_FOREVER;
+  if (cfg->dvr_retention_days > DVR_RET_FOREVER)
+    cfg->dvr_retention_days = DVR_RET_FOREVER;
+}
+
+static htsmsg_t *
+dvr_config_class_save(idnode_t *self, char *filename, size_t fsize)
+{
+  dvr_config_t *cfg = (dvr_config_t *)self;
+  htsmsg_t *m = htsmsg_create_map();
+  char ubuf[UUID_HEX_SIZE];
+  idnode_save(&cfg->dvr_id, m);
+  snprintf(filename, fsize, "dvr/config/%s", idnode_uuid_as_str(&cfg->dvr_id, ubuf));
+  return m;
 }
 
 static void
@@ -787,6 +781,7 @@ const idclass_t dvr_config_class = {
   .ic_class      = "dvrconfig",
   .ic_caption    = N_("DVR configuration profile"),
   .ic_event      = "dvrconfig",
+  .ic_changed    = dvr_config_class_changed,
   .ic_save       = dvr_config_class_save,
   .ic_get_title  = dvr_config_class_get_title,
   .ic_delete     = dvr_config_class_delete,
index 9a34c9a474356dcc5ce6393f429fbc4205cdc125..ab1b9e1ab283e484b8134875ad910108cd2ae91a 100644 (file)
@@ -134,7 +134,7 @@ dvr_entry_dont_rerecord(dvr_entry_t *de, int dont_rerecord)
   dont_rerecord = dont_rerecord ? 1 : 0;
   if (de->de_dont_rerecord ? 1 : 0 != dont_rerecord) {
     de->de_dont_rerecord = dont_rerecord;
-    dvr_entry_save(de);
+    idnode_changed(&de->de_id);
     idnode_notify_changed(&de->de_id);
     htsp_dvr_entry_update(de);
   }
@@ -162,9 +162,9 @@ dvr_entry_change_parent_child(dvr_entry_t *parent, dvr_entry_t *child, void *ori
     if (parent->de_child) {
       p = parent->de_child->de_parent;
       parent->de_child->de_parent = NULL;
-      if (save && p && p != origin) dvr_entry_save(p);
+      if (save && p && p != origin) idnode_changed(&p->de_id);
       parent->de_child = NULL;
-      if (save && origin != parent) dvr_entry_save(parent);
+      if (save && origin != parent) idnode_changed(&parent->de_id);
       return 1;
     }
     return 0;
@@ -173,9 +173,9 @@ dvr_entry_change_parent_child(dvr_entry_t *parent, dvr_entry_t *child, void *ori
     if (child->de_parent) {
       p = child->de_parent->de_child;
       child->de_parent->de_child = NULL;
-      if (save && p && p != origin) dvr_entry_save(p);
+      if (save && p && p != origin) idnode_changed(&p->de_id);
       child->de_parent = NULL;
-      if (save && origin != child) dvr_entry_save(child);
+      if (save && origin != child) idnode_changed(&child->de_id);
       return 1;
     }
     return 0;
@@ -183,17 +183,17 @@ dvr_entry_change_parent_child(dvr_entry_t *parent, dvr_entry_t *child, void *ori
   if (parent->de_child) {
     p = parent->de_child->de_parent;
     parent->de_child->de_parent = NULL;
-    if (save && p) dvr_entry_save(p);
+    if (save && p) idnode_changed(&p->de_id);
   }
   if (child->de_parent) {
     p = child->de_parent->de_child;
     child->de_parent->de_child = NULL;
-    if (save && p) dvr_entry_save(p);
+    if (save && p) idnode_changed(&p->de_id);
   }
   parent->de_child = child;
   child->de_parent = parent;
-  if (save && origin != parent) dvr_entry_save(parent);
-  if (save && origin != child) dvr_entry_save(child);
+  if (save && origin != parent) idnode_changed(&parent->de_id);
+  if (save && origin != child) idnode_changed(&child->de_id);
   return 1;
 }
 
@@ -410,7 +410,7 @@ dvr_entry_retention_timer(dvr_entry_t *de)
       return;
     }
     if (save)
-      dvr_entry_save(de);
+      idnode_changed(&de->de_id);
   }
 
   if (retention < DVR_RET_ONREMOVE) {
@@ -873,7 +873,7 @@ dvr_entry_create_(int enabled, const char *config_uuid, epg_broadcast_t *e,
          idnode_uuid_as_str(&de->de_id, ubuf),
         lang_str_get(de->de_title, NULL), DVR_CH_NAME(de), tbuf, creator ?: "");
 
-  dvr_entry_save(de);
+  idnode_changed(&de->de_id);
   return de;
 }
 
@@ -953,7 +953,7 @@ dvr_entry_clone(dvr_entry_t *de)
     } else {
       dvr_entry_set_timer(n);
     }
-    dvr_entry_save(n);
+    idnode_changed(&n->de_id);
   }
 
   return n == NULL ? de : n;
@@ -1057,7 +1057,7 @@ not_so_good:
   } else {
     /* we have already queued similar recordings, mark as resolved */
     de->de_dont_rerecord = 1;
-    dvr_entry_save(de);
+    idnode_changed(&de->de_id);
   }
 
   return 0;
@@ -1389,45 +1389,10 @@ dvr_entry_destroy_by_config(dvr_config_t *cfg, int delconf)
     if (def)
       LIST_INSERT_HEAD(&def->dvr_entries, de, de_config_link);
     if (delconf)
-      dvr_entry_save(de);
-  }
-}
-
-/**
- *
- */
-void
-dvr_entry_save(dvr_entry_t *de)
-{
-  htsmsg_t *m = htsmsg_create_map(), *e, *l, *c, *info;
-  htsmsg_field_t *f;
-  char ubuf[UUID_HEX_SIZE];
-  const char *filename;
-
-  lock_assert(&global_lock);
-
-  idnode_save(&de->de_id, m);
-  if (de->de_files) {
-    l = htsmsg_create_list();
-    HTSMSG_FOREACH(f, de->de_files)
-      if ((e = htsmsg_field_get_map(f)) != NULL) {
-        filename = htsmsg_get_str(e, "filename");
-        info = htsmsg_get_list(e, "info");
-        if (filename) {
-          c = htsmsg_create_map();
-          htsmsg_add_str(c, "filename", filename);
-          if (info)
-            htsmsg_add_msg(c, "info", htsmsg_copy(info));
-          htsmsg_add_msg(l, NULL, c);
-        }
-      }
-    htsmsg_add_msg(m, "files", l);
+      idnode_changed(&de->de_id);
   }
-  hts_settings_save(m, "dvr/log/%s", idnode_uuid_as_str(&de->de_id, ubuf));
-  htsmsg_destroy(m);
 }
 
-
 /**
  *
  */
@@ -1767,7 +1732,7 @@ dvr_event_removed(epg_broadcast_t *e)
     if (de->de_bcast != e)
       continue;
     dvr_entry_assign_broadcast(de, NULL);
-    dvr_entry_save(de);
+    idnode_changed(&de->de_id);
   }
 }
 
@@ -1921,7 +1886,7 @@ dvr_stop_recording(dvr_entry_t *de, int stopcode, int saveconf, int clone)
     return;
 
   if (saveconf)
-    dvr_entry_save(de);
+    idnode_changed(&de->de_id);
 
   dvr_entry_retention_timer(de);
 
@@ -2039,16 +2004,44 @@ dvr_entry_purge(dvr_entry_t *de, int delconf)
  * **************************************************************************/
 
 static void
-dvr_entry_class_save(idnode_t *self)
+dvr_entry_class_changed(idnode_t *self)
 {
   dvr_entry_t *de = (dvr_entry_t *)self;
-  dvr_entry_save(de);
   if (dvr_entry_is_valid(de))
     dvr_entry_set_timer(de);
-
   htsp_dvr_entry_update(de);
 }
 
+static htsmsg_t *
+dvr_entry_class_save(idnode_t *self, char *filename, size_t fsize)
+{
+  dvr_entry_t *de = (dvr_entry_t *)self;
+  htsmsg_t *m = htsmsg_create_map(), *e, *l, *c, *info;
+  htsmsg_field_t *f;
+  char ubuf[UUID_HEX_SIZE];
+  const char *filename2;
+
+  idnode_save(&de->de_id, m);
+  if (de->de_files) {
+    l = htsmsg_create_list();
+    HTSMSG_FOREACH(f, de->de_files)
+      if ((e = htsmsg_field_get_map(f)) != NULL) {
+        filename2 = htsmsg_get_str(e, "filename");
+        info = htsmsg_get_list(e, "info");
+        if (filename2) {
+          c = htsmsg_create_map();
+          htsmsg_add_str(c, "filename", filename2);
+          if (info)
+            htsmsg_add_msg(c, "info", htsmsg_copy(info));
+          htsmsg_add_msg(l, NULL, c);
+        }
+      }
+    htsmsg_add_msg(m, "files", l);
+  }
+  snprintf(filename, fsize, "dvr/log/%s", idnode_uuid_as_str(&de->de_id, ubuf));
+  return m;
+}
+
 static void
 dvr_entry_class_delete(idnode_t *self)
 {
@@ -2811,6 +2804,7 @@ const idclass_t dvr_entry_class = {
   .ic_class     = "dvrentry",
   .ic_caption   = N_("DVR entry"),
   .ic_event     = "dvrentry",
+  .ic_changed   = dvr_entry_class_changed,
   .ic_save      = dvr_entry_class_save,
   .ic_get_title = dvr_entry_class_get_title,
   .ic_delete    = dvr_entry_class_delete,
index 75ceea5fce11f465674d36ebb0afb820732f08db..0a4d87ce72cd32ed4dde78609f7b08c1ed21b699 100644 (file)
@@ -261,7 +261,7 @@ _dvr_inotify_moved
     if (to) {
       snprintf(path, sizeof(path), "%s/%s", die->path, to);
       htsmsg_set_str(m, "filename", path);
-      dvr_entry_save(de);
+      idnode_changed(&de->de_id);
     } else {
       htsmsg_field_destroy(de->de_files, f);
       if (htsmsg_is_empty(de->de_files))
index bf140a02c9a8ba9ae404fdab703cd1f0180aa898..56fb6423225fdda1a5e26ec8805d4cb998fc02a0 100644 (file)
@@ -77,7 +77,7 @@ dvr_timerec_purge_spawn(dvr_timerec_entry_t *dte, int delconf)
       if (de->de_sched_state == DVR_SCHEDULED)
         dvr_entry_cancel(de, 0);
       else
-        dvr_entry_save(de);
+        idnode_changed(&de->de_id);
     }
   }
 }
@@ -209,10 +209,8 @@ dvr_timerec_create_htsp(htsmsg_t *conf)
   dte = dvr_timerec_create(NULL, conf);
   htsmsg_destroy(conf);
 
-  if (dte) {
-    dvr_timerec_save(dte);
-    dvr_timerec_check(dte);
-  }
+  if (dte)
+    idnode_changed(&dte->dte_id);
 
   return dte;
 }
@@ -221,9 +219,7 @@ void
 dvr_timerec_update_htsp (dvr_timerec_entry_t *dte, htsmsg_t *conf)
 {
   idnode_update(&dte->dte_id, conf);
-  dvr_timerec_save(dte);
-  dvr_timerec_check(dte);
-  htsp_timerec_entry_update(dte);
+  idnode_changed(&dte->dte_id);
   tvhlog(LOG_INFO, "timerec", "\"%s\" on \"%s\": Updated", dte->dte_title ? dte->dte_title : "",
       (dte->dte_channel && dte->dte_channel->ch_name) ? dte->dte_channel->ch_name : "any channel");
 }
@@ -262,35 +258,29 @@ timerec_entry_destroy(dvr_timerec_entry_t *dte, int delconf)
   free(dte);
 }
 
-/**
- *
- */
-void
-dvr_timerec_save(dvr_timerec_entry_t *dte)
-{
-  htsmsg_t *m = htsmsg_create_map();
-  char ubuf[UUID_HEX_SIZE];
-
-  lock_assert(&global_lock);
-
-  idnode_save(&dte->dte_id, m);
-  hts_settings_save(m, "dvr/timerec/%s", idnode_uuid_as_str(&dte->dte_id, ubuf));
-  htsmsg_destroy(m);
-}
-
 /* **************************************************************************
  * DVR Autorec Entry Class definition
  * **************************************************************************/
 
 static void
-dvr_timerec_entry_class_save(idnode_t *self)
+dvr_timerec_entry_class_changed(idnode_t *self)
 {
   dvr_timerec_entry_t *dte = (dvr_timerec_entry_t *)self;
-  dvr_timerec_save(dte);
   dvr_timerec_check(dte);
   htsp_timerec_entry_update(dte);
 }
 
+static htsmsg_t *
+dvr_timerec_entry_class_save(idnode_t *self, char *filename, size_t fsize)
+{
+  dvr_timerec_entry_t *dte = (dvr_timerec_entry_t *)self;
+  htsmsg_t *m = htsmsg_create_map();
+  char ubuf[UUID_HEX_SIZE];
+  idnode_save(&dte->dte_id, m);
+  snprintf(filename, fsize, "dvr/timerec/%s", idnode_uuid_as_str(&dte->dte_id, ubuf));
+  return m;
+}
+
 static void
 dvr_timerec_entry_class_delete(idnode_t *self)
 {
@@ -527,6 +517,7 @@ const idclass_t dvr_timerec_entry_class = {
   .ic_class      = "dvrtimerec",
   .ic_caption    = N_("DVR time record entry"),
   .ic_event      = "dvrtimerec",
+  .ic_changed    = dvr_timerec_entry_class_changed,
   .ic_save       = dvr_timerec_entry_class_save,
   .ic_get_title  = dvr_timerec_entry_class_get_title,
   .ic_delete     = dvr_timerec_entry_class_delete,
@@ -775,7 +766,7 @@ timerec_destroy_by_config(dvr_config_t *kcfg, int delconf)
       LIST_INSERT_HEAD(&cfg->dvr_timerec_entries, dte, dte_config_link);
     dte->dte_config = cfg;
     if (delconf)
-      dvr_timerec_save(dte);
+      idnode_changed(&dte->dte_id);
   }
 }
 
index ac323fb999044f4fd647bdb6148533ef3bdbf0e8..afe03f15752981c1d81daa341da6a0cebc28e845 100644 (file)
@@ -267,7 +267,7 @@ dvr_disk_space_cleanup(dvr_config_t *cfg)
         dvr_entry_destroy(oldest, 1); // also delete database entry
       } else {
         if (dvr_entry_delete(oldest)) // delete actual file
-          dvr_entry_save(oldest);
+          idnode_changed(&oldest->de_id);
       }
     } else {
       tvhlog(LOG_WARNING, "dvr", "%s \"until space needed\" recordings found for config \"%s\", you are running out of disk space very soon!",
index c2aa44cc81d90eeff5f7c6d52febd7d195657ea3..8474c6b1b3218de3800e388fa09d60d463b3ebd2 100644 (file)
@@ -185,14 +185,23 @@ static void _epggrab_load ( void )
   xmltv_load();
 }
 
-void epggrab_save ( void )
-{
-  epggrab_module_t *mod;
-  htsmsg_t *m, *a;
+/* **************************************************************************
+ * Class
+ * *************************************************************************/
 
+static void
+epggrab_class_changed(idnode_t *self)
+{
   /* Register */
   epggrab_confver++;
   pthread_cond_signal(&epggrab_cond);
+}
+
+static htsmsg_t *
+epggrab_class_save(idnode_t *self, char *filename, size_t fsize)
+{
+  epggrab_module_t *mod;
+  htsmsg_t *m, *a;
 
   /* Save */
   m = htsmsg_create_map();
@@ -205,17 +214,8 @@ void epggrab_save ( void )
     htsmsg_add_msg(a, mod->id, m);
   }
   htsmsg_add_msg(m, "modules", a);
-  hts_settings_save(m, "epggrab/config");
-  htsmsg_destroy(m);
-}
-
-/* **************************************************************************
- * Class
- * *************************************************************************/
-
-static void epggrab_class_save(idnode_t *self)
-{
-  epggrab_save();
+  snprintf(filename, fsize, "epggrab/config");
+  return m;
 }
 
 epggrab_conf_t epggrab_conf = {
@@ -243,6 +243,7 @@ const idclass_t epggrab_class = {
   .ic_caption    = N_("EPG grabber configuration"),
   .ic_event      = "epggrab",
   .ic_perm_def   = ACCESS_ADMIN,
+  .ic_changed    = epggrab_class_changed,
   .ic_save       = epggrab_class_save,
   .ic_groups     = (const property_group_t[]) {
       {
index 17bbc2065b2219d4e67f1c206a2b949fe717abfb..73e96958898c23d156f1d50821230467d68e6b9d 100644 (file)
@@ -310,7 +310,6 @@ void epggrab_ota_trigger          ( int secs );
  */
 void epggrab_init                 ( void );
 void epggrab_done                 ( void );
-void epggrab_save                 ( void );
 void epggrab_ota_init             ( void );
 void epggrab_ota_post             ( void );
 void epggrab_ota_shutdown         ( void );
index 0396319c60b45b62d37c8e292e8d667a72c2b51f..865773f9c6262b40cce8925c8ede87605b5764f4 100644 (file)
@@ -171,10 +171,10 @@ epggrab_channel_link ( epggrab_channel_t *ec, channel_t *ch, void *origin )
   if (ec->icon && epggrab_conf.channel_reicon)
     save |= channel_set_icon(ch, ec->icon);
   if (save)
-    channel_save(ch);
+    idnode_changed(&ch->ch_id);
 
   if (origin == NULL)
-    epggrab_channel_save(ec);
+    idnode_changed(&ec->idnode);
   return 1;
 }
 
@@ -198,7 +198,7 @@ int epggrab_channel_set_name ( epggrab_channel_t *ec, const char *name )
       LIST_FOREACH(ilm, &ec->channels, ilm_in1_link) {
         ch = (channel_t *)ilm->ilm_in2;
         if (channel_set_name(ch, name))
-          channel_save(ch);
+          idnode_changed(&ch->ch_id);
       }
     }
     save = 1;
@@ -224,7 +224,7 @@ int epggrab_channel_set_icon ( epggrab_channel_t *ec, const char *icon )
       LIST_FOREACH(ilm, &ec->channels, ilm_in1_link) {
         ch = (channel_t *)ilm->ilm_in2;
         if (channel_set_icon(ch, icon))
-          channel_save(ch);
+          idnode_changed(&ch->ch_id);
       }
     }
     save = 1;
@@ -250,7 +250,7 @@ int epggrab_channel_set_number ( epggrab_channel_t *ec, int major, int minor )
         if (channel_set_number(ch,
                                lcn / CHANNEL_SPLIT,
                                lcn % CHANNEL_SPLIT))
-          channel_save(ch);
+          idnode_changed(&ch->ch_id);
       }
     }
     save = 1;
@@ -303,7 +303,7 @@ void epggrab_channel_updated ( epggrab_channel_t *ec )
     epggrab_channel_autolink(ec);
 
   /* Save */
-  epggrab_channel_save(ec);
+  idnode_changed(&ec->idnode);
 }
 
 /* ID comparison */
@@ -387,16 +387,6 @@ epggrab_channel_t *epggrab_channel_find
   return ec;
 }
 
-void epggrab_channel_save( epggrab_channel_t *ec )
-{
-  htsmsg_t *m = htsmsg_create_map();
-  char ubuf[UUID_HEX_SIZE];
-  idnode_save(&ec->idnode, m);
-  hts_settings_save(m, "epggrab/%s/channels/%s",
-                    ec->mod->saveid, idnode_uuid_as_str(&ec->idnode, ubuf));
-  htsmsg_destroy(m);
-}
-
 void epggrab_channel_destroy( epggrab_channel_t *ec, int delconf, int rb_remove )
 {
   char ubuf[UUID_HEX_SIZE];
@@ -538,10 +528,16 @@ epggrab_channel_class_get_title(idnode_t *self, const char *lang)
   return prop_sbuf;
 }
 
-static void
-epggrab_channel_class_save(idnode_t *self)
+static htsmsg_t *
+epggrab_channel_class_save(idnode_t *self, char *filename, size_t fsize)
 {
-  epggrab_channel_save((epggrab_channel_t *)self);
+  epggrab_channel_t *ec = (epggrab_channel_t *)self;
+  htsmsg_t *m = htsmsg_create_map();
+  char ubuf[UUID_HEX_SIZE];
+  idnode_save(&ec->idnode, m);
+  snprintf(filename, fsize, "epggrab/%s/channels/%s",
+           ec->mod->saveid, idnode_uuid_as_str(&ec->idnode, ubuf));
+  return m;
 }
 
 static void
index 3f607d58c5498421e154d018d967232a6eb8b486..833157018da81aa7196561c471d14cffc48a13ec 100644 (file)
@@ -84,11 +84,12 @@ static const char *epggrab_mod_class_title(idnode_t *self, const char *lang)
   return prop_sbuf;
 }
 
-static void epggrab_mod_class_save(idnode_t *self)
+static void
+epggrab_mod_class_changed(idnode_t *self)
 {
   epggrab_module_t *mod = (epggrab_module_t *)self;
   epggrab_activate_module(mod, mod->enabled);
-  epggrab_save();
+  idnode_changed(&epggrab_conf.idnode);
 }
 
 static const void *epggrab_mod_class_type_get(void *o)
@@ -109,7 +110,7 @@ const idclass_t epggrab_mod_class = {
   .ic_event      = "epggrab_mod",
   .ic_perm_def   = ACCESS_ADMIN,
   .ic_get_title  = epggrab_mod_class_title,
-  .ic_save       = epggrab_mod_class_save,
+  .ic_changed    = epggrab_mod_class_changed,
   .ic_groups     = (const property_group_t[]) {
      {
         .name   = N_("Settings"),
index 7f9031ed41550663e3bb0e3a04621cf5d8ce37a3..6273781a11e3b422c7565b6dcadf402bf677440d 100644 (file)
@@ -26,8 +26,6 @@
 
 struct esfilter_entry_queue esfilters[ESF_CLASS_LAST + 1];
 
-static void esfilter_class_save(idnode_t *self);
-
 /*
  * Class masks
  */
@@ -128,7 +126,7 @@ esfilter_reindex(esfilter_class_t cls)
   TAILQ_FOREACH(esf, &esfilters[cls], esf_link)
     if (esf->esf_save) {
       esf->esf_save = 0;
-      esfilter_class_save((idnode_t *)esf);
+      idnode_changed(&esf->esf_id);
     }
 }
 
@@ -185,7 +183,7 @@ esfilter_create
   if (!conf)
     esfilter_reindex(esf->esf_class);
   if (save)
-    esfilter_class_save((idnode_t *)esf);
+    idnode_changed(&esf->esf_id);
   return esf;
 }
 
@@ -205,14 +203,14 @@ esfilter_delete(esfilter_t *esf, int delconf)
  * Class functions
  */
 
-static void
-esfilter_class_save(idnode_t *self)
+static htsmsg_t *
+esfilter_class_save(idnode_t *self, char *filename, size_t fsize)
 {
   htsmsg_t *c = htsmsg_create_map();
   char ubuf[UUID_HEX_SIZE];
   idnode_save(self, c);
-  hts_settings_save(c, "esfilter/%s", idnode_uuid_as_str(self, ubuf));
-  htsmsg_destroy(c);
+  snprintf(filename, fsize, "esfilter/%s", idnode_uuid_as_str(self, ubuf));
+  return c;
 }
 
 static const char *
index 0fe0eaddf6524e78f546978c807fb0d351c3932b..972ab2f57f968f9a89eeb9f0be7f141705b31d8f 100644 (file)
@@ -161,6 +161,11 @@ idnode_unlink(idnode_t *in)
   RB_REMOVE(in->in_domain, in, in_domain_link);
   tvhtrace("idnode", "unlink node %s", idnode_uuid_as_str(in, ubuf));
   idnode_notify(in, "delete");
+
+  if (in->in_save) {
+    TAILQ_REMOVE(&idnodes_save, in->in_save, ise_link);
+    in->in_save = NULL;
+  }
 }
 
 /**
@@ -1067,18 +1072,30 @@ idnode_class_write_values
 }
 
 static void
-idnode_savefn ( idnode_t *self )
+idnode_changedfn ( idnode_t *self )
 {
   const idclass_t *idc = self->in_class;
   while (idc) {
-    if (idc->ic_save) {
-      idc->ic_save(self);
+    if (idc->ic_changed) {
+      idc->ic_changed(self);
       break;
     }
     idc = idc->ic_super;
   }
 }
 
+static htsmsg_t *
+idnode_savefn ( idnode_t *self, char *filename, size_t fsize )
+{
+  const idclass_t *idc = self->in_class;
+  while (idc) {
+    if (idc->ic_save)
+      return idc->ic_save(self, filename, fsize);
+    idc = idc->ic_super;
+  }
+  return NULL;
+}
+
 static void
 idnode_save_queue ( idnode_t *self )
 {
@@ -1100,8 +1117,10 @@ idnode_write0 ( idnode_t *self, htsmsg_t *c, int optmask, int dosave )
   int save = 0;
   const idclass_t *idc = self->in_class;
   save = idnode_class_write_values(self, idc, c, optmask);
-  if ((idc->ic_flags & IDCLASS_ALWAYS_SAVE) != 0 || (save && dosave))
+  if ((idc->ic_flags & IDCLASS_ALWAYS_SAVE) != 0 || (save && dosave)) {
+    idnode_changedfn(self);
     idnode_save_queue(self);
+  }
   if (dosave)
     idnode_notify_changed(self);
   // Note: always output event if "dosave", reason is that UI updates on
@@ -1644,6 +1663,8 @@ static void *
 save_thread ( void *aux )
 {
   idnode_save_t *ise;
+  htsmsg_t *m;
+  char filename[PATH_MAX];
 
   tvhtread_renice(15);
 
@@ -1654,17 +1675,29 @@ save_thread ( void *aux )
       pthread_cond_wait(&save_cond, &global_lock);
       continue;
     }
-    idnode_savefn(ise->ise_node);
+    m = idnode_savefn(ise->ise_node, filename, sizeof(filename));
     ise->ise_node->in_save = NULL;
     TAILQ_REMOVE(&idnodes_save, ise, ise_link);
+    pthread_mutex_unlock(&global_lock);
     free(ise);
+    if (m) {
+      hts_settings_save(m, "%s", filename);
+      htsmsg_destroy(m);
+    }
+    pthread_mutex_lock(&global_lock);
   }
 
   while ((ise = TAILQ_FIRST(&idnodes_save)) != NULL) {
-    idnode_savefn(ise->ise_node);
+    m = idnode_savefn(ise->ise_node, filename, sizeof(filename));
     ise->ise_node->in_save = NULL;
     TAILQ_REMOVE(&idnodes_save, ise, ise_link);
+    pthread_mutex_unlock(&global_lock);
     free(ise);
+    if (m) {
+      hts_settings_save(m, "%s", filename);
+      htsmsg_destroy(m);
+    }
+    pthread_mutex_lock(&global_lock);
   }
 
   pthread_mutex_unlock(&global_lock);
index 28fe3a892c4ba837e2a782d13eb61207bb1c5582..8a032d852bcf3b59b43f8b0a2a7fc4d680564879 100644 (file)
@@ -73,7 +73,8 @@ struct idclass {
   /* Callbacks */
   idnode_set_t   *(*ic_get_childs) (idnode_t *self);
   const char     *(*ic_get_title)  (idnode_t *self, const char *lang);
-  void            (*ic_save)       (idnode_t *self);
+  void            (*ic_changed)    (idnode_t *self);
+  htsmsg_t       *(*ic_save)       (idnode_t *self, char *filename, size_t fsize);
   void            (*ic_delete)     (idnode_t *self);
   void            (*ic_moveup)     (idnode_t *self);
   void            (*ic_movedown)   (idnode_t *self);
index 2ed82b6dd3c8c898d32b2e3e0241cad35d6f005d..4ad03b8f595e343377b4270a3a0acc1bb1c3a5f8 100644 (file)
@@ -69,7 +69,7 @@ struct imagecache_config imagecache_conf = {
   .idnode.in_class = &imagecache_class,
 };
 
-static void imagecache_save(idnode_t *self);
+static htsmsg_t *imagecache_save(idnode_t *self, char *filename, size_t fsize);
 
 const idclass_t imagecache_class = {
   .ic_snode      = (idnode_t *)&imagecache_conf,
@@ -507,14 +507,14 @@ imagecache_done ( void )
 /*
  * Save
  */
-static void
-imagecache_save ( idnode_t *self )
+static htsmsg_t *
+imagecache_save ( idnode_t *self, char *filename, size_t fsize )
 {
   htsmsg_t *c = htsmsg_create_map();
   idnode_save(&imagecache_conf.idnode, c);
-  hts_settings_save(c, "imagecache/config");
-  htsmsg_destroy(c);
+  snprintf(filename, fsize, "imagecache/config");
   pthread_cond_broadcast(&imagecache_cond);
+  return c;
 }
 
 /*
index 663b9a6dd06fab411cfefbd430627aeb07152c73..f644e39131071b348e5dc8a0bd01f24de4bd3879 100644 (file)
@@ -327,7 +327,7 @@ struct mpegts_network
    */
   void              (*mn_delete)       (mpegts_network_t*, int delconf);
   void              (*mn_display_name) (mpegts_network_t*, char *buf, size_t len);
-  void              (*mn_config_save)  (mpegts_network_t*);
+  htsmsg_t *        (*mn_config_save)  (mpegts_network_t*, char *filename, size_t fsize);
   mpegts_mux_t*     (*mn_create_mux)
     (mpegts_network_t*, void *origin, uint16_t onid, uint16_t tsid,
      void *conf, int force);
@@ -487,7 +487,7 @@ struct mpegts_mux
    */
 
   void (*mm_delete)           (mpegts_mux_t *mm, int delconf);
-  void (*mm_config_save)      (mpegts_mux_t *mm);
+  htsmsg_t *(*mm_config_save) (mpegts_mux_t *mm, char *filename, size_t fsize);
   void (*mm_display_name)     (mpegts_mux_t*, char *buf, size_t len);
   int  (*mm_is_enabled)       (mpegts_mux_t *mm);
   void (*mm_stop)             (mpegts_mux_t *mm, int force, int reason);
index cfa198187d7d4e204035a3184fb238221a51b327..d8b1f7e31775592016f7cd95497051ff187fc36a 100644 (file)
@@ -461,7 +461,7 @@ dvb_desc_service_list
       if (bi)
         dvb_bat_find_service(bi, s, 0, UINT_MAX);
       if (save)
-        s->s_config_save((service_t*)s);
+        idnode_changed(&s->s_id);
     }
   }
   return 0;
@@ -493,7 +493,7 @@ dvb_desc_local_channel
                     s->s_dvb_channel_num != lcn) {
           s->s_dvb_channel_dtag = dtag;
           s->s_dvb_channel_num = lcn;
-          s->s_config_save((service_t*)s);
+          idnode_changed(&s->s_id);
           service_refresh_channel((service_t*)s);
         }
       }
@@ -1398,9 +1398,9 @@ dvb_nit_callback
     tvhdebug(mt->mt_name, "network %04X (%d) [%s]", nbid, nbid, name);
     save |= mpegts_network_set_network_name(mn, name);
     if (save)
-      mn->mn_config_save(mn);
+      idnode_changed(&mn->mn_id);
     if (mpegts_mux_set_network_name(mm, name))
-      mm->mm_config_save(mm);
+      idnode_changed(&mm->mm_id);
   }
 
   /* Transport length */
@@ -1734,7 +1734,7 @@ atsc_vct_callback
 
         /* Save */
         if (save)
-          s->s_config_save((service_t*)s);
+          idnode_changed(&s->s_id);
      }
 
     /* Move on */
index 14b3ba64b9e2de3113e6387e227fcd88db31ee1a..99895584057fccb93c459e3e908cf4ab4ee340f0 100644 (file)
@@ -123,8 +123,10 @@ dvb_fastscan_create(htsmsg_t *e)
   if (bq == NULL)
     goto fail;
   bq->bq_shield = 1;
-  if (bq->bq_saveflag)
-    bouquet_save(bq, 1);
+  if (bq->bq_saveflag) {
+    bq->bq_saveflag = 0;
+    idnode_changed(&bq->bq_id);
+  }
 
   fs = RB_INSERT_SORTED(&fastscan_rb, fastscan_rb_skel, link, _fs_cmp);
   if (!fs) {
index 05882a8923034536857ed8607426e2a2a2f78b4c..9b47da8ee6acd8f5419097ae351d0472b2b2b294 100644 (file)
@@ -899,15 +899,15 @@ iptv_network_mux_class ( mpegts_network_t *mm )
   return &iptv_mux_class;
 }
 
-static void
-iptv_network_config_save ( mpegts_network_t *mn )
+static htsmsg_t *
+iptv_network_config_save ( mpegts_network_t *mn, char *filename, size_t fsize )
 {
   htsmsg_t *c = htsmsg_create_map();
   char ubuf[UUID_HEX_SIZE];
   idnode_save(&mn->mn_id, c);
-  hts_settings_save(c, "input/iptv/networks/%s/config",
-                    idnode_uuid_as_str(&mn->mn_id, ubuf));
-  htsmsg_destroy(c);
+  snprintf(filename, fsize, "input/iptv/networks/%s/config",
+           idnode_uuid_as_str(&mn->mn_id, ubuf));
+  return c;
 }
 
 iptv_network_t *
index 8378f27abfb33119361ee0108c0d538a05b48258..2a4b80bf2714eade1b15e88f7fb1c81a29a4ef93 100644 (file)
@@ -277,7 +277,7 @@ skip_url:
   htsmsg_destroy(conf);
 
   if (im) {
-    im->mm_config_save((mpegts_mux_t *)im);
+    idnode_changed(&im->mm_id);
     (*total)++;
     (*count)++;
   }
index d6e83c3a02b3657a3b89f2ab6b32a59a7889e7db..94ab7315e3a4adeb1d1054af5d542f92db0a98c2 100644 (file)
@@ -261,17 +261,17 @@ const idclass_t iptv_mux_class =
   }
 };
 
-static void
-iptv_mux_config_save ( mpegts_mux_t *mm )
+static htsmsg_t *
+iptv_mux_config_save ( mpegts_mux_t *mm, char *filename, size_t fsize )
 {
   char ubuf1[UUID_HEX_SIZE];
   char ubuf2[UUID_HEX_SIZE];
   htsmsg_t *c = htsmsg_create_map();
   mpegts_mux_save(mm, c);
-  hts_settings_save(c, "input/iptv/networks/%s/muxes/%s/config",
-                    idnode_uuid_as_str(&mm->mm_network->mn_id, ubuf1),
-                    idnode_uuid_as_str(&mm->mm_id, ubuf2));
-  htsmsg_destroy(c);
+  snprintf(filename, fsize, "input/iptv/networks/%s/muxes/%s/config",
+           idnode_uuid_as_str(&mm->mm_network->mn_id, ubuf1),
+           idnode_uuid_as_str(&mm->mm_id, ubuf2));
+  return c;
 }
 
 static void
index 54a80c83263477da782db72a75668a26897a517d..5b5cc40b02082f9dea2dc8b4122d737922999051 100644 (file)
@@ -22,8 +22,8 @@
 
 extern const idclass_t mpegts_service_class;
 
-static void
-iptv_service_config_save ( service_t *s )
+static htsmsg_t *
+iptv_service_config_save ( service_t *s, char *filename, size_t fsize )
 {
   mpegts_mux_t     *mm = ((mpegts_service_t *)s)->s_dvb_mux;
   htsmsg_t         *c  = htsmsg_create_map();
@@ -32,11 +32,11 @@ iptv_service_config_save ( service_t *s )
   char ubuf2[UUID_HEX_SIZE];
 
   service_save(s, c);
-  hts_settings_save(c, "input/iptv/networks/%s/muxes/%s/services/%s",
-                    idnode_uuid_as_str(&mm->mm_network->mn_id, ubuf0),
-                    idnode_uuid_as_str(&mm->mm_id, ubuf1),
-                    idnode_uuid_as_str(&s->s_id, ubuf2));
-  htsmsg_destroy(c);
+  snprintf(filename, fsize, "input/iptv/networks/%s/muxes/%s/services/%s",
+           idnode_uuid_as_str(&mm->mm_network->mn_id, ubuf0),
+           idnode_uuid_as_str(&mm->mm_id, ubuf1),
+           idnode_uuid_as_str(&s->s_id, ubuf2));
+  return c;
 }
 
 static void
index b8e6fe46472a0c8be1af3bb706ac1a5dcedf49f6..4988c55b91898c2de8f8a37715c5d8418897381d 100644 (file)
  * DVB Adapter
  * **************************************************************************/
 
-static void
-linuxdvb_adapter_class_save ( idnode_t *in )
+static htsmsg_t *
+linuxdvb_adapter_class_save ( idnode_t *in, char *filename, size_t fsize )
 {
   linuxdvb_adapter_t *la = (linuxdvb_adapter_t*)in;
-  linuxdvb_adapter_save(la);
+  htsmsg_t *m, *l;
+  linuxdvb_frontend_t *lfe;
+#if ENABLE_LINUXDVB_CA
+  linuxdvb_ca_t *lca;
+#endif
+  char ubuf[UUID_HEX_SIZE];
+
+  m = htsmsg_create_map();
+  idnode_save(&la->th_id, m);
+
+  /* Frontends */
+  l = htsmsg_create_map();
+  LIST_FOREACH(lfe, &la->la_frontends, lfe_link)
+    linuxdvb_frontend_save(lfe, l);
+  htsmsg_add_msg(m, "frontends", l);
+
+  /* CAs */
+#if ENABLE_LINUXDVB_CA
+  l = htsmsg_create_map();
+  LIST_FOREACH(lca, &la->la_ca_devices, lca_link)
+    linuxdvb_ca_save(lca, l);
+  htsmsg_add_msg(m, "ca_devices", l);
+#endif
+
+  /* Save */
+  snprintf(filename, fsize, "input/linuxdvb/adapters/%s",
+           idnode_uuid_as_str(&la->th_id, ubuf));
+  return m;
 }
 
 static idnode_set_t *
@@ -98,42 +125,6 @@ const idclass_t linuxdvb_adapter_class =
   }
 };
 
-/*
- * Save data
- */
-void
-linuxdvb_adapter_save ( linuxdvb_adapter_t *la )
-{
-  htsmsg_t *m, *l;
-  linuxdvb_frontend_t *lfe;
-#if ENABLE_LINUXDVB_CA
-  linuxdvb_ca_t *lca;
-#endif
-  char ubuf[UUID_HEX_SIZE];
-
-  m = htsmsg_create_map();
-  idnode_save(&la->th_id, m);
-
-  /* Frontends */
-  l = htsmsg_create_map();
-  LIST_FOREACH(lfe, &la->la_frontends, lfe_link)
-    linuxdvb_frontend_save(lfe, l);
-  htsmsg_add_msg(m, "frontends", l);
-
-  /* CAs */
-#if ENABLE_LINUXDVB_CA
-  l = htsmsg_create_map();
-  LIST_FOREACH(lca, &la->la_ca_devices, lca_link)
-    linuxdvb_ca_save(lca, l);
-  htsmsg_add_msg(m, "ca_devices", l);
-#endif
-
-  /* Save */
-  hts_settings_save(m, "input/linuxdvb/adapters/%s",
-                    idnode_uuid_as_str(&la->th_id, ubuf));
-  htsmsg_destroy(m);
-}
-
 /*
  * Check if enabled
  */
@@ -488,7 +479,7 @@ linuxdvb_adapter_add ( const char *path )
 
   /* Save configuration */
   if (save && la)
-    linuxdvb_adapter_save(la);
+    linuxdvb_adapter_changed(la);
 }
 
 static void
index adcc8796a73526c6347ec402a7b8c1850506077b..517513f68450ec9d73cd32dad621189430b25efb 100644 (file)
@@ -115,10 +115,10 @@ ciplus13_app_ai_data_rate_info(linuxdvb_ca_t *lca, ciplus13_data_rate_t rate)
 }
 
 static void
-linuxdvb_ca_class_save ( idnode_t *in )
+linuxdvb_ca_class_changed ( idnode_t *in )
 {
   linuxdvb_adapter_t *la = ((linuxdvb_ca_t*)in)->lca_adapter;
-  linuxdvb_adapter_save(la);
+  linuxdvb_adapter_changed(la);
 }
 
 static void
@@ -179,7 +179,7 @@ const idclass_t linuxdvb_ca_class =
 {
   .ic_class      = "linuxdvb_ca",
   .ic_caption    = N_("Linux DVB CA"),
-  .ic_save       = linuxdvb_ca_class_save,
+  .ic_changed    = linuxdvb_ca_class_changed,
   .ic_get_title  = linuxdvb_ca_class_get_title,
   .ic_properties = (const property_t[]) {
     {
index 3303e8751eda02a241062a53866d834b5313cc60..805c52d4df8ccf04bab72a4295efd4f329684460 100644 (file)
@@ -45,10 +45,10 @@ linuxdvb_frontend_input_thread ( void *aux );
  * *************************************************************************/
 
 static void
-linuxdvb_frontend_class_save ( idnode_t *in )
+linuxdvb_frontend_class_changed ( idnode_t *in )
 {
   linuxdvb_adapter_t *la = ((linuxdvb_frontend_t*)in)->lfe_adapter;
-  linuxdvb_adapter_save(la);
+  linuxdvb_adapter_changed(la);
 }
 
 const idclass_t linuxdvb_frontend_class =
@@ -56,7 +56,7 @@ const idclass_t linuxdvb_frontend_class =
   .ic_super      = &mpegts_input_class,
   .ic_class      = "linuxdvb_frontend",
   .ic_caption    = N_("Linux DVB frontend"),
-  .ic_save       = linuxdvb_frontend_class_save,
+  .ic_changed    = linuxdvb_frontend_class_changed,
   .ic_properties = (const property_t[]) {
     {
       .type     = PT_STR,
@@ -1836,7 +1836,7 @@ linuxdvb_frontend_wizard_set( tvh_input_t *ti, htsmsg_t *conf, const char *lang
     }
     if (linuxdvb_frontend_wizard_network(lfe))
       mpegts_input_set_enabled((mpegts_input_t *)lfe, 1);
-    linuxdvb_adapter_save(lfe->lfe_adapter);
+    linuxdvb_adapter_changed(lfe->lfe_adapter);
   } else {
     htsmsg_destroy(nlist);
   }
index 8d824215f4384558cba08db99fd2558ff692ec00..09b5bcf09b7f1f68cbc64f04d790f9388f992baa 100644 (file)
@@ -356,7 +356,8 @@ void linuxdvb_adapter_init ( void );
 
 void linuxdvb_adapter_done ( void );
 
-void linuxdvb_adapter_save ( linuxdvb_adapter_t *la );
+static inline void linuxdvb_adapter_changed ( linuxdvb_adapter_t *la )
+  { idnode_changed(&la->th_id); }
 
 int  linuxdvb_adapter_current_weight ( linuxdvb_adapter_t *la );
 
index 34629afd4acff2b984413f6e0c70faf815a2bcb6..e72f8284353be993d601fef93fa4fccddd0c2994 100644 (file)
@@ -138,12 +138,12 @@ linuxdvb_satconf_class_get_title ( idnode_t *p, const char *lang )
 }
 
 static void
-linuxdvb_satconf_class_save ( idnode_t *s )
+linuxdvb_satconf_class_changed ( idnode_t *s )
 {
   linuxdvb_satconf_t  *ls  = (linuxdvb_satconf_t*)s;
   linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)ls->ls_frontend;
   linuxdvb_adapter_t  *la  = lfe->lfe_adapter;
-  linuxdvb_adapter_save(la);
+  linuxdvb_adapter_changed(la);
 }
 
 static const void *
@@ -214,7 +214,7 @@ const idclass_t linuxdvb_satconf_class =
   .ic_caption    = N_("DVB-S satellite configuration"),
   .ic_event      = "linuxdvb_satconf",
   .ic_get_title  = linuxdvb_satconf_class_get_title,
-  .ic_save       = linuxdvb_satconf_class_save,
+  .ic_changed    = linuxdvb_satconf_class_changed,
   .ic_properties = (const property_t[]) {
     {
       .type     = PT_BOOL,
@@ -1302,10 +1302,10 @@ linuxdvb_satconf_ele_class_get_childs ( idnode_t *o )
 }
 
 static void
-linuxdvb_satconf_ele_class_save ( idnode_t *in )
+linuxdvb_satconf_ele_class_changed ( idnode_t *in )
 {
   linuxdvb_satconf_ele_t *lse = (linuxdvb_satconf_ele_t*)in;
-  linuxdvb_satconf_class_save(&lse->lse_parent->ls_id);
+  linuxdvb_satconf_class_changed(&lse->lse_parent->ls_id);
 }
 
 const idclass_t linuxdvb_satconf_ele_class =
@@ -1315,7 +1315,7 @@ const idclass_t linuxdvb_satconf_ele_class =
   .ic_event      = "linuxdvb_satconf_ele",
   .ic_get_title  = linuxdvb_satconf_ele_class_get_title,
   .ic_get_childs = linuxdvb_satconf_ele_class_get_childs,
-  .ic_save       = linuxdvb_satconf_ele_class_save,
+  .ic_changed    = linuxdvb_satconf_ele_class_changed,
   .ic_properties = (const property_t[]) {
     {
       .type     = PT_BOOL,
@@ -1477,11 +1477,11 @@ linuxdvb_diseqc_class_get_title ( idnode_t *o, const char *lang )
 }
 
 static void
-linuxdvb_diseqc_class_save ( idnode_t *o )
+linuxdvb_diseqc_class_changed ( idnode_t *o )
 {
   linuxdvb_diseqc_t *ld = (linuxdvb_diseqc_t*)o;
   if (ld->ld_satconf)
-    linuxdvb_satconf_ele_class_save(&ld->ld_satconf->lse_id);
+    linuxdvb_satconf_ele_class_changed(&ld->ld_satconf->lse_id);
 }
 
 const idclass_t linuxdvb_diseqc_class =
@@ -1490,7 +1490,7 @@ const idclass_t linuxdvb_diseqc_class =
   .ic_caption     = N_("DiseqC"),
   .ic_event       = "linuxdvb_diseqc",
   .ic_get_title   = linuxdvb_diseqc_class_get_title,
-  .ic_save        = linuxdvb_diseqc_class_save,
+  .ic_changed     = linuxdvb_diseqc_class_changed,
 };
 
 linuxdvb_diseqc_t *
index c392985d5e449d0d00f40c8459f3e2e79affad0b..44c66a6d9101541ca6e8082368fa5d48c3f56280 100644 (file)
@@ -288,11 +288,13 @@ mpegts_mux_instance_weight ( mpegts_mux_instance_t *mmi )
  * Class definition
  * ***************************************************************************/
 
-static void
-mpegts_mux_class_save ( idnode_t *self )
+static htsmsg_t *
+mpegts_mux_class_save ( idnode_t *self, char *filename, size_t fsize )
 {
   mpegts_mux_t *mm = (mpegts_mux_t*)self;
-  if (mm->mm_config_save) mm->mm_config_save(mm);
+  if (mm->mm_config_save)
+    return mm->mm_config_save(mm, filename, fsize);
+  return NULL;
 }
 
 static void
@@ -696,9 +698,10 @@ mpegts_mux_delete ( mpegts_mux_t *mm, int delconf )
   free(mm);
 }
 
-static void
-mpegts_mux_config_save ( mpegts_mux_t *mm )
+static htsmsg_t *
+mpegts_mux_config_save ( mpegts_mux_t *mm, char *filename, size_t fsize )
 {
+  return NULL;
 }
 
 static int
@@ -1189,8 +1192,7 @@ mpegts_mux_set_onid ( mpegts_mux_t *mm, uint16_t onid )
     return 0;
   mm->mm_onid = onid;
   mpegts_mux_nice_name(mm, buf, sizeof(buf));
-  mm->mm_config_save(mm);
-  idnode_notify_changed(&mm->mm_id);
+  idnode_changed(&mm->mm_id);
   return 1;
 }
 
@@ -1202,13 +1204,12 @@ mpegts_mux_set_tsid ( mpegts_mux_t *mm, uint16_t tsid, int force )
   if (!force && mm->mm_tsid)
     return 0;
   mm->mm_tsid = tsid;
-  mm->mm_config_save(mm);
   if (tvhtrace_enabled()) {
     char buf[256];
     mpegts_mux_nice_name(mm, buf, sizeof(buf));
     tvhtrace("mpegts", "%s - set tsid %04X (%d)", buf, tsid, tsid);
   }
-  idnode_notify_changed(&mm->mm_id);
+  idnode_changed(&mm->mm_id);
   return 1;
 }
 
@@ -1218,13 +1219,12 @@ mpegts_mux_set_crid_authority ( mpegts_mux_t *mm, const char *defauth )
   if (defauth && !strcmp(defauth, mm->mm_crid_authority ?: ""))
     return 0;
   tvh_str_update(&mm->mm_crid_authority, defauth);
-  mm->mm_config_save(mm);
   if (tvhtrace_enabled()) {
     char buf[256];
     mpegts_mux_nice_name(mm, buf, sizeof(buf));
     tvhtrace("mpegts", "%s - set crid authority %s", buf, defauth);
   }
-  idnode_notify_changed(&mm->mm_id);
+  idnode_changed(&mm->mm_id);
   return 1;
 }
 
index c10034ed54d8dbca4e23449accb5c1cdf64654f8..88c1ef325bd8c490f59140284b924b04cb3d2301 100644 (file)
@@ -896,17 +896,17 @@ const idclass_t dvb_mux_dab_class =
  * Class methods
  * *************************************************************************/
 
-static void
-dvb_mux_config_save ( mpegts_mux_t *mm )
+static htsmsg_t *
+dvb_mux_config_save ( mpegts_mux_t *mm, char *filename, size_t fsize )
 {
   char ubuf1[UUID_HEX_SIZE];
   char ubuf2[UUID_HEX_SIZE];
   htsmsg_t *c = htsmsg_create_map();
   mpegts_mux_save(mm, c);
-  hts_settings_save(c, "input/dvb/networks/%s/muxes/%s/config",
-                    idnode_uuid_as_str(&mm->mm_network->mn_id, ubuf1),
-                    idnode_uuid_as_str(&mm->mm_id, ubuf2));
-  htsmsg_destroy(c);
+  snprintf(filename, fsize, "input/dvb/networks/%s/muxes/%s/config",
+           idnode_uuid_as_str(&mm->mm_network->mn_id, ubuf1),
+           idnode_uuid_as_str(&mm->mm_id, ubuf2));
+  return c;
 }
 
 static void
index fc1aa53539d139633f267146dfd1a861f02a3b34..1a20181bf18bb39578cbc05a2805d526a3ee0bdc 100644 (file)
@@ -60,15 +60,22 @@ mpegts_mux_sched_set_timer ( mpegts_mux_sched_t *mms )
 }
 
 static void
-mpegts_mux_sched_class_save ( idnode_t *in )
+mpegts_mux_sched_class_changed ( idnode_t *in )
 {
   mpegts_mux_sched_t *mms = (mpegts_mux_sched_t*)in;
 
   /* Update timer */
   mpegts_mux_sched_set_timer(mms);
+}
 
-  /* Save */
-  mpegts_mux_sched_save(mms);
+static htsmsg_t *
+mpegts_mux_sched_class_save ( idnode_t *in, char *filename, size_t fsize )
+{
+  htsmsg_t *c = htsmsg_create_map();
+  char ubuf[UUID_HEX_SIZE];
+  idnode_save(in, c);
+  snprintf(filename, fsize, "muxsched/%s", idnode_uuid_as_str(in, ubuf));
+  return c;
 }
 
 static void
@@ -117,6 +124,7 @@ const idclass_t mpegts_mux_sched_class =
   .ic_class      = "mpegts_mux_sched",
   .ic_caption    = N_("Mux schedule entry"),
   .ic_event      = "mpegts_mux_sched",
+  .ic_changed    = mpegts_mux_sched_class_changed,
   .ic_save       = mpegts_mux_sched_class_save,
   .ic_delete     = mpegts_mux_sched_class_delete,
   .ic_properties = (const property_t[]){
@@ -299,16 +307,6 @@ mpegts_mux_sched_create ( const char *uuid, htsmsg_t *conf )
   return mms;
 }
 
-void
-mpegts_mux_sched_save ( mpegts_mux_sched_t *mms )
-{
-  htsmsg_t *c = htsmsg_create_map();
-  char ubuf[UUID_HEX_SIZE];
-  idnode_save(&mms->mms_id, c);
-  hts_settings_save(c, "muxsched/%s", idnode_uuid_as_str(&mms->mms_id, ubuf));
-  htsmsg_destroy(c);
-}
-
 void
 mpegts_mux_sched_delete ( mpegts_mux_sched_t *mms, int delconf )
 {
index c7cd85dff941042c410c151250a73b1590c79ae3..97d01ed49ba7dcd25f37f54e21aadbb744a032e4 100644 (file)
@@ -67,7 +67,6 @@ typedef struct mpegts_mux_sched
 
 mpegts_mux_sched_t *mpegts_mux_sched_create ( const char *uuid, htsmsg_t *c );
 void mpegts_mux_sched_delete ( mpegts_mux_sched_t *mms, int delconf );
-void mpegts_mux_sched_save   ( mpegts_mux_sched_t *mms );
 
 void mpegts_mux_sched_init ( void );
 void mpegts_mux_sched_done ( void );
index e30c84215e87c85ed7e21f37ca970a73af69b511..a607ce4e90f8d582bb391ad1555c6113eba1a546 100644 (file)
  * Class definition
  * ***************************************************************************/
 
-static void
+static htsmsg_t *
 mpegts_network_class_save
-  ( idnode_t *in )
+  ( idnode_t *in, char *filename, size_t fsize )
 {
   mpegts_network_t *mn = (mpegts_network_t*)in;
   if (mn->mn_config_save)
-    mn->mn_config_save(mn);
+    return mn->mn_config_save(mn, filename, fsize);
+  return NULL;
 }
 
 static const char *
@@ -302,11 +303,12 @@ mpegts_network_display_name
   strncpy(buf, mn->mn_network_name ?: "unknown", len);
 }
 
-static void
+static htsmsg_t *
 mpegts_network_config_save
-  ( mpegts_network_t *mn )
+  ( mpegts_network_t *mn, char *filename, size_t size )
 {
   // Nothing - leave to child classes
+  return NULL;
 }
 
 static mpegts_mux_t *
@@ -552,7 +554,7 @@ mpegts_network_wizard_create
   mn = mnb->build(mnb->idc, conf);
   htsmsg_destroy(conf);
   if (mn)
-    mn->mn_config_save(mn);
+    idnode_changed(&mn->mn_id);
 
 found:
   if (mn && nlist) {
index e3881da8e8a14bd869171dd653d4fc24eaba5a58..cff0010e58f657053b35a92d32bd13c9ce09043e 100644 (file)
@@ -83,7 +83,7 @@ dvb_network_scanfile_set ( dvb_network_t *ln, const char *id )
       mm = dvb_mux_create0(ln, MPEGTS_ONID_NONE, MPEGTS_TSID_NONE,
                            dmc, NULL, NULL);
       if (mm)
-        mm->mm_config_save((mpegts_mux_t *)mm);
+        idnode_changed(&mm->mm_id);
       if (tvhtrace_enabled()) {
         char buf[128];
         dvb_mux_conf_str(dmc, buf, sizeof(buf));
@@ -549,16 +549,16 @@ dvb_network_find_mux
   return (dvb_mux_t *)mm;
 }
 
-static void
-dvb_network_config_save ( mpegts_network_t *mn )
+static htsmsg_t *
+dvb_network_config_save ( mpegts_network_t *mn, char *filename, size_t fsize )
 {
   htsmsg_t *c = htsmsg_create_map();
   char ubuf[UUID_HEX_SIZE];
   idnode_save(&mn->mn_id, c);
   htsmsg_add_str(c, "class", mn->mn_id.in_class->ic_class);
-  hts_settings_save(c, "input/dvb/networks/%s/config",
-                    idnode_uuid_as_str(&mn->mn_id, ubuf));
-  htsmsg_destroy(c);
+  snprintf(filename, fsize, "input/dvb/networks/%s/config",
+           idnode_uuid_as_str(&mn->mn_id, ubuf));
+  return c;
 }
 
 const idclass_t *
@@ -741,7 +741,7 @@ save:
   if (mm && save) {
     mm->mm_dmc_origin        = origin;
     mm->mm_dmc_origin_expire = dispatch_clock + 3600 * 24; /* one day */
-    mm->mm_config_save((mpegts_mux_t *)mm);
+    idnode_changed(&mm->mm_id);
   }
 noop:
   return (mpegts_mux_t *)mm;
index 3ec575a5dc3809a099c1f1c7345bb7ef074c368e..08845d5d843580f03a78563aa5e27ffa2687961b 100644 (file)
@@ -79,7 +79,7 @@ mpegts_network_scan_timer_cb ( void *p )
     TAILQ_REMOVE(&mn->mn_scan_pend, mm, mm_scan_link);
     if (mm->mm_scan_result != MM_SCAN_FAIL) {
       mm->mm_scan_result = MM_SCAN_FAIL;
-      mm->mm_config_save(mm);
+      idnode_changed(&mm->mm_id);
     }
     mm->mm_scan_state  = MM_SCAN_STATE_IDLE;
     mm->mm_scan_weight = 0;
@@ -124,7 +124,7 @@ mpegts_network_scan_mux_done0
 
   if (result != MM_SCAN_NONE && mm->mm_scan_result != result) {
     mm->mm_scan_result = result;
-    mm->mm_config_save(mm);
+    idnode_changed(&mm->mm_id);
   }
 
   /* Re-enable? */
@@ -392,10 +392,9 @@ tsid_lookup:
                                             MPEGTS_ONID_NONE,
                                             MPEGTS_TSID_NONE,
                                             mux, NULL, NULL);
-        if (mm)
-        {
-          mm->mm_config_save(mm);
+        if (mm) {
           char buf[256];
+          idnode_changed(&mm->mm_id);
           mn->mn_display_name(mn, buf, sizeof(buf));
           tvhinfo("mpegts", "fastscan mux add to network '%s'", buf);
         }
index 8cc75a0c43de428dd8f27cac4aec6bd061b7db4f..76ff2b6b7874223109e84ba26e7709a33cf34466 100644 (file)
@@ -269,8 +269,8 @@ mpegts_service_is_enabled(service_t *t, int flags)
 /*
  * Save
  */
-static void
-mpegts_service_config_save ( service_t *t )
+static htsmsg_t *
+mpegts_service_config_save ( service_t *t, char *filename, size_t fsize )
 {
   htsmsg_t *c = htsmsg_create_map();
   mpegts_service_t *s = (mpegts_service_t*)t;
@@ -278,11 +278,11 @@ mpegts_service_config_save ( service_t *t )
   char ubuf1[UUID_HEX_SIZE];
   char ubuf2[UUID_HEX_SIZE];
   service_save(t, c);
-  hts_settings_save(c, "input/dvb/networks/%s/muxes/%s/services/%s",
-                    idnode_uuid_as_str(&s->s_dvb_mux->mm_network->mn_id, ubuf0),
-                    idnode_uuid_as_str(&s->s_dvb_mux->mm_id, ubuf1),
-                    idnode_uuid_as_str(&s->s_id, ubuf2));
-  htsmsg_destroy(c);
+  snprintf(filename, fsize, "input/dvb/networks/%s/muxes/%s/services/%s",
+           idnode_uuid_as_str(&s->s_dvb_mux->mm_network->mn_id, ubuf0),
+           idnode_uuid_as_str(&s->s_dvb_mux->mm_id, ubuf1),
+           idnode_uuid_as_str(&s->s_id, ubuf2));
+  return c;
 }
 
 /*
index e3226815bec379fa28e88b877f602bf4bede63ef..bd32e8c41c74796445c432c00d63154d015a430f 100644 (file)
@@ -117,10 +117,28 @@ satip_device_nicename( satip_device_t *sd, char *buf, int len )
  * SAT-IP client
  */
 
-static void
-satip_device_class_save ( idnode_t *in )
+static htsmsg_t *
+satip_device_class_save ( idnode_t *in, char *filename, size_t fsize )
 {
-  satip_device_save((satip_device_t *)in);
+  satip_device_t *sd = (satip_device_t *)in;
+  satip_frontend_t *lfe;
+  htsmsg_t *m, *l;
+  char ubuf[UUID_HEX_SIZE];
+
+  if (sd->sd_nosave)
+    return NULL;
+
+  m = htsmsg_create_map();
+  idnode_save(&sd->th_id, m);
+
+  l = htsmsg_create_map();
+  TAILQ_FOREACH(lfe, &sd->sd_frontends, sf_link)
+    satip_frontend_save(lfe, l);
+  htsmsg_add_msg(m, "frontends", l);
+
+  snprintf(filename, fsize, "input/satip/adapters/%s",
+           idnode_uuid_as_str(&sd->th_id, ubuf));
+  return m;
 }
 
 static idnode_set_t *
@@ -655,7 +673,7 @@ satip_device_create( satip_device_info_t *info )
   }
 
   if (save)
-    satip_device_save(sd);
+    satip_device_changed(sd);
 
   sd->sd_inload = 0;
 
@@ -694,29 +712,6 @@ satip_device_find_by_descurl( const char *descurl )
   return NULL;
 }
 
-void
-satip_device_save( satip_device_t *sd )
-{
-  satip_frontend_t *lfe;
-  htsmsg_t *m, *l;
-  char ubuf[UUID_HEX_SIZE];
-
-  if (sd->sd_nosave)
-    return;
-
-  m = htsmsg_create_map();
-  idnode_save(&sd->th_id, m);
-
-  l = htsmsg_create_map();
-  TAILQ_FOREACH(lfe, &sd->sd_frontends, sf_link)
-    satip_frontend_save(lfe, l);
-  htsmsg_add_msg(m, "frontends", l);
-
-  hts_settings_save(m, "input/satip/adapters/%s",
-                    idnode_uuid_as_str(&sd->th_id, ubuf));
-  htsmsg_destroy(m);
-}
-
 void
 satip_device_destroy( satip_device_t *sd )
 {
index 0b7e65368e8ee36434be1ba6cb7772da40ae7cf2..72f73f18c5a66bca76d9a988a3a3f534fb97e284 100644 (file)
@@ -94,10 +94,10 @@ satip_frontend_signal_cb( void *aux )
  * *************************************************************************/
 
 static void
-satip_frontend_class_save ( idnode_t *in )
+satip_frontend_class_changed ( idnode_t *in )
 {
   satip_device_t *la = ((satip_frontend_t*)in)->sf_device;
-  satip_device_save(la);
+  satip_device_changed(la);
 }
 
 static int
@@ -138,7 +138,7 @@ const idclass_t satip_frontend_class =
   .ic_super      = &mpegts_input_class,
   .ic_class      = "satip_frontend",
   .ic_caption    = N_("SAT>IP DVB frontend"),
-  .ic_save       = satip_frontend_class_save,
+  .ic_changed    = satip_frontend_class_changed,
   .ic_properties = (const property_t[]) {
     {
       .type     = PT_INT,
@@ -1809,7 +1809,7 @@ satip_frontend_wizard_set( tvh_input_t *ti, htsmsg_t *conf, const char *lang )
     htsmsg_destroy(conf);
     if (satip_frontend_wizard_network(lfe))
       mpegts_input_set_enabled((mpegts_input_t *)lfe, 1);
-    satip_device_save(lfe->sf_device);
+    satip_device_changed(lfe->sf_device);
   } else {
     htsmsg_destroy(nlist);
   }
index 21fd4a4404364877337284abaa9b649ae7a83d95..23ec7977a315906cdafeef5b9edfe0422e01c400 100644 (file)
@@ -197,7 +197,8 @@ void satip_device_init ( void );
 
 void satip_device_done ( void );
 
-void satip_device_save ( satip_device_t *sd );
+static inline void satip_device_changed ( satip_device_t *sd )
+  { idnode_changed(&sd->th_id); }
 
 void satip_device_destroy ( satip_device_t *sd );
 
index 35254c09ec2b9b52fabe6f6935cd995747683358..ccc8e6acc8ab318467cde8cc04a5de49765b7495 100644 (file)
@@ -169,10 +169,10 @@ satip_satconf_class_get_title ( idnode_t *o, const char *lang )
 }
 
 static void
-satip_satconf_class_save ( idnode_t *in )
+satip_satconf_class_changed ( idnode_t *in )
 {
   satip_satconf_t *sfc = (satip_satconf_t*)in;
-  satip_device_save(sfc->sfc_lfe->sf_device);
+  satip_device_changed(sfc->sfc_lfe->sf_device);
 }
 
 const idclass_t satip_satconf_class =
@@ -181,7 +181,7 @@ const idclass_t satip_satconf_class =
   .ic_caption    = N_("Satconf"),
   .ic_event      = "satip_satconf",
   .ic_get_title  = satip_satconf_class_get_title,
-  .ic_save       = satip_satconf_class_save,
+  .ic_changed    = satip_satconf_class_changed,
   .ic_properties = (const property_t[]) {
     {
       .type     = PT_BOOL,
index 51df7b79bee3dbf30867e553052a30ddea583cd3..a19ce7369c8b40ef0ed170a1945d763af4b86684 100644 (file)
@@ -33,9 +33,10 @@ tsfile_input_list_t      tsfile_inputs;
 extern const idclass_t mpegts_service_class;
 extern const idclass_t mpegts_network_class;
 
-static void
-tsfile_service_config_save ( service_t *s )
+static htsmsg_t *
+tsfile_service_config_save ( service_t *s, char *filename, size_t fsize )
 {
+  return NULL;
 }
 
 static void
index a3fedbbe09bdb839053c8284d851fb400253f4b2..bc6cd724fa30a96a7b6f1c2bdc5ce98365e43a8c 100644 (file)
@@ -46,9 +46,10 @@ tsfile_mux_instance_create
   return mmi;
 }
 
-static void
-iptv_mux_config_save ( mpegts_mux_t *m )
+static htsmsg_t *
+iptv_mux_config_save ( mpegts_mux_t *m, char *filename, size_t fsize )
 {
+  return NULL;
 }
 
 mpegts_mux_t *
index 007b6936249cce7abc43a4f705c74bb775dca236..b032c4af8adeee80f3fc562d3dc0a395f964f8b3 100644 (file)
            hdhomerun_discover_find_devices_custom_v2
 #endif
 
-static void
-tvhdhomerun_device_class_save ( idnode_t *in )
+static htsmsg_t *
+tvhdhomerun_device_class_save ( idnode_t *in, char *filename, size_t fsize )
 {
-  tvhdhomerun_device_save((tvhdhomerun_device_t *)in);
+  tvhdhomerun_device_t *hd = (tvhdhomerun_device_t *)in;
+  tvhdhomerun_frontend_t *lfe;
+  htsmsg_t *m, *l;
+  char ubuf[UUID_HEX_SIZE];
+
+  m = htsmsg_create_map();
+  idnode_save(&hd->th_id, m);
+
+  l = htsmsg_create_map();
+  TAILQ_FOREACH(lfe, &hd->hd_frontends, hf_link)
+    tvhdhomerun_frontend_save(lfe, l);
+  htsmsg_add_msg(m, "frontends", l);
+
+  htsmsg_add_str(m, "fe_override", hd->hd_override_type);
+
+  snprintf(filename, fsize, "input/tvhdhomerun/adapters/%s",
+           idnode_uuid_as_str(&hd->th_id, ubuf));
+  return m;
 }
 
 static idnode_set_t *
@@ -189,28 +206,6 @@ const idclass_t tvhdhomerun_device_class =
 };
 
 
-void
-tvhdhomerun_device_save( tvhdhomerun_device_t *hd )
-{
-  tvhdhomerun_frontend_t *lfe;
-  htsmsg_t *m, *l;
-  char ubuf[UUID_HEX_SIZE];
-
-  m = htsmsg_create_map();
-  idnode_save(&hd->th_id, m);
-
-  l = htsmsg_create_map();
-  TAILQ_FOREACH(lfe, &hd->hd_frontends, hf_link)
-    tvhdhomerun_frontend_save(lfe, l);
-  htsmsg_add_msg(m, "frontends", l);
-
-  htsmsg_add_str(m, "fe_override", hd->hd_override_type);
-
-  hts_settings_save(m, "input/tvhdhomerun/adapters/%s",
-                    idnode_uuid_as_str(&hd->th_id, ubuf));
-  htsmsg_destroy(m);
-}
-
 static void
 tvhdhomerun_discovery_destroy(tvhdhomerun_discovery_t *d, int unlink)
 {
@@ -342,7 +337,7 @@ static void tvhdhomerun_device_create(struct hdhomerun_discover_device_t *dInfo)
 
 
   if (save)
-    tvhdhomerun_device_save(hd);
+    tvhdhomerun_device_changed(hd);
 
   htsmsg_destroy(conf);
 }
index 19393eef188473ecdaaf87a155a2e8d21bbe1c7d..54c29eb86f94e0f8e05eb4bf14fc297a18af998c 100644 (file)
@@ -512,10 +512,10 @@ tvhdhomerun_frontend_network_list ( mpegts_input_t *mi )
 }
 
 static void
-tvhdhomerun_frontend_class_save ( idnode_t *in )
+tvhdhomerun_frontend_class_changed ( idnode_t *in )
 {
   tvhdhomerun_device_t *la = ((tvhdhomerun_frontend_t*)in)->hf_device;
-  tvhdhomerun_device_save(la);
+  tvhdhomerun_device_changed(la);
 }
 
 void
@@ -540,7 +540,7 @@ const idclass_t tvhdhomerun_frontend_class =
   .ic_super      = &mpegts_input_class,
   .ic_class      = "tvhdhomerun_frontend",
   .ic_caption    = N_("HDHomeRun DVB frontend"),
-  .ic_save       = tvhdhomerun_frontend_class_save,
+  .ic_changed    = tvhdhomerun_frontend_class_changed,
   .ic_properties = (const property_t[]) {
     {
       .type     = PT_INT,
@@ -628,7 +628,7 @@ tvhdhomerun_frontend_wizard_set( tvh_input_t *ti, htsmsg_t *conf, const char *la
     htsmsg_destroy(nlist);
     if (tvhdhomerun_frontend_wizard_network(hfe))
       mpegts_input_set_enabled((mpegts_input_t *)hfe, 1);
-    tvhdhomerun_device_save(hfe->hf_device);
+    tvhdhomerun_device_changed(hfe->hf_device);
   } else {
     htsmsg_destroy(nlist);
   }
index c6a255cd9c372dc54cee9bb71816d12747e81188..bf000d6c400d6ae753a2552b0ee45396fd01e09a 100644 (file)
@@ -134,7 +134,9 @@ tvhdhomerun_frontend_create( tvhdhomerun_device_t *hd, struct hdhomerun_discover
 
 void tvhdhomerun_frontend_delete ( tvhdhomerun_frontend_t *lfe );
 
-void tvhdhomerun_device_save ( tvhdhomerun_device_t *sd );
+static inline void tvhdhomerun_device_changed ( tvhdhomerun_device_t *sd )
+  { idnode_changed(&sd->th_id); }
+
 void tvhdhomerun_frontend_save ( tvhdhomerun_frontend_t *lfe, htsmsg_t *m );
 
 #endif
index 81002f7114f9174d01dc7f67944c0090c804f2e1..17982a1d5b69c965d7de667ec38cf10c7f09308f 100644 (file)
@@ -41,8 +41,6 @@ static LIST_HEAD(,profile_chain) profile_chains;
 
 static profile_t *profile_default;
 
-static void profile_class_save ( idnode_t *in );
-
 /*
  *
  */
@@ -114,7 +112,7 @@ profile_create
   pro->pro_refcount = 1;
   TAILQ_INSERT_TAIL(&profiles, pro, pro_link);
   if (save)
-    profile_class_save((idnode_t *)pro);
+    idnode_changed(&pro->pro_id);
   if (pro->pro_conf_changed)
     pro->pro_conf_changed(pro);
   return pro;
@@ -146,8 +144,8 @@ profile_delete(profile_t *pro, int delconf)
   profile_release(pro);
 }
 
-static void
-profile_class_save ( idnode_t *in )
+static htsmsg_t *
+profile_class_save ( idnode_t *in, char *filename, size_t fsize )
 {
   profile_t *pro = (profile_t *)in;
   htsmsg_t *c = htsmsg_create_map();
@@ -157,10 +155,10 @@ profile_class_save ( idnode_t *in )
   idnode_save(in, c);
   if (pro->pro_shield)
     htsmsg_add_bool(c, "shield", 1);
-  hts_settings_save(c, "profile/%s", idnode_uuid_as_str(in, ubuf));
-  htsmsg_destroy(c);
+  snprintf(filename, fsize, "profile/%s", idnode_uuid_as_str(in, ubuf));
   if (pro->pro_conf_changed)
     pro->pro_conf_changed(pro);
+  return c;
 }
 
 static const char *
@@ -224,7 +222,7 @@ profile_class_default_set(void *o, const void *v)
     old = profile_default;
     profile_default = pro;
     if (old)
-      profile_class_save(&old->pro_id);
+      idnode_changed(&old->pro_id);
     return 1;
   }
   return 0;
index 8b6d3f5b9dc0397166b69820fee7e9fe99b5c72a..090ce4a16f3df4680594e537794bd9ca3f1ffa3b 100644 (file)
@@ -550,9 +550,9 @@ struct satip_server_conf satip_server_conf = {
   .satip_allow_remote_weight = 1
 };
 
-static void satip_server_class_save(idnode_t *self)
+static void satip_server_class_changed(idnode_t *self)
 {
-  config_save();
+  idnode_changed(&config.idnode);
   satip_server_save();
 }
 
@@ -572,7 +572,7 @@ const idclass_t satip_server_class = {
   .ic_caption    = N_("SAT>IP server"),
   .ic_event      = "satip_server",
   .ic_perm_def   = ACCESS_ADMIN,
-  .ic_save       = satip_server_class_save,
+  .ic_changed    = satip_server_class_changed,
   .ic_groups     = (const property_group_t[]) {
       {
          .name   = N_("General"),
@@ -745,7 +745,6 @@ static void satip_server_save(void)
   int descramble, rewrite_pmt, muxcnf;
   char *nat_ip;
 
-  config_save();
   if (!satip_server_rtsp_port_locked) {
     satips_rtsp_port(0);
     if (satip_server_rtsp_port > 0) {
@@ -849,7 +848,7 @@ void satip_server_register(void)
   }
 
   if (save)
-    config_save();
+    idnode_changed(&config.idnode);
 
   satips_upnp_discovery = upnp_service_create(upnp_service);
   if (satips_upnp_discovery == NULL) {
index 5790e3b1976ae0b1111748eadb431fc4f028342c..2c3f3d00e9ad02e2f157f204b52e0846f2c7981d 100644 (file)
@@ -51,7 +51,7 @@
 
 static void service_data_timeout(void *aux);
 static void service_class_delete(struct idnode *self);
-static void service_class_save(struct idnode *self);
+static htsmsg_t *service_class_save(struct idnode *self, char *filename, size_t fsize);
 
 struct service_queue service_all;
 struct service_queue service_raw_all;
@@ -1391,12 +1391,13 @@ service_class_delete(struct idnode *self)
 /**
  *
  */
-static void
-service_class_save(struct idnode *self)
+static htsmsg_t *
+service_class_save(struct idnode *self, char *filename, size_t fsize)
 {
   service_t *s = (service_t *)self;
   if (s->s_config_save)
-    s->s_config_save(s);
+    return s->s_config_save(s, filename, fsize);
+  return NULL;
 }
 
 /**
@@ -1426,7 +1427,7 @@ service_saver(void *aux)
     pthread_mutex_lock(&global_lock);
 
     if(t->s_status != SERVICE_ZOMBIE && t->s_config_save)
-      t->s_config_save(t);
+      idnode_changed(&t->s_id);
     if(t->s_status == SERVICE_RUNNING && restart)
       service_restart(t);
     service_unref(t);
index 7fa2bcff5123b603b9a78d3a5954d9b81d214c89..8783823a3af8aa5640b46137f529746699f1f54c 100644 (file)
@@ -319,7 +319,7 @@ typedef struct service {
 
   void (*s_stop_feed)(struct service *t);
 
-  void (*s_config_save)(struct service *t);
+  htsmsg_t *(*s_config_save)(struct service *t, char *filename, size_t fsize);
 
   void (*s_setsourceinfo)(struct service *t, struct source_info *si);
 
index 3ca9cadf32824ace45a359728be005fcb1b6fb53..7b63324e88e92b2dcbd3f6d8b47de98672ca5faf 100644 (file)
@@ -268,8 +268,7 @@ service_mapper_process
     }
 
     /* save */
-    idnode_notify_changed(&chn->ch_id);
-    channel_save(chn);
+    idnode_changed(&chn->ch_id);
   }
   if (!bq) {
     service_mapper_stat.ok++;
@@ -421,19 +420,21 @@ service_mapper_reset_stats (void)
 /*
  * Save settings
  */
-static void service_mapper_conf_class_save ( idnode_t *self )
+static htsmsg_t *
+service_mapper_conf_class_save ( idnode_t *self, char *filename, size_t fsize )
 {
   htsmsg_t *m;
 
   m = htsmsg_create_map();
   idnode_save(&service_mapper_conf.idnode, m);
-  hts_settings_save(m, "service_mapper/config");
-  htsmsg_destroy(m);
+  snprintf(filename, fsize, "service_mapper/config");
 
   if (!htsmsg_is_empty(service_mapper_conf.services))
     service_mapper_start(&service_mapper_conf.d, service_mapper_conf.services);
   htsmsg_destroy(service_mapper_conf.services);
   service_mapper_conf.services = NULL;
+
+  return m;
 }
 
 /*
index d540dc52cf270b9647e8400cc67cfe741a0d486d..d265ff613c99743b373489da325d01a80d1c8ed1 100644 (file)
@@ -477,10 +477,6 @@ tvhlog_end ( void )
  * Configuration
  */
 
-static void tvhlog_class_save(idnode_t *self)
-{
-}
-
 static const void *
 tvhlog_class_path_get ( void *o )
 {
@@ -626,7 +622,6 @@ const idclass_t tvhlog_conf_class = {
   .ic_caption    = N_("Debugging"),
   .ic_event      = "tvhlog_conf",
   .ic_perm_def   = ACCESS_ADMIN,
-  .ic_save       = tvhlog_class_save,
   .ic_groups     = (const property_group_t[]) {
     {
       .name   = N_("Settings"),
index ec201bf8a1f2b7f261c061c1ef5fe3a81029bbf9..f0b42633809368c0248956051fc821d509b97d71 100644 (file)
@@ -120,7 +120,7 @@ typedef struct wizard_hello {
 } wizard_hello_t;
 
 
-static void hello_save(idnode_t *in)
+static void hello_changed(idnode_t *in)
 {
   wizard_page_t *p = (wizard_page_t *)in;
   wizard_hello_t *w = p->aux;
@@ -146,7 +146,7 @@ static void hello_save(idnode_t *in)
     save = 1;
   }
   if (save)
-    config_save();
+    idnode_changed(&config.idnode);
 }
 
 BASIC_STR_OPS(wizard_hello_t, ui_lang)
@@ -252,7 +252,7 @@ wizard_page_t *wizard_hello(const char *lang)
 
   ic->ic_properties = props;
   ic->ic_groups = groups;
-  ic->ic_save = hello_save;
+  ic->ic_changed = hello_changed;
   page->aux = w = calloc(1, sizeof(wizard_hello_t));
 
   if (config.language_ui)
@@ -288,7 +288,7 @@ typedef struct wizard_login {
 } wizard_login_t;
 
 
-static void login_save(idnode_t *in)
+static void login_changed(idnode_t *in)
 {
   wizard_page_t *p = (wizard_page_t *)in;
   wizard_login_t *w = p->aux;
@@ -324,7 +324,7 @@ static void login_save(idnode_t *in)
   ae = access_entry_create(NULL, conf);
   if (ae) {
     ae->ae_wizard = 1;
-    access_entry_save(ae);
+    idnode_changed(&ae->ae_id);
   }
   htsmsg_destroy(conf);
 
@@ -336,7 +336,7 @@ static void login_save(idnode_t *in)
     pw = passwd_entry_create(NULL, conf);
     if (pw) {
       pw->pw_wizard = 1;
-      passwd_entry_save(pw);
+      idnode_changed(&pw->pw_id);
     }
     htsmsg_destroy(conf);
   }
@@ -355,7 +355,7 @@ static void login_save(idnode_t *in)
     ae = access_entry_create(NULL, conf);
     if (ae) {
       ae->ae_wizard = 1;
-      access_entry_save(ae);
+      idnode_changed(&ae->ae_id);
     }
     htsmsg_destroy(conf);
 
@@ -367,7 +367,7 @@ static void login_save(idnode_t *in)
       pw = passwd_entry_create(NULL, conf);
       if (pw) {
         pw->pw_wizard = 1;
-        passwd_entry_save(pw);
+        idnode_changed(&pw->pw_id);
       }
       htsmsg_destroy(conf);
     }
@@ -484,7 +484,7 @@ wizard_page_t *wizard_login(const char *lang)
 
   ic->ic_properties = props;
   ic->ic_groups = groups;
-  ic->ic_save = login_save;
+  ic->ic_changed = login_changed;
   page->aux = w = calloc(1, sizeof(wizard_login_t));
 
   TAILQ_FOREACH(ae, &access_entries, ae_link) {
@@ -539,7 +539,7 @@ static void network_free(wizard_page_t *page)
   page_free(page);
 }
 
-static void network_save(idnode_t *in)
+static void network_changed(idnode_t *in)
 {
   wizard_page_t *p = (wizard_page_t *)in;
   wizard_network_t *w = p->aux;
@@ -720,7 +720,7 @@ wizard_page_t *wizard_network(const char *lang)
   page->aux = w = calloc(1, sizeof(wizard_network_t));
   ic->ic_groups = groups;
   ic->ic_properties = w->props;
-  ic->ic_save = network_save;
+  ic->ic_changed = network_changed;
   page->free = network_free;
   snprintf(w->lang, sizeof(w->lang), "%s", lang ?: "");
 
@@ -777,7 +777,7 @@ static void muxes_free(wizard_page_t *page)
   page_free(page);
 }
 
-static void muxes_save(idnode_t *in)
+static void muxes_changed(idnode_t *in)
 {
   wizard_page_t *p = (wizard_page_t *)in;
   wizard_muxes_t *w = p->aux;
@@ -989,7 +989,7 @@ wizard_page_t *wizard_muxes(const char *lang)
   page->aux = w = calloc(1, sizeof(wizard_muxes_t));
   ic->ic_groups = groups;
   ic->ic_properties = w->props;
-  ic->ic_save = muxes_save;
+  ic->ic_changed = muxes_changed;
   page->free = muxes_free;
   snprintf(w->lang, sizeof(w->lang), "%s", lang ?: "");
 
@@ -1084,7 +1084,7 @@ typedef struct wizard_mapping {
   int nettags;
 } wizard_mapping_t;
 
-static void mapping_save(idnode_t *in)
+static void mapping_changed(idnode_t *in)
 {
   wizard_page_t *p = (wizard_page_t *)in;
   wizard_mapping_t *w = p->aux;
@@ -1162,7 +1162,7 @@ wizard_page_t *wizard_mapping(const char *lang)
   idclass_t *ic = (idclass_t *)page->idnode.in_class;
   wizard_mapping_t *w;
   ic->ic_properties = props;
-  ic->ic_save = mapping_save;
+  ic->ic_changed = mapping_changed;
   page->aux = w = calloc(1, sizeof(wizard_mapping_t));
   w->provtags = service_mapper_conf.d.provider_tags;
   w->nettags = service_mapper_conf.d.network_tags;
@@ -1173,7 +1173,7 @@ wizard_page_t *wizard_mapping(const char *lang)
  * Discovered channels
  */
 
-static void channels_save(idnode_t *in)
+static void channels_changed(idnode_t *in)
 {
   access_entry_t *ae, *ae_next;
 
@@ -1226,7 +1226,7 @@ wizard_page_t *wizard_channels(const char *lang)
 
   ic->ic_properties = props;
   ic->ic_flags |= IDCLASS_ALWAYS_SAVE;
-  ic->ic_save = channels_save;
+  ic->ic_changed = channels_changed;
   /* do we have an admin created by wizard? */
   TAILQ_FOREACH(ae, &access_entries, ae_link)
     if (ae->ae_admin && ae->ae_wizard) break;