1 /*
2 * Tvheadend - idnode (class) system
3 *
4 * Copyright (C) 2013 Andreas Öman
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef __TVH_IDNODE_H__
21 #define __TVH_IDNODE_H__
22
23 #include "tvheadend.h"
24 #include "prop.h"
25 #include "uuid.h"
26
27 #include <regex.h>
28
29 struct access;
30 typedef struct idnode idnode_t;
31 typedef struct idnode_save idnode_save_t;
32
33 #define IDNODE_SAVE_DELAY (3 * MONOCLOCK_RESOLUTION)
34
35 #define SAVEPTR_OUTOFSERVICE ((void *)((intptr_t)-1LL))
36
37 /*
38 * Node set
39 */
40 typedef struct idnode_set
41 {
42 idnode_t **is_array; ///< Array of nodes
43 size_t is_alloc; ///< Size of is_array
44 size_t is_count; ///< Current usage of is_array
45 uint8_t is_sorted; ///< Sorted array of nodes
46 } idnode_set_t;
47
48 /*
49 * Property groups
50 */
51 typedef struct property_group
52 {
53 const char *name;
54 uint32_t number;
55 uint32_t parent;
56 uint32_t column;
57 } property_group_t;
58
59 /*
60 * Class definition
61 */
62 #define IDCLASS_ALWAYS_SAVE (1<<0) ///< Always call the save callback
63
64 #define CLASS_DOC(name) extern const char *tvh_doc_##name##_class[];
65
66 typedef struct idclass idclass_t;
67 struct idclass {
68 const struct idclass *ic_super; ///< Parent class
69 const char *ic_class; ///< Class name
70 const char *ic_caption; ///< Class description
71 const char *ic_order; ///< Property order (comma-separated)
72 const char **ic_doc; ///< NULL terminated array of strings
73 const property_group_t *ic_groups; ///< Groups for visual representation
74 const property_t *ic_properties; ///< Property list
75 const char *ic_event; ///< Events to fire on add/delete/title
76 uint32_t ic_perm_def; ///< Default permissions
77 uint32_t ic_flags; ///< Extra flags
78 idnode_t *ic_snode; ///< Simple node
79
80 /* Callbacks */
81 idnode_set_t *(*ic_get_childs) (idnode_t *self);
82 const char *(*ic_get_title) (idnode_t *self, const char *lang);
83 void (*ic_changed) (idnode_t *self);
84 htsmsg_t *(*ic_save) (idnode_t *self, char *filename, size_t fsize);
85 void (*ic_delete) (idnode_t *self);
86 void (*ic_moveup) (idnode_t *self);
87 void (*ic_movedown) (idnode_t *self);
88 int (*ic_perm) (idnode_t *self, struct access *a, htsmsg_t *msg_to_write);
89 };
90
91
92 typedef RB_HEAD(, idnode) idnodes_rb_t;
93
94 /*
95 * Node definition
96 */
97 struct idnode {
98 tvh_uuid_t in_uuid; ///< Unique ID
99 RB_ENTRY(idnode) in_link; ///< Global hash
100 RB_ENTRY(idnode) in_domain_link; ///< Root class link (domain)
101 idnodes_rb_t *in_domain; ///< Domain nodes
102 const idclass_t *in_class; ///< Class definition
103 struct access *in_access; ///< Actual permissions
104 idnode_save_t *in_save; ///< Pointer to the save link
105 };
106
107 /*
108 * Node save list
109 */
110 struct idnode_save {
111 TAILQ_ENTRY(idnode_save) ise_link; ///< List chain
112 idnode_t *ise_node; ///< Node owning this
113 int64_t ise_reqtime; ///< First request
114 };
115
116 /*
117 * Simple list
118 */
119 typedef struct idnode_slist {
120 const char *id;
121 const char *name;
122 size_t off;
123 } idnode_slist_t;
124
125 /*
126 * Node list mapping definition
127 */
128 struct idnode_list_mapping;
129
130 typedef struct idnode_list_head {
131 struct idnode_list_mapping *lh_first;
132 } idnode_list_head_t;
133
134 typedef struct idnode_list_mapping {
135 LIST_ENTRY(idnode_list_mapping) ilm_in1_link;
136 LIST_ENTRY(idnode_list_mapping) ilm_in2_link;
137
138 idnode_t *ilm_in1;
139 idnode_t *ilm_in2;
140
141 uint8_t ilm_in1_save;
142 uint8_t ilm_in2_save;
143 uint8_t ilm_mark;
144 } idnode_list_mapping_t;
145
146 /*
147 * Sorting definition
148 */
149 typedef struct idnode_sort {
150 const char *lang; ///< Language (UI)
151 const char *key; ///< Sort key
152 enum {
153 IS_ASC,
154 IS_DSC
155 } dir; ///< Sort direction
156 } idnode_sort_t;
157
158 /*
159 * Filter definition
160 */
161 typedef struct idnode_filter_ele
162 {
163 LIST_ENTRY(idnode_filter_ele) link; ///< List link
164
165 int checked;
166 char *key; ///< Filter key
167 enum {
168 IF_STR,
169 IF_NUM,
170 IF_DBL,
171 IF_BOOL
172 } type; ///< Filter type
173 union {
174 int b;
175 char *s;
176 struct {
177 int64_t n;
178 int64_t intsplit;
179 } n;
180 double dbl;
181 regex_t re;
182 } u; ///< Filter data
183 enum {
184 IC_EQ, ///< Equals
185 IC_LT, ///< LT
186 IC_GT, ///< GT
187 IC_IN, ///< contains (STR only)
188 IC_RE, ///< regexp (STR only)
189 } comp; ///< Filter comparison
190 } idnode_filter_ele_t;
191
192 typedef LIST_HEAD(,idnode_filter_ele) idnode_filter_t;
193
194 extern idnode_t tvhlog_conf;
195 extern const idclass_t tvhlog_conf_class;
196
197 void idnode_boot(void);
198 void idnode_init(void);
199 void idnode_done(void);
200
201 #define IDNODE_SHORT_UUID (1<<0)
202
203 int idnode_insert(idnode_t *in, const char *uuid, const idclass_t *idc, int flags);
204 void idnode_unlink(idnode_t *in);
205
206 uint32_t idnode_get_short_uuid (const idnode_t *in);
207 const char *idnode_uuid_as_str (const idnode_t *in, char *buf);
208 idnode_set_t *idnode_get_childs (idnode_t *in);
209 const char *idnode_get_title (idnode_t *in, const char *lang);
210 int idnode_is_leaf (idnode_t *in);
211 int idnode_is_instance (idnode_t *in, const idclass_t *idc);
212 void idnode_delete (idnode_t *in);
213 void idnode_moveup (idnode_t *in);
214 void idnode_movedown (idnode_t *in);
215
216 void idnode_changed (idnode_t *in);
217
218 void *idnode_find (const char *uuid, const idclass_t *idc, const idnodes_rb_t *nodes);
219 idnode_set_t *idnode_find_all(const idclass_t *idc, const idnodes_rb_t *nodes);
220
221
222 void idnode_notify (idnode_t *in, const char *action);
223 void idnode_notify_changed (void *in);
224 void idnode_notify_title_changed (void *in, const char *lang);
225
226 void idclass_register ( const idclass_t *idc );
227 const idclass_t *idclass_find ( const char *name );
228 idclass_t const **idclass_find_all(void);
229 idclass_t const **idclass_find_children(const char *name);
230 const char **idclass_get_doc(const idclass_t *idc);
231 const char *idclass_get_caption ( const idclass_t *idc, const char *lang );
232 htsmsg_t *idclass_serialize0 (const idclass_t *idc, htsmsg_t *list, int optmask, const char *lang);
233 htsmsg_t *idnode_serialize0 (idnode_t *self, htsmsg_t *list, int optmask, const char *lang);
234 void idnode_read0 (idnode_t *self, htsmsg_t *m, htsmsg_t *list, int optmask, const char *lang);
235 int idnode_write0 (idnode_t *self, htsmsg_t *m, int optmask, int dosave);
236 void idnode_save_check (idnode_t *self, int weak);
237
238 #define idclass_serialize(idc, lang) idclass_serialize0(idc, NULL, 0, lang)
239 #define idclass_serializedoc(idc, lang) idclass_serialize0(idc, NULL, PO_DOC, lang)
240 #define idnode_serialize(in, lang) idnode_serialize0(in, NULL, 0, lang)
241 #define idnode_load(in, m) idnode_write0(in, m, PO_NOSAVE, 0)
242 #define idnode_save(in, m) idnode_read0(in, m, NULL, PO_NOSAVE | PO_USERAW, NULL)
243 #define idnode_update(in, m) idnode_write0(in, m, PO_RDONLY | PO_WRONCE, 1)
244
245 int idnode_perm(idnode_t *self, struct access *a, htsmsg_t *msg_to_write);
idnode_perm_unset(idnode_t * self)246 static inline void idnode_perm_unset(idnode_t *self) { self->in_access = NULL; }
247
248 #define idnode_lang(self) \
249 (((idnode_t *)self)->in_access ? \
250 ((idnode_t *)self)->in_access->aa_lang : NULL)
251 #define idnode_lang_ui(self) \
252 (((idnode_t *)self)->in_access ? \
253 ((idnode_t *)self)->in_access->aa_lang_ui : NULL)
254
255 htsmsg_t * idnode_slist_enum ( idnode_t *in, idnode_slist_t *options, const char *lang );
256 htsmsg_t * idnode_slist_get ( idnode_t *in, idnode_slist_t *options );
257 int idnode_slist_set ( idnode_t *in, idnode_slist_t *options, const htsmsg_t *vals );
258 char * idnode_slist_rend ( idnode_t *in, idnode_slist_t *options, const char *lang );
259
260 idnode_list_mapping_t * idnode_list_link
261 ( idnode_t *in1, idnode_list_head_t *in1_list,
262 idnode_t *in2, idnode_list_head_t *in2_list,
263 void *origin, uint32_t savemask );
264 void idnode_list_unlink ( idnode_list_mapping_t *ilm, void *origin );
265 void idnode_list_destroy ( idnode_list_head_t *ilh, void *origin );
266 htsmsg_t * idnode_list_get1 ( idnode_list_head_t *in1_list );
267 htsmsg_t * idnode_list_get2 ( idnode_list_head_t *in2_list );
268 char * idnode_list_get_csv1 ( idnode_list_head_t *in1_list, const char *lang );
269 char * idnode_list_get_csv2 ( idnode_list_head_t *in2_list, const char *lang );
270 int idnode_list_set1 ( idnode_t *in1, idnode_list_head_t *in1_list,
271 const idclass_t *in2_class, htsmsg_t *in2_list,
272 int (*in2_create)(idnode_t *in1, idnode_t *in2, void *origin) );
273 int idnode_list_set2 ( idnode_t *in2, idnode_list_head_t *in2_list,
274 const idclass_t *in1_class, htsmsg_t *in1_list,
275 int (*in2_create)(idnode_t *in1, idnode_t *in2, void *origin) );
276
277 const char *idnode_get_str (idnode_t *self, const char *key );
278 int idnode_get_u32 (idnode_t *self, const char *key, uint32_t *u32);
279 int idnode_get_s64 (idnode_t *self, const char *key, int64_t *s64);
280 int idnode_get_s64_atomic (idnode_t *self, const char *key, int64_t *s64);
281 int idnode_get_dbl (idnode_t *self, const char *key, double *dbl);
282 int idnode_get_bool(idnode_t *self, const char *key, int *b);
283 int idnode_get_time(idnode_t *self, const char *key, time_t *tm);
284
285 void idnode_filter_add_str
286 (idnode_filter_t *f, const char *k, const char *v, int t);
287 void idnode_filter_add_num
288 (idnode_filter_t *f, const char *k, int64_t s64, int t, int64_t intsplit);
289 void idnode_filter_add_dbl
290 (idnode_filter_t *f, const char *k, double dbl, int t);
291 void idnode_filter_add_bool
292 (idnode_filter_t *f, const char *k, int b, int t);
293 void idnode_filter_clear
294 (idnode_filter_t *f);
295 int idnode_filter
296 ( idnode_t *in, idnode_filter_t *filt, const char *lang );
idnode_set_create(int sorted)297 static inline idnode_set_t * idnode_set_create(int sorted)
298 { idnode_set_t *is = calloc(1, sizeof(idnode_set_t));
299 is->is_sorted = sorted; return is; }
300 void idnode_set_alloc ( idnode_set_t *is, size_t alloc );
301 void idnode_set_add
302 ( idnode_set_t *is, idnode_t *in, idnode_filter_t *filt, const char *lang );
303 int idnode_set_remove ( idnode_set_t *is, idnode_t *in );
304 ssize_t idnode_set_find_index( idnode_set_t *is, idnode_t *in );
idnode_set_exists(idnode_set_t * is,idnode_t * in)305 static inline int idnode_set_exists ( idnode_set_t *is, idnode_t *in )
306 { return idnode_set_find_index(is, in) >= 0; }
307 void idnode_set_sort ( idnode_set_t *is, idnode_sort_t *s );
308 void idnode_set_sort_by_title ( idnode_set_t *is, const char *lang );
309 htsmsg_t *idnode_set_as_htsmsg ( idnode_set_t *is );
310 void idnode_set_clear ( idnode_set_t *is );
311 void idnode_set_free ( idnode_set_t *is );
312
313 #endif /* __TVH_IDNODE_H__ */
314
315 /******************************************************************************
316 * Editor Configuration
317 *
318 * vim:sts=2:ts=2:sw=2:et
319 *****************************************************************************/
320