improve opacity and fix bug
[src/app-framework-main.git] / src / wgt-info.c
1 /*
2  Copyright 2015 IoT.bzh
3
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8      http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16
17 #include <stdlib.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <assert.h>
21 #include <syslog.h>
22 #include <libxml/tree.h>
23
24 #include "verbose.h"
25 #include "wgt.h"
26 #include "wgt-config.h"
27 #include "wgt-info.h"
28
29 struct wgt_info {
30         int refcount;
31         struct wgt *wgt;
32         struct wgt_desc desc;
33 };
34
35 static int getpropbool(xmlNodePtr node, const char *prop, int def)
36 {
37         int result;
38         char *val = xmlGetProp(node, prop);
39         if (!val)
40                 result = def;
41         else {
42                 if (!strcmp(val, "true"))
43                         result = 1;
44                 else if (!strcmp(val, "false"))
45                         result = 0;
46                 else
47                         result = def;
48                 xmlFree(val);
49         }
50         return result;
51 }
52
53 static int getpropnum(xmlNodePtr node, const char *prop, int def)
54 {
55         int result;
56         char *val = xmlGetProp(node, prop);
57         if (!val)
58                 result = def;
59         else {
60                 result = atoi(val);
61                 xmlFree(val);
62         }
63         return result;
64 }
65
66 static xmlChar *optprop(xmlNodePtr node, const char *prop)
67 {
68         return node ? xmlGetProp(node, prop) : NULL;
69 }
70
71 static xmlChar *optcontent(xmlNodePtr node)
72 {
73         return node ? xmlNodeGetContent(node) : NULL;
74 }
75
76 static int fill_desc(struct wgt_desc *desc, int want_icons, int want_features, int want_preferences)
77 {
78         xmlNodePtr node, pnode;
79         struct wgt_desc_icon *icon, **icontail;
80         struct wgt_desc_feature *feature, **featuretail;
81         struct wgt_desc_preference *preference, **preferencetail;
82         struct wgt_desc_param *param, **paramtail;
83
84         node = wgt_config_widget();
85         if (!node) {
86                 warning("no widget");
87                 errno = EINVAL;
88                 return -1;
89         }
90         desc->id = xmlGetProp(node, wgt_config_string_id);
91         desc->version = xmlGetProp(node, wgt_config_string_version);
92         desc->width = getpropnum(node, wgt_config_string_width, 0);
93         desc->height = getpropnum(node, wgt_config_string_height, 0);
94         desc->viewmodes = xmlGetProp(node, wgt_config_string_viewmodes);
95         desc->defaultlocale = xmlGetProp(node, wgt_config_string_defaultlocale);
96
97         node = wgt_config_name();
98         desc->name = optcontent(node);
99         desc->name_short = optprop(node, wgt_config_string_short);
100
101         node = wgt_config_description();
102         desc->description = optcontent(node);
103
104         node = wgt_config_author();
105         desc->author = optcontent(node);
106         desc->author_href = optprop(node, wgt_config_string_href);
107         desc->author_email = optprop(node, wgt_config_string_email);
108
109         node = wgt_config_license();
110         desc->license = optcontent(node);
111         desc->license_href = optprop(node, wgt_config_string_href);
112         
113         node = wgt_config_content();
114         desc->content_src = optprop(node, wgt_config_string_src);
115         if (node && desc->content_src == NULL) {
116                 warning("content without src");
117                 errno = EINVAL;
118                 return -1;
119         }
120         desc->content_type = optprop(node, wgt_config_string_type);
121         desc->content_encoding = optprop(node, wgt_config_string_encoding);
122
123         if (want_icons) {
124                 icontail = &desc->icons;
125                 node = wgt_config_first_icon();
126                 while (node) {
127                         icon = malloc(sizeof * icon);
128                         if (icon == NULL) {
129                                 errno = ENOMEM;
130                                 return -1;
131                         }
132                         icon->src = xmlGetProp(node, wgt_config_string_src);
133                         icon->width = getpropnum(node, wgt_config_string_width, 0);
134                         icon->height = getpropnum(node, wgt_config_string_height, 0);
135
136                         icon->next = NULL;
137                         *icontail = icon;
138
139                         if (icon->src == NULL) {
140                                 warning("icon without src");
141                                 errno = EINVAL;
142                                 return -1;
143                         }
144                         icontail = &icon->next;
145                         node = wgt_config_next_icon(node);
146                 }
147         }
148
149         if (want_features) {
150                 featuretail = &desc->features;
151                 node = wgt_config_first_feature();
152                 while (node) {
153                         feature = malloc(sizeof * feature);
154                         if (feature == NULL) {
155                                 errno = ENOMEM;
156                                 return -1;
157                         }
158                         feature->name = xmlGetProp(node, wgt_config_string_name);
159                         feature->required = getpropbool(node, wgt_config_string_required, 1);
160                         feature->params = NULL;
161
162                         feature->next = NULL;
163                         *featuretail = feature;
164
165                         if (feature->name == NULL) {
166                                 warning("feature without name");
167                                 errno = EINVAL;
168                                 return -1;
169                         }
170
171                         paramtail = &feature->params;
172                         pnode = wgt_config_first_param(node);
173                         while (pnode) {
174                                 param = malloc(sizeof * param);
175                                 if (param == NULL) {
176                                         errno = ENOMEM;
177                                         return -1;
178                                 }
179                                 param->name = xmlGetProp(pnode, wgt_config_string_name);
180                                 param->value = xmlGetProp(pnode, wgt_config_string_value);
181
182                                 param->next = NULL;
183                                 *paramtail = param;
184
185                                 if (param->name == NULL || param->value == NULL) {
186                                         warning("param without name or value");
187                                         errno = EINVAL;
188                                         return -1;
189                                 }
190
191                                 paramtail = &param->next;
192                                 pnode = wgt_config_next_param(pnode);
193                         }
194
195                         featuretail = &feature->next;
196                         node = wgt_config_next_feature(node);
197                 }
198         }
199
200         if (want_preferences) {
201                 preferencetail = &desc->preferences;
202                 node = wgt_config_first_preference();
203                 while (node) {
204                         preference = malloc(sizeof * preference);
205                         if (preference == NULL) {
206                                 errno = ENOMEM;
207                                 return -1;
208                         }
209                         preference->name = xmlGetProp(node, wgt_config_string_name);
210                         preference->value = xmlGetProp(node, wgt_config_string_value);
211                         preference->readonly = getpropbool(node, wgt_config_string_readonly, 0);
212
213                         *preferencetail = preference;
214                         preference->next = NULL;
215
216                         if (preference->name == NULL) {
217                                 warning("preference without name");
218                                 errno = EINVAL;
219                                 return -1;
220                         }
221
222                         preferencetail = &preference->next;
223                         node = wgt_config_next_preference(node);
224                 }
225         }
226         return 0;
227 }
228
229 static void free_desc(struct wgt_desc *desc)
230 {
231         struct wgt_desc_icon *icon;
232         struct wgt_desc_feature *feature;
233         struct wgt_desc_preference *preference;
234         struct wgt_desc_param *param;
235
236         xmlFree(desc->id);
237         xmlFree(desc->version);
238         xmlFree(desc->viewmodes);
239         xmlFree(desc->defaultlocale);
240         xmlFree(desc->name);
241         xmlFree(desc->name_short);
242         xmlFree(desc->description);
243         xmlFree(desc->author);
244         xmlFree(desc->author_href);
245         xmlFree(desc->author_email);
246         xmlFree(desc->license);
247         xmlFree(desc->license_href);
248         xmlFree(desc->content_src);
249         xmlFree(desc->content_type);
250         xmlFree(desc->content_encoding);
251
252         while(desc->icons) {
253                 icon = desc->icons;
254                 desc->icons = icon->next;
255                 xmlFree(icon->src);
256                 free(icon);
257         }
258
259         while(desc->features) {
260                 feature = desc->features;
261                 desc->features = feature->next;
262                 xmlFree(feature->name);
263                 while(feature->params) {
264                         param = feature->params;
265                         feature->params = param->next;
266                         xmlFree(param->name);
267                         xmlFree(param->value);
268                         free(param);
269                 }
270                 free(feature);
271         }
272
273         while(desc->preferences) {
274                 preference = desc->preferences;
275                 desc->preferences = preference->next;
276                 xmlFree(preference->name);
277                 xmlFree(preference->value);
278                 free(preference);
279         }
280 }
281
282 static void dump_desc(struct wgt_desc *desc, FILE *f, const char *prefix)
283 {
284         struct wgt_desc_icon *icon;
285         struct wgt_desc_feature *feature;
286         struct wgt_desc_preference *preference;
287         struct wgt_desc_param *param;
288
289         if (desc->id) fprintf(f, "%sid: %s\n", prefix, desc->id);
290         if (desc->width) fprintf(f, "%swidth: %d\n", prefix, desc->width);
291         if (desc->height) fprintf(f, "%sheight: %d\n", prefix, desc->height);
292         if (desc->version) fprintf(f, "%sversion: %s\n", prefix, desc->version);
293         if (desc->viewmodes) fprintf(f, "%sviewmodes: %s\n", prefix, desc->viewmodes);
294         if (desc->defaultlocale) fprintf(f, "%sdefaultlocale: %s\n", prefix, desc->defaultlocale);
295         if (desc->name) fprintf(f, "%sname: %s\n", prefix, desc->name);
296         if (desc->name_short) fprintf(f, "%sname_short: %s\n", prefix, desc->name_short);
297         if (desc->description) fprintf(f, "%sdescription: %s\n", prefix, desc->description);
298         if (desc->author) fprintf(f, "%sauthor: %s\n", prefix, desc->author);
299         if (desc->author_href) fprintf(f, "%sauthor_href: %s\n", prefix, desc->author_href);
300         if (desc->author_email) fprintf(f, "%sauthor_email: %s\n", prefix, desc->author_email);
301         if (desc->license) fprintf(f, "%slicense: %s\n", prefix, desc->license);
302         if (desc->license_href) fprintf(f, "%slicense_href: %s\n", prefix, desc->license_href);
303         if (desc->content_src) fprintf(f, "%scontent_src: %s\n", prefix, desc->content_src);
304         if (desc->content_type) fprintf(f, "%scontent_type: %s\n", prefix, desc->content_type);
305         if (desc->content_encoding) fprintf(f, "%scontent_encoding: %s\n", prefix, desc->content_encoding);
306
307         icon = desc->icons;
308         while(icon) {
309                 fprintf(f, "%s+ icon src: %s\n", prefix, icon->src);
310                 if (icon->width) fprintf(f, "%s       width: %d\n", prefix, icon->width);
311                 if (icon->height) fprintf(f, "%s       height: %d\n", prefix, icon->height);
312                 icon = icon->next;
313         }
314
315         feature = desc->features;
316         while(feature) {
317                 fprintf(f, "%s+ feature name: %s\n", prefix, feature->name);
318                 fprintf(f, "%s          required: %s\n", prefix, feature->required ? "true" : "false");
319                 param = feature->params;
320                 while(param) {
321                         fprintf(f, "%s          + param name: %s\n", prefix, param->name);
322                         fprintf(f, "%s                  value: %s\n", prefix, param->value);
323                         param = param->next;
324                 }
325                 feature = feature->next;
326         }
327
328         preference = desc->preferences;
329         while(preference) {
330                 fprintf(f, "%s+ preference name: %s\n", prefix, preference->name);
331                 if (preference->value) fprintf(f, "%s             value: %s\n", prefix, preference->value);
332                 fprintf(f, "%s             readonly: %s\n", prefix, preference->readonly ? "true" : "false");
333                 preference = preference->next;
334         }
335 }
336
337 struct wgt_info *wgt_info_get(struct wgt *wgt, int icons, int features, int preferences)
338 {
339         int rc;
340         struct wgt_info *result;
341
342         assert(wgt);
343         assert(wgt_is_connected(wgt));
344         rc = wgt_config_open(wgt);
345         if (rc) {
346                 errno = EINVAL;
347                 return NULL;
348         }
349
350         result = calloc(sizeof * result, 1);
351         if (!result) {
352                 wgt_config_close();
353                 errno = ENOMEM;
354                 return NULL;
355         }
356         result->refcount = 1;
357         result->wgt = wgt;
358         wgt_addref(wgt);
359
360         rc = fill_desc(&result->desc, icons, features, preferences);
361         wgt_config_close();
362         if (rc) {
363                 wgt_info_unref(result);
364                 return NULL;
365         }
366         return result;
367 }
368
369 const struct wgt_desc *wgt_info_desc(struct wgt_info *ifo)
370 {
371         return &ifo->desc;
372 }
373
374 void wgt_info_addref(struct wgt_info *ifo)
375 {
376         assert(ifo);
377         assert(ifo->refcount > 0);
378         ifo->refcount++;
379 }
380
381 void wgt_info_unref(struct wgt_info *ifo)
382 {
383         assert(ifo);
384         assert(ifo->refcount > 0);
385         if (--ifo->refcount)
386                 return;
387
388         free_desc(&ifo->desc);
389         wgt_unref(ifo->wgt);
390         free(ifo);
391 }
392
393 void wgt_info_dump(struct wgt_info *ifo, int fd, const char *prefix)
394 {
395         FILE *f;
396
397         assert(ifo);
398         f = fdopen(fd, "w");
399         if (f == NULL)
400                 warning("can't fdopen in wgt_info_dump");
401         else {
402                 dump_desc(&ifo->desc, f, prefix);
403                 fclose(f);
404         }
405 }
406