Update orientation value
[platform/core/appfw/data-provider-slave.git] / src / client.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 #include <stdio.h>
18 #include <unistd.h>
19 #include <errno.h>
20 #include <malloc.h>
21
22 #include <Elementary.h>
23 #include <Eina.h>
24 #include <Ecore.h>
25 #include <Ecore_X.h>
26
27 #include <app.h>
28 #include <dlog.h>
29 #include <aul.h>
30 #include <sqlite3.h>
31
32 #include <widget_provider.h> /* widget_provider */
33 #include <widget_errno.h> /* widget_service */
34 #include <widget_script.h> /* widget_service - widget_event_info */
35 #include <widget_conf.h>
36 #include <widget/widget_internal.h> /* widget - WIDGET_SYS_EVENT_XXX */
37 #include <widget/widget.h> /* widget - WIDGET_SYS_EVENT_XXX */
38
39 #include "critical_log.h"
40 #include "debug.h"
41 #include "client.h"
42 #include "so_handler.h"
43 #include "widget.h"
44 #include "util.h"
45 #include "conf.h"
46 #include "main.h"
47
48 struct pre_callback_item {
49         widget_pre_callback_t cb;
50         void *data;
51 };
52
53 static struct info {
54         Ecore_Timer *ping_timer;
55         Eina_List *widget_pre_callback_list[WIDGET_PRE_CALLBACK_COUNT];
56 } s_info = {
57         .ping_timer = NULL,
58         .widget_pre_callback_list = { NULL, },
59 };
60
61 static void invoke_pre_callback(widget_pre_callback_e type, const char *id)
62 {
63         Eina_List *l;
64         Eina_List *n;
65         struct pre_callback_item *item;
66
67         EINA_LIST_FOREACH_SAFE(s_info.widget_pre_callback_list[type], l, n, item) {
68                 item->cb(id, item->data);
69         }
70 }
71
72 int widget_provider_app_add_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
73 {
74         struct pre_callback_item *item;
75         Eina_List *l;
76
77         if (!cb || type == WIDGET_PRE_CALLBACK_COUNT) {
78                 return WIDGET_ERROR_INVALID_PARAMETER;
79         }
80
81         EINA_LIST_FOREACH(s_info.widget_pre_callback_list[type], l, item) {
82                 if (item->cb == cb && item->data == data) {
83                         return WIDGET_ERROR_ALREADY_EXIST;
84                 }
85         }
86
87         item = malloc(sizeof(*item));
88         if (!item) {
89                 ErrPrint("malloc: %d\n", errno);
90                 return WIDGET_ERROR_OUT_OF_MEMORY;
91         }
92
93         item->cb = cb;
94         item->data = data;
95
96         s_info.widget_pre_callback_list[type] = eina_list_append(s_info.widget_pre_callback_list[type], item);
97         return 0;
98 }
99
100 int widget_provider_app_del_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data)
101 {
102         Eina_List *l;
103         Eina_List *n;
104         struct pre_callback_item *item;
105
106         if (!cb || type == WIDGET_PRE_CALLBACK_COUNT) {
107                 ErrPrint("Invalid parameter\n");
108                 return WIDGET_ERROR_INVALID_PARAMETER;
109         }
110
111         EINA_LIST_FOREACH_SAFE(s_info.widget_pre_callback_list[type], l, n, item) {
112                 if (item->cb == cb && item->data == data) {
113                         s_info.widget_pre_callback_list[type] = eina_list_remove_list(s_info.widget_pre_callback_list[type], l);
114                         free(item);
115                         return WIDGET_ERROR_NONE;
116                 }
117         }
118
119         return WIDGET_ERROR_NOT_EXIST;
120 }
121
122 static int method_new(struct widget_event_arg *arg, int *width, int *height, double *priority, void *data)
123 {
124         int ret;
125         struct widget_create_arg _arg;
126         DbgPrint("Create: pkgname[%s], id[%s], content[%s], timeout[%d], has_script[%d], period[%lf], cluster[%s], category[%s], skip[%d], abi[%s], size: %dx%d\n",
127                         arg->pkgname,
128                         arg->id,
129                         arg->info.widget_create.content,
130                         arg->info.widget_create.timeout,
131                         arg->info.widget_create.has_script,
132                         arg->info.widget_create.period,
133                         arg->info.widget_create.cluster, arg->info.widget_create.category,
134                         arg->info.widget_create.skip_need_to_create,
135                         arg->info.widget_create.abi,
136                         arg->info.widget_create.width,
137                         arg->info.widget_create.height);
138
139         if (!arg->info.widget_create.content || !strlen(arg->info.widget_create.content)) {
140                 DbgPrint("Use default content: \"%s\"\n", WIDGET_CONF_DEFAULT_CONTENT);
141                 arg->info.widget_create.content = WIDGET_CONF_DEFAULT_CONTENT;
142         }
143
144         _arg.content = arg->info.widget_create.content;
145         _arg.timeout = arg->info.widget_create.timeout;
146         _arg.has_widget_script = arg->info.widget_create.has_script;
147         _arg.period = arg->info.widget_create.period;
148         _arg.cluster = arg->info.widget_create.cluster;
149         _arg.category = arg->info.widget_create.category;
150         _arg.abi = arg->info.widget_create.abi;
151         _arg.skip_need_to_create = arg->info.widget_create.skip_need_to_create;
152         _arg.direct_addr = arg->info.widget_create.direct_addr;
153
154         invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
155
156         ret = widget_create(arg->pkgname, arg->id,
157                         &_arg,
158                         width, height, priority,
159                         &arg->info.widget_create.out_content,
160                         &arg->info.widget_create.out_title);
161
162         if (ret == 0) {
163                 if (widget_set_orientation(arg->pkgname, arg->id, arg->info.widget_create.degree) < 0) {
164                         ErrPrint("Failed to set orientation %s - %d\n", arg->id, arg->info.widget_create.degree);
165                 }
166                 if (arg->info.widget_create.width > 0 && arg->info.widget_create.height > 0) {
167                         DbgPrint("Create size: %dx%d (created: %dx%d)\n", arg->info.widget_create.width, arg->info.widget_create.height, *width, *height);
168                         if (*width != arg->info.widget_create.width || *height != arg->info.widget_create.height) {
169                                 int tmp;
170                                 tmp = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.widget_create.width, arg->info.widget_create.height);
171                                 DbgPrint("widget_resize returns: %d\n", tmp);
172                                 if (tmp == (int)WIDGET_ERROR_NONE) {
173                                         /*!
174                                          * \note
175                                          * Just returns resized canvas size.
176                                          * Even if it is not ready to render contents.
177                                          * Provider will allocate render buffer using this size.
178                                          */
179                                         *width = arg->info.widget_create.width;
180                                         *height = arg->info.widget_create.height;
181                                 }
182                         }
183                 }
184
185                 arg->info.widget_create.out_is_pinned_up = (widget_viewer_is_pinned_up(arg->pkgname, arg->id) == 1);
186         } else {
187                 ErrPrint("widget_create returns %d\n", ret);
188         }
189
190         if (widget_is_all_paused()) {
191                 DbgPrint("Box is paused\n");
192                 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_PAUSED);
193         }
194
195         return ret;
196 }
197
198 static int method_renew(struct widget_event_arg *arg, void *data)
199 {
200         int ret;
201         int w;
202         int h;
203         double priority;
204         struct widget_create_arg _arg;
205
206         DbgPrint("Re-create: pkgname[%s], id[%s], content[%s], timeout[%d], has_script[%d], period[%lf], cluster[%s], category[%s], abi[%s]\n",
207                         arg->pkgname, arg->id,
208                         arg->info.widget_recreate.content,
209                         arg->info.widget_recreate.timeout,
210                         arg->info.widget_recreate.has_script,
211                         arg->info.widget_recreate.period,
212                         arg->info.widget_recreate.cluster,
213                         arg->info.widget_recreate.category,
214                         arg->info.widget_recreate.abi);
215
216         if (!arg->info.widget_recreate.content || !strlen(arg->info.widget_recreate.content)) {
217                 DbgPrint("Use default content: \"%s\"\n", WIDGET_CONF_DEFAULT_CONTENT);
218                 arg->info.widget_recreate.content = WIDGET_CONF_DEFAULT_CONTENT;
219         }
220
221         _arg.content = arg->info.widget_recreate.content;
222         _arg.timeout = arg->info.widget_recreate.timeout;
223         _arg.has_widget_script = arg->info.widget_recreate.has_script;
224         _arg.period = arg->info.widget_recreate.period;
225         _arg.cluster = arg->info.widget_recreate.cluster;
226         _arg.category = arg->info.widget_recreate.category;
227         _arg.abi = arg->info.widget_recreate.abi;
228         _arg.skip_need_to_create = 1;
229         _arg.direct_addr = arg->info.widget_recreate.direct_addr;
230
231         invoke_pre_callback(WIDGET_PRE_CREATE_CALLBACK, arg->id);
232
233         ret = widget_create(arg->pkgname, arg->id,
234                         &_arg,
235                         &w, &h, &priority,
236                         &arg->info.widget_recreate.out_content,
237                         &arg->info.widget_recreate.out_title);
238         if (ret == 0) {
239                 if (widget_set_orientation(arg->pkgname, arg->id, arg->info.widget_create.degree) < 0) {
240                         ErrPrint("Failed to set orientation %s - %d\n", arg->id, arg->info.widget_create.degree);
241                 }
242
243                 if (w != arg->info.widget_recreate.width || h != arg->info.widget_recreate.height) {
244                         int tmp;
245                         tmp = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.widget_recreate.width, arg->info.widget_recreate.height);
246                         if (tmp < 0) {
247                                 DbgPrint("Resize[%dx%d] returns: %d\n", arg->info.widget_recreate.width, arg->info.widget_recreate.height, tmp);
248                         }
249                 } else {
250                         DbgPrint("No need to change the size: %dx%d\n", w, h);
251                 }
252
253                 arg->info.widget_recreate.out_is_pinned_up = (widget_viewer_is_pinned_up(arg->pkgname, arg->id) == 1);
254         } else {
255                 ErrPrint("widget_create returns %d\n", ret);
256         }
257
258         if (widget_is_all_paused()) {
259                 DbgPrint("Box is paused\n");
260                 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_PAUSED);
261         }
262
263         return ret;
264 }
265
266 static int method_delete(struct widget_event_arg *arg, void *data)
267 {
268         int ret;
269
270         DbgPrint("pkgname[%s] id[%s]\n", arg->pkgname, arg->id);
271
272         if (arg->info.widget_destroy.type == WIDGET_DESTROY_TYPE_DEFAULT || arg->info.widget_destroy.type == WIDGET_DESTROY_TYPE_UNINSTALL) {
273                 DbgPrint("Box is deleted from the viewer\n");
274                 (void)widget_system_event(arg->pkgname, arg->id, WIDGET_SYS_EVENT_DELETED);
275         }
276
277         invoke_pre_callback(WIDGET_PRE_DESTROY_CALLBACK, arg->id);
278         ret = widget_destroy(arg->pkgname, arg->id, 0);
279         return ret;
280 }
281
282 static int method_content_event(struct widget_event_arg *arg, void *data)
283 {
284         int ret;
285         struct widget_event_info info;
286
287         info = arg->info.content_event.info;
288
289         ret = widget_script_event(arg->pkgname, arg->id,
290                         arg->info.content_event.signal_name, arg->info.content_event.source,
291                         &info);
292         return ret;
293 }
294
295 static int method_clicked(struct widget_event_arg *arg, void *data)
296 {
297         int ret;
298
299         DbgPrint("pkgname[%s] id[%s] event[%s] timestamp[%lf] x[%lf] y[%lf]\n",
300                         arg->pkgname, arg->id,
301                         arg->info.clicked.event, arg->info.clicked.timestamp,
302                         arg->info.clicked.x, arg->info.clicked.y);
303         ret = widget_clicked(arg->pkgname, arg->id,
304                         arg->info.clicked.event,
305                         arg->info.clicked.timestamp, arg->info.clicked.x, arg->info.clicked.y);
306
307         return ret;
308 }
309
310 static int method_text_signal(struct widget_event_arg *arg, void *data)
311 {
312         int ret;
313         struct widget_event_info info;
314
315         info = arg->info.text_signal.info;
316
317         DbgPrint("pkgname[%s] id[%s] signal_name[%s] source[%s]\n", arg->pkgname, arg->id, arg->info.text_signal.signal_name, arg->info.text_signal.source);
318         ret = widget_script_event(arg->pkgname, arg->id,
319                         arg->info.text_signal.signal_name, arg->info.text_signal.source,
320                         &info);
321
322         return ret;
323 }
324
325 static int method_resize(struct widget_event_arg *arg, void *data)
326 {
327         int ret;
328
329         invoke_pre_callback(WIDGET_PRE_RESIZE_CALLBACK, arg->id);
330
331         DbgPrint("pkgname[%s] id[%s] w[%d] h[%d]\n", arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
332         ret = widget_viewer_resize_widget(arg->pkgname, arg->id, arg->info.resize.w, arg->info.resize.h);
333
334         return ret;
335 }
336
337 static int method_set_period(struct widget_event_arg *arg, void *data)
338 {
339         int ret;
340         DbgPrint("pkgname[%s] id[%s] period[%lf]\n", arg->pkgname, arg->id, arg->info.set_period.period);
341         ret = widget_viewer_set_period(arg->pkgname, arg->id, arg->info.set_period.period);
342         return ret;
343 }
344
345 static int method_change_group(struct widget_event_arg *arg, void *data)
346 {
347         int ret;
348         DbgPrint("pkgname[%s] id[%s] cluster[%s] category[%s]\n", arg->pkgname, arg->id, arg->info.change_group.cluster, arg->info.change_group.category);
349         ret = widget_change_group(arg->pkgname, arg->id, arg->info.change_group.cluster, arg->info.change_group.category);
350         return ret;
351 }
352
353 static int method_pinup(struct widget_event_arg *arg, void *data)
354 {
355         DbgPrint("pkgname[%s] id[%s] state[%d]\n", arg->pkgname, arg->id, arg->info.pinup.state);
356         arg->info.pinup.content_info = widget_pinup(arg->pkgname, arg->id, arg->info.pinup.state);
357         return arg->info.pinup.content_info ? WIDGET_ERROR_NONE : WIDGET_ERROR_NOT_SUPPORTED;
358 }
359
360 static int method_update_content(struct widget_event_arg *arg, void *data)
361 {
362         int ret;
363
364         if (!arg->id || !strlen(arg->id)) {
365                 if (arg->info.update_content.content && strlen(arg->info.update_content.content)) {
366                         DbgPrint("pkgname[%s] content[%s]\n", arg->pkgname, arg->info.update_content.content);
367                         ret = widget_set_content_info_all(arg->pkgname, arg->info.update_content.content);
368                 } else {
369                         DbgPrint("pkgname[%s] cluster[%s] category[%s]\n", arg->pkgname, arg->info.update_content.cluster, arg->info.update_content.category);
370                         ret = widget_update_all(arg->pkgname, arg->info.update_content.cluster, arg->info.update_content.category, arg->info.update_content.force);
371                 }
372         } else {
373                 if (arg->info.update_content.content && strlen(arg->info.update_content.content)) {
374                         DbgPrint("id[%s] content[%s]\n", arg->id, arg->info.update_content.content);
375                         ret = widget_set_content_info(arg->pkgname, arg->id, arg->info.update_content.content);
376                 } else {
377                         DbgPrint("Update [%s]\n", arg->id);
378                         ret = widget_update(arg->pkgname, arg->id, arg->info.update_content.force);
379                 }
380         }
381
382         return ret;
383 }
384
385 static int method_pause(struct widget_event_arg *arg, void *data)
386 {
387         widget_pause_all();
388
389         if (s_info.ping_timer) {
390                 ecore_timer_freeze(s_info.ping_timer);
391         }
392
393         if (WIDGET_CONF_SLAVE_AUTO_CACHE_FLUSH) {
394                 elm_cache_all_flush();
395                 sqlite3_release_memory(WIDGET_CONF_SQLITE_FLUSH_MAX);
396                 malloc_trim(0);
397         }
398
399         return WIDGET_ERROR_NONE;
400 }
401
402 static int method_resume(struct widget_event_arg *arg, void *data)
403 {
404         widget_resume_all();
405
406         if (s_info.ping_timer) {
407                 ecore_timer_thaw(s_info.ping_timer);
408         }
409
410         return WIDGET_ERROR_NONE;
411 }
412
413 static Eina_Bool send_ping_cb(void *data)
414 {
415         widget_provider_send_ping();
416         return ECORE_CALLBACK_RENEW;
417 }
418
419 static int method_disconnected(struct widget_event_arg *arg, void *data)
420 {
421         if (s_info.ping_timer) {
422                 ecore_timer_del(s_info.ping_timer);
423                 s_info.ping_timer = NULL;
424         }
425
426         main_app_exit();
427         return WIDGET_ERROR_NONE;
428 }
429
430 static int method_connected(struct widget_event_arg *arg, void *data)
431 {
432         int ret;
433         ret = widget_provider_send_hello();
434         if (ret == 0) {
435                 double ping_interval;
436
437                 ping_interval = WIDGET_CONF_DEFAULT_PING_TIME / 2.0f;
438                 DbgPrint("Ping Timer: %lf\n", ping_interval);
439
440                 s_info.ping_timer = ecore_timer_add(ping_interval, send_ping_cb, NULL);
441                 if (!s_info.ping_timer) {
442                         ErrPrint("Failed to add a ping timer\n");
443                 }
444         }
445
446         return WIDGET_ERROR_NONE;
447 }
448
449 static int method_gbar_created(struct widget_event_arg *arg, void *data)
450 {
451         int ret;
452
453         ret = widget_open_gbar(arg->pkgname, arg->id);
454         if (ret < 0) {
455                 DbgPrint("%s Open PD: %d\n", arg->id, ret);
456         }
457
458         return WIDGET_ERROR_NONE;
459 }
460
461 static int method_gbar_destroyed(struct widget_event_arg *arg, void *data)
462 {
463         int ret;
464
465         ret = widget_close_gbar(arg->pkgname, arg->id);
466         if (ret < 0) {
467                 DbgPrint("%s Close PD: %d\n", arg->id, ret);
468         }
469
470         return WIDGET_ERROR_NONE;
471 }
472
473 static int method_gbar_moved(struct widget_event_arg *arg, void *data)
474 {
475         int ret;
476         struct widget_event_info info;
477
478         memset(&info, 0, sizeof(info));
479         info.pointer.x = arg->info.gbar_move.x;
480         info.pointer.y = arg->info.gbar_move.y;
481         info.pointer.down = 0;
482
483         ret = widget_script_event(arg->pkgname, arg->id,
484                         "gbar,move", util_uri_to_path(arg->id), &info);
485         return ret;
486 }
487
488 static int method_widget_pause(struct widget_event_arg *arg, void *data)
489 {
490         int ret;
491
492         ret = widget_pause(arg->pkgname, arg->id);
493
494         if (WIDGET_CONF_SLAVE_AUTO_CACHE_FLUSH) {
495                 elm_cache_all_flush();
496                 sqlite3_release_memory(WIDGET_CONF_SQLITE_FLUSH_MAX);
497                 malloc_trim(0);
498         }
499
500         return ret;
501 }
502
503 static int method_widget_resume(struct widget_event_arg *arg, void *data)
504 {
505         return widget_resume(arg->pkgname, arg->id);
506 }
507
508 static int method_viewer_connected(struct widget_event_arg *arg, void *data)
509 {
510         return widget_viewer_connected(arg->pkgname, arg->id, arg->info.viewer_connected.direct_addr);
511 }
512
513 static int method_viewer_disconnected(struct widget_event_arg *arg, void *data)
514 {
515         return widget_viewer_disconnected(arg->pkgname, arg->id, arg->info.viewer_disconnected.direct_addr);
516 }
517
518 static int method_orientation(struct widget_event_arg *arg, void *data)
519 {
520         int ret;
521
522         ret = widget_set_orientation(arg->pkgname, arg->id, arg->info.orientation.degree);
523         invoke_pre_callback(WIDGET_PRE_ORIENTATION_CALLBACK, arg->id);
524
525         return ret;
526 }
527
528 HAPI int client_init(const char *name, const char *abi, const char *accel, int secured)
529 {
530         struct widget_event_table table = {
531                 .widget_create = method_new,
532                 .widget_recreate = method_renew,
533                 .widget_destroy = method_delete,
534                 .content_event = method_content_event,
535                 .clicked = method_clicked,
536                 .text_signal = method_text_signal,
537                 .resize = method_resize,
538                 .set_period = method_set_period,
539                 .change_group = method_change_group,
540                 .pinup = method_pinup,
541                 .update_content = method_update_content,
542                 .pause = method_pause,
543                 .resume = method_resume,
544                 .disconnected = method_disconnected,
545                 .connected = method_connected,
546                 .gbar_create = method_gbar_created,
547                 .gbar_destroy = method_gbar_destroyed,
548                 .gbar_move = method_gbar_moved,
549                 .widget_pause = method_widget_pause,
550                 .widget_resume = method_widget_resume,
551                 .viewer_connected = method_viewer_connected,
552                 .viewer_disconnected = method_viewer_disconnected,
553                 .orientation = method_orientation,
554         };
555
556         widget_provider_prepare_init(abi, accel, secured);
557         return widget_provider_init(util_screen_get(), name, &table, NULL, 1, 1);
558 }
559
560 HAPI int client_fini(void)
561 {
562         (void)widget_provider_fini();
563         return WIDGET_ERROR_NONE;
564 }
565
566 /* End of a file */
567