Fix build error
[platform/core/appfw/data-provider-slave.git] / icon_src / main.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (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://floralicense.org/license/
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 #if defined(LOG_TAG)
18 #undef LOG_TAG
19 #define LOG_TAG "ICON_PROVIDER"
20 #endif
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <Elementary.h>
27
28 #include <glib.h>
29 #include <glib-object.h>
30 #include <gio/gio.h>
31 #include <Ecore.h>
32 #include <app.h>
33 #include <Edje.h>
34 #include <Eina.h>
35
36 #include <vconf.h>
37 #include <dlog.h>
38 #include <bundle.h>
39 #include <widget_service/widget_service.h>
40 #include <widget_errno.h>
41 #include <widget_provider.h>
42
43 #include <system_settings.h>
44
45 #include <packet.h>
46 #include <com-core.h>
47 #include <com-core_packet.h>
48
49 #include <shortcut.h>
50 #include <shortcut_private.h>
51
52 #include "util.h"
53 #include "debug.h"
54
55 #define UTILITY_ADDR    "/tmp/.utility.service"
56 #if !defined(DEFAULT_ICON_LAYOUT)
57 #define DEFAULT_ICON_LAYOUT "/usr/apps/org.tizen.data-provider-slave/res/edje/icon.edj"
58 #endif
59
60 #if !defined(DEFAULT_ICON_GROUP)
61 #define DEFAULT_ICON_GROUP "default"
62 #endif
63
64 #define TEXT_CLASS      "tizen"
65 #define DEFAULT_FONT_SIZE       -100
66
67 int script_handler_parse_desc(Evas_Object *edje, const char *descfile);
68
69 static struct info {
70         int client_fd;
71         const char *socket_file;
72         char *font_name;
73 } s_info = {
74         .client_fd = -1,
75         .socket_file = UTILITY_ADDR,
76         .font_name = NULL,
77 };
78
79 #define TTL     30.0f   /* Can alive only 30 seconds from the last event */
80 #define QUALITY_N_COMPRESS "quality=100 compress=1"
81
82 /*!
83  * Defined for libwidget
84  */
85 const char *widget_find_pkgname(const char *filename)
86 {
87         return NULL;
88 }
89
90 int widget_request_update_by_id(const char *filename)
91 {
92         return WIDGET_ERROR_NOT_EXIST;
93 }
94
95 int widget_trigger_update_monitor(const char *id, int is_pd)
96 {
97         return WIDGET_ERROR_INVALID_PARAMETER;
98 }
99
100 static inline Evas *create_virtual_canvas(int w, int h)
101 {
102         Ecore_Evas *internal_ee;
103         Evas *internal_e;
104
105         // Create virtual canvas
106         internal_ee = ecore_evas_buffer_new(w, h);
107         if (!internal_ee) {
108                 ErrPrint("Failed to create a new canvas buffer\n");
109                 return NULL;
110         }
111
112         ecore_evas_alpha_set(internal_ee, EINA_TRUE);
113         ecore_evas_manual_render_set(internal_ee, EINA_TRUE);
114
115         // Get the "Evas" object from a virtual canvas
116         internal_e = ecore_evas_get(internal_ee);
117         if (!internal_e) {
118                 ecore_evas_free(internal_ee);
119                 ErrPrint("Faield to get Evas object\n");
120                 return NULL;
121         }
122
123         ecore_evas_resize(internal_ee, w, h);
124         ecore_evas_show(internal_ee);
125
126         return internal_e;
127 }
128
129 static inline int flush_data_to_file(Evas *e, char *data, const char *filename, int w, int h)
130 {
131         Evas_Object *output;
132
133         output = evas_object_image_add(e);
134         if (!output) {
135                 ErrPrint("Failed to create an image object\n");
136                 return EXIT_FAILURE;
137         }
138
139         evas_object_image_data_set(output, NULL);
140         evas_object_image_colorspace_set(output, EVAS_COLORSPACE_ARGB8888);
141         evas_object_image_alpha_set(output, EINA_TRUE);
142         evas_object_image_size_set(output, w, h);
143         evas_object_image_smooth_scale_set(output, EINA_TRUE);
144         evas_object_image_data_set(output, data);
145         evas_object_image_data_update_add(output, 0, 0, w, h);
146
147         if (evas_object_image_save(output, filename, NULL, QUALITY_N_COMPRESS) == EINA_FALSE) {
148                 evas_object_del(output);
149                 ErrPrint("Faield to save a captured image (%s)\n", filename);
150                 return EXIT_FAILURE;
151         }
152
153         evas_object_del(output);
154
155         if (access(filename, F_OK) != 0) {
156                 ErrPrint("File %s is not found\n", filename);
157                 return EXIT_FAILURE;
158         }
159
160         return EXIT_SUCCESS;
161 }
162
163 static inline int flush_to_file(Evas *e, const char *filename, int w, int h)
164 {
165         void *data;
166         Ecore_Evas *internal_ee;
167
168         internal_ee = ecore_evas_ecore_evas_get(e);
169         if (!internal_ee) {
170                 ErrPrint("Failed to get ecore evas\n");
171                 return EXIT_FAILURE;
172         }
173
174         ecore_evas_manual_render(internal_ee);
175
176         // Get a pointer of a buffer of the virtual canvas
177         data = (void *)ecore_evas_buffer_pixels_get(internal_ee);
178         if (!data) {
179                 ErrPrint("Failed to get pixel data\n");
180                 return EXIT_FAILURE;
181         }
182
183         return flush_data_to_file(e, data, filename, w, h);
184 }
185
186 static inline int destroy_virtual_canvas(Evas *e)
187 {
188         Ecore_Evas *ee;
189
190         ee = ecore_evas_ecore_evas_get(e);
191         if (!ee) {
192                 ErrPrint("Failed to ecore evas object\n");
193                 return EXIT_FAILURE;
194         }
195
196         ecore_evas_free(ee);
197         return EXIT_SUCCESS;
198 }
199
200 static int disconnected_cb(int handle, void *data)
201 {
202         s_info.client_fd = -1;
203         elm_exit();
204         return 0;
205 }
206
207 static inline int convert_shortcut_type_to_lb_type(int shortcut_type, char **str)
208 {
209         char *_str;
210
211         if (!str) {
212                 str = &_str;
213         }
214
215         switch (shortcut_type) {
216         case WIDGET_SIZE_TYPE_1x1:
217                 *str = "1x1";
218                 return WIDGET_SIZE_TYPE_1x1;
219         case WIDGET_SIZE_TYPE_2x1:
220                 *str = "2x1";
221                 return WIDGET_SIZE_TYPE_2x1;
222         case WIDGET_SIZE_TYPE_2x2:
223                 *str = "2x2";
224                 return WIDGET_SIZE_TYPE_2x2;
225         case WIDGET_SIZE_TYPE_4x1:
226                 *str = "4x1";
227                 return WIDGET_SIZE_TYPE_4x1;
228         case WIDGET_SIZE_TYPE_4x2:
229                 *str = "4x2";
230                 return WIDGET_SIZE_TYPE_4x2;
231         case WIDGET_SIZE_TYPE_4x3:
232                 *str = "4x3";
233                 return WIDGET_SIZE_TYPE_4x3;
234         case WIDGET_SIZE_TYPE_4x4:
235                 *str = "4x4";
236                 return WIDGET_SIZE_TYPE_4x4;
237         case WIDGET_SIZE_TYPE_4x5:
238                 *str = "4x5";
239                 return WIDGET_SIZE_TYPE_4x5;
240         case WIDGET_SIZE_TYPE_4x6:
241                 *str = "4x6";
242                 return WIDGET_SIZE_TYPE_4x6;
243         case WIDGET_SIZE_TYPE_EASY_1x1:
244                 *str = "easy,1x1";
245                 return WIDGET_SIZE_TYPE_EASY_1x1;
246         case WIDGET_SIZE_TYPE_EASY_3x1:
247                 *str = "easy,3x1";
248                 return WIDGET_SIZE_TYPE_EASY_3x1;
249         case WIDGET_SIZE_TYPE_EASY_3x3:
250                 *str = "easy,3x3";
251                 return WIDGET_SIZE_TYPE_EASY_3x3;
252         default:
253                 *str = "?x?";
254                 return WIDGET_SIZE_TYPE_UNKNOWN;
255         }
256 }
257
258 static struct packet *icon_create(pid_t pid, int handle, const struct packet *packet)
259 {
260         Evas *e;
261         const char *edje_path;
262         const char *group;
263         const char *desc_file;
264         const char *output;
265         int size_type;
266         int ret;
267         int w;
268         int h;
269         Evas_Object *edje;
270         Evas_Object *parent;
271         char _group[16];
272         char *size_str;
273
274         ret = packet_get(packet, "sssis", &edje_path, &group, &desc_file, &size_type, &output);
275         if (ret != 5) {
276                 ErrPrint("Invalid parameters");
277                 ret = -EINVAL;
278                 goto out;
279         }
280
281         if (!edje_path || !strlen(edje_path)) {
282                 edje_path = DEFAULT_ICON_LAYOUT;
283         }
284
285         size_type = convert_shortcut_type_to_lb_type(size_type, &size_str);
286         if (!group || !strlen(group)) {
287                 snprintf(_group, sizeof(_group), DEFAULT_ICON_GROUP",%s", size_str);
288                 group = _group;
289         }
290         DbgPrint("Selected layout: %s(%s)\n", edje_path, group);
291
292         ret = widget_service_get_size(size_type, &w, &h);
293         if (ret != WIDGET_ERROR_NONE) {
294                 ErrPrint("Unable to get size(%d): %d\n", size_type, ret);
295                 goto out;
296         }
297
298         e = create_virtual_canvas(w, h);
299         if (!e) {
300                 ErrPrint("Unable to create a canvas: %dx%d\n", w, h);
301                 ret = WIDGET_ERROR_FAULT;
302                 goto out;
303         }
304
305         parent = evas_object_rectangle_add(e);
306         if (!parent) {
307                 ErrPrint("Unable to create a parent\n");
308                 destroy_virtual_canvas(e);
309                 ret = WIDGET_ERROR_FAULT;
310                 goto out;
311         }
312
313         evas_object_resize(parent, w, h);
314         evas_object_color_set(parent, 0, 0, 0, 0);
315         evas_object_show(parent);
316
317         edje = elm_layout_add(parent);
318         if (!edje) {
319                 ErrPrint("Unable to add an edje object\n");
320                 evas_object_del(parent);
321                 destroy_virtual_canvas(e);
322                 goto out;
323         }
324
325         if (elm_layout_file_set(edje, edje_path, group) == EINA_FALSE) {
326                 Edje_Load_Error err;
327                 err = edje_object_load_error_get(elm_layout_edje_get(edje));
328                 if (err != EDJE_LOAD_ERROR_NONE) {
329                         ErrPrint("Uanble to load an edje %s(%s) - %s\n", edje_path, group, edje_load_error_str(err));
330                 }
331                 evas_object_del(edje);
332                 evas_object_del(parent);
333                 destroy_virtual_canvas(e);
334                 goto out;
335         }
336
337         evas_object_resize(edje, w, h);
338         evas_object_show(edje);
339
340         if (script_handler_parse_desc(edje, desc_file) != WIDGET_ERROR_NONE) {
341                 ErrPrint("Unable to parse the %s\n", desc_file);
342         }
343
344         flush_to_file(e, output, w, h);
345         evas_object_del(edje);
346         evas_object_del(parent);
347         destroy_virtual_canvas(e);
348
349 out:
350         if (ret < 0) {
351                 /* Desc file should be deleted if it fails to create an icon image */
352                 if (unlink(desc_file) < 0) {
353                         ErrPrint("unlink(%s): %d\n", desc_file, errno);
354                 }
355         }
356
357         return packet_create_reply(packet, "i", ret);
358 }
359
360 static inline int client_init(void)
361 {
362         int ret;
363         struct packet *packet;
364         static struct method service_table[] = {
365                 {
366                         .cmd = "icon_create",
367                         .handler = icon_create,
368                 },
369                 {
370                         .cmd = NULL,
371                         .handler = NULL,
372                 },
373         };
374
375         com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
376
377         s_info.client_fd = com_core_packet_client_init(s_info.socket_file, 0, service_table);
378         if (s_info.client_fd < 0) {
379                 ErrPrint("Failed to make a connection to the master\n");
380                 return -EFAULT;
381         }
382
383         packet = packet_create_noack("service_register", "");
384         if (!packet) {
385                 ErrPrint("Failed to build a packet\n");
386                 return -EFAULT;
387         }
388
389         ret = com_core_packet_send_only(s_info.client_fd, packet);
390         DbgPrint("Service register sent: %d\n", ret);
391         packet_destroy(packet);
392         if (ret != 0) {
393                 com_core_packet_client_fini(s_info.client_fd);
394                 s_info.client_fd = -1;
395                 ret = -EFAULT;
396         } else {
397                 ret = 0;
398         }
399
400         DbgPrint("Server FD: %d\n", s_info.client_fd);
401         return ret;
402 }
403
404 static inline void client_fini(void)
405 {
406         if (s_info.client_fd < 0) {
407                 DbgPrint("Client is not initiated\n");
408                 return;
409         }
410
411         com_core_packet_client_fini(s_info.client_fd);
412         s_info.client_fd = -1;
413 }
414
415 static void update_font_cb(void *data)
416 {
417         Eina_List *list;
418         char *text;
419
420         list = edje_text_class_list();
421         DbgPrint("List: %p\n", list);
422         if (list) {
423                 EINA_LIST_FREE(list, text) {
424                         if (!strncasecmp(text, TEXT_CLASS, strlen(TEXT_CLASS))) {
425                                 DbgPrint("Update text class %s (%s, %d)\n", text, s_info.font_name, DEFAULT_FONT_SIZE);
426                                 edje_text_class_del(text);
427                                 edje_text_class_set(text, s_info.font_name, DEFAULT_FONT_SIZE);
428                         } else {
429                                 DbgPrint("Skip text class %s\n", text);
430                         }
431                 }
432         } else {
433                 DbgPrint("New (%s, %d)\n", s_info.font_name, DEFAULT_FONT_SIZE);
434                 edje_text_class_set(TEXT_CLASS, s_info.font_name, DEFAULT_FONT_SIZE);
435         }
436 }
437
438 static void font_changed_cb(keynode_t *node, void *user_data)
439 {
440         char *font_name;
441
442 //      evas_font_reinit();
443
444         if (s_info.font_name) {
445                 font_name = vconf_get_str("db/setting/accessibility/font_name");
446                 if (!font_name) {
447                         ErrPrint("Invalid font name (NULL)\n");
448                         return;
449                 }
450
451                 if (!strcmp(s_info.font_name, font_name)) {
452                         DbgPrint("Font is not changed (Old: %s(%p) <> New: %s(%p))\n", s_info.font_name, s_info.font_name, font_name, font_name);
453                         free(font_name);
454                         return;
455                 }
456
457                 DbgPrint("Release old font name: %s(%p)\n", s_info.font_name, s_info.font_name);
458                 free(s_info.font_name);
459         } else {
460                 int ret;
461
462                 font_name = NULL;
463                 ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_FONT_TYPE, &font_name);
464                 if (ret != SYSTEM_SETTINGS_ERROR_NONE || !font_name) {
465                         ErrPrint("system settings: %d, font_name[%p]\n", ret, font_name);
466                         return;
467                 }
468         }
469
470         s_info.font_name = font_name;
471         DbgPrint("Font name is changed to %s(%p)\n", s_info.font_name, s_info.font_name);
472
473         update_font_cb(NULL);
474 }
475
476 static bool app_create(void *data)
477 {
478         int ret;
479
480         if (client_init() < 0) {
481                 ErrPrint("Unable to initiate the client\n");
482                 return FALSE;
483         }
484
485         /*!
486          * Send a request to reigister as a service.
487          */
488         ret = vconf_notify_key_changed("db/setting/accessibility/font_name", font_changed_cb, NULL);
489         if (ret < 0) {
490                 DbgPrint("System font is changed: %d\n", ret);
491         }
492
493         font_changed_cb(NULL, NULL);
494         return TRUE;
495 }
496
497 static void app_terminate(void *data)
498 {
499         int ret;
500
501         ret = vconf_ignore_key_changed("db/setting/accessibility/font_name", font_changed_cb);
502         if (ret < 0) {
503                 DbgPrint("Remove font change callback: %d\n", ret);
504         }
505
506         client_fini();
507
508         free(s_info.font_name);
509         s_info.font_name = NULL;
510         return;
511 }
512
513 static void app_pause(void *data)
514 {
515         /* Will not be called */
516         return;
517 }
518
519 static void app_resume(void *data)
520 {
521         /* Will not be called */
522         return;
523 }
524
525 static void app_control(app_control_h service, void *data)
526 {
527 }
528
529 int main(int argc, char *argv[])
530 {
531         int ret;
532         ui_app_lifecycle_callback_s event_callback;
533
534         event_callback.create = app_create;
535         event_callback.terminate = app_terminate;
536         event_callback.pause = app_pause;
537         event_callback.resume = app_resume;
538         event_callback.app_control = app_control;
539
540         ret = ui_app_main(argc, argv, &event_callback, NULL);
541         return ret;
542 }
543
544 /* End of a file */