diff --git a/src/idnode.c b/src/idnode.c
index e8f356d5..7952d0ad 100644
--- a/src/idnode.c
+++ b/src/idnode.c
@@ -1,3 +1,22 @@
+/*
+ * Tvheadend - idnode (class) system
+ *
+ * Copyright (C) 2013 Andreas Öman
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
#define _GNU_SOURCE
#include
#include
@@ -10,11 +29,14 @@
#include "notify.h"
#include "settings.h"
-static int randfd = 0;
+static int randfd = 0;
+static RB_HEAD(,idnode) idnodes;
-RB_HEAD(idnode_tree, idnode);
+static void idnode_updated(idnode_t *in, int optmask);
-static struct idnode_tree idnodes;
+/* **************************************************************************
+ * Utilities
+ * *************************************************************************/
/**
*
@@ -71,6 +93,18 @@ bin2hex(char *dst, size_t dstlen, const uint8_t *src, size_t srclen)
*dst = 0;
}
+/**
+ *
+ */
+static int
+in_cmp(const idnode_t *a, const idnode_t *b)
+{
+ return memcmp(a->in_uuid, b->in_uuid, 16);
+}
+
+/* **************************************************************************
+ * Registration
+ * *************************************************************************/
/**
*
@@ -83,17 +117,6 @@ idnode_init(void)
exit(1);
}
-
-/**
- *
- */
-static int
-in_cmp(const idnode_t *a, const idnode_t *b)
-{
- return memcmp(a->in_uuid, b->in_uuid, 16);
-}
-
-
/**
*
*/
@@ -121,6 +144,18 @@ idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class)
return 0;
}
+/**
+ *
+ */
+void
+idnode_unlink(idnode_t *in)
+{
+ RB_REMOVE(&idnodes, in, in_link);
+}
+
+/* **************************************************************************
+ * Info
+ * *************************************************************************/
/**
*
@@ -136,61 +171,6 @@ idnode_uuid_as_str(const idnode_t *in)
return b;
}
-
-/**
- *
- */
-void *
-idnode_find(const char *uuid, const idclass_t *idc)
-{
- idnode_t skel, *r;
-
- if(hex2bin(skel.in_uuid, 16, uuid))
- return NULL;
- r = RB_FIND(&idnodes, &skel, in_link, in_cmp);
- if(r != NULL && idc != NULL) {
- const idclass_t *c = r->in_class;
- for(;c != NULL; c = c->ic_super) {
- if(idc == c)
- return r;
- }
- return NULL;
- }
- return r;
-}
-
-
-/**
- *
- */
-void
-idnode_unlink(idnode_t *in)
-{
- RB_REMOVE(&idnodes, in, in_link);
-}
-
-
-/**
- * Recursive to get superclass nodes first
- */
-static void
-add_params(struct idnode *self, const idclass_t *ic, htsmsg_t *p)
-{
- if(ic->ic_super != NULL)
- add_params(self, ic->ic_super, p);
-
- if(TAILQ_FIRST(&p->hm_fields) != NULL) {
- // Only add separator if not empty
- htsmsg_t *m = htsmsg_create_map();
- htsmsg_add_str(m, "caption", ic->ic_caption ?: ic->ic_class);
- htsmsg_add_str(m, "type", "separator");
- htsmsg_add_msg(p, NULL, m);
- }
-
- prop_add_params_to_msg(self, ic->ic_properties, p);
-}
-
-
/**
*
*/
@@ -209,7 +189,7 @@ idnode_get_title(idnode_t *in)
/**
*
*/
-idnode_t **
+idnode_set_t *
idnode_get_childs(idnode_t *in)
{
if(in == NULL)
@@ -223,7 +203,6 @@ idnode_get_childs(idnode_t *in)
return NULL;
}
-
/**
*
*/
@@ -231,8 +210,6 @@ int
idnode_is_leaf(idnode_t *in)
{
const idclass_t *ic = in->in_class;
- if(ic->ic_leaf)
- return 1;
for(; ic != NULL; ic = ic->ic_super) {
if(ic->ic_get_childs != NULL)
return 0;
@@ -240,137 +217,9 @@ idnode_is_leaf(idnode_t *in)
return 1;
}
-
-
-/**
- *
- */
-htsmsg_t *
-idnode_serialize(struct idnode *self)
-{
- const idclass_t *c = self->in_class;
- htsmsg_t *m;
- if(c->ic_serialize != NULL) {
- m = c->ic_serialize(self);
- } else {
- m = htsmsg_create_map();
- htsmsg_add_str(m, "id", idnode_uuid_as_str(self));
- htsmsg_add_str(m, "text", idnode_get_title(self));
-
- htsmsg_t *p = htsmsg_create_list();
- add_params(self, c, p);
-
- htsmsg_add_msg(m, "params", p);
-
- }
- return m;
-}
-
-/**
- *
- */
-static void
-idnode_updated(idnode_t *in)
-{
- const idclass_t *ic = in->in_class;
-
- for(; ic != NULL; ic = ic->ic_super) {
- if(ic->ic_save != NULL) {
- ic->ic_save(in);
- break;
- }
- }
-
- // Tell about updated parameters
-
- htsmsg_t *m = htsmsg_create_map();
- htsmsg_add_str(m, "id", idnode_uuid_as_str(in));
-
- htsmsg_t *p = htsmsg_create_list();
- add_params(in, in->in_class, p);
- htsmsg_add_msg(m, "params", p);
-
- notify_by_msg("idnodeParamsChanged", m);
-}
-
-
-/**
- *
- */
-void
-idnode_set_prop(idnode_t *in, const char *key, const char *value)
-{
- const idclass_t *ic = in->in_class;
- int do_save = 0;
- for(;ic != NULL; ic = ic->ic_super) {
- int x = prop_set(in, ic->ic_properties, key, value);
- if(x == -1)
- continue;
- do_save |= x;
- break;
- }
- if(do_save)
- idnode_updated(in);
-}
-
-
-/**
- *
- */
-void
-idnode_update_all_props(idnode_t *in,
- const char *(*getvalue)(void *opaque, const char *key),
- void *opaque)
-{
- const idclass_t *ic = in->in_class;
- int do_save = 0;
- for(;ic != NULL; ic = ic->ic_super)
- do_save |= prop_update_all(in, ic->ic_properties, getvalue, opaque);
- if(do_save)
- idnode_updated(in);
-}
-
-
-/**
- *
- */
-void
-idnode_notify_title_changed(void *obj)
-{
- idnode_t *in = obj;
- htsmsg_t *m = htsmsg_create_map();
- htsmsg_add_str(m, "id", idnode_uuid_as_str(in));
- htsmsg_add_str(m, "text", idnode_get_title(in));
- notify_by_msg("idnodeNameChanged", m);
-}
-
-/*
- * Save
- */
-void
-idnode_save ( idnode_t *self, htsmsg_t *c )
-{
- const idclass_t *idc = self->in_class;
- while (idc) {
- prop_read_values(self, idc->ic_properties, c);
- idc = idc->ic_super;
- }
-}
-
-/*
- * Load
- */
-void
-idnode_load ( idnode_t *self, htsmsg_t *c, int dosave )
-{
- const idclass_t *idc = self->in_class;
- while (idc) {
- prop_write_values(self, idc->ic_properties, c);
- idc = idc->ic_super;
- }
- if (dosave)
- idnode_updated(self);
-}
+/* **************************************************************************
+ * Properties
+ * *************************************************************************/
static const property_t *
idnode_find_prop
@@ -408,6 +257,9 @@ idnode_get_str
return NULL;
}
+/*
+ * Get field as unsigned int
+ */
int
idnode_get_u32
( idnode_t *self, const char *key, uint32_t *u32 )
@@ -433,8 +285,75 @@ idnode_get_u32
return 1;
}
+/*
+ * Get field as BOOL
+ */
+int
+idnode_get_bool
+ ( idnode_t *self, const char *key, int *b )
+{
+ const property_t *p = idnode_find_prop(self, key);
+ if (p) {
+ void *ptr = self;
+ ptr += p->off;
+ switch (p->type) {
+ case PT_BOOL:
+ *b = *(int*)ptr;
+ return 0;
+ default:
+ break;
+ }
+ }
+ return 1;
+}
+
/* **************************************************************************
- * Set procsesing
+ * Lookup
+ * *************************************************************************/
+
+/**
+ *
+ */
+void *
+idnode_find(const char *uuid, const idclass_t *idc)
+{
+ idnode_t skel, *r;
+
+ if(hex2bin(skel.in_uuid, 16, uuid))
+ return NULL;
+ r = RB_FIND(&idnodes, &skel, in_link, in_cmp);
+ if(r != NULL && idc != NULL) {
+ const idclass_t *c = r->in_class;
+ for(;c != NULL; c = c->ic_super) {
+ if(idc == c)
+ return r;
+ }
+ return NULL;
+ }
+ return r;
+}
+
+idnode_set_t *
+idnode_find_all ( const idclass_t *idc )
+{
+ idnode_t *in;
+ const idclass_t *ic;
+ idnode_set_t *is = calloc(1, sizeof(idnode_set_t));
+ RB_FOREACH(in, &idnodes, in_link) {
+ ic = in->in_class;
+ while (ic) {
+ if (ic == idc) {
+ idnode_set_add(is, in, NULL);
+ break;
+ }
+ ic = ic->ic_super;
+ }
+ }
+ return is;
+}
+
+/* **************************************************************************
+ * Set processing
* *************************************************************************/
static int
@@ -626,21 +545,140 @@ idnode_set_free ( idnode_set_t *is )
free(is);
}
-idnode_set_t *
-idnode_find_all ( const idclass_t *idc )
+/* **************************************************************************
+ * Write
+ * *************************************************************************/
+
+int
+idnode_write0 ( idnode_t *self, htsmsg_t *c, int optmask, int dosave )
{
- idnode_t *in;
- const idclass_t *ic;
- idnode_set_t *is = calloc(1, sizeof(idnode_set_t));
- RB_FOREACH(in, &idnodes, in_link) {
- ic = in->in_class;
- while (ic) {
- if (ic == idc) {
- idnode_set_add(is, in, NULL);
- break;
- }
- ic = ic->ic_super;
+ int save = 0;
+ const idclass_t *idc = self->in_class;
+ for (; idc; idc = idc->ic_super)
+ save |= prop_write_values(self, idc->ic_properties, c, optmask);
+ if (save && dosave)
+ idnode_updated(self, optmask);
+ return save;
+}
+
+/* **************************************************************************
+ * Read
+ * *************************************************************************/
+
+/*
+ * Save
+ */
+void
+idnode_read0 ( idnode_t *self, htsmsg_t *c, int optmask )
+{
+ const idclass_t *idc = self->in_class;
+ for (; idc; idc = idc->ic_super)
+ prop_read_values(self, idc->ic_properties, c, optmask);
+}
+
+/**
+ * Recursive to get superclass nodes first
+ */
+static void
+add_params(struct idnode *self, const idclass_t *ic, htsmsg_t *p, int optmask)
+{
+ /* Parent first */
+ if(ic->ic_super != NULL)
+ add_params(self, ic->ic_super, p, optmask);
+
+ /* Seperator (if not empty) */
+ if(TAILQ_FIRST(&p->hm_fields) != NULL) {
+ htsmsg_t *m = htsmsg_create_map();
+ htsmsg_add_str(m, "caption", ic->ic_caption ?: ic->ic_class);
+ htsmsg_add_str(m, "type", "separator");
+ htsmsg_add_msg(p, NULL, m);
+ }
+
+ /* Properties */
+ prop_serialize(self, ic->ic_properties, p, optmask);
+}
+
+static htsmsg_t *
+idnode_params (const idclass_t *idc, idnode_t *self, int optmask)
+{
+ htsmsg_t *p = htsmsg_create_list();
+ add_params(self, idc, p, optmask);
+ return p;
+}
+
+/*
+ * Just get the class definition
+ */
+htsmsg_t *
+idclass_serialize0(const idclass_t *idc, int optmask)
+{
+ return idnode_params(idc, NULL, optmask);
+}
+
+/**
+ *
+ */
+htsmsg_t *
+idnode_serialize0(idnode_t *self, int optmask)
+{
+ const idclass_t *idc = self->in_class;
+
+ htsmsg_t *m = htsmsg_create_map();
+ htsmsg_add_str(m, "uuid", idnode_uuid_as_str(self));
+ htsmsg_add_str(m, "text", idnode_get_title(self));
+
+ htsmsg_add_msg(m, "params", idnode_params(idc, self, optmask));
+
+ return m;
+}
+
+/* **************************************************************************
+ * Notifcation
+ * *************************************************************************/
+
+/**
+ *
+ */
+static void
+idnode_updated(idnode_t *in, int optmask)
+{
+ const idclass_t *ic = in->in_class;
+
+ /* Save */
+ for(; ic != NULL; ic = ic->ic_super) {
+ if(ic->ic_save != NULL) {
+ ic->ic_save(in);
+ break;
}
}
- return is;
+
+ /* Notification */
+
+ htsmsg_t *m = htsmsg_create_map();
+ htsmsg_add_str(m, "id", idnode_uuid_as_str(in));
+
+ htsmsg_t *p = htsmsg_create_list();
+ add_params(in, in->in_class, p, optmask);
+ htsmsg_add_msg(m, "params", p);
+
+ notify_by_msg("idnodeParamsChanged", m);
}
+
+/**
+ *
+ */
+void
+idnode_notify_title_changed(void *obj)
+{
+ idnode_t *in = obj;
+ htsmsg_t *m = htsmsg_create_map();
+ htsmsg_add_str(m, "id", idnode_uuid_as_str(in));
+ htsmsg_add_str(m, "text", idnode_get_title(in));
+ notify_by_msg("idnodeNameChanged", m);
+}
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/idnode.h b/src/idnode.h
index 947a0a31..5e6f40f0 100644
--- a/src/idnode.h
+++ b/src/idnode.h
@@ -1,4 +1,24 @@
-#pragma once
+/*
+ * Tvheadend - idnode (class) system
+ *
+ * Copyright (C) 2013 Andreas Öman
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __TVH_IDNODE_H__
+#define __TVH_IDNODE_H__
#include "tvheadend.h"
#include "prop.h"
@@ -6,107 +26,112 @@
#include
struct htsmsg;
-struct idnode;
+typedef struct idnode idnode_t;
+/*
+ * Node set
+ */
+typedef struct idnode_set
+{
+ idnode_t **is_array; ///< Array of nodes
+ size_t is_alloc; ///< Size of is_array
+ size_t is_count; ///< Current usage of is_array
+} idnode_set_t;
+
+/*
+ * Class definition
+ */
typedef struct idclass {
- const struct idclass *ic_super;
- const char *ic_class;
- const char *ic_caption;
- int ic_leaf;
- struct htsmsg *(*ic_serialize)(struct idnode *self);
- struct idnode **(*ic_get_childs)(struct idnode *self);
- const char *(*ic_get_title)(struct idnode *self);
- void (*ic_save)(struct idnode *self);
- const property_t *ic_properties;
+ const struct idclass *ic_super; /// Parent class
+ const char *ic_class; /// Class name
+ const char *ic_caption; /// Class description
+ const property_t *ic_properties; /// Property list
+
+ /* Callbacks */
+ idnode_set_t *(*ic_get_childs)(idnode_t *self);
+ const char *(*ic_get_title) (idnode_t *self);
+ void (*ic_save) (idnode_t *self);
} idclass_t;
+/*
+ * Node definition
+ */
+struct idnode {
+ uint8_t in_uuid[16]; ///< Unique ID
+ RB_ENTRY(idnode) in_link; ///< Global hash
+ const idclass_t *in_class; ///< Class definition
+};
-typedef struct idnode {
- uint8_t in_uuid[16];
- RB_ENTRY(idnode) in_link;
- const idclass_t *in_class;
-} idnode_t;
-
+/*
+ * Sorting definition
+ */
typedef struct idnode_sort {
- const char *key;
+ const char *key; ///< Sort key
enum {
IS_ASC,
IS_DSC
- } dir;
+ } dir; ///< Sort direction
} idnode_sort_t;
+/*
+ * Filter definition
+ */
typedef struct idnode_filter_ele
{
- LIST_ENTRY(idnode_filter_ele) link;
- char *key;
+ LIST_ENTRY(idnode_filter_ele) link; ///< List link
+
+ char *key; ///< Filter key
enum {
IF_STR,
IF_NUM,
IF_BOOL
- } type;
+ } type; ///< Filter type
union {
int b;
char *s;
int64_t n;
regex_t re;
- } u;
+ } u; ///< Filter data
enum {
- IC_EQ, // Equals
- IC_LT, // LT
- IC_GT, // GT
- IC_IN, // contains (STR only)
- IC_RE, // regexp (STR only)
- } comp;
+ IC_EQ, ///< Equals
+ IC_LT, ///< LT
+ IC_GT, ///< GT
+ IC_IN, ///< contains (STR only)
+ IC_RE, ///< regexp (STR only)
+ } comp; ///< Filter comparison
} idnode_filter_ele_t;
typedef LIST_HEAD(,idnode_filter_ele) idnode_filter_t;
-typedef struct idnode_set
-{
- idnode_t **is_array;
- size_t is_alloc;
- size_t is_count;
-} idnode_set_t;
-
void idnode_init(void);
-int idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class);
-
-const char *idnode_uuid_as_str(const idnode_t *in);
-
-void *idnode_find(const char *uuid, const idclass_t *class);
-
-idnode_set_t *idnode_find_all(const idclass_t *class);
-
-idnode_t **idnode_get_childs(idnode_t *in);
-
-int idnode_is_leaf(idnode_t *in);
-
+int idnode_insert(idnode_t *in, const char *uuid, const idclass_t *class);
void idnode_unlink(idnode_t *in);
-htsmsg_t *idnode_serialize(struct idnode *self);
+const char *idnode_uuid_as_str (const idnode_t *in);
+idnode_set_t *idnode_get_childs (idnode_t *in);
+int idnode_is_leaf (idnode_t *in);
-void idnode_set_prop(idnode_t *in, const char *key, const char *value);
-
-const property_t* idnode_get_prop(idnode_t *in, const char *key);
-
-void idnode_update_all_props(idnode_t *in,
- const char *(*getvalue)(void *opaque,
- const char *key),
- void *opaque);
+void *idnode_find (const char *uuid, const idclass_t *class);
+idnode_set_t *idnode_find_all(const idclass_t *class);
void idnode_notify_title_changed(void *obj);
-void idnode_save ( idnode_t *self, htsmsg_t *m );
-void idnode_load ( idnode_t *self, htsmsg_t *m, int dosave );
+htsmsg_t *idclass_serialize0 (const idclass_t *idc, int optmask);
+htsmsg_t *idnode_serialize0 (idnode_t *self, int optmask);
+void idnode_read0 (idnode_t *self, htsmsg_t *m, int optmask);
+int idnode_write0 (idnode_t *self, htsmsg_t *m, int optmask, int dosave);
-const char *idnode_get_str ( idnode_t *self, const char *key );
-int idnode_get_u32(idnode_t *self, const char *key, uint32_t *u32);
-int idnode_get_bool(idnode_t *self, const char *key, int *b);
+#define idclass_serialize(idc) idclass_serialize0(idc, 0)
+#define idnode_serialize(in) idnode_serialize0(in, 0)
+#define idnode_load(in, m) idnode_write0(in, m, PO_NOSAVE, 0)
+#define idnode_save(in, m) idnode_read0(in, m, PO_NOSAVE)
+#define idnode_update(in, m) idnode_write0(in, m, PO_RDONLY | PO_WRONCE, 1)
+
+const char *idnode_get_str (idnode_t *self, const char *key );
+int idnode_get_u32 (idnode_t *self, const char *key, uint32_t *u32);
+int idnode_get_bool(idnode_t *self, const char *key, int *b);
-/*
- * Set processing
- */
void idnode_filter_add_str
(idnode_filter_t *f, const char *k, const char *v, int t);
void idnode_filter_add_num
@@ -117,7 +142,16 @@ void idnode_filter_clear
(idnode_filter_t *f);
int idnode_filter
( idnode_t *in, idnode_filter_t *filt );
+#define idnode_set_create() calloc(1, sizeof(idnode_set_t))
void idnode_set_add
( idnode_set_t *is, idnode_t *in, idnode_filter_t *filt );
void idnode_set_sort ( idnode_set_t *is, idnode_sort_t *s );
void idnode_set_free ( idnode_set_t *is );
+
+#endif /* __TVH_IDNODE_H__ */
+
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/prop.c b/src/prop.c
index 5d521616..21c200cd 100644
--- a/src/prop.c
+++ b/src/prop.c
@@ -1,16 +1,38 @@
+/*
+ * Tvheadend - property system (part of idnode)
+ *
+ * Copyright (C) 2013 Andreas Öman
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
#include
#include
#include "tvheadend.h"
#include "prop.h"
+/* **************************************************************************
+ * Utilities
+ * *************************************************************************/
+#define TO_FROM(x, y) ((x) << 16 | (y))
-
-
-/**
- *
+/*
+ * Bool conversion
*/
+#if 0
static int
str_to_bool(const char *s)
{
@@ -25,6 +47,18 @@ str_to_bool(const char *s)
return 1;
return 0;
}
+#endif
+
+/**
+ *
+ */
+const static struct strtab typetab[] = {
+ { "bool", PT_BOOL },
+ { "int", PT_INT },
+ { "str", PT_STR },
+ { "u16", PT_U16 },
+ { "u32", PT_U32 },
+};
const property_t *
@@ -37,65 +71,109 @@ prop_find(const property_t *p, const char *id)
return NULL;
}
-
-
-#define TO_FROM(x, y) ((x) << 16 | (y))
+/* **************************************************************************
+ * Write
+ * *************************************************************************/
/**
*
*/
-void
-prop_write_values(void *obj, const property_t *pl, htsmsg_t *m)
+int
+prop_write_values(void *obj, const property_t *pl, htsmsg_t *m, int optmask)
{
+ int save = 0;
htsmsg_field_t *f;
HTSMSG_FOREACH(f, m) {
if(f->hmf_name == NULL)
continue;
+
+ /* Find Property */
const property_t *p = prop_find(pl, f->hmf_name);
if(p == NULL) {
- //fprintf(stderr, "Property %s unmappable\n", f->hmf_name);
+ tvhwarn("prop", "invalid property %s", f->hmf_name);
continue;
}
- if(p->options & PO_NOSAVE) continue;
+
+ /* Ignore */
+ if(p->opts & optmask) continue;
- void *val = obj + p->off;
+ /* Write */
+ void *v = obj + p->off;
switch(TO_FROM(p->type, f->hmf_type)) {
- case TO_FROM(PT_BOOL, HMF_BOOL):
- *(int *)val = f->hmf_bool;
- break;
- case TO_FROM(PT_BOOL, HMF_S64):
- *(int *)val = !!f->hmf_s64;
- break;
- case TO_FROM(PT_INT, HMF_S64):
- *(int *)val = f->hmf_s64;
- break;
- case TO_FROM(PT_U16, HMF_S64):
- *(uint16_t *)val = f->hmf_s64;
- break;
- case TO_FROM(PT_U32, HMF_S64):
- *(uint32_t *)val = f->hmf_s64;
- break;
- case TO_FROM(PT_STR, HMF_STR):
- if(p->str_set != NULL)
- p->str_set(obj, f->hmf_str);
- else
- mystrset(val, f->hmf_str);
+ case TO_FROM(PT_BOOL, HMF_BOOL): {
+ int *val = v;
+ if (*val != f->hmf_bool) {
+ *val = f->hmf_bool;
+ save = 1;
+ }
break;
}
+ case TO_FROM(PT_BOOL, HMF_S64): {
+ int *val = v;
+ if (*val != !!f->hmf_s64) {
+ *val = !!f->hmf_s64;
+ save = 1;
+ }
+ break;
+ }
+ case TO_FROM(PT_INT, HMF_S64): {
+ int *val = v;
+ if (*val != f->hmf_s64) {
+ *val = f->hmf_s64;
+ save = 1;
+ }
+ break;
+ }
+ case TO_FROM(PT_U16, HMF_S64): {
+ uint16_t *val = v;
+ if (*val != f->hmf_s64) {
+ *val = f->hmf_s64;
+ save = 1;
+ }
+ break;
+ }
+ case TO_FROM(PT_U32, HMF_S64): {
+ uint32_t *val = v;
+ if (*val != f->hmf_s64) {
+ *val = f->hmf_s64;
+ save = 1;
+ }
+ break;
+ }
+ case TO_FROM(PT_STR, HMF_STR): {
+ char **val = v;
+ if(p->str_set != NULL)
+ save |= p->str_set(obj, f->hmf_str);
+ else if (!strcmp(*val ?: "", f->hmf_str)) {
+ free(*val);
+ *val = strdup(f->hmf_str);
+ save = 1;
+ }
+ break;
+ }
+ }
}
+ return save;
}
-
+/* **************************************************************************
+ * Read
+ * *************************************************************************/
/**
*
*/
static void
-prop_read_value(void *obj, const property_t *p, htsmsg_t *m, const char *name)
+prop_read_value
+ (void *obj, const property_t *p, htsmsg_t *m, const char *name, int optmask)
{
const char *s;
const void *val = obj + p->off;
+ /* Ignore */
+ if (p->opts & optmask) return;
+
+ /* Read */
switch(p->type) {
case PT_BOOL:
htsmsg_add_bool(m, name, *(int *)val);
@@ -125,147 +203,52 @@ prop_read_value(void *obj, const property_t *p, htsmsg_t *m, const char *name)
*
*/
void
-prop_read_values(void *obj, const property_t *p, htsmsg_t *m)
+prop_read_values(void *obj, const property_t *pl, htsmsg_t *m, int optmask)
{
- if(p == NULL)
+ if(pl == NULL)
return;
- int i = 0;
- for(;p[i].id; i++)
- prop_read_value(obj, p+i, m, p[i].id);
+ for (; pl->id; pl++)
+ prop_read_value(obj, pl, m, pl->id, optmask);
}
-
-/**
- *
- */
-const static struct strtab typetab[] = {
- { "bool", PT_BOOL },
- { "int", PT_INT },
- { "str", PT_STR },
- { "u16", PT_U16 },
- { "u32", PT_U32 },
-};
-
-
/**
*
*/
void
-prop_add_params_to_msg(void *obj, const property_t *p, htsmsg_t *msg)
+prop_serialize(void *obj, const property_t *pl, htsmsg_t *msg, int optmask)
{
- if(p == NULL)
+ if(pl == NULL)
return;
- int i = 0;
- for(;p[i].id; i++) {
+
+ for(; pl->id; pl++) {
htsmsg_t *m = htsmsg_create_map();
- htsmsg_add_str(m, "id", p[i].id);
- htsmsg_add_str(m, "caption", p[i].name);
- htsmsg_add_str(m, "type", val2str(p[i].type, typetab) ?: "unknown");
- if (p->options & PO_RDONLY)
- htsmsg_add_u32(m, "rdonly", 1);
- if (p->options & PO_NOSAVE)
- htsmsg_add_u32(m, "nosave", 1);
- if (p[i].type == PT_STR && p[i].str_enum) {
- htsmsg_t *l = htsmsg_create_list();
- const char **e = p[i].str_enum(obj);
- while (*e) {
- htsmsg_add_str(l, NULL, *e);
- e++;
- }
- htsmsg_add_msg(m, "enum", l);
- } else if (p[i].type == PT_STR && p[i].str_enum2) {
- htsmsg_add_msg(m, "enum", p[i].str_enum2(obj));
- }
- if (obj)
- prop_read_value(obj, p+i, m, "value");
htsmsg_add_msg(msg, NULL, m);
+
+ /* Metadata */
+ htsmsg_add_str(m, "id", pl->id);
+ htsmsg_add_str(m, "caption", pl->name);
+ htsmsg_add_str(m, "type", val2str(pl->type, typetab) ?: "unknown");
+
+ /* Options */
+ if (pl->opts & PO_RDONLY)
+ htsmsg_add_u32(m, "rdonly", 1);
+ if (pl->opts & PO_NOSAVE)
+ htsmsg_add_u32(m, "nosave", 1);
+ if (pl->opts & PO_WRONCE)
+ htsmsg_add_u32(m, "wronce", 1);
+
+ /* Enum list */
+ if (pl->str_enum)
+ htsmsg_add_msg(m, "enum", pl->str_enum(obj));
+
+ /* Data */
+ if (obj)
+ prop_read_value(obj, pl, m, "value", optmask);
}
}
-
-/**
- * value can be NULL
+/******************************************************************************
+ * Editor Configuration
*
- * Return 1 if we actually changed something
- */
-static int
-prop_seti(void *obj, const property_t *p, const char *value)
-{
- int i;
- uint32_t u32;
- uint16_t u16;
- const char *s;
-
- if (p->options & PO_NOSAVE) return 0;
-
- void *val = obj + p->off;
- switch(p->type) {
-
- case PT_BOOL:
- i = str_to_bool(value);
- if(0)
- case PT_INT:
- i = value ? atoi(value) : 0;
- if(*(int *)val == i)
- return 0; // Already set
- *(int *)val = i;
- break;
- case PT_U16:
- u16 = value ? atoi(value) : 0;
- if(*(uint16_t *)val == u16)
- return 0;
- *(uint16_t *)val = u16;
- break;
- case PT_U32:
- u32 = value ? atoi(value) : 0;
- if(*(uint32_t *)val == u32)
- return 0;
- *(uint32_t *)val = u32;
- break;
- case PT_STR:
- if(p->str_get != NULL)
- s = p->str_get(obj);
- else
- s = *(const char **)val;
-
- if(!strcmp(s ?: "", value ?: ""))
- return 0;
-
- if(p->str_set != NULL)
- p->str_set(obj, value);
- else
- mystrset(val, value);
- break;
- }
- if(p->notify)
- p->notify(obj);
- return 1;
-}
-
-
-/**
- * Return 1 if something changed
- */
-int
-prop_set(void *obj, const property_t *p, const char *key, const char *value)
-{
- if((p = prop_find(p, key)) == NULL)
- return -1;
- return prop_seti(obj, p, value);
-}
-
-
-/**
- *
- */
-int
-prop_update_all(void *obj, const property_t *p,
- const char *(*getvalue)(void *opaque, const char *key),
- void *opaque)
-{
- int i = 0;
- int r = 0;
- for(; p[i].id; i++)
- r |= prop_seti(obj, p+i, getvalue(opaque, p[i].id));
- return r;
-}
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/
diff --git a/src/prop.h b/src/prop.h
index 83c2fdca..a9e1ce98 100644
--- a/src/prop.h
+++ b/src/prop.h
@@ -1,8 +1,32 @@
-#pragma once
+/*
+ * Tvheadend - property system (part of idnode)
+ *
+ * Copyright (C) 2013 Andreas Öman
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __TVH_PROP_H__
+#define __TVH_PROP_H__
+
#include
#include "htsmsg.h"
+/*
+ * Property types
+ */
typedef enum {
PT_BOOL,
PT_STR,
@@ -11,64 +35,51 @@ typedef enum {
PT_U32,
} prop_type_t;
-#define PO_NONE 0x0
-#define PO_RDONLY 0x1 // Note: if this is changed, change PROPDEF2
-#define PO_NOSAVE 0x2
-#define PO_WRONCE 0x4
+/*
+ * Property options
+ */
+#define PO_NONE 0x00
+#define PO_RDONLY 0x01 // Property is read-only
+#define PO_NOSAVE 0x02 // Property is transient (not saved)
+#define PO_WRONCE 0x04 // Property is write-once (i.e. on creation)
+/*
+ * Property definition
+ */
typedef struct property {
- const char *id;
- const char *name;
- prop_type_t type;
- size_t off;
- int options;
+ const char *id; ///< Property Key
+ const char *name; ///< Textual description
+ prop_type_t type; ///< Type
+ size_t off; ///< Offset into object
+ int opts; ///< Options
- const char *(*str_get)(void *ptr);
- void (*str_set)(void *ptr, const char *str);
- const char **(*str_enum)(void *ptr);
- htsmsg_t *(*str_enum2)(void *ptr);
+ /* String based processing */
+ const char *(*str_get) (void *ptr);
+ int (*str_set) (void *ptr, const char *str);
+ htsmsg_t *(*str_enum) (void *ptr);
+ // Note: htsmsg_t can either be a string list or object list
+ // where the object has "key" and "val" fields
- void (*notify)(void *ptr);
+ /* Notification callback */
+ void (*notify) (void *ptr);
} property_t;
const property_t *prop_find(const property_t *p, const char *name);
-void prop_add_params_to_msg(void *obj, const property_t *p, htsmsg_t *msg);
+int prop_write_values
+ (void *obj, const property_t *pl, htsmsg_t *m, int optmask);
-void prop_write_values(void *ptr, const property_t *pl, htsmsg_t *m);
+void prop_read_values
+ (void *obj, const property_t *pl, htsmsg_t *m, int optmask);
-void prop_read_values(void *obj, const property_t *p, htsmsg_t *m);
+void prop_serialize
+ (void *obj, const property_t *pl, htsmsg_t *m, int optmask);
-int prop_set(void *obj, const property_t *p, const char *key, const char *val);
-
-int prop_update_all(void *obj, const property_t *p,
- const char *(*getvalue)(void *opaque, const char *key),
- void *opaque);
-
-#define PROPDEF0(_i, _n, _t, _o)\
- .id = _i,\
- .name = _n,\
- .type = _t,\
- .options = _o
-
-#define PROPDEF1(_i, _n, _t, _o, _v)\
- .id = _i,\
- .name = _n,\
- .type = _t,\
- .off = offsetof(_o, _v)
-
-#define PROPDEF2(_i, _n, _t, _o, _v, _r)\
- .id = _i,\
- .name = _n,\
- .type = _t,\
- .off = offsetof(_o, _v),\
- .options = _r
-
-#define PROPDEF3(_i, _n, _t, _o, _v, _c)\
- .id = _i,\
- .name = _n,\
- .type = _t,\
- .off = offsetof(_o, _v),\
- .options = _c
+#endif /* __TVH_PROP_H__ */
+/******************************************************************************
+ * Editor Configuration
+ *
+ * vim:sts=2:ts=2:sw=2:et
+ *****************************************************************************/