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