]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
idnode: add light notify functions, big get_title() cleanups
authorJaroslav Kysela <perex@perex.cz>
Wed, 6 Dec 2017 10:11:59 +0000 (11:11 +0100)
committerJaroslav Kysela <perex@perex.cz>
Wed, 6 Dec 2017 10:11:59 +0000 (11:11 +0100)
38 files changed:
src/access.c
src/api/api_caclient.c
src/api/api_epggrab.c
src/api/api_idnode.c
src/bouquet.c
src/channels.c
src/descrambler/caclient.c
src/descrambler/capmt.c
src/descrambler/constcw.c
src/dvr/dvr_autorec.c
src/dvr/dvr_config.c
src/dvr/dvr_db.c
src/dvr/dvr_timerec.c
src/epggrab/channel.c
src/epggrab/module.c
src/esfilter.c
src/idnode.c
src/idnode.h
src/input/mpegts/iptv/iptv.c
src/input/mpegts/linuxdvb/linuxdvb_adapter.c
src/input/mpegts/linuxdvb/linuxdvb_ca.c
src/input/mpegts/linuxdvb/linuxdvb_en50494.c
src/input/mpegts/linuxdvb/linuxdvb_lnb.c
src/input/mpegts/linuxdvb/linuxdvb_rotor.c
src/input/mpegts/linuxdvb/linuxdvb_satconf.c
src/input/mpegts/linuxdvb/linuxdvb_switch.c
src/input/mpegts/mpegts_input.c
src/input/mpegts/mpegts_mux.c
src/input/mpegts/mpegts_network.c
src/input/mpegts/satip/satip.c
src/input/mpegts/satip/satip_satconf.c
src/input/mpegts/tvhdhomerun/tvhdhomerun.c
src/memoryinfo.c
src/notify.h
src/profile.c
src/service.c
src/subscriptions.c
src/webui/comet.c

index b29550be6e457b9e5899df504656a0a5ecbe5edc..2c4d0a0f822a95ef0eef0b6f64efbac0eaaf74db 100644 (file)
@@ -1213,23 +1213,25 @@ access_entry_class_movedown(idnode_t *self)
   }
 }
 
-static const char *
-access_entry_class_get_title (idnode_t *self, const char *lang)
+static void
+access_entry_class_get_title
+  (idnode_t *self, const char *lang, char *buf, size_t dstsize)
 {
   access_entry_t *ae = (access_entry_t *)self;
-  const char *s = ae->ae_username;
 
   if (ae->ae_comment && ae->ae_comment[0] != '\0') {
     if (ae->ae_username && ae->ae_username[0]) {
-      snprintf(prop_sbuf, PROP_SBUF_LEN, "%s (%s)", ae->ae_username, ae->ae_comment);
-      s = prop_sbuf;
+      snprintf(buf, dstsize, "%s (%s)", ae->ae_username, ae->ae_comment);
+      return;
     } else {
-      s = ae->ae_comment;
+      snprintf(buf, dstsize, "%s", ae->ae_comment);
+      return;
     }
   }
-  if (s == NULL || *s == '\0')
-    s = "";
-  return s;
+  if (ae->ae_username && ae->ae_username[0] != '\0')
+    snprintf(buf, dstsize, "%s", ae->ae_username);
+  else
+    buf[0] = '\0';
 }
 
 static int
@@ -1966,14 +1968,17 @@ passwd_entry_class_delete(idnode_t *self)
   passwd_entry_destroy(pw, 1);
 }
 
-static const char *
-passwd_entry_class_get_title (idnode_t *self, const char *lang)
+static void
+passwd_entry_class_get_title
+  (idnode_t *self, const char *lang, char *dst, size_t dstsize)
 {
   passwd_entry_t *pw = (passwd_entry_t *)self;
 
-  if (pw->pw_comment && pw->pw_comment[0] != '\0')
-    return pw->pw_comment;
-  return pw->pw_username ?: "";
+  if (pw->pw_comment && pw->pw_comment[0] != '\0') {
+    snprintf(dst, dstsize, "%s", pw->pw_comment);
+  } else {
+    snprintf(dst, dstsize, "%s", pw->pw_username ?: "");
+  }
 }
 
 static int
@@ -2136,14 +2141,16 @@ ipblock_entry_class_save(idnode_t *self, char *filename, size_t fsize)
   return c;
 }
 
-static const char *
-ipblock_entry_class_get_title (idnode_t *self, const char *lang)
+static void
+ipblock_entry_class_get_title
+  (idnode_t *self, const char *lang, char *dst, size_t dstsize)
 {
   ipblock_entry_t *ib = (ipblock_entry_t *)self;
 
   if (ib->ib_comment && ib->ib_comment[0] != '\0')
-    return ib->ib_comment;
-  return N_("IP blocking");
+    snprintf(dst, dstsize, "%s", ib->ib_comment);
+  else
+    snprintf(dst, dstsize, "%s", tvh_gettext_lang(lang, N_("IP blocking")));
 }
 
 static void
index 49b1470da3c038b4f146cdb6d9ef58f50e523b9d..cf14335a97923428a25a819fa363f9dcde464054 100644 (file)
@@ -32,14 +32,14 @@ api_caclient_list
 {
   caclient_t *cac;
   htsmsg_t *l, *e;
-  char ubuf[UUID_HEX_SIZE];
+  char ubuf[UUID_HEX_SIZE], buf[384];
 
   l = htsmsg_create_list();
   pthread_mutex_lock(&global_lock);
   TAILQ_FOREACH(cac, &caclients, cac_link) {
     e = htsmsg_create_map();
     htsmsg_add_str(e, "uuid", idnode_uuid_as_str(&cac->cac_id, ubuf));
-    htsmsg_add_str(e, "title", idnode_get_title(&cac->cac_id, perm->aa_lang_ui));
+    htsmsg_add_str(e, "title", idnode_get_title(&cac->cac_id, perm->aa_lang_ui, buf, sizeof(buf)));
     htsmsg_add_str(e, "status", caclient_get_status(cac));
     htsmsg_add_msg(l, NULL, e);
   }
index f53f6f00e6c111de922eafc6e55fb1b8f7757fbf..5e8d064c16484af80caf939d407cf8d8ea7cdad7 100644 (file)
@@ -38,13 +38,13 @@ api_epggrab_module_list
 {
   htsmsg_t *l = htsmsg_create_list(), *m;
   epggrab_module_t *mod;
-  char ubuf[UUID_HEX_SIZE];
+  char ubuf[UUID_HEX_SIZE], buf[384];
   pthread_mutex_lock(&global_lock);
   LIST_FOREACH(mod, &epggrab_modules, link) {
     m = htsmsg_create_map();
     htsmsg_add_str(m, "uuid", idnode_uuid_as_str(&mod->idnode, ubuf));
     htsmsg_add_str(m, "status", epggrab_module_get_status(mod));
-    htsmsg_add_str(m, "title", idnode_get_title(&mod->idnode, perm->aa_lang_ui));
+    htsmsg_add_str(m, "title", idnode_get_title(&mod->idnode, perm->aa_lang_ui, buf, sizeof(buf)));
     htsmsg_add_msg(l, NULL, m);
   }
   pthread_mutex_unlock(&global_lock);
index fe7b42623f532d55b654d33d5b0d87f7e4306e75..517315a2f24cc887768d3481c25dd587a0501e0a 100644 (file)
@@ -177,7 +177,7 @@ api_idnode_load_by_class0
   idnode_set_t    *is;
   idnode_t        *in;
   htsmsg_t        *l, *e;
-  char ubuf[UUID_HEX_SIZE];
+  char ubuf[UUID_HEX_SIZE], buf[384];
 
   // TODO: this only works if pass as integer
   _enum = htsmsg_get_bool_or_default(args, "enum", 0);
@@ -197,7 +197,7 @@ api_idnode_load_by_class0
       /* Name/UUID only */
       if (_enum) {
         e = htsmsg_create_key_val(idnode_uuid_as_str(in, ubuf),
-                                  idnode_get_title(in, perm->aa_lang_ui));
+                                  idnode_get_title(in, perm->aa_lang_ui, buf, sizeof(buf)));
 
       /* Full record */
       } else {
index 53d397c18c9cb6d83c8c1be0b7ae52c1d8c4923b..d88033838f65412467e4640329a10265b0533fda 100644 (file)
@@ -681,14 +681,16 @@ bouquet_class_delete(idnode_t *self)
   bouquet_delete((bouquet_t *)self);
 }
 
-static const char *
-bouquet_class_get_title (idnode_t *self, const char *lang)
+static void
+bouquet_class_get_title
+  (idnode_t *self, const char *lang, char *dst, size_t dstsize)
 {
   bouquet_t *bq = (bouquet_t *)self;
 
   if (bq->bq_comment && bq->bq_comment[0] != '\0')
-    return bq->bq_comment;
-  return bq->bq_name ?: "";
+    snprintf(dst, dstsize, "%s", bq->bq_comment);
+  else
+    snprintf(dst, dstsize, "%s", bq->bq_name ?: "");
 }
 
 /* exported for others */
index 41115ee6c1f0fed8b17d8441254f2809b240f1ab..085e42667cc0020d1361f706c91f8fc2485ffae4 100644 (file)
@@ -217,10 +217,13 @@ channel_class_get_icon ( void *obj )
   return &prop_ptr;
 }
 
-static const char *
-channel_class_get_title ( idnode_t *self, const char *lang )
+static void
+channel_class_get_title
+  ( idnode_t *self, const char *lang, char *dst, size_t dstsize )
 {
-  return channel_get_name((channel_t*)self, tvh_gettext_lang(lang, channel_blank_name));
+  const char *s = channel_get_name((channel_t*)self,
+                                   tvh_gettext_lang(lang, channel_blank_name));
+  snprintf(dst, dstsize, "%s", s);
 }
 
 /* exported for others */
@@ -1500,11 +1503,12 @@ channel_tag_class_delete(idnode_t *self)
   channel_tag_destroy((channel_tag_t *)self, 1);
 }
 
-static const char *
-channel_tag_class_get_title (idnode_t *self, const char *lang)
+static void
+channel_tag_class_get_title
+  (idnode_t *self, const char *lang, char *dst, size_t dstsize)
 {
   channel_tag_t *ct = (channel_tag_t *)self;
-  return ct->ct_name ?: "";
+  snprintf(dst, dstsize, "%s", ct->ct_name ?: "");
 }
 
 static void
index edbc371e9849a035fcb931d24e48e75c9cb34999..e5c9b775c1d76a80699abfc89d364cf05c393f51 100644 (file)
@@ -188,15 +188,17 @@ caclient_class_save ( idnode_t *in, char *filename, size_t fsize )
   return c;
 }
 
-static const char *
-caclient_class_get_title ( idnode_t *in, const char *lang )
+static void
+caclient_class_get_title
+  ( idnode_t *in, const char *lang, char *dst, size_t dstsize )
 {
   caclient_t *cac = (caclient_t *)in;
-  if (cac->cac_name && cac->cac_name[0])
-    return cac->cac_name;
-  snprintf(prop_sbuf, PROP_SBUF_LEN,
-           tvh_gettext_lang(lang, N_("CA client %i")), cac->cac_index);
-  return prop_sbuf;
+  if (cac->cac_name && cac->cac_name[0]) {
+    snprintf(dst, dstsize, "%s", cac->cac_name);
+  } else {
+    snprintf(dst, dstsize,
+             tvh_gettext_lang(lang, N_("CA client %i")), cac->cac_index);
+  }
 }
 
 static void
@@ -297,7 +299,7 @@ const idclass_t caclient_class =
       .name     = N_("Client name"),
       .desc     = N_("Name of the client."),
       .off      = offsetof(caclient_t, cac_name),
-      .notify   = idnode_notify_title_changed,
+      .notify   = idnode_notify_title_changed_lang,
     },
     {
       .type     = PT_STR,
index 6ba631400bd0d1653b86d360862c7f52fc6062ce..e3eac35b740ae4ecf4cb8c367ffa267b5bec0ae0 100644 (file)
@@ -260,6 +260,8 @@ typedef struct capmt {
 
   pthread_t capmt_tid;
 
+  char capmt_name[128];
+
   /* from capmt configuration */
   char *capmt_sockfile;
   int   capmt_port;
@@ -308,7 +310,8 @@ static void capmt_send_client_info(capmt_t *capmt);
 static inline const char *
 capmt_name(capmt_t *capmt)
 {
-  return idnode_get_title(&capmt->cac_id, NULL);
+  return idnode_get_title(&capmt->cac_id, NULL,
+                          capmt->capmt_name, sizeof(capmt->capmt_name));
 }
 
 static inline int
@@ -1922,7 +1925,7 @@ capmt_thread(void *aux)
       d = 60;
     }
 
-    tvhinfo(LS_CAPMT, "%s: Automatic reconnection attempt in in %d seconds", idnode_get_title(&capmt->cac_id, NULL), d);
+    tvhinfo(LS_CAPMT, "%s: Automatic reconnection attempt in in %d seconds", capmt_name(capmt), d);
 
     mono = mclk() + sec2mono(d);
     do {
index cd3aefefd5a85b5f6eb5a9be837100456e35350b..7f3c6004c36d8d6b9fc2c0f845b5d75530c4a820 100644 (file)
@@ -36,6 +36,8 @@ typedef struct constcw_service {
 typedef struct constcw {
   caclient_t;
 
+  char     ccw_name[128];
+
   /* From configuration */
   uint16_t ccw_caid;           /* CA ID */
   uint32_t ccw_providerid;     /* CA provider ID */
@@ -52,7 +54,8 @@ typedef struct constcw {
 static const char *
 constcw_name(constcw_t *ccw)
 {
-  return idnode_get_title(&ccw->cac_id, NULL);
+  return idnode_get_title(&ccw->cac_id, NULL,
+                          ccw->ccw_name, sizeof(ccw->ccw_name));
 }
 
 /**
index 0abf9d30123df8ed71c9693510f8760130639649..ae04f873b9aaf337e3633a6eb7fe908598517a1c 100644 (file)
@@ -506,8 +506,9 @@ dvr_autorec_entry_class_perm(idnode_t *self, access_t *a, htsmsg_t *msg_to_write
   return 0;
 }
 
-static const char *
-dvr_autorec_entry_class_get_title (idnode_t *self, const char *lang)
+static void
+dvr_autorec_entry_class_get_title
+  (idnode_t *self, const char *lang, char *dst, size_t dstsize)
 {
   dvr_autorec_entry_t *dae = (dvr_autorec_entry_t *)self;
   const char *s = "";
@@ -515,7 +516,7 @@ dvr_autorec_entry_class_get_title (idnode_t *self, const char *lang)
     s = dae->dae_name;
   else if (dae->dae_comment && dae->dae_comment[0] != '\0')
     s = dae->dae_comment;
-  return s;
+  snprintf(dst, dstsize, "%s", s);
 }
 
 static int
index bcb09cfc729e108391de609c39db513778959719..0a25b6c8d96b526d33bc5a6ce851be8858437129 100644 (file)
@@ -682,13 +682,16 @@ dvr_config_class_profile_rend(void *o, const char *lang)
   return NULL;
 }
 
-static const char *
-dvr_config_class_get_title (idnode_t *self, const char *lang)
+static void
+dvr_config_class_get_title
+  (idnode_t *self, const char *lang, char *dst, size_t dstsize)
 {
   dvr_config_t *cfg = (dvr_config_t *)self;
-  if (!dvr_config_is_default(cfg))
-    return cfg->dvr_config_name;
-  return N_("(Default profile)");
+  if (!dvr_config_is_default(cfg)) {
+    snprintf(dst, dstsize, "%s", cfg->dvr_config_name);
+  } else {
+    snprintf(dst, dstsize, "%s", tvh_gettext_lang(lang, N_("(Default profile)")));
+  }
 }
 
 static int
index 6535a24becda521d1c5414fad4fd0b45280247f2..f548a4ca7333f290ca631a4a1b1fc8029dec75a7 100644 (file)
@@ -2634,8 +2634,9 @@ dvr_entry_class_perm(idnode_t *self, access_t *a, htsmsg_t *msg_to_write)
   return 0;
 }
 
-static const char *
-dvr_entry_class_get_title (idnode_t *self, const char *lang)
+static void
+dvr_entry_class_get_title
+  (idnode_t *self, const char *lang, char *dst, size_t dstsize)
 {
   dvr_entry_t *de = (dvr_entry_t *)self;
   const char *s;
@@ -2648,7 +2649,7 @@ dvr_entry_class_get_title (idnode_t *self, const char *lang)
         s = lang_str_get(de->de_desc, NULL);
     }
   }
-  return s;
+  snprintf(dst, dstsize, "%s", s);
 }
 
 static int
index ae1ca683652ad419049934170321cb4d8d307e12..be5ecd74d65a4db7585a804d018eca8fd800cfdf 100644 (file)
@@ -303,8 +303,9 @@ dvr_timerec_entry_class_perm(idnode_t *self, access_t *a, htsmsg_t *msg_to_write
   return 0;
 }
 
-static const char *
-dvr_timerec_entry_class_get_title (idnode_t *self, const char *lang)
+static void
+dvr_timerec_entry_class_get_title
+  (idnode_t *self, const char *lang, char *dst, size_t dstsize)
 {
   dvr_timerec_entry_t *dte = (dvr_timerec_entry_t *)self;
   const char *s = "";
@@ -312,7 +313,7 @@ dvr_timerec_entry_class_get_title (idnode_t *self, const char *lang)
     s = dte->dte_name;
   else if (dte->dte_comment && dte->dte_comment[0] != '\0')
     s = dte->dte_comment;
-  return s;
+  snprintf(dst, dstsize, "%s", s);
 }
 
 static int
index 9b82217fefcd9eb71df83b10e835a0f85cff6ee9..f9e98b52c757b4f0d507e902d7e4001277ac7ed1 100644 (file)
@@ -539,14 +539,14 @@ epggrab_channel_is_ota ( epggrab_channel_t *ec )
  * Class
  */
 
-static const char *
-epggrab_channel_class_get_title(idnode_t *self, const char *lang)
+static void
+epggrab_channel_class_get_title
+  (idnode_t *self, const char *lang, char *dst, size_t dstsize)
 {
   epggrab_channel_t *ec = (epggrab_channel_t*)self;
 
-  snprintf(prop_sbuf, PROP_SBUF_LEN, "%s: %s (%s)",
+  snprintf(dst, dstsize, "%s: %s (%s)",
            ec->name ?: ec->id, ec->id, ec->mod->name);
-  return prop_sbuf;
 }
 
 static htsmsg_t *
index fc9fa1e3e92c8905c1be38743bddefab25b4b077..ca1b238f2766d6de55088ad3d622d6908ec4ca04 100644 (file)
@@ -73,13 +73,13 @@ epggrab_module_get_status(epggrab_module_t *mod)
  * Class
  */
 
-static const char *epggrab_mod_class_title(idnode_t *self, const char *lang)
+static void epggrab_mod_class_title
+  (idnode_t *self, const char *lang, char *dst, size_t dstsize)
 {
   epggrab_module_t *mod = (epggrab_module_t *)self;
   const char *s1 = tvh_gettext_lang(lang, epggrab_module_type(mod));
   const char *s2 = tvh_str_default(mod->name, mod->id);
-  snprintf(prop_sbuf, PROP_SBUF_LEN, "%s: %s", s1, s2);
-  return prop_sbuf;
+  snprintf(dst, dstsize, "%s: %s", s1, s2);
 }
 
 static void
index 11949610b0cf7687c1ff1026d08998760f009dd7..a6bef849b768f08cfd8842b81a8a269b63bddaa9 100644 (file)
@@ -215,13 +215,6 @@ esfilter_class_save(idnode_t *self, char *filename, size_t fsize)
   return c;
 }
 
-static const char *
-esfilter_class_get_title(idnode_t *self, const char *lang)
-{
-  esfilter_t *esf = (esfilter_t *)self;
-  return idnode_uuid_as_str(&esf->esf_id, prop_sbuf);
-}
-
 static void
 esfilter_class_delete(idnode_t *self)
 {
@@ -594,7 +587,6 @@ const idclass_t esfilter_class = {
   .ic_event      = "esfilter",
   .ic_perm_def   = ACCESS_ADMIN,
   .ic_save       = esfilter_class_save,
-  .ic_get_title  = esfilter_class_get_title,
   .ic_delete     = esfilter_class_delete,
   .ic_moveup     = esfilter_class_moveup,
   .ic_movedown   = esfilter_class_movedown,
index 6380009717ab0774805b0452404a8ebee5d14203..1701f45ae9a47b26b5b101214d7b35c6f67d40f6 100644 (file)
@@ -41,15 +41,20 @@ typedef struct idclass_link
   RB_ENTRY(idclass_link) link;
 } idclass_link_t;
 
+pthread_mutex_t                 idnode_mutex = PTHREAD_MUTEX_INITIALIZER;
 static idnodes_rb_t             idnodes;
 static RB_HEAD(,idclass_link)   idclasses;
 static RB_HEAD(,idclass_link)   idrootclasses;
 static TAILQ_HEAD(,idnode_save) idnodes_save;
 
-tvh_cond_t save_cond;
-pthread_t save_tid;
-static int save_running;
-static mtimer_t save_timer;
+static tvh_cond_t save_cond;
+static pthread_t  save_tid;
+static int        save_running;
+static mtimer_t   save_timer;
+
+static pthread_mutex_t idnode_lnotify_mutex = PTHREAD_MUTEX_INITIALIZER;
+static tvh_uuid_set_t  idnode_lnotify_set;
+static tvh_uuid_set_t  idnode_lnotify_title_set;
 
 SKEL_DECLARE(idclasses_skel, idclass_link_t);
 
@@ -101,6 +106,8 @@ idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class, int flags)
 
   lock_assert(&global_lock);
 
+  idnode_lock();
+
   in->in_class = class;
   do {
 
@@ -145,6 +152,8 @@ idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class, int flags)
   c = RB_INSERT_SORTED(in->in_domain, in, in_domain_link, in_cmp);
   assert(c == NULL);
 
+  idnode_unlock();
+
   /* Fire event */
   idnode_notify(in, "create");
 
@@ -160,8 +169,10 @@ idnode_unlink(idnode_t *in)
   char ubuf[UUID_HEX_SIZE];
 
   lock_assert(&global_lock);
+  idnode_lock();
   RB_REMOVE(&idnodes, in, in_link);
   RB_REMOVE(in->in_domain, in, in_domain_link);
+  idnode_unlock();
   tvhtrace(LS_IDNODE, "unlink node %s", idnode_uuid_as_str(in, ubuf));
   idnode_notify(in, "delete");
   assert(in->in_save == NULL || in->in_save == SAVEPTR_OUTOFSERVICE);
@@ -232,15 +243,19 @@ idnode_uuid_as_str(const idnode_t *in, char *uuid)
  *
  */
 const char *
-idnode_get_title(idnode_t *in, const char *lang)
+idnode_get_title(idnode_t *in, const char *lang, char *dst, size_t dstsize)
 {
   static char ubuf[UUID_HEX_SIZE];
   const idclass_t *ic = in->in_class;
   for(; ic != NULL; ic = ic->ic_super) {
-    if(ic->ic_get_title != NULL)
-      return ic->ic_get_title(in, lang);
+    if(ic->ic_get_title != NULL) {
+      ic->ic_get_title(in, lang, dst, dstsize);
+      return dst;
+    }
   }
-  return idnode_uuid_as_str(in, ubuf);
+  strncpy(dst, idnode_uuid_as_str(in, ubuf), dstsize);
+  dst[dstsize-1] = 0;
+  return dst;
 }
 
 
@@ -701,9 +716,11 @@ idnode_cmp_title
 {
   idnode_t      *ina  = *(idnode_t**)a;
   idnode_t      *inb  = *(idnode_t**)b;
-  const char *sa = idnode_get_title(ina, (const char *)lang);
-  const char *sb = idnode_get_title(inb, (const char *)lang);
-  return strcmp(sa ?: "", sb ?: "");
+  char bufa[384];
+  char bufb[384];
+  idnode_get_title(ina, (const char *)lang, bufa, sizeof(bufa));
+  idnode_get_title(inb, (const char *)lang, bufb, sizeof(bufb));
+  return strcmp(bufa, bufb);
 }
 
 #define safecmp(a, b) ((a) > (b) ? 1 : ((a) < (b) ? -1 : 0))
@@ -1516,7 +1533,7 @@ idnode_serialize0(idnode_t *self, htsmsg_t *list, int optmask, const char *lang)
 {
   const idclass_t *idc = self->in_class;
   const char *uuid, *s;
-  char ubuf[UUID_HEX_SIZE];
+  char ubuf[UUID_HEX_SIZE], buf[384];
 
   htsmsg_t *m = htsmsg_create_map();
   if (!idc->ic_snode) {
@@ -1524,7 +1541,7 @@ idnode_serialize0(idnode_t *self, htsmsg_t *list, int optmask, const char *lang)
     htsmsg_add_str(m, "uuid", uuid);
     htsmsg_add_str(m, "id",   uuid);
   }
-  htsmsg_add_str(m, "text", idnode_get_title(self, lang) ?: "");
+  htsmsg_add_str(m, "text", idnode_get_title(self, lang, buf, sizeof(buf)) ?: "");
   if ((s = idclass_get_caption(idc, lang)))
     htsmsg_add_str(m, "caption", s);
   if ((s = idclass_get_class(idc)))
@@ -1759,9 +1776,10 @@ idnode_list_get_csv1
   char *str;
   idnode_list_mapping_t *ilm;
   htsmsg_t *l = htsmsg_create_list();
+  char buf[384];
 
   LIST_FOREACH(ilm, in1_list, ilm_in1_link)
-    htsmsg_add_str(l, NULL, idnode_get_title(ilm->ilm_in2, lang));
+    htsmsg_add_str(l, NULL, idnode_get_title(ilm->ilm_in2, lang, buf, sizeof(buf)));
 
   str = htsmsg_list_2_csv(l, ',', 1);
   htsmsg_destroy(l);
@@ -1775,9 +1793,10 @@ idnode_list_get_csv2
   char *str;
   idnode_list_mapping_t *ilm;
   htsmsg_t *l = htsmsg_create_list();
+  char buf[384];
 
   LIST_FOREACH(ilm, in2_list, ilm_in2_link)
-    htsmsg_add_str(l, NULL, idnode_get_title(ilm->ilm_in1, lang));
+    htsmsg_add_str(l, NULL, idnode_get_title(ilm->ilm_in1, lang, buf, sizeof(buf)));
 
   str = htsmsg_list_2_csv(l, ',', 1);
   htsmsg_destroy(l);
@@ -1898,16 +1917,21 @@ idnode_notify_changed (void *in)
 }
 
 void
-idnode_notify_title_changed (void *in, const char *lang)
+idnode_notify_title_changed (void *in)
 {
   char ubuf[UUID_HEX_SIZE];
   htsmsg_t *m = htsmsg_create_map();
   htsmsg_add_str(m, "uuid", idnode_uuid_as_str(in, ubuf));
-  htsmsg_add_str(m, "text", idnode_get_title(in, lang));
-  notify_by_msg("title", m, 0);
+  notify_by_msg("title", m, NOTIFY_REWRITE_TITLE);
   idnode_notify_changed(in);
 }
 
+void
+idnode_notify_title_changed_lang (void *in, const char *lang)
+{
+  return idnode_notify_title_changed(in);
+}
+
 /* **************************************************************************
  * Save thread
  * *************************************************************************/
@@ -1916,32 +1940,69 @@ static void *
 save_thread ( void *aux )
 {
   idnode_save_t *ise;
+  idnode_t *in;
   htsmsg_t *m;
+  uint32_t u32;
+  tvh_uuid_t *uuid;
   char filename[PATH_MAX];
+  tvh_uuid_set_t set, tset;
+
+  uuid_set_init(&set, 10);
+  uuid_set_init(&tset, 10);
 
   tvhthread_renice(15);
 
   pthread_mutex_lock(&global_lock);
 
   while (atomic_get(&save_running)) {
-    if ((ise = TAILQ_FIRST(&idnodes_save)) == NULL ||
-        (ise->ise_reqtime + IDNODE_SAVE_DELAY > mclk())) {
+    if (((ise = TAILQ_FIRST(&idnodes_save)) == NULL ||
+         (ise->ise_reqtime + IDNODE_SAVE_DELAY > mclk())) &&
+         uuid_set_empty(&idnode_lnotify_set) &&
+         uuid_set_empty(&idnode_lnotify_title_set)) {
       if (ise)
         mtimer_arm_abs(&save_timer, idnode_save_trigger_thread_cb, NULL,
                        ise->ise_reqtime + IDNODE_SAVE_DELAY);
       tvh_cond_wait(&save_cond, &global_lock);
       continue;
     }
-    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);
+    if (ise) {
+      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_lock(&idnode_lnotify_mutex);
+    if (!uuid_set_empty(&idnode_lnotify_set)) {
+      set = idnode_lnotify_set;
+      uuid_set_init(&idnode_lnotify_set, 10);
+    }
+    if (!uuid_set_empty(&idnode_lnotify_title_set)) {
+      tset = idnode_lnotify_title_set;
+      uuid_set_init(&idnode_lnotify_title_set, 10);
+    }
+    pthread_mutex_unlock(&idnode_lnotify_mutex);
+    if (!uuid_set_empty(&set)) {
+      UUID_SET_FOREACH(uuid, &set, u32) {
+        in = idnode_find0(uuid, NULL, NULL);
+        if (in)
+         idnode_notify_changed(in);
+      }
+      uuid_set_free(&set);
+    }
+    if (!uuid_set_empty(&tset)) {
+      UUID_SET_FOREACH(uuid, &tset, u32) {
+        in = idnode_find0(uuid, NULL, NULL);
+        if (in)
+          idnode_notify_title_changed(in);
+      }
+      uuid_set_free(&tset);
     }
-    pthread_mutex_lock(&global_lock);
   }
 
   mtimer_disarm(&save_timer);
@@ -1963,6 +2024,26 @@ save_thread ( void *aux )
   return NULL;
 }
 
+/* **************************************************************************
+ * Light update - outside global lock
+ * *************************************************************************/
+
+void idnode_lnotify_changed( void *in )
+{
+  pthread_mutex_lock(&idnode_lnotify_mutex);
+  uuid_set_add(&idnode_lnotify_set, &((idnode_t *)in)->in_uuid);
+  pthread_mutex_unlock(&idnode_lnotify_mutex);
+  tvh_cond_signal(&save_cond, 0);
+}
+
+void idnode_lnotify_title_changed( void *in )
+{
+  pthread_mutex_lock(&idnode_lnotify_mutex);
+  uuid_set_add(&idnode_lnotify_title_set, &((idnode_t *)in)->in_uuid);
+  pthread_mutex_unlock(&idnode_lnotify_mutex);
+  tvh_cond_signal(&save_cond, 0);
+}
+
 /* **************************************************************************
  * Initialization
  * *************************************************************************/
@@ -1975,6 +2056,8 @@ idnode_boot(void)
   RB_INIT(&idrootclasses);
   TAILQ_INIT(&idnodes_save);
   tvh_cond_init(&save_cond);
+  uuid_set_init(&idnode_lnotify_set, 10);
+  uuid_set_init(&idnode_lnotify_title_set, 10);
 }
 
 void
@@ -2003,6 +2086,9 @@ idnode_done(void)
     free(il);
   }
   SKEL_FREE(idclasses_skel);
+
+  uuid_set_free(&idnode_lnotify_set);
+  uuid_set_free(&idnode_lnotify_title_set);
 }
 
 /******************************************************************************
index 8ffafe962139e4c77e508c3e6b0cc766f37f5183..506518852a29e01b15d1bdf8220356f46c9af829 100644 (file)
@@ -79,7 +79,7 @@ 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_get_title)  (idnode_t *self, const char *lang, char *dst, size_t dstsize);
   void            (*ic_changed)    (idnode_t *self);
   htsmsg_t       *(*ic_save)       (idnode_t *self, char *filename, size_t fsize);
   void            (*ic_load)       (idnode_t *self, htsmsg_t *conf);
@@ -194,11 +194,17 @@ typedef LIST_HEAD(,idnode_filter_ele) idnode_filter_t;
 
 extern idnode_t tvhlog_conf;
 extern const idclass_t tvhlog_conf_class;
+extern pthread_mutex_t idnode_mutex;
 
 void idnode_boot(void);
 void idnode_init(void);
 void idnode_done(void);
 
+static inline void idnode_lock(void)
+  { pthread_mutex_lock(&idnode_mutex); }
+static inline void idnode_unlock(void)
+  { pthread_mutex_unlock(&idnode_mutex); }
+
 #define IDNODE_SHORT_UUID (1<<0)
 
 int  idnode_insert(idnode_t *in, const char *uuid, const idclass_t *idc, int flags);
@@ -207,7 +213,7 @@ void idnode_unlink(idnode_t *in);
 uint32_t      idnode_get_short_uuid (const idnode_t *in);
 const char   *idnode_uuid_as_str  (const idnode_t *in, char *buf);
 idnode_set_t *idnode_get_childs   (idnode_t *in);
-const char   *idnode_get_title    (idnode_t *in, const char *lang);
+const char   *idnode_get_title    (idnode_t *in, const char *lang, char *dst, size_t dstsize);
 int           idnode_is_leaf      (idnode_t *in);
 int           idnode_is_instance  (idnode_t *in, const idclass_t *idc);
 void          idnode_delete       (idnode_t *in);
@@ -223,7 +229,11 @@ idnode_set_t *idnode_find_all(const idclass_t *idc, const idnodes_rb_t *nodes);
 
 void idnode_notify (idnode_t *in, const char *action);
 void idnode_notify_changed (void *in);
-void idnode_notify_title_changed (void *in, const char *lang);
+void idnode_notify_title_changed (void *in);
+void idnode_notify_title_changed_lang (void *in, const char *lang);
+
+void idnode_lnotify_changed (void *in);
+void idnode_lnotify_title_changed (void *in);
 
 void idclass_register ( const idclass_t *idc );
 const idclass_t *idclass_find ( const char *name );
index bf8b4d62fb5bcd07a782a9513194e5374d47877f..10227721eddfb8ecc4bea923d41dfeae05a2427b 100644 (file)
@@ -84,10 +84,11 @@ iptv_handler_find ( const char *scheme )
  * IPTV input
  * *************************************************************************/
 
-static const char *
-iptv_input_class_get_title ( idnode_t *self, const char *lang )
+static void
+iptv_input_class_get_title
+  ( idnode_t *self, const char *lang, char *dst, size_t dstsize )
 {
-  return tvh_gettext_lang(lang, N_("IPTV"));
+  snprintf(dst, dstsize, "%s", tvh_gettext_lang(lang, N_("IPTV")));
 }
 
 extern const idclass_t mpegts_input_class;
@@ -516,6 +517,7 @@ iptv_input_recv_packets ( iptv_mux_t *im, ssize_t len )
   iptv_network_t *in = (iptv_network_t*)im->mm_network;
   mpegts_mux_instance_t *mmi;
   mpegts_pcr_t pcr;
+  char buf[384];
   int64_t s64;
 
   pcr.pcr_first = PTS_UNSET;
@@ -528,7 +530,7 @@ iptv_input_recv_packets ( iptv_mux_t *im, ssize_t len )
         in->in_bps > in->in_max_bandwidth * 1024) {
       if (!in->in_bw_limited) {
         tvhinfo(LS_IPTV, "%s bandwidth limited exceeded",
-                idnode_get_title(&in->mn_id, NULL));
+                idnode_get_title(&in->mn_id, NULL, buf, sizeof(buf)));
         in->in_bw_limited = 1;
       }
     }
index 69c4ecd6e433a8c3c2d92580e38395bfb8481cc6..37f57d0935cfd193de9cf502075232a4c484bc56 100644 (file)
@@ -103,11 +103,12 @@ linuxdvb_adapter_class_get_childs ( idnode_t *in )
   return is;
 }
 
-static const char *
-linuxdvb_adapter_class_get_title ( idnode_t *in, const char *lang )
+static void
+linuxdvb_adapter_class_get_title
+  ( idnode_t *in, const char *lang, char *dst, size_t dstsize )
 {
   linuxdvb_adapter_t *la = (linuxdvb_adapter_t*)in;
-  return la->la_name ?: la->la_rootpath;
+  snprintf(dst, dstsize, "%s", la->la_name ?: la->la_rootpath);
 }
 
 static const void *
index 238b883d4a682b2a9c5a0df7887660b194d91d26..41802342647c8dd4ea42383842b690de1087e2a6 100644 (file)
@@ -162,7 +162,7 @@ linuxdvb_ca_class_enabled_notify ( void *p, const char *lang )
 #endif
     }
 
-    idnode_notify_title_changed(&lca->lca_id, lang);
+    idnode_notify_title_changed(&lca->lca_id);
   }
 }
 
@@ -175,20 +175,18 @@ linuxdvb_ca_class_high_bitrate_notify ( void *p, const char *lang )
                                  CIPLUS13_DATA_RATE_72_MBPS);
 }
 
-static const char *
-linuxdvb_ca_class_get_title ( idnode_t *in, const char *lang )
+static void
+linuxdvb_ca_class_get_title
+  ( idnode_t *in, const char *lang, char *dst, size_t dstsize )
 {
   linuxdvb_ca_t *lca = (linuxdvb_ca_t *) in;
-  static char buf[256];
   if (!lca->lca_enabled)
-    snprintf(buf, sizeof(buf), "ca%u: disabled", lca->lca_number);
+    snprintf(dst, dstsize, "ca%u: disabled", lca->lca_number);
   else if (lca->lca_state == CA_SLOT_STATE_EMPTY)
-    snprintf(buf, sizeof(buf), "ca%u: slot empty", lca->lca_number);
+    snprintf(dst, dstsize, "ca%u: slot empty", lca->lca_number);
   else
-    snprintf(buf, sizeof(buf), "ca%u: %s (%s)", lca->lca_number,
-           lca->lca_cam_menu_string, lca->lca_state_str);
-
-  return buf;
+    snprintf(dst, dstsize, "ca%u: %s (%s)", lca->lca_number,
+            lca->lca_cam_menu_string, lca->lca_state_str);
 }
 
 static const void *
@@ -529,7 +527,7 @@ linuxdvb_ca_ai_callback(void *arg, uint8_t slot_id, uint16_t session_num,
     snprintf(lca->lca_cam_menu_string, sizeof(lca->lca_cam_menu_string),
              "%.*s", menu_string_len, menu_string);
 
-    idnode_notify_title_changed(&lca->lca_id, NULL);
+    idnode_notify_title_changed(&lca->lca_id);
 
     return 0;
 }
@@ -804,7 +802,7 @@ linuxdvb_ca_monitor ( void *aux )
   if (lca->lca_state != state) {
     tvhnotice(LS_LINUXDVB, "%s: CAM slot %u status changed to %s",
                            lca->lca_name, csi.num, lca->lca_state_str);
-    idnode_notify_title_changed(&lca->lca_id, NULL);
+    idnode_notify_title_changed(&lca->lca_id);
     lca->lca_state = state;
   }
 
index 9c815959e5016c1142b5053b7a468dd465b2feb4..6a7d26f8da74ef34a7c7dfc163e6a8389a67124f 100644 (file)
 /* prevention of self raised DiSEqC collisions */
 static pthread_mutex_t linuxdvb_en50494_lock;
 
-static const char *
-linuxdvb_en50494_class_get_title ( idnode_t *o, const char *lang )
+static void
+linuxdvb_en50494_class_get_title
+  ( idnode_t *o, const char *lang, char *dst, size_t dstsize )
 {
-  static const char *title = N_("Unicable I (EN50494)");
-  return tvh_gettext_lang(lang, title);
+  const char *title = N_("Unicable I (EN50494)");
+  snprintf(dst, dstsize, "%s", tvh_gettext_lang(lang, title));
 }
 
-static const char *
-linuxdvb_en50607_class_get_title ( idnode_t *o, const char *lang )
+static void
+linuxdvb_en50607_class_get_title
+  ( idnode_t *o, const char *lang, char *dst, size_t dstsize )
 {
-  static const char *title = N_("Unicable II (EN50607)");
-  return tvh_gettext_lang(lang, title);
+  const char *title = N_("Unicable II (EN50607)");
+  snprintf(dst, dstsize, "%s", tvh_gettext_lang(lang, title));
 }
 
 static htsmsg_t *
index 754f1bfdef2ec6a7fd4631d44985259499d6548c..2a976d05e2ff0fb8d464778f2a1bf18c62bd0868 100644 (file)
@@ -43,13 +43,12 @@ typedef struct linuxdvb_lnb_conf
   int lnb_switch;
 } linuxdvb_lnb_conf_t;
 
-static const char *
-linuxdvb_lnb_class_get_title ( idnode_t *o, const char *lang )
+static void
+linuxdvb_lnb_class_get_title
+  ( idnode_t *o, const char *lang, char *dst, size_t dstsize )
 {
-  static char buf[256];
   linuxdvb_diseqc_t *ld = (linuxdvb_diseqc_t*)o;
-  snprintf(buf, sizeof(buf), "LNB: %s", ld->ld_type);
-  return buf;
+  snprintf(dst, dstsize, tvh_gettext_lang(lang, N_("LNB: %s")), ld->ld_type);
 }
 
 extern const idclass_t linuxdvb_diseqc_class;
index 698dce91c09cfb1b7cb8568fe3c956641a420c9b..0ee2d6fe73678dc7e46bbc4661d60a6602a050ed 100644 (file)
@@ -75,13 +75,12 @@ typedef struct linuxdvb_rotor
 
 #ifndef ROTOR_TEST
 
-static const char *
-linuxdvb_rotor_class_get_title ( idnode_t *o, const char *lang )
+static void
+linuxdvb_rotor_class_get_title
+  ( idnode_t *o, const char *lang, char *dst, size_t dstsize )
 {
-  static char buf[256];
   linuxdvb_diseqc_t *ld = (linuxdvb_diseqc_t*)o;
-  snprintf(buf, sizeof(buf), "Rotor: %s", ld->ld_type);
-  return buf;
+  snprintf(dst, dstsize, tvh_gettext_lang(lang, N_("Rotor: %s")), ld->ld_type);
 }
 
 extern const idclass_t linuxdvb_diseqc_class;
index 75944c3ec0efe851b5c831f917d6ebafc5ab5752..3c78e40291cad6499a6125157faeecf58cddd171 100644 (file)
@@ -147,13 +147,14 @@ linuxdvb_satconf_class_network_getset(1);
 linuxdvb_satconf_class_network_getset(2);
 linuxdvb_satconf_class_network_getset(3);
 
-static const char *
-linuxdvb_satconf_class_get_title ( idnode_t *p, const char *lang )
+static void
+linuxdvb_satconf_class_get_title
+  ( idnode_t *p, const char *lang, char *dst, size_t dstsize )
 {
   linuxdvb_satconf_t *ls = (linuxdvb_satconf_t*)p;
   struct linuxdvb_satconf_type *lst =
     linuxdvb_satconf_type_find(ls->ls_type);
-  return lst ? lst->name : ls->ls_type;
+  snprintf(dst, dstsize, "%s", lst ? lst->name : ls->ls_type);
 }
 
 static void
@@ -1419,10 +1420,11 @@ linuxdvb_satconf_ele_class_rotortype_get ( void *o )
   return &prop_ptr;
 }
 
-static const char *
-linuxdvb_satconf_ele_class_get_title ( idnode_t *o, const char *lang )
+static void
+linuxdvb_satconf_ele_class_get_title
+  ( idnode_t *o, const char *lang, char *dst, size_t dstsize )
 {
-  return ((linuxdvb_satconf_ele_t *)o)->lse_name;
+  snprintf(dst, dstsize, "%s", ((linuxdvb_satconf_ele_t *)o)->lse_name);
 }
 
 static idnode_set_t *
@@ -1487,7 +1489,7 @@ const idclass_t linuxdvb_satconf_ele_class =
       .id       = "displayname",
       .name     = N_("Name"),
       .off      = offsetof(linuxdvb_satconf_ele_t, lse_name),
-      .notify   = idnode_notify_title_changed,
+      .notify   = idnode_notify_title_changed_lang,
     },
     {
       .type     = PT_INT,
@@ -1630,11 +1632,12 @@ linuxdvb_satconf_delete ( linuxdvb_satconf_t *ls, int delconf )
  * DiseqC
  *****************************************************************************/
 
-static const char *
-linuxdvb_diseqc_class_get_title ( idnode_t *o, const char *lang )
+static void
+linuxdvb_diseqc_class_get_title
+  ( idnode_t *o, const char *lang, char *dst, size_t dstsize )
 {
   linuxdvb_diseqc_t *ld = (linuxdvb_diseqc_t*)o;
-  return ld->ld_type;
+  snprintf(dst, dstsize, "%s", ld->ld_type);
 }
 
 static void
index e53279a2ccf7c5df9219b7903d3c5a3b8b86564a..e9e61192c6e47ea3fc43ca1cc20bb9961a9cf94a 100644 (file)
@@ -98,13 +98,12 @@ linuxdvb_switch_class_toneburst_list ( void *o, const char *lang )
   return strtab2htsmsg(tab, 1, lang);
 }
 
-static const char *
-linuxdvb_switch_class_get_title ( idnode_t *o, const char *lang )
+static void
+linuxdvb_switch_class_get_title
+  ( idnode_t *o, const char *lang, char *dst, size_t dstsize )
 {
-  static char buf[256];
   linuxdvb_diseqc_t *ld = (linuxdvb_diseqc_t*)o;
-  snprintf(buf, sizeof(buf), tvh_gettext_lang(lang, N_("Switch: %s")), ld->ld_type);
-  return buf;
+  snprintf(dst, dstsize, tvh_gettext_lang(lang, N_("Switch: %s")), ld->ld_type);
 }
 
 extern const idclass_t linuxdvb_diseqc_class;
index 1d090f43e0861665c8d4db0cb74992523e69d3af..9a0733324828755292a71c4df728ed4a84fef906 100644 (file)
@@ -57,13 +57,12 @@ mpegts_input_dbus_notify(mpegts_input_t *mi, int64_t subs)
  * Class definition
  * *************************************************************************/
 
-static const char *
-mpegts_input_class_get_title ( idnode_t *in, const char *lang )
+static void
+mpegts_input_class_get_title
+  ( idnode_t *in, const char *lang, char *dst, size_t dstsize )
 {
-  static char buf[512];
   mpegts_input_t *mi = (mpegts_input_t*)in;
-  mi->mi_display_name(mi, buf, sizeof(buf));
-  return buf;
+  mi->mi_display_name(mi, dst, dstsize);
 }
 
 const void *
@@ -121,11 +120,15 @@ mpegts_input_class_network_rend ( void *obj, const char *lang )
 {
   char *str;
   mpegts_network_link_t *mnl;  
+  mpegts_network_t *mn;
   mpegts_input_t *mi = obj;
   htsmsg_t        *l = htsmsg_create_list();
+  char buf[384];
 
-  LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link)
-    htsmsg_add_str(l, NULL, idnode_get_title(&mnl->mnl_network->mn_id, lang));
+  LIST_FOREACH(mnl, &mi->mi_networks, mnl_mi_link) {
+    mn = mnl->mnl_network;
+    htsmsg_add_str(l, NULL, idnode_get_title(&mn->mn_id, lang, buf, sizeof(buf)));
+  }
 
   str = htsmsg_list_2_csv(l, ',', 1);
   htsmsg_destroy(l);
@@ -197,7 +200,7 @@ mpegts_input_class_linked_enum( void * self, const char *lang )
 {
   mpegts_input_t *mi = self, *mi2;
   tvh_input_t *ti;
-  char ubuf[UUID_HEX_SIZE];
+  char ubuf[UUID_HEX_SIZE], buf[384];
   htsmsg_t *m = htsmsg_create_list();
   htsmsg_t *e = htsmsg_create_key_val("", tvh_gettext_lang(lang, N_("Not linked")));
   htsmsg_add_msg(m, NULL, e);
@@ -206,7 +209,7 @@ mpegts_input_class_linked_enum( void * self, const char *lang )
       mi2 = (mpegts_input_t *)ti;
       if (mi2 != mi) {
         e = htsmsg_create_key_val(idnode_uuid_as_str(&ti->ti_id, ubuf),
-                                  idnode_get_title(&mi2->ti_id, lang));
+                                  idnode_get_title(&mi2->ti_id, lang, buf, sizeof(buf)));
         htsmsg_add_msg(m, NULL, e);
       }
   }
@@ -271,7 +274,7 @@ const idclass_t mpegts_input_class =
       .name     = N_("Name"),
       .desc     = N_("Name of the tuner/adapter."),
       .off      = offsetof(mpegts_input_t, mi_name),
-      .notify   = idnode_notify_title_changed,
+      .notify   = idnode_notify_title_changed_lang,
     },
     {
       .type     = PT_BOOL,
index 6e9a124412cb302bb6868c97e0b4ac3b5dc03754..3421f495caab4a50b8781ef7fd0c980a5a453d31 100644 (file)
@@ -314,12 +314,11 @@ mpegts_mux_class_delete ( idnode_t *self )
   if (mm->mm_delete) mm->mm_delete(mm, 1);
 }
 
-static const char *
-mpegts_mux_class_get_title ( idnode_t *self, const char *lang )
+static void
+mpegts_mux_class_get_title
+  ( idnode_t *self, const char *lang, char *dst, size_t dstsize )
 {
-  static __thread char buf[256];
-  mpegts_mux_nice_name((mpegts_mux_t*)self, buf, sizeof(buf));
-  return buf;
+  mpegts_mux_nice_name((mpegts_mux_t*)self, dst, dstsize);
 }
 
 static const void *
index 1f3e367250b08a6b7fefe832911e34f656e23f8a..f4114db4518340e0280ecec740180755bca9b03b 100644 (file)
@@ -41,15 +41,14 @@ mpegts_network_class_save
   return NULL;
 }
 
-static const char *
-mpegts_network_class_get_title ( idnode_t *in, const char *lang )
+static void
+mpegts_network_class_get_title
+  ( idnode_t *in, const char *lang, char *dst, size_t dstsize )
 {
-  static char buf[256];
   mpegts_network_t *mn = (mpegts_network_t*)in;
-  *buf = 0;
+  *dst = 0;
   if (mn->mn_display_name)
-    mn->mn_display_name(mn, buf, sizeof(buf));
-  return buf;
+    mn->mn_display_name(mn, dst, dstsize);
 }
 
 static const void *
@@ -176,7 +175,7 @@ const idclass_t mpegts_network_class =
       .name     = N_("Network name"),
       .desc     = N_("Name of the network."),
       .off      = offsetof(mpegts_network_t, mn_network_name),
-      .notify   = idnode_notify_title_changed,
+      .notify   = idnode_notify_title_changed_lang,
     },
     {
       .type     = PT_STR,
index 766c9f5f55dfa9de93e0738569d38efbfae7660a..778a16f55ef0ec87e1f944e8e875e60bd43aeaeb 100644 (file)
@@ -171,14 +171,12 @@ satip_device_class_get_childs ( idnode_t *in )
   return is;
 }
 
-static const char *
-satip_device_class_get_title( idnode_t *in, const char *lang )
+static void
+satip_device_class_get_title
+  ( idnode_t *in, const char *lang, char *dst, size_t dstsize )
 {
-  static char buf[256];
   satip_device_t *sd = (satip_device_t *)in;
-  snprintf(buf, sizeof(buf),
-           "%s - %s", sd->sd_info.friendlyname, sd->sd_info.addr);
-  return buf;
+  snprintf(dst, dstsize, "%s - %s", sd->sd_info.friendlyname, sd->sd_info.addr);
 }
 
 static const char *satip_tunercfg_tab[] = {
index 14465cd5b988abc164df50e007c9f39339457144..8fb0465dcd21dd8f543a18870bc50a93f244a6d4 100644 (file)
@@ -317,10 +317,11 @@ satip_satconf_class_network_rend( void *o, const char *lang )
   return str;
 }
 
-static const char *
-satip_satconf_class_get_title ( idnode_t *o, const char *lang )
+static void
+satip_satconf_class_get_title
+  ( idnode_t *o, const char *lang, char *dst, size_t size )
 {
-  return ((satip_satconf_t *)o)->sfc_name;
+  snprintf(dst, size, "%s", ((satip_satconf_t *)o)->sfc_name);
 }
 
 static void
@@ -362,7 +363,7 @@ const idclass_t satip_satconf_class =
       .name     = N_("Name"),
       .desc     = N_("Set the display name."),
       .off      = offsetof(satip_satconf_t, sfc_name),
-      .notify   = idnode_notify_title_changed,
+      .notify   = idnode_notify_title_changed_lang,
     },
     {
       .type     = PT_INT,
index 7e4f0d76d94efbaf855f5a1ef2ba87ae75cf362a..228229c4bfd1a3c09001b2c780ccbb21e80c53ba 100644 (file)
@@ -83,15 +83,15 @@ static pthread_t tvhdhomerun_discovery_tid;
 static pthread_mutex_t tvhdhomerun_discovery_lock;
 static tvh_cond_t tvhdhomerun_discovery_cond;
 
-static const char *
-tvhdhomerun_device_class_get_title( idnode_t *in, const char *lang )
+static void
+tvhdhomerun_device_class_get_title
+  ( idnode_t *in, const char *lang, char *dst, size_t dstsize )
 {
   tvhdhomerun_device_t *hd = (tvhdhomerun_device_t *)in;
   char ip[64];
   tcp_get_str_from_ip(&hd->hd_info.ip_address, ip, sizeof(ip));
-  snprintf(prop_sbuf, PROP_SBUF_LEN,
+  snprintf(dst, dstsize,
            "%s - %s", hd->hd_info.friendlyname, ip);
-  return prop_sbuf;
 }
 
 static const void *
index c23b5677f541087b7022db0b3b1ae735c90c07d3..8039164a522e6fc88293a26230e28b3b8b7efe56 100644 (file)
 
 struct memoryinfo_list memoryinfo_entries;
 
-static const char *
-service_class_get_title ( idnode_t *self, const char *lang )
+static void
+service_class_get_title
+  ( idnode_t *self, const char *lang, char *dst, size_t dstsize )
 {
-  return ((memoryinfo_t *)self)->my_name;
+  snprintf(dst, dstsize, "%s", ((memoryinfo_t *)self)->my_name);
 }
 
 CLASS_DOC(memoryinfo)
index a494516291ab586c143389bf2b18bb9369dbf3ca..570c93a71561b27a1a33fbfe08f9391e308438c1 100644 (file)
@@ -21,7 +21,8 @@
 
 #include "htsmsg.h"
 
-#define NOTIFY_REWRITE_SUBSCRIPTIONS 1
+#define NOTIFY_REWRITE_TITLE         1
+#define NOTIFY_REWRITE_SUBSCRIPTIONS 2
 
 void notify_by_msg(const char *class, htsmsg_t *m, int rewrite);
 
index c8919a2afd0d3a341239f052babf2d83dd6f9442..df8b03395f1f3bcff9026063702f51e9483388f8 100644 (file)
@@ -167,14 +167,16 @@ profile_class_save ( idnode_t *in, char *filename, size_t fsize )
   return c;
 }
 
-static const char *
-profile_class_get_title ( idnode_t *in, const char *lang )
+static void
+profile_class_get_title
+  ( idnode_t *in, const char *lang, char *dst, size_t dstsize )
 {
   profile_t *pro = (profile_t *)in;
-  if (pro->pro_name && pro->pro_name[0])
-    return pro->pro_name;
-  snprintf(prop_sbuf, sizeof(prop_sbuf), "%s", idclass_get_caption(in->in_class, lang));
-  return prop_sbuf;
+  if (pro->pro_name && pro->pro_name[0]) {
+    snprintf(dst, dstsize, "%s", pro->pro_name);
+  } else {
+    snprintf(dst, dstsize, "%s", idclass_get_caption(in->in_class, lang));
+  }
 }
 
 static void
@@ -331,7 +333,7 @@ const idclass_t profile_class =
       .desc     = N_("The name of the profile."),
       .off      = offsetof(profile_t, pro_name),
       .get_opts = profile_class_name_opts,
-      .notify   = idnode_notify_title_changed,
+      .notify   = idnode_notify_title_changed_lang,
       .group    = 1
     },
     {
index 80b6ac518293cdff3afffa982e25667e217fcfc9..beb33c781c95338908e57b82953937f5df2fca3a 100644 (file)
@@ -96,10 +96,12 @@ service_class_channel_set
                           service_mapper_create);
 }
 
-static const char *
-service_class_get_title ( idnode_t *self, const char *lang )
+static void
+service_class_get_title
+  ( idnode_t *self, const char *lang, char *dst, size_t dstsize )
 {
-  return service_get_full_channel_name((service_t *)self);
+  snprintf(dst, dstsize, "%s",
+           service_get_full_channel_name((service_t *)self) ?: "");
 }
 
 static const void *
index e55f0e0e31f22a86488ae39540729dc430f4898d..a176c9626f461dd25fed6ce2c915a5f106f53e60 100644 (file)
@@ -1069,7 +1069,8 @@ subscription_create_msg(th_subscription_t *s, const char *lang)
     if (s->ths_prch != NULL) {
       pro = s->ths_prch->prch_pro;
       if (pro)
-        htsmsg_add_str(m, "profile", idnode_get_title(&pro->pro_id, lang));
+        htsmsg_add_str(m, "profile",
+                       idnode_get_title(&pro->pro_id, lang, buf, sizeof(buf)));
     }
 
   } else if(s->ths_dvrfile != NULL)
index 0dfaccaf68890ca0903ae72d66b7dba086472b74..0d3dec0cc297780c2cad3b78d917096ad03dc838 100644 (file)
@@ -523,10 +523,28 @@ comet_mailbox_rewrite_str(htsmsg_t *m, const char *key, const char *lang)
   }
 }
 
+static void
+comet_mailbox_rewrite_title(htsmsg_t *m, const char *lang)
+{
+  idnode_t *in;
+  const char *s = htsmsg_get_str(m, "uuid");
+  char buf[384];
+  if (s) {
+    idnode_lock();
+    in = idnode_find(s, NULL, NULL);
+    if (in)
+      htsmsg_set_str(m, "text", idnode_get_title(in, lang, buf, sizeof(buf)));
+    idnode_unlock();
+  }
+}
+
 static void
 comet_mailbox_rewrite_msg(int rewrite, htsmsg_t *m, const char *lang)
 {
   switch (rewrite) {
+  case NOTIFY_REWRITE_TITLE:
+    comet_mailbox_rewrite_title(m, lang);
+    break;
   case NOTIFY_REWRITE_SUBSCRIPTIONS:
     comet_mailbox_rewrite_str(m, "state", lang);
     break;